Added PODs.
[koha.git] / C4 / Reserves2.pm
1 package C4::Reserves2; #assumes C4/Reserves2
2
3
4 # Copyright 2000-2002 Katipo Communications
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
11 # version.
12 #
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along with
18 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19 # Suite 330, Boston, MA  02111-1307 USA
20
21 use strict;
22 require Exporter;
23 use DBI;
24 use C4::Database;
25 use C4::Search;
26 #use C4::Accounts;
27
28 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
29   
30 # set the version for version checking
31 $VERSION = 0.01;
32     
33 @ISA = qw(Exporter);
34 @EXPORT = qw(&FindReserves &CheckReserves &CheckWaiting &CancelReserve &FillReserve &ReserveWaiting &CreateReserve &updatereserves &getreservetitle &Findgroupreserve);
35                                                     
36 # make all your functions, whether exported or not;
37
38 sub FindReserves {
39   my ($bib,$bor)=@_;
40   my $dbh=C4Connect;
41   my $query="SELECT *,reserves.branchcode,biblio.title AS btitle
42                       FROM reserves,borrowers,biblio ";
43   if ($bib ne ''){
44       $bib = $dbh->quote($bib);
45       if ($bor ne ''){
46           $bor = $dbh->quote($bor);
47           $query .=  " where reserves.biblionumber   = $bib
48                          and borrowers.borrowernumber = $bor 
49                          and reserves.borrowernumber = borrowers.borrowernumber 
50                          and biblio.biblionumber     = $bib 
51                          and cancellationdate is NULL 
52                          and (found <> 'F' or found is NULL)";
53       } else {
54           $query .= " where reserves.borrowernumber = borrowers.borrowernumber
55                         and biblio.biblionumber     = $bib 
56                         and reserves.biblionumber   = $bib
57                         and cancellationdate is NULL 
58                         and (found <> 'F' or found is NULL)";
59       }
60   } else {
61       $query .= " where borrowers.borrowernumber = $bor 
62                     and reserves.borrowernumber  = borrowers.borrowernumber 
63                     and reserves.biblionumber    = biblio.biblionumber 
64                     and cancellationdate is NULL and 
65                     (found <> 'F' or found is NULL)";
66   }
67   $query.=" order by priority";
68   my $sth=$dbh->prepare($query);
69   $sth->execute;
70   my $i=0;
71   my @results;
72   while (my $data=$sth->fetchrow_hashref){
73       if ($data->{'constrainttype'} eq 'o') {
74           my $conquery = "SELECT biblioitemnumber FROM reserveconstraints 
75                            WHERE biblionumber   = ? 
76                              AND borrowernumber = ?
77                              AND reservedate    = ?";
78           my $csth=$dbh->prepare($conquery);
79           my $bibn = $data->{'biblionumber'};
80           my $born = $data->{'borrowernumber'};
81           my $resd = $data->{'reservedate'};
82           $csth->execute($bibn, $born, $resd);
83           my ($bibitemno) = $csth->fetchrow_array;
84           $csth->finish;
85           my $bdata = C4::Search::bibitemdata($bibitemno);
86           foreach my $key (keys %$bdata) {
87               $data->{$key} = $bdata->{$key};
88           }
89       }
90       $results[$i]=$data;
91       $i++;
92   }
93 #  print $query;
94   $sth->finish;
95   $dbh->disconnect;
96   return($i,\@results);
97 }
98
99 sub CheckReserves {
100     my ($item, $barcode) = @_;
101 #    warn "In CheckReserves: itemnumber = $item";
102     my $dbh=C4Connect;
103     my $sth;
104     if ($item) {
105         my $qitem=$dbh->quote($item);
106 # get the biblionumber...
107         $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
108                              FROM items, biblioitems, itemtypes 
109                             WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
110                               AND biblioitems.itemtype = itemtypes.itemtype
111                               AND itemnumber=$qitem");
112     } else {
113         my $qbc=$dbh->quote($barcode);
114 # get the biblionumber...
115         $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
116                              FROM items, biblioitems, itemtypes 
117                             WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
118                               AND biblioitems.itemtype = itemtypes.itemtype
119                               AND barcode=$qbc");
120     }
121     $sth->execute;
122     my ($biblio, $bibitem, $notforloan) = $sth->fetchrow_array;
123     $sth->finish;
124     $dbh->disconnect;
125 # if item is not for loan it cannot be reserved either.....
126     return (0, 0) if ($notforloan);
127 # get the reserves...
128     my ($count, @reserves) = Findgroupreserve($bibitem, $biblio);
129     my $priority = 10000000; 
130     my $highest;
131     if ($count) {
132         foreach my $res (@reserves) {
133             if ($res->{'itemnumber'} == $item) {
134                 return ("Waiting", $res);
135             } else {
136                 if ($res->{'priority'} != 0 && $res->{'priority'} < $priority) {
137                     $priority = $res->{'priority'};
138                     $highest = $res;
139                 }
140             }
141         }
142     }
143     if ($highest) {
144         $highest->{'itemnumber'} = $item;
145         return ("Reserved", $highest);
146     } else {
147         return (0, 0);
148     }
149 }
150
151 sub CancelReserve {
152     my ($biblio, $item, $borr) = @_;
153     my $dbh=C4Connect;
154     #warn "In CancelReserve";
155     if (($item and $borr) and (not $biblio)) {
156 # removing a waiting reserve record....
157         $item = $dbh->quote($item);
158         $borr = $dbh->quote($borr);
159 # update the database...
160         my $query = "update reserves set cancellationdate = now(), 
161                                          found            = Null, 
162                                          priority         = 0 
163                                    where itemnumber       = $item 
164                                      and borrowernumber   = $borr";
165         my $sth = $dbh->prepare($query);
166         $sth->execute;
167         $sth->finish;
168     }
169     if (($biblio and $borr) and (not $item)) {
170 # removing a reserve record....
171         my $q_biblio = $dbh->quote($biblio);
172         $borr = $dbh->quote($borr);
173 # get the prioritiy on this record....
174         my $query = "SELECT priority FROM reserves 
175                                     WHERE biblionumber   = $q_biblio 
176                                       AND borrowernumber = $borr
177                                       AND cancellationdate is NULL 
178                                       AND (found <> 'F' or found is NULL)";
179         my $sth=$dbh->prepare($query);
180         $sth->execute;
181         my ($priority) = $sth->fetchrow_array;
182         $sth->finish;
183 # update the database, removing the record...
184         my $query = "update reserves set cancellationdate = now(), 
185                                          found            = Null, 
186                                          priority         = 0 
187                                    where biblionumber     = $q_biblio 
188                                      and borrowernumber   = $borr
189                                      and cancellationdate is NULL 
190                                      and (found <> 'F' or found is NULL)";
191         my $sth = $dbh->prepare($query);
192         $sth->execute;
193         $sth->finish;
194 # now fix the priority on the others....
195         fixpriority($priority, $biblio);
196     }
197     $dbh->disconnect;
198 }
199
200
201 sub FillReserve {
202     my ($res) = @_;
203     my $dbh=C4Connect;
204 # fillinf a reserve record....
205     my $biblio = $res->{'biblionumber'}; my $qbiblio = $dbh->quote($biblio);
206     my $borr = $res->{'borrowernumber'}; $borr = $dbh->quote($borr);
207     my $resdate = $res->{'reservedate'}; $resdate = $dbh->quote($resdate);
208 # get the prioritiy on this record....
209     my $query = "SELECT priority FROM reserves 
210                                 WHERE biblionumber   = $qbiblio 
211                                   AND borrowernumber = $borr
212                                   AND reservedate    = $resdate)";
213     my $sth=$dbh->prepare($query);
214     $sth->execute;
215     my ($priority) = $sth->fetchrow_array;
216     $sth->finish;
217 # update the database...
218     my $query = "UPDATE reserves SET found            = 'F', 
219                                      priority         = 0 
220                                WHERE biblionumber     = $qbiblio
221                                  AND reservedate      = $resdate
222                                  AND borrowernumber   = $borr";
223     my $sth = $dbh->prepare($query);
224     $sth->execute;
225     $sth->finish;
226 # now fix the priority on the others (if the priority wasnt already sorted!)....
227     unless ($priority == 0) {
228         fixpriority($priority, $biblio);
229     }
230     $dbh->disconnect;
231 }
232
233 sub fixpriority {
234     my ($priority, $biblio) =  @_;
235     my $dbh = C4Connect;
236     my ($count, $reserves) = FindReserves($biblio);
237     foreach my $rec (@$reserves) {
238         if ($rec->{'priority'} > $priority) {
239             my $newpr = $rec->{'priority'};      $newpr = $dbh->quote($newpr - 1);
240             my $nbib = $rec->{'biblionumber'};   $nbib = $dbh->quote($nbib);
241             my $nbor = $rec->{'borrowernumber'}; $nbor = $dbh->quote($nbor);
242             my $nresd = $rec->{'reservedate'};   $nresd = $dbh->quote($nresd);
243             my $query = "UPDATE reserves SET priority = $newpr 
244                                WHERE biblionumber     = $nbib 
245                                  AND borrowernumber   = $nbor
246                                  AND reservedate      = $nresd";
247             #warn $query;
248             my $sth = $dbh->prepare($query);
249             $sth->execute;
250             $sth->finish;
251         } 
252     }
253     $dbh->disconnect;
254 }
255
256
257
258 sub ReserveWaiting {
259     my ($item, $borr) = @_;
260     my $dbh = C4Connect;
261     $item = $dbh->quote($item);
262     $borr = $dbh->quote($borr);
263 # get priority and biblionumber....
264     my $query = "SELECT reserves.priority     as priority, 
265                         reserves.biblionumber as biblionumber,
266                         reserves.branchcode   as branchcode, 
267                         reserves.timestamp     as timestamp
268                       FROM reserves,items 
269                      WHERE reserves.biblionumber   = items.biblionumber 
270                        AND items.itemnumber        = $item 
271                        AND reserves.borrowernumber = $borr 
272                        AND reserves.cancellationdate is NULL
273                        AND (reserves.found <> 'F' or reserves.found is NULL)";
274     my $sth = $dbh->prepare($query);
275     $sth->execute;
276     my $data = $sth->fetchrow_hashref;
277     $sth->finish;
278     my $biblio = $data->{'biblionumber'};
279     my $timestamp = $data->{'timestamp'};
280     my $q_biblio = $dbh->quote($biblio);
281     my $q_timestamp = $dbh->quote($timestamp);
282     warn "Timestamp: ".$timestamp."\n";
283 # update reserves record....
284     $query = "UPDATE reserves SET priority = 0, found = 'W', itemnumber = $item 
285                             WHERE borrowernumber = $borr 
286                               AND biblionumber = $q_biblio 
287                               AND timestamp = $q_timestamp";
288     warn "Query: ".$query."\n";
289     $sth = $dbh->prepare($query);
290     $sth->execute;
291     $sth->finish;
292     $dbh->disconnect;
293 # now fix up the remaining priorities....
294     fixpriority($data->{'priority'}, $biblio);
295     my $branchcode = $data->{'branchcode'};
296     return $branchcode;
297 }
298
299 sub CheckWaiting {
300     my ($borr)=@_;
301     my $dbh = C4Connect;
302     $borr = $dbh->quote($borr);
303     my @itemswaiting;
304     my $query = "SELECT * FROM reserves
305                          WHERE borrowernumber = $borr
306                            AND reserves.found = 'W' 
307                            AND cancellationdate is NULL";
308     my $sth = $dbh->prepare($query);
309     $sth->execute();
310     my $cnt=0;
311     if (my $data=$sth->fetchrow_hashref) {
312         @itemswaiting[$cnt] =$data;
313         $cnt ++;
314     }
315     $sth->finish;
316     return ($cnt,\@itemswaiting);
317 }
318
319 sub Findgroupreserve {
320   my ($bibitem,$biblio)=@_;
321   my $dbh=C4Connect;
322   $bibitem=$dbh->quote($bibitem);
323   my $query = "SELECT reserves.biblionumber               AS biblionumber, 
324                       reserves.borrowernumber             AS borrowernumber, 
325                       reserves.reservedate                AS reservedate, 
326                       reserves.branchcode                 AS branchcode, 
327                       reserves.cancellationdate           AS cancellationdate, 
328                       reserves.found                      AS found, 
329                       reserves.reservenotes               AS reservenotes, 
330                       reserves.priority                   AS priority, 
331                       reserves.timestamp                  AS timestamp, 
332                       reserveconstraints.biblioitemnumber AS biblioitemnumber, 
333                       reserves.itemnumber                 AS itemnumber 
334                  FROM reserves LEFT JOIN reserveconstraints
335                    ON reserves.biblionumber = reserveconstraints.biblionumber
336                 WHERE reserves.biblionumber = $biblio
337                   AND ( ( reserveconstraints.biblioitemnumber = $bibitem 
338                       AND reserves.borrowernumber = reserveconstraints.borrowernumber
339                       AND reserves.reservedate    =reserveconstraints.reservedate )
340                    OR reserves.constrainttype='a' )
341                   AND reserves.cancellationdate is NULL
342                   AND (reserves.found <> 'F' or reserves.found is NULL)";
343   my $sth=$dbh->prepare($query);
344   $sth->execute;
345   my $i=0;
346   my @results;
347   while (my $data=$sth->fetchrow_hashref){
348     $results[$i]=$data;
349     $i++;
350   }
351   $sth->finish;
352   $dbh->disconnect;
353   return($i,@results);
354 }
355
356 sub CreateReserve {                                                           
357   my
358 ($env,$branch,$borrnum,$biblionumber,$constraint,$bibitems,$priority,$notes,$title)= @_;   
359   my $fee=CalcReserveFee($env,$borrnum,$biblionumber,$constraint,$bibitems);
360   my $dbh = &C4Connect;       
361   my $const = lc substr($constraint,0,1);       
362   my @datearr = localtime(time);                                
363   my $resdate =(1900+$datearr[5])."-".($datearr[4]+1)."-".$datearr[3];                   
364   #eval {                                                           
365   # updates take place here             
366   if ($fee > 0) {           
367 #    print $fee;
368     my $nextacctno = &getnextacctno($env,$borrnum,$dbh);   
369     my $updquery = "insert into accountlines       
370     (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
371                                                           values
372     ($borrnum,$nextacctno,now(),$fee,'Reserve Charge - $title','Res',$fee)";          
373     my $usth = $dbh->prepare($updquery);                      
374     $usth->execute;             
375     $usth->finish;                        
376   }                     
377   #if ($const eq 'a'){
378     my $query="insert into reserves
379    (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,priority,reservenotes)
380     values
381 ('$borrnum','$biblionumber','$resdate','$branch','$const','$priority','$notes')";   
382     my $sth = $dbh->prepare($query);                        
383     $sth->execute();                
384     $sth->finish;
385   #}
386   if (($const eq "o") || ($const eq "e")) {     
387     my $numitems = @$bibitems;             
388     my $i = 0;                                        
389     while ($i < $numitems) {   
390       my $biblioitem = @$bibitems[$i];   
391       my $query = "insert into
392       reserveconstraints                          
393       (borrowernumber,biblionumber,reservedate,biblioitemnumber)         
394       values
395       ('$borrnum','$biblionumber','$resdate','$biblioitem')";                 
396       my $sth = $dbh->prepare($query);                    
397       $sth->execute();
398       $sth->finish;
399       $i++;                         
400     }                                   
401   } 
402 #  print $query;
403   $dbh->disconnect();         
404   return();   
405 }             
406
407 sub CalcReserveFee {
408   my ($env,$borrnum,$biblionumber,$constraint,$bibitems) = @_;        
409   #check for issues;    
410   my $dbh = &C4Connect;           
411   my $const = lc substr($constraint,0,1); 
412   my $query = "SELECT * FROM borrowers,categories 
413                 WHERE (borrowernumber = ?)         
414                   AND (borrowers.categorycode = categories.categorycode)";   
415   my $sth = $dbh->prepare($query);                       
416   $sth->execute($borrnum);                                    
417   my $data = $sth->fetchrow_hashref;                  
418   $sth->finish();
419   my $fee = $data->{'reservefee'};       
420   my $cntitems = @->$bibitems;   
421   if ($fee > 0) {                         
422     # check for items on issue      
423     # first find biblioitem records       
424     my @biblioitems;    
425     my $query1 = "SELECT * FROM biblio,biblioitems                           
426                    WHERE (biblio.biblionumber = ?)     
427                      AND (biblio.biblionumber = biblioitems.biblionumber)";
428     my $sth1 = $dbh->prepare($query1);                   
429     $sth1->execute($biblionumber);                                     
430     while (my $data1=$sth1->fetchrow_hashref) { 
431       if ($const eq "a") {    
432         push @biblioitems,$data1;       
433       } else {                     
434         my $found = 0;        
435         my $x = 0;
436         while ($x < $cntitems) {                                             
437           if (@$bibitems->{'biblioitemnumber'} == $data->{'biblioitemnumber'}) {         
438             $found = 1;   
439           }               
440           $x++;                                       
441         }               
442         if ($const eq 'o') {
443           if ( $found == 1) {
444             push @biblioitems,$data1;
445           }                            
446         } else {
447           if ($found == 0) {
448             push @biblioitems,$data1;
449           } 
450         }     
451       }   
452     }             
453     $sth1->finish;                                  
454     my $cntitemsfound = @biblioitems; 
455     my $issues = 0;                 
456     my $x = 0;                   
457     my $allissued = 1; 
458     while ($x < $cntitemsfound) { 
459       my $bitdata = $biblioitems[$x];                                       
460       my $query2 = "SELECT * FROM items                   
461                      WHERE biblioitemnumber = ?";     
462       my $sth2 = $dbh->prepare($query2);                       
463       $sth2->execute($bitdata->{'biblioitemnumber'});   
464       while (my $itdata=$sth2->fetchrow_hashref) { 
465         my $query3 = "SELECT * FROM issues
466                        WHERE itemnumber = ? 
467                          AND returndate IS NULL";
468         
469         my $sth3 = $dbh->prepare($query3);                      
470         $sth3->execute($itdata->{'itemnumber'});                     
471         if (my $isdata=$sth3->fetchrow_hashref) {
472         } else {
473           $allissued = 0; 
474         }  
475       }                                                           
476       $x++;   
477     }         
478     if ($allissued == 0) { 
479       my $rquery = "SELECT * FROM reserves WHERE biblionumber = ?"; 
480       my $rsth = $dbh->prepare($rquery);   
481       $rsth->execute($biblionumber);   
482       if (my $rdata = $rsth->fetchrow_hashref) { 
483       } else {                                     
484         $fee = 0;                                                           
485       }   
486     }             
487   }                   
488 #  print "fee $fee";
489   $dbh->disconnect();   
490   return $fee;                                      
491 }                   
492
493 sub getnextacctno {                                                           
494   my ($env,$bornumber,$dbh)=@_;           
495   my $nextaccntno = 1;      
496   my $query = "select * from accountlines                             
497   where (borrowernumber = '$bornumber')                               
498   order by accountno desc";                       
499   my $sth = $dbh->prepare($query);                                  
500   $sth->execute;                    
501   if (my $accdata=$sth->fetchrow_hashref){    
502     $nextaccntno = $accdata->{'accountno'} + 1;           
503   }                       
504   $sth->finish;                                       
505   return($nextaccntno);                   
506 }              
507
508 sub updatereserves{
509   #subroutine to update a reserve 
510   my ($rank,$biblio,$borrower,$del,$branch)=@_;
511   my $dbh=C4Connect;
512   my $query="Update reserves ";
513   if ($del ==0){
514     $query.="set  priority='$rank',branchcode='$branch' where
515     biblionumber=$biblio and borrowernumber=$borrower";
516   } else {
517     $query="Select * from reserves where biblionumber=$biblio and
518     borrowernumber=$borrower";
519     my $sth=$dbh->prepare($query);
520     $sth->execute;
521     my $data=$sth->fetchrow_hashref;
522     $sth->finish;
523     $query="Select * from reserves where biblionumber=$biblio and 
524     priority > '$data->{'priority'}' and cancellationdate is NULL 
525     order by priority";
526     my $sth2=$dbh->prepare($query) || die $dbh->errstr;
527     $sth2->execute || die $sth2->errstr;
528     while (my $data=$sth2->fetchrow_hashref){
529       $data->{'priority'}--;
530       $query="Update reserves set priority=$data->{'priority'} where
531       biblionumber=$data->{'biblionumber'} and
532       borrowernumber=$data->{'borrowernumber'}";
533       my $sth3=$dbh->prepare($query);
534       $sth3->execute || die $sth3->errstr;
535       $sth3->finish;
536     }
537     $sth2->finish;
538     $query="update reserves set cancellationdate=now() where biblionumber=$biblio 
539     and borrowernumber=$borrower";    
540   }
541   my $sth=$dbh->prepare($query);
542   $sth->execute;
543   $sth->finish;  
544   $dbh->disconnect;
545 }
546
547 sub getreservetitle {
548  my ($biblio,$bor,$date,$timestamp)=@_;
549  my $dbh=C4Connect;
550  my $query="Select * from reserveconstraints,biblioitems where
551  reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber
552  and reserveconstraints.biblionumber=$biblio and reserveconstraints.borrowernumber
553  = $bor and reserveconstraints.reservedate='$date' and
554  reserveconstraints.timestamp=$timestamp";
555  my $sth=$dbh->prepare($query);
556  $sth->execute;
557  my $data=$sth->fetchrow_hashref;
558  $sth->finish;
559  $dbh->disconnect;
560 # print $query;
561  return($data);
562 }
563
564
565
566
567
568                         
569 END { }       # module clean-up code here (global destructor)