Work in progress still, committing for testing
[koha.git] / C4 / Reserves2.pm
1 # -*- tab-width: 8 -*-
2 # NOTE: This file uses standard 8-character tabs
3
4 package C4::Reserves2;
5
6 # $Id$
7
8 # Copyright 2000-2002 Katipo Communications
9 #
10 # This file is part of Koha.
11 #
12 # Koha is free software; you can redistribute it and/or modify it under the
13 # terms of the GNU General Public License as published by the Free Software
14 # Foundation; either version 2 of the License, or (at your option) any later
15 # version.
16 #
17 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
18 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License along with
22 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23 # Suite 330, Boston, MA  02111-1307 USA
24
25 use strict;
26 require Exporter;
27 use DBI;
28 use C4::Context;
29 use C4::Biblio;
30
31 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
32
33 # set the version for version checking
34 $VERSION = 0.01;
35
36 =head1 NAME
37
38 C4::Reserves2 - FIXME
39
40 =head1 SYNOPSIS
41
42   use C4::Reserves2;
43
44 =head1 DESCRIPTION
45
46 FIXME
47
48 =head1 FUNCTIONS
49
50 =over 2
51
52 =cut
53
54 @ISA = qw(Exporter);
55 # FIXME Take out CalcReserveFee after it can be removed from opac-reserves.pl
56 @EXPORT = qw(
57     &FindReserves
58     &CheckReserves
59     &CheckWaiting
60     &CancelReserve
61     &CalcReserveFee
62     &FillReserve
63     &ReserveWaiting
64     &CreateReserve
65     &updatereserves
66     &UpdateReserve
67     &getreservetitle
68     &Findgroupreserve
69 );
70
71 # make all your functions, whether exported or not;
72
73 =item FindReserves
74
75   ($count, $results) = &FindReserves($biblionumber, $borrowernumber);
76
77 Looks books up in the reserves. C<$biblionumber> is the biblionumber
78 of the book to look up. C<$borrowernumber> is the borrower number of a
79 patron whose books to look up.
80
81 Either C<$biblionumber> or C<$borrowernumber> may be the empty string,
82 but not both. If both are specified, C<&FindReserves> looks up the
83 given book for the given patron. If only C<$biblionumber> is
84 specified, C<&FindReserves> looks up that book for all patrons. If
85 only C<$borrowernumber> is specified, C<&FindReserves> looks up all of
86 that patron's reserves. If neither is specified, C<&FindReserves>
87 barfs.
88
89 For each book thus found, C<&FindReserves> checks the reserve
90 constraints and does something I don't understand.
91
92 C<&FindReserves> returns a two-element array:
93
94 C<$count> is the number of elements in C<$results>.
95
96 C<$results> is a reference-to-array; each element is a
97 reference-to-hash, whose keys are (I think) all of the fields of the
98 reserves, borrowers, and biblio tables of the Koha database.
99
100 =cut
101 #'
102 sub FindReserves {
103         my ($bib,$bor)=@_;
104         my $dbh = C4::Context->dbh;
105         # Find the desired items in the reserves
106         my $query="SELECT *,reserves.branchcode,biblio.title AS btitle, reserves.timestamp as rtimestamp FROM reserves,borrowers,biblio ";
107         # FIXME - These three bits of SQL seem to contain a fair amount of
108         # redundancy. Wouldn't it be better to have a @clauses array, add
109         # one or two clauses as necessary, then join(" AND ", @clauses) ?
110         # FIXME: not keen on quote() and interpolation either, but it looks safe
111         if ($bib ne ''){
112                 $bib = $dbh->quote($bib);
113                 if ($bor ne ''){
114                         # Both $bib and $bor specified
115                         # Find a particular book for a particular patron
116                         $bor = $dbh->quote($bor);
117                         $query .=  " where reserves.biblionumber   = $bib
118                                                 and borrowers.borrowernumber = $bor
119                                                 and reserves.borrowernumber = borrowers.borrowernumber
120                                                 and biblio.biblionumber     = $bib
121                                                 and cancellationdate is NULL
122                                                 and (found <> 'F' or found is NULL)";
123                 } else {
124                         # $bib specified, but not $bor
125                         # Find a particular book for all patrons
126                         $query .= " where reserves.borrowernumber = borrowers.borrowernumber
127                                         and biblio.biblionumber     = $bib
128                                         and reserves.biblionumber   = $bib
129                                         and cancellationdate is NULL
130                                         and (found <> 'F' or found is NULL)";
131                 }
132         } else {
133                 # FIXME - Check that $bor was given
134                 # No $bib given.
135                 # Find all books for the given patron.
136                 $query .= " where borrowers.borrowernumber = $bor
137                                         and reserves.borrowernumber  = borrowers.borrowernumber
138                                         and reserves.biblionumber    = biblio.biblionumber
139                                         and cancellationdate is NULL and
140                                         (found <> 'F' or found is NULL)";
141         }
142         $query.=" order by priority";
143         my $sth=$dbh->prepare($query);
144         $sth->execute;
145         my @results;
146         while (my $data=$sth->fetchrow_hashref){
147                 # FIXME - What is this if-statement doing? How do constraints work?
148                 if ($data->{'constrainttype'} eq 'o') {
149                         my $csth=$dbh->prepare("SELECT biblioitemnumber FROM reserveconstraints
150                                                         WHERE biblionumber   = ?
151                                                         AND borrowernumber = ?
152                                                         AND reservedate    = ?");
153                         $csth->execute($data->{'biblionumber'}, $data->{'borrowernumber'}, $data->{'reservedate'});
154                         my ($bibitemno) = $csth->fetchrow_array;
155                         $csth->finish;
156                         # Look up the book we just found.
157                         my $bdata = bibitemdata($bibitemno);
158                         # Add the results of this latest search to the current
159                         # results.
160                         # FIXME - An 'each' would probably be more efficient.
161                         foreach my $key (keys %$bdata) {
162                                 $data->{$key} = $bdata->{$key};
163                         }
164                 }
165                 push @results, $data;
166         }
167         $sth->finish;
168         return($#results+1,\@results);
169 }
170
171 =item CheckReserves
172
173   ($status, $reserve) = &CheckReserves($itemnumber, $barcode);
174
175 Find a book in the reserves.
176
177 C<$itemnumber> is the book's item number. C<$barcode> is its barcode.
178 Either one, but not both, may be false. If both are specified,
179 C<&CheckReserves> uses C<$itemnumber>.
180
181 $itemnubmer can be false, in which case uses the barcode. (Never uses
182 both. $itemnumber gets priority).
183
184 As I understand it, C<&CheckReserves> looks for the given item in the
185 reserves. If it is found, that's a match, and C<$status> is set to
186 C<Waiting>.
187
188 Otherwise, it finds the most important item in the reserves with the
189 same biblio number as this book (I'm not clear on this) and returns it
190 with C<$status> set to C<Reserved>.
191
192 C<&CheckReserves> returns a two-element list:
193
194 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
195
196 C<$reserve> is the reserve item that matched. It is a
197 reference-to-hash whose keys are mostly the fields of the reserves
198 table in the Koha database.
199
200 =cut
201 #'
202 sub CheckReserves {
203     my ($item, $barcode) = @_;
204 #    warn "In CheckReserves: itemnumber = $item";
205     my $dbh = C4::Context->dbh;
206     my $sth;
207     if ($item) {
208         my $qitem=$dbh->quote($item);
209         # Look up the item by itemnumber
210         $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
211                              FROM items, biblioitems, itemtypes
212                             WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
213                               AND biblioitems.itemtype = itemtypes.itemtype
214                               AND itemnumber=$qitem");
215     } else {
216         my $qbc=$dbh->quote($barcode);
217         # Look up the item by barcode
218         $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
219                              FROM items, biblioitems, itemtypes
220                             WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
221                               AND biblioitems.itemtype = itemtypes.itemtype
222                               AND barcode=$qbc");
223         # FIXME - This function uses $item later on. Ought to set it here.
224     }
225     $sth->execute;
226     my ($biblio, $bibitem, $notforloan) = $sth->fetchrow_array;
227     $sth->finish;
228 # if item is not for loan it cannot be reserved either.....
229     return (0, 0) if ($notforloan);
230 # get the reserves...
231     # Find this item in the reserves
232     my ($count, @reserves) = Findgroupreserve($bibitem, $biblio);
233     # $priority and $highest are used to find the most important item
234     # in the list returned by &Findgroupreserve. (The lower $priority,
235     # the more important the item.)
236     # $highest is the most important item we've seen so far.
237     my $priority = 10000000;
238     my $highest;
239     if ($count) {
240         foreach my $res (@reserves) {
241             # FIXME - $item might be undefined or empty: the caller
242             # might be searching by barcode.
243             if ($res->{'itemnumber'} == $item) {
244                 # Found it
245                 return ("Waiting", $res);
246             } else {
247                 # See if this item is more important than what we've got
248                 # so far.
249                 if ($res->{'priority'} != 0 && $res->{'priority'} < $priority) {
250                     $priority = $res->{'priority'};
251                     $highest = $res;
252                 }
253             }
254         }
255     }
256
257     # If we get this far, then no exact match was found. Print the
258     # most important item on the list. I think this tells us who's
259     # next in line to get this book.
260     if ($highest) {     # FIXME - $highest might be undefined
261         $highest->{'itemnumber'} = $item;
262         return ("Reserved", $highest);
263     } else {
264         return (0, 0);
265     }
266 }
267
268 =item CancelReserve
269
270   &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
271
272 Cancels a reserve.
273
274 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
275 cancel, but not both: if both are given, C<&CancelReserve> does
276 nothing.
277
278 C<$borrowernumber> is the borrower number of the patron on whose
279 behalf the book was reserved.
280
281 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
282 priorities of the other people who are waiting on the book.
283
284 =cut
285 #'
286 sub CancelReserve {
287     my ($biblio, $item, $borr) = @_;
288     my $dbh = C4::Context->dbh;
289     #warn "In CancelReserve";
290     if (($item and $borr) and (not $biblio)) {
291                 # removing a waiting reserve record....
292                 # update the database...
293                 my $sth = $dbh->prepare("update reserves set cancellationdate = now(),
294                                                                                         found            = Null,
295                                                                                         priority         = 0
296                                                                         where itemnumber       = ?
297                                                                                 and borrowernumber   = ?");
298                 $sth->execute($item,$borr);
299                 $sth->finish;
300     }
301     if (($biblio and $borr) and (not $item)) {
302                 # removing a reserve record....
303                 # get the prioritiy on this record....
304                 my $priority;
305                 my $sth=$dbh->prepare("SELECT priority FROM reserves
306                                                                                 WHERE biblionumber   = ?
307                                                                                 AND borrowernumber = ?
308                                                                                 AND cancellationdate is NULL
309                                                                                 AND (found <> 'F' or found is NULL)");
310                 $sth->execute($biblio,$borr);
311                 ($priority) = $sth->fetchrow_array;
312                 $sth->finish;
313
314                 # update the database, removing the record...
315                 $sth = $dbh->prepare("update reserves set cancellationdate = now(),
316                                                                                         found            = Null,
317                                                                                         priority         = 0
318                                                                         where biblionumber     = ?
319                                                                                 and borrowernumber   = ?
320                                                                                 and cancellationdate is NULL
321                                                                                 and (found <> 'F' or found is NULL)");
322                 $sth->execute($biblio,$borr);
323                 $sth->finish;
324                 # now fix the priority on the others....
325                 fixpriority($priority, $biblio);
326     }
327 }
328
329 =item FillReserve
330
331   &FillReserve($reserve);
332
333 Fill a reserve. If I understand this correctly, this means that the
334 reserved book has been found and given to the patron who reserved it.
335
336 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
337 whose keys are fields from the reserves table in the Koha database.
338
339 =cut
340 #'
341 sub FillReserve {
342     my ($res) = @_;
343     my $dbh = C4::Context->dbh;
344
345     # fill in a reserve record....
346     # FIXME - Remove some of the redundancy here
347     my $biblio = $res->{'biblionumber'}; my $qbiblio =$biblio;
348     my $borr = $res->{'borrowernumber'}; 
349     my $resdate = $res->{'reservedate'}; 
350
351     # get the priority on this record....
352     my $priority;
353     {
354     my $query = "SELECT priority FROM reserves
355                                 WHERE biblionumber   = ?
356                                   AND borrowernumber = ?
357                                   AND reservedate    = ?";
358     my $sth=$dbh->prepare($query);
359     $sth->execute($qbiblio,$borr,$resdate);
360     ($priority) = $sth->fetchrow_array;
361     $sth->finish;
362     }
363
364     # update the database...
365     {
366     my $query = "UPDATE reserves SET found            = 'F',
367                                      priority         = 0
368                                WHERE biblionumber     = ?
369                                  AND reservedate      = ?
370                                  AND borrowernumber   = ?";
371     my $sth = $dbh->prepare($query);
372     $sth->execute($qbiblio,$resdate,$borr);
373     $sth->finish;
374     }
375
376     # now fix the priority on the others (if the priority wasn't
377     # already sorted!)....
378     unless ($priority == 0) {
379         fixpriority($priority, $biblio);
380     }
381 }
382
383 # Only used internally
384 # Decrements (makes more important) the reserves for all of the
385 # entries waiting on the given book, if their priority is > $priority.
386 sub fixpriority {
387     my ($priority, $biblio) =  @_;
388     my $dbh = C4::Context->dbh;
389     my ($count, $reserves) = FindReserves($biblio);
390     foreach my $rec (@$reserves) {
391         if ($rec->{'priority'} > $priority) {
392             my $sth = $dbh->prepare("UPDATE reserves SET priority = ?
393                                WHERE biblionumber     = ?
394                                  AND borrowernumber   = ?
395                                  AND reservedate      = ?");
396             $sth->execute($rec->{'priority'},$rec->{'biblionumber'},$rec->{'borrowernumber'},$rec->{'reservedate'});
397             $sth->finish;
398         }
399     }
400 }
401
402 # XXX - POD
403 sub ReserveWaiting {
404     my ($item, $borr) = @_;
405     my $dbh = C4::Context->dbh;
406 # get priority and biblionumber....
407     my $sth = $dbh->prepare("SELECT reserves.priority     as priority,
408                         reserves.biblionumber as biblionumber,
409                         reserves.branchcode   as branchcode,
410                         reserves.timestamp     as timestamp
411                       FROM reserves,items
412                      WHERE reserves.biblionumber   = items.biblionumber
413                        AND items.itemnumber        = ?
414                        AND reserves.borrowernumber = ?
415                        AND reserves.cancellationdate is NULL
416                        AND (reserves.found <> 'F' or reserves.found is NULL)");
417     $sth->execute($item,$borr);
418     my $data = $sth->fetchrow_hashref;
419     $sth->finish;
420     my $biblio = $data->{'biblionumber'};
421     my $timestamp = $data->{'timestamp'};
422 # update reserves record....
423     $sth = $dbh->prepare("UPDATE reserves SET priority = 0, found = 'W', itemnumber = ?
424                             WHERE borrowernumber = ?
425                               AND biblionumber = ?
426                               AND timestamp = ?");
427     $sth->execute($item,$borr,$biblio,$timestamp);
428     $sth->finish;
429 # now fix up the remaining priorities....
430     fixpriority($data->{'priority'}, $biblio);
431     my $branchcode = $data->{'branchcode'};
432     return $branchcode;
433 }
434
435 # XXX - POD
436 sub CheckWaiting {
437     my ($borr)=@_;
438     my $dbh = C4::Context->dbh;
439     my @itemswaiting;
440     my $sth = $dbh->prepare("SELECT * FROM reserves
441                          WHERE borrowernumber = ?
442                            AND reserves.found = 'W'
443                            AND cancellationdate is NULL");
444     $sth->execute($borr);
445     while (my $data=$sth->fetchrow_hashref) {
446           push(@itemswaiting,$data);
447     }
448     $sth->finish;
449     return (scalar(@itemswaiting),\@itemswaiting);
450 }
451
452 =item Findgroupreserve
453
454   ($count, @results) = &Findgroupreserve($biblioitemnumber, $biblionumber);
455
456 I don't know what this does, because I don't understand how reserve
457 constraints work. I think the idea is that you reserve a particular
458 biblio, and the constraint allows you to restrict it to a given
459 biblioitem (e.g., if you want to borrow the audio book edition of "The
460 Prophet", rather than the first available publication).
461
462 C<&Findgroupreserve> returns a two-element array:
463
464 C<$count> is the number of elements in C<@results>.
465
466 C<@results> is an array of references-to-hash whose keys are mostly
467 fields from the reserves table of the Koha database, plus
468 C<biblioitemnumber>.
469
470 =cut
471 #'
472 sub Findgroupreserve {
473   my ($bibitem,$biblio)=@_;
474   my $dbh = C4::Context->dbh;
475   my $sth=$dbh->prepare("SELECT reserves.biblionumber               AS biblionumber,
476                       reserves.borrowernumber             AS borrowernumber,
477                       reserves.reservedate                AS reservedate,
478                       reserves.branchcode                 AS branchcode,
479                       reserves.cancellationdate           AS cancellationdate,
480                       reserves.found                      AS found,
481                       reserves.reservenotes               AS reservenotes,
482                       reserves.priority                   AS priority,
483                       reserves.timestamp                  AS timestamp,
484                       reserveconstraints.biblioitemnumber AS biblioitemnumber,
485                       reserves.itemnumber                 AS itemnumber
486                  FROM reserves LEFT JOIN reserveconstraints
487                    ON reserves.biblionumber = reserveconstraints.biblionumber
488                 WHERE reserves.biblionumber = ?
489                   AND ( ( reserveconstraints.biblioitemnumber = ?
490                       AND reserves.borrowernumber = reserveconstraints.borrowernumber
491                       AND reserves.reservedate    =reserveconstraints.reservedate )
492                    OR reserves.constrainttype='a' )
493                   AND reserves.cancellationdate is NULL
494                   AND (reserves.found <> 'F' or reserves.found is NULL)");
495   $sth->execute($biblio, $bibitem);
496   my @results;
497   while (my $data=$sth->fetchrow_hashref){
498     push(@results,$data);
499   }
500   $sth->finish;
501   return(scalar(@results),@results);
502 }
503
504 # FIXME - A somewhat different version of this function appears in
505 # C4::Reserves. Pick one and stick with it.
506 # XXX - POD
507 sub CreateReserve {
508   my
509 ($env,$branch,$borrnum,$biblionumber,$constraint,$bibitems,$priority,$notes,$title)= @_;
510   my $fee=CalcReserveFee($env,$borrnum,$biblionumber,$constraint,$bibitems);
511   my $dbh = C4::Context->dbh;
512   my $const = lc substr($constraint,0,1);
513   my @datearr = localtime(time);
514   my $resdate =(1900+$datearr[5])."-".($datearr[4]+1)."-".$datearr[3];
515   #eval {
516   # updates take place here
517   if ($fee > 0) {
518 #    print $fee;
519     my $nextacctno = &getnextacctno($env,$borrnum,$dbh);
520     my $usth = $dbh->prepare("insert into accountlines
521     (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
522                                                           values
523     (?,?,now(),?,?,'Res',?)");
524     $usth->execute($borrnum,$nextacctno,$fee,"Reserve Charge - $title",$fee);
525     $usth->finish;
526   }
527   #if ($const eq 'a'){
528     my $sth = $dbh->prepare("insert into reserves
529    (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,priority,reservenotes)
530     values (?,?,?,?,?,?,?)");
531     $sth->execute($borrnum,$biblionumber,$resdate,$branch,$const,$priority,$notes);
532     $sth->finish;
533   #}
534   if (($const eq "o") || ($const eq "e")) {
535     my $numitems = @$bibitems;
536     my $i = 0;
537     while ($i < $numitems) {
538       my $biblioitem = @$bibitems[$i];
539       my $sth = $dbh->prepare("insert into
540       reserveconstraints
541       (borrowernumber,biblionumber,reservedate,biblioitemnumber)
542       values (?,?,?,?)");
543       $sth->execute($borrnum,$biblionumber,$resdate,$biblioitem);
544       $sth->finish;
545       $i++;
546     }
547   }
548 #  print $query;
549   return();
550 }
551
552 # FIXME - A functionally identical version of this function appears in
553 # C4::Reserves. Pick one and stick with it.
554 # XXX - Internal use only
555 # FIXME - opac-reserves.pl need to use it, temporarily put into @EXPORT
556 sub CalcReserveFee {
557   my ($env,$borrnum,$biblionumber,$constraint,$bibitems) = @_;
558   #check for issues;
559   my $dbh = C4::Context->dbh;
560   my $const = lc substr($constraint,0,1);
561   my $sth = $dbh->prepare("SELECT * FROM borrowers,categories
562                 WHERE (borrowernumber = ?)
563                   AND (borrowers.categorycode = categories.categorycode)");
564   $sth->execute($borrnum);
565   my $data = $sth->fetchrow_hashref;
566   $sth->finish();
567   my $fee = $data->{'reservefee'};
568   my $cntitems = @->$bibitems;
569   if ($fee > 0) {
570     # check for items on issue
571     # first find biblioitem records
572     my @biblioitems;
573     my $sth1 = $dbh->prepare("SELECT * FROM biblio,biblioitems
574                    WHERE (biblio.biblionumber = ?)
575                      AND (biblio.biblionumber = biblioitems.biblionumber)");
576     $sth1->execute($biblionumber);
577     while (my $data1=$sth1->fetchrow_hashref) {
578       if ($const eq "a") {
579         push @biblioitems,$data1;
580       } else {
581         my $found = 0;
582         my $x = 0;
583         while ($x < $cntitems) {
584           if (@$bibitems->{'biblioitemnumber'} == $data->{'biblioitemnumber'}) {
585             $found = 1;
586           }
587           $x++;
588         }
589         if ($const eq 'o') {
590           if ( $found == 1) {
591             push @biblioitems,$data1;
592           }
593         } else {
594           if ($found == 0) {
595             push @biblioitems,$data1;
596           }
597         }
598       }
599     }
600     $sth1->finish;
601     my $cntitemsfound = @biblioitems;
602     my $issues = 0;
603     my $x = 0;
604     my $allissued = 1;
605     while ($x < $cntitemsfound) {
606       my $bitdata = $biblioitems[$x];
607       my $sth2 = $dbh->prepare("SELECT * FROM items
608                      WHERE biblioitemnumber = ?");
609       $sth2->execute($bitdata->{'biblioitemnumber'});
610       while (my $itdata=$sth2->fetchrow_hashref) {
611         my $sth3 = $dbh->prepare("SELECT * FROM issues
612                        WHERE itemnumber = ?
613                          AND returndate IS NULL");
614         $sth3->execute($itdata->{'itemnumber'});
615         if (my $isdata=$sth3->fetchrow_hashref) {
616         } else {
617           $allissued = 0;
618         }
619       }
620       $x++;
621     }
622     if ($allissued == 0) {
623       my $rsth = $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
624       $rsth->execute($biblionumber);
625       if (my $rdata = $rsth->fetchrow_hashref) {
626       } else {
627         $fee = 0;
628       }
629     }
630   }
631 #  print "fee $fee";
632   return $fee;
633 }
634
635 # XXX - Internal use
636 sub getnextacctno {
637   my ($env,$bornumber,$dbh)=@_;
638   my $nextaccntno = 1;
639   my $sth = $dbh->prepare("select * from accountlines
640   where (borrowernumber = ?)
641   order by accountno desc");
642   $sth->execute($bornumber);
643   if (my $accdata=$sth->fetchrow_hashref){
644     $nextaccntno = $accdata->{'accountno'} + 1;
645   }
646   $sth->finish;
647   return($nextaccntno);
648 }
649
650 # XXX - POD
651 sub updatereserves{
652   #subroutine to update a reserve
653   my ($rank,$biblio,$borrower,$del,$branch)=@_;
654   my $dbh = C4::Context->dbh;
655   if ($del == 0){
656     my $sth = $dbh->prepare("Update reserves set priority=?,branchcode=? where
657     biblionumber=? and borrowernumber=?");
658     $sth->execute($rank,$branch,$biblio,$borrower);
659     $sth->finish();
660   } else {
661     my $sth=$dbh->prepare("Select * from reserves where biblionumber=? and
662     borrowernumber=?");
663     $sth->execute($biblio,$borrower);
664     my $data=$sth->fetchrow_hashref;
665     $sth->finish();
666     $sth=$dbh->prepare("Select * from reserves where biblionumber=? and
667     priority > ? and cancellationdate is NULL
668     order by priority") || die $dbh->errstr;
669     $sth->execute($biblio,$data->{'priority'}) || die $sth->errstr;
670     while (my $data=$sth->fetchrow_hashref){
671       $data->{'priority'}--;
672       my $sth3=$dbh->prepare("Update reserves set priority=?
673       where biblionumber=? and borrowernumber=?");
674       $sth3->execute($data->{'priority'},$data->{'biblionumber'},$data->{'borrowernumber'}) || die $sth3->errstr;
675       $sth3->finish();
676     }
677     $sth->finish();
678     $sth=$dbh->prepare("update reserves set cancellationdate=now() where biblionumber=?
679     and borrowernumber=?");
680     $sth->execute($biblio,$borrower);
681     $sth->finish;
682   }
683 }
684
685 # XXX - POD
686 sub UpdateReserve {
687     #subroutine to update a reserve
688     my ($rank,$biblio,$borrower,$branch)=@_;
689     return if $rank eq "W";
690     return if $rank eq "n";
691     my $dbh = C4::Context->dbh;
692     if ($rank eq "del") {
693         my $sth=$dbh->prepare("UPDATE reserves SET cancellationdate=now()
694                                    WHERE biblionumber   = ?
695                                      AND borrowernumber = ?
696                                      AND cancellationdate is NULL
697                                      AND (found <> 'F' or found is NULL)");
698         $sth->execute($biblio, $borrower);
699         $sth->finish;
700     } else {
701         my $sth=$dbh->prepare("UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = NULL, found = NULL
702                                    WHERE biblionumber   = ?
703                                      AND borrowernumber = ?
704                                      AND cancellationdate is NULL
705                                      AND (found <> 'F' or found is NULL)");
706         $sth->execute($rank, $branch, $biblio, $borrower);
707         $sth->finish;
708     }
709 }
710
711 # XXX - POD
712 sub getreservetitle {
713  my ($biblio,$bor,$date,$timestamp)=@_;
714  my $dbh = C4::Context->dbh;
715  my $sth=$dbh->prepare("Select * from reserveconstraints,biblioitems where
716  reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber
717  and reserveconstraints.biblionumber=? and reserveconstraints.borrowernumber
718  = ? and reserveconstraints.reservedate=? and
719  reserveconstraints.timestamp=?");
720  $sth->execute($biblio,$bor,$date,$timestamp);
721  my $data=$sth->fetchrow_hashref;
722  $sth->finish;
723  return($data);
724 }