rewrote CheckReserves so that it can be called with a barcode as well as on itemnumber.
[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                       FROM reserves,items 
268                      WHERE reserves.biblionumber   = items.biblionumber 
269                        AND items.itemnumber        = $item 
270                        AND reserves.borrowernumber = $borr 
271                        AND reserves.cancellationdate is NULL
272                        AND (reserves.found <> 'F' or reserves.found is NULL)";
273     my $sth = $dbh->prepare($query);
274     $sth->execute;
275     my $data = $sth->fetchrow_hashref;
276     $sth->finish;
277     my $biblio = $data->{'biblionumber'};
278     my $q_biblio = $dbh->quote($biblio);
279 # update reserves record....
280     $query = "UPDATE reserves SET priority = 0, found = 'W', itemnumber = $item 
281                             WHERE borrowernumber = $borr AND biblionumber = $q_biblio";
282     $sth = $dbh->prepare($query);
283     $sth->execute;
284     $sth->finish;
285     $dbh->disconnect;
286 # now fix up the remaining priorities....
287     fixpriority($data->{'priority'}, $biblio);
288     my $branchcode = $data->{'branchcode'};
289     return $branchcode;
290 }
291
292 sub CheckWaiting {
293     my ($borr)=@_;
294     my $dbh = C4Connect;
295     $borr = $dbh->quote($borr);
296     my @itemswaiting;
297     my $query = "SELECT * FROM reserves
298                          WHERE borrowernumber = $borr
299                            AND reserves.found = 'W' 
300                            AND cancellationdate is NULL";
301     my $sth = $dbh->prepare($query);
302     $sth->execute();
303     my $cnt=0;
304     if (my $data=$sth->fetchrow_hashref) {
305         @itemswaiting[$cnt] =$data;
306         $cnt ++;
307     }
308     $sth->finish;
309     return ($cnt,\@itemswaiting);
310 }
311
312 sub Findgroupreserve {
313   my ($bibitem,$biblio)=@_;
314   my $dbh=C4Connect;
315   $bibitem=$dbh->quote($bibitem);
316   my $query = "SELECT reserves.biblionumber               AS biblionumber, 
317                       reserves.borrowernumber             AS borrowernumber, 
318                       reserves.reservedate                AS reservedate, 
319                       reserves.branchcode                 AS branchcode, 
320                       reserves.cancellationdate           AS cancellationdate, 
321                       reserves.found                      AS found, 
322                       reserves.reservenotes               AS reservenotes, 
323                       reserves.priority                   AS priority, 
324                       reserves.timestamp                  AS timestamp, 
325                       reserveconstraints.biblioitemnumber AS biblioitemnumber, 
326                       reserves.itemnumber                 AS itemnumber 
327                  FROM reserves LEFT JOIN reserveconstraints
328                    ON reserves.biblionumber = reserveconstraints.biblionumber
329                 WHERE reserves.biblionumber = $biblio
330                   AND ( ( reserveconstraints.biblioitemnumber = $bibitem 
331                       AND reserves.borrowernumber = reserveconstraints.borrowernumber
332                       AND reserves.reservedate    =reserveconstraints.reservedate )
333                    OR reserves.constrainttype='a' )
334                   AND reserves.cancellationdate is NULL
335                   AND (reserves.found <> 'F' or reserves.found is NULL)";
336   my $sth=$dbh->prepare($query);
337   $sth->execute;
338   my $i=0;
339   my @results;
340   while (my $data=$sth->fetchrow_hashref){
341     $results[$i]=$data;
342     $i++;
343   }
344   $sth->finish;
345   $dbh->disconnect;
346   return($i,@results);
347 }
348
349 sub CreateReserve {                                                           
350   my
351 ($env,$branch,$borrnum,$biblionumber,$constraint,$bibitems,$priority,$notes,$title)= @_;   
352   my $fee=CalcReserveFee($env,$borrnum,$biblionumber,$constraint,$bibitems);
353   my $dbh = &C4Connect;       
354   my $const = lc substr($constraint,0,1);       
355   my @datearr = localtime(time);                                
356   my $resdate =(1900+$datearr[5])."-".($datearr[4]+1)."-".$datearr[3];                   
357   #eval {                                                           
358   # updates take place here             
359   if ($fee > 0) {           
360 #    print $fee;
361     my $nextacctno = &getnextacctno($env,$borrnum,$dbh);   
362     my $updquery = "insert into accountlines       
363     (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
364                                                           values
365     ($borrnum,$nextacctno,now(),$fee,'Reserve Charge - $title','Res',$fee)";          
366     my $usth = $dbh->prepare($updquery);                      
367     $usth->execute;             
368     $usth->finish;                        
369   }                     
370   #if ($const eq 'a'){
371     my $query="insert into reserves
372    (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,priority,reservenotes)
373     values
374 ('$borrnum','$biblionumber','$resdate','$branch','$const','$priority','$notes')";   
375     my $sth = $dbh->prepare($query);                        
376     $sth->execute();                
377     $sth->finish;
378   #}
379   if (($const eq "o") || ($const eq "e")) {     
380     my $numitems = @$bibitems;             
381     my $i = 0;                                        
382     while ($i < $numitems) {   
383       my $biblioitem = @$bibitems[$i];   
384       my $query = "insert into
385       reserveconstraints                          
386       (borrowernumber,biblionumber,reservedate,biblioitemnumber)         
387       values
388       ('$borrnum','$biblionumber','$resdate','$biblioitem')";                 
389       my $sth = $dbh->prepare($query);                    
390       $sth->execute();
391       $sth->finish;
392       $i++;                         
393     }                                   
394   } 
395 #  print $query;
396   $dbh->disconnect();         
397   return();   
398 }             
399
400 sub CalcReserveFee {
401   my ($env,$borrnum,$biblionumber,$constraint,$bibitems) = @_;        
402   #check for issues;    
403   my $dbh = &C4Connect;           
404   my $const = lc substr($constraint,0,1); 
405   my $query = "SELECT * FROM borrowers,categories 
406                 WHERE (borrowernumber = ?)         
407                   AND (borrowers.categorycode = categories.categorycode)";   
408   my $sth = $dbh->prepare($query);                       
409   $sth->execute($borrnum);                                    
410   my $data = $sth->fetchrow_hashref;                  
411   $sth->finish();
412   my $fee = $data->{'reservefee'};       
413   my $cntitems = @->$bibitems;   
414   if ($fee > 0) {                         
415     # check for items on issue      
416     # first find biblioitem records       
417     my @biblioitems;    
418     my $query1 = "SELECT * FROM biblio,biblioitems                           
419                    WHERE (biblio.biblionumber = ?)     
420                      AND (biblio.biblionumber = biblioitems.biblionumber)";
421     my $sth1 = $dbh->prepare($query1);                   
422     $sth1->execute($biblionumber);                                     
423     while (my $data1=$sth1->fetchrow_hashref) { 
424       if ($const eq "a") {    
425         push @biblioitems,$data1;       
426       } else {                     
427         my $found = 0;        
428         my $x = 0;
429         while ($x < $cntitems) {                                             
430           if (@$bibitems->{'biblioitemnumber'} == $data->{'biblioitemnumber'}) {         
431             $found = 1;   
432           }               
433           $x++;                                       
434         }               
435         if ($const eq 'o') {
436           if ( $found == 1) {
437             push @biblioitems,$data1;
438           }                            
439         } else {
440           if ($found == 0) {
441             push @biblioitems,$data1;
442           } 
443         }     
444       }   
445     }             
446     $sth1->finish;                                  
447     my $cntitemsfound = @biblioitems; 
448     my $issues = 0;                 
449     my $x = 0;                   
450     my $allissued = 1; 
451     while ($x < $cntitemsfound) { 
452       my $bitdata = $biblioitems[$x];                                       
453       my $query2 = "SELECT * FROM items                   
454                      WHERE biblioitemnumber = ?";     
455       my $sth2 = $dbh->prepare($query2);                       
456       $sth2->execute($bitdata->{'biblioitemnumber'});   
457       while (my $itdata=$sth2->fetchrow_hashref) { 
458         my $query3 = "SELECT * FROM issues
459                        WHERE itemnumber = ? 
460                          AND returndate IS NULL";
461         
462         my $sth3 = $dbh->prepare($query3);                      
463         $sth3->execute($itdata->{'itemnumber'});                     
464         if (my $isdata=$sth3->fetchrow_hashref) {
465         } else {
466           $allissued = 0; 
467         }  
468       }                                                           
469       $x++;   
470     }         
471     if ($allissued == 0) { 
472       my $rquery = "SELECT * FROM reserves WHERE biblionumber = ?"; 
473       my $rsth = $dbh->prepare($rquery);   
474       $rsth->execute($biblionumber);   
475       if (my $rdata = $rsth->fetchrow_hashref) { 
476       } else {                                     
477         $fee = 0;                                                           
478       }   
479     }             
480   }                   
481 #  print "fee $fee";
482   $dbh->disconnect();   
483   return $fee;                                      
484 }                   
485
486 sub getnextacctno {                                                           
487   my ($env,$bornumber,$dbh)=@_;           
488   my $nextaccntno = 1;      
489   my $query = "select * from accountlines                             
490   where (borrowernumber = '$bornumber')                               
491   order by accountno desc";                       
492   my $sth = $dbh->prepare($query);                                  
493   $sth->execute;                    
494   if (my $accdata=$sth->fetchrow_hashref){    
495     $nextaccntno = $accdata->{'accountno'} + 1;           
496   }                       
497   $sth->finish;                                       
498   return($nextaccntno);                   
499 }              
500
501 sub updatereserves{
502   #subroutine to update a reserve 
503   my ($rank,$biblio,$borrower,$del,$branch)=@_;
504   my $dbh=C4Connect;
505   my $query="Update reserves ";
506   if ($del ==0){
507     $query.="set  priority='$rank',branchcode='$branch' where
508     biblionumber=$biblio and borrowernumber=$borrower";
509   } else {
510     $query="Select * from reserves where biblionumber=$biblio and
511     borrowernumber=$borrower";
512     my $sth=$dbh->prepare($query);
513     $sth->execute;
514     my $data=$sth->fetchrow_hashref;
515     $sth->finish;
516     $query="Select * from reserves where biblionumber=$biblio and 
517     priority > '$data->{'priority'}' and cancellationdate is NULL 
518     order by priority";
519     my $sth2=$dbh->prepare($query) || die $dbh->errstr;
520     $sth2->execute || die $sth2->errstr;
521     while (my $data=$sth2->fetchrow_hashref){
522       $data->{'priority'}--;
523       $query="Update reserves set priority=$data->{'priority'} where
524       biblionumber=$data->{'biblionumber'} and
525       borrowernumber=$data->{'borrowernumber'}";
526       my $sth3=$dbh->prepare($query);
527       $sth3->execute || die $sth3->errstr;
528       $sth3->finish;
529     }
530     $sth2->finish;
531     $query="update reserves set cancellationdate=now() where biblionumber=$biblio 
532     and borrowernumber=$borrower";    
533   }
534   my $sth=$dbh->prepare($query);
535   $sth->execute;
536   $sth->finish;  
537   $dbh->disconnect;
538 }
539
540 sub getreservetitle {
541  my ($biblio,$bor,$date,$timestamp)=@_;
542  my $dbh=C4Connect;
543  my $query="Select * from reserveconstraints,biblioitems where
544  reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber
545  and reserveconstraints.biblionumber=$biblio and reserveconstraints.borrowernumber
546  = $bor and reserveconstraints.reservedate='$date' and
547  reserveconstraints.timestamp=$timestamp";
548  my $sth=$dbh->prepare($query);
549  $sth->execute;
550  my $data=$sth->fetchrow_hashref;
551  $sth->finish;
552  $dbh->disconnect;
553 # print $query;
554  return($data);
555 }
556
557
558
559
560
561                         
562 END { }       # module clean-up code here (global destructor)