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