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