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