2 # NOTE: This file uses standard 8-character tabs
6 # Copyright 2000-2002 Katipo Communications
8 # This file is part of Koha.
10 # Koha is free software; you can redistribute it and/or modify it under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License along with
20 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
21 # Suite 330, Boston, MA 02111-1307 USA
32 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
33 my $library_name = C4::Context->preference("LibraryName");
35 # set the version for version checking
36 $VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v) . "." . join( "_", map { sprintf "%03d", $_ } @v ); };
40 C4::Reserves - Koha functions for dealing with reservation.
48 this modules provides somes functions to deal with reservations.
61 &GetReservesFromItemnumber
62 &GetReservesFromBiblionumber
63 &GetReservesFromBorrowernumber
77 &ModReserveMinusPriority
86 AddReserve($branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$notes,$title,$checkitem,$found)
92 $branch, $borrowernumber, $biblionumber,
93 $constraint, $bibitems, $priority, $notes,
94 $title, $checkitem, $found
97 GetReserveFee($borrowernumber, $biblionumber, $constraint,
99 my $dbh = C4::Context->dbh;
100 my $const = lc substr( $constraint, 0, 1 );
101 my @datearr = localtime(time);
103 ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
106 # If the reserv had the waiting status, we had the value of the resdate
107 if ( $found eq 'W' ) {
108 $waitingdate = $resdate;
112 # updates take place here
114 my $nextacctno = &getnextacctno( $borrowernumber );
116 INSERT INTO accountlines
117 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
119 (?,?,now(),?,?,'Res',?)
121 my $usth = $dbh->prepare($query);
122 $usth->execute( $borrowernumber, $nextacctno, $fee,
123 "Reserve Charge - $title", $fee );
130 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
131 priority,reservenotes,itemnumber,found,waitingdate)
136 my $sth = $dbh->prepare($query);
138 $borrowernumber, $biblionumber, $resdate, $branch,
139 $const, $priority, $notes, $checkitem,
145 if ( ( $const eq "o" ) || ( $const eq "e" ) ) {
146 my $numitems = @$bibitems;
148 while ( $i < $numitems ) {
149 my $biblioitem = @$bibitems[$i];
151 INSERT INTO reserveconstraints
152 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
156 my $sth = $dbh->prepare("");
157 $sth->execute( $borrowernumber, $biblionumber, $resdate,
166 =item GetReservesFromBiblionumber
168 @borrowerreserv=&GetReserves($biblionumber,$itemnumber,$borrowernumber);
170 this function get the list of reservation for an C<$biblionumber>, C<$itemnumber> or C<$borrowernumber>
172 Only 1 argument has to be passed.
176 sub GetReservesFromBiblionumber {
177 my ( $biblionumber, $itemnumber, $borrowernumber ) = @_;
178 my $dbh = C4::Context->dbh;
180 # Find the desired items in the reserves
183 timestamp AS rtimestamp,
192 WHERE cancellationdate IS NULL
193 AND (found <> \'F\' OR found IS NULL)
196 my $sth = $dbh->prepare($query);
197 $sth->execute($biblionumber);
200 while ( my $data = $sth->fetchrow_hashref ) {
202 # FIXME - What is this if-statement doing? How do constraints work?
203 if ( $data->{constrainttype} eq 'o' ) {
205 SELECT biblioitemnumber
206 FROM reserveconstraints
207 WHERE biblionumber = ?
208 AND borrowernumber = ?
211 my $csth = $dbh->prepare($query);
212 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
213 $data->{reservedate}, );
216 while ( my $bibitemnos = $csth->fetchrow_array ) {
217 push( @bibitemno, $bibitemnos );
219 my $count = @bibitemno;
221 # if we have two or more different specific itemtypes
222 # reserved by same person on same day
225 $bdata = GetBiblioItemData( $bibitemno[$i] );
230 # Look up the book we just found.
231 $bdata = GetBiblioItemData( $bibitemno[0] );
235 # Add the results of this latest search to the current
237 # FIXME - An 'each' would probably be more efficient.
238 foreach my $key ( keys %$bdata ) {
239 $data->{$key} = $bdata->{$key};
242 push @results, $data;
245 return ( $#results + 1, \@results );
248 sub GetReservesFromItemnumber {
249 my ( $itemnumber ) = @_;
250 my $dbh = C4::Context->dbh;
252 SELECT reservedate,borrowernumber,branchcode
255 AND cancellationdate IS NULL
256 AND (found <> 'F' OR found IS NULL)
258 my $sth_res = $dbh->prepare($query);
259 $sth_res->execute($itemnumber);
260 my ( $reservedate, $borrowernumber,$branchcode ) = $sth_res->fetchrow_array;
261 return ( $reservedate, $borrowernumber, $branchcode );
264 sub GetReservesFromBorrowernumber {
265 my ( $borrowernumber, $status ) = @_;
266 my $dbh = C4::Context->dbh;
269 $sth = $dbh->prepare("
272 WHERE borrowernumber=?
273 AND cancellationdate IS NULL
277 $sth->execute($borrowernumber,$status);
279 $sth = $dbh->prepare("
282 WHERE borrowernumber=?
283 AND cancellationdate IS NULL
284 AND (found != 'F' or found is null)
287 $sth->execute($borrowernumber);
290 while ( my $data = $sth->fetchrow_hashref ) {
291 push @borrowerreserv, $data;
293 return @borrowerreserv;
295 #-------------------------------------------------------------------------------------
297 =item GetReserveCount
299 $number = &GetReserveCount($borrowernumber);
301 this function returns the number of reservation for a borrower given on input arg.
305 sub GetReserveCount {
306 my ($borrowernumber) = @_;
308 my $dbh = C4::Context->dbh;
311 SELECT COUNT(*) AS counter
313 WHERE borrowernumber = ?
314 AND cancellationdate IS NULL
315 AND (found != \'F\' OR found IS NULL)
317 my $sth = $dbh->prepare($query);
318 $sth->execute($borrowernumber);
319 my $row = $sth->fetchrow_hashref;
322 return $row->{counter};
325 =item GetOtherReserves
327 ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber);
329 Check queued list of this document and check if this document must be transfered
333 sub GetOtherReserves {
334 my ($itemnumber) = @_;
337 my ( $restype, $checkreserves ) = CheckReserves($itemnumber);
338 if ($checkreserves) {
339 my $iteminfo = GetItem($itemnumber);
340 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
341 $messages->{'transfert'} = $checkreserves->{'branchcode'};
342 #minus priorities of others reservs
343 ModReserveMinusPriority(
345 $checkreserves->{'borrowernumber'},
346 $iteminfo->{'biblionumber'}
349 #launch the subroutine dotransfer
350 C4::Circulation::ModItemTransfer(
352 $iteminfo->{'holdingbranch'},
353 $checkreserves->{'branchcode'}
358 #step 2b : case of a reservation on the same branch, set the waiting status
360 $messages->{'waiting'} = 1;
361 ModReserveMinusPriority(
363 $checkreserves->{'borrowernumber'},
364 $iteminfo->{'biblionumber'}
366 ModReserveStatus($itemnumber,'W');
369 $nextreservinfo = $checkreserves->{'borrowernumber'};
372 return ( $messages, $nextreservinfo );
376 my ($borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
379 my $dbh = C4::Context->dbh;
380 my $const = lc substr( $constraint, 0, 1 );
382 SELECT * FROM borrowers,categories
383 WHERE borrowernumber = ?
384 AND borrowers.categorycode = categories.categorycode
386 my $sth = $dbh->prepare($query);
387 $sth->execute($borrowernumber);
388 my $data = $sth->fetchrow_hashref;
390 my $fee = $data->{'reservefee'};
391 my $cntitems = @- > $bibitems;
395 # check for items on issue
396 # first find biblioitem records
398 my $sth1 = $dbh->prepare(
399 "SELECT * FROM biblio,biblioitems
400 WHERE (biblio.biblionumber = ?)
401 AND (biblio.biblionumber = biblioitems.biblionumber)"
403 $sth1->execute($biblionumber);
404 while ( my $data1 = $sth1->fetchrow_hashref ) {
405 if ( $const eq "a" ) {
406 push @biblioitems, $data1;
411 while ( $x < $cntitems ) {
412 if ( @$bibitems->{'biblioitemnumber'} ==
413 $data->{'biblioitemnumber'} )
419 if ( $const eq 'o' ) {
421 push @biblioitems, $data1;
426 push @biblioitems, $data1;
432 my $cntitemsfound = @biblioitems;
436 while ( $x < $cntitemsfound ) {
437 my $bitdata = $biblioitems[$x];
438 my $sth2 = $dbh->prepare(
440 WHERE biblioitemnumber = ?"
442 $sth2->execute( $bitdata->{'biblioitemnumber'} );
443 while ( my $itdata = $sth2->fetchrow_hashref ) {
444 my $sth3 = $dbh->prepare(
445 "SELECT * FROM issues
447 AND returndate IS NULL"
449 $sth3->execute( $itdata->{'itemnumber'} );
450 if ( my $isdata = $sth3->fetchrow_hashref ) {
458 if ( $allissued == 0 ) {
460 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
461 $rsth->execute($biblionumber);
462 if ( my $rdata = $rsth->fetchrow_hashref ) {
474 =head2 GetReservesToBranch
476 @transreserv = GetReservesToBranch( $frombranch );
478 Get reserve list for a given branch
482 sub GetReservesToBranch {
483 my ( $frombranch ) = @_;
484 my $dbh = C4::Context->dbh;
485 my $sth = $dbh->prepare(
486 "SELECT borrowernumber,reservedate,itemnumber,timestamp
488 WHERE priority='0' AND cancellationdate is null
492 $sth->execute( $frombranch );
495 while ( my $data = $sth->fetchrow_hashref ) {
496 $transreserv[$i] = $data;
500 return (@transreserv);
503 =head2 GetReservesForBranch
505 @transreserv = GetReservesForBranch($frombranch);
509 sub GetReservesForBranch {
510 my ($frombranch) = @_;
511 my $dbh = C4::Context->dbh;
512 my $sth = $dbh->prepare( "
513 SELECT borrowernumber,reservedate,itemnumber,waitingdate
516 AND cancellationdate IS NULL
519 ORDER BY waitingdate" );
520 $sth->execute($frombranch);
523 while ( my $data = $sth->fetchrow_hashref ) {
524 $transreserv[$i] = $data;
528 return (@transreserv);
533 ($status, $reserve) = &CheckReserves($itemnumber);
535 Find a book in the reserves.
537 C<$itemnumber> is the book's item number.
539 As I understand it, C<&CheckReserves> looks for the given item in the
540 reserves. If it is found, that's a match, and C<$status> is set to
543 Otherwise, it finds the most important item in the reserves with the
544 same biblio number as this book (I'm not clear on this) and returns it
545 with C<$status> set to C<Reserved>.
547 C<&CheckReserves> returns a two-element list:
549 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
551 C<$reserve> is the reserve item that matched. It is a
552 reference-to-hash whose keys are mostly the fields of the reserves
553 table in the Koha database.
558 my ( $item, $barcode ) = @_;
559 my $dbh = C4::Context->dbh;
562 my $qitem = $dbh->quote($item);
563 # Look up the item by itemnumber
565 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
566 FROM items, biblioitems, itemtypes
567 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
568 AND biblioitems.itemtype = itemtypes.itemtype
569 AND itemnumber=$qitem
571 $sth = $dbh->prepare($query);
574 my $qbc = $dbh->quote($barcode);
575 # Look up the item by barcode
577 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
578 FROM items, biblioitems, itemtypes
579 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
580 AND biblioitems.itemtype = itemtypes.itemtype
583 $sth = $dbh->prepare($query);
585 # FIXME - This function uses $item later on. Ought to set it here.
588 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
591 # if item is not for loan it cannot be reserved either.....
592 return ( 0, 0 ) if $notforloan;
594 # get the reserves...
595 # Find this item in the reserves
596 my @reserves = _Findgroupreserve( $bibitem, $biblio );
597 my $count = scalar @reserves;
599 # $priority and $highest are used to find the most important item
600 # in the list returned by &_Findgroupreserve. (The lower $priority,
601 # the more important the item.)
602 # $highest is the most important item we've seen so far.
603 my $priority = 10000000;
606 foreach my $res (@reserves) {
607 # FIXME - $item might be undefined or empty: the caller
608 # might be searching by barcode.
609 if ( $res->{'itemnumber'} == $item ) {
611 return ( "Waiting", $res );
614 # See if this item is more important than what we've got
616 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
618 $priority = $res->{'priority'};
625 # If we get this far, then no exact match was found. Print the
626 # most important item on the list. I think this tells us who's
627 # next in line to get this book.
628 if ($highest) { # FIXME - $highest might be undefined
629 $highest->{'itemnumber'} = $item;
630 return ( "Reserved", $highest );
639 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
643 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
644 cancel, but not both: if both are given, C<&CancelReserve> does
647 C<$borrowernumber> is the borrower number of the patron on whose
648 behalf the book was reserved.
650 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
651 priorities of the other people who are waiting on the book.
656 my ( $biblio, $item, $borr ) = @_;
657 my $dbh = C4::Context->dbh;
658 if ( ( $item and $borr ) and ( not $biblio ) ) {
659 # removing a waiting reserve record....
660 # update the database...
663 SET cancellationdate = now(),
667 AND borrowernumber = ?
669 my $sth = $dbh->prepare($query);
670 $sth->execute( $item, $borr );
673 if ( ( $biblio and $borr ) and ( not $item ) ) {
674 # removing a reserve record....
675 # get the prioritiy on this record....
678 SELECT priority FROM reserves
679 WHERE biblionumber = ?
680 AND borrowernumber = ?
681 AND cancellationdate IS NULL
682 AND itemnumber IS NULL
683 AND (found <> 'F' OR found IS NULL)
685 my $sth = $dbh->prepare($query);
686 $sth->execute( $biblio, $borr );
687 ($priority) = $sth->fetchrow_array;
691 SET cancellationdate = now(),
694 WHERE biblionumber = ?
695 AND borrowernumber = ?
696 AND cancellationdate IS NULL
697 AND (found <> 'F' or found IS NULL)
700 # update the database, removing the record...
701 $sth = $dbh->prepare($query);
702 $sth->execute( $biblio, $borr );
705 # now fix the priority on the others....
706 _FixPriority( $priority, $biblio );
712 &ModReserve($rank,$biblio,$borrower,$branch)
717 #subroutine to update a reserve
718 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
719 return if $rank eq "W";
720 return if $rank eq "n";
721 my $dbh = C4::Context->dbh;
722 if ( $rank eq "del" ) {
725 SET cancellationdate=now()
726 WHERE biblionumber = ?
727 AND borrowernumber = ?
728 AND cancellationdate is NULL
729 AND (found <> 'F' or found is NULL)
731 my $sth = $dbh->prepare($query);
732 $sth->execute( $biblio, $borrower );
738 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
739 WHERE biblionumber = ?
740 AND borrowernumber = ?
741 AND cancellationdate is NULL
742 AND (found <> 'F' or found is NULL)
744 my $sth = $dbh->prepare($query);
745 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
747 _FixPriority( $biblio, $borrower, $rank);
753 &ModReserveFill($reserve);
755 Fill a reserve. If I understand this correctly, this means that the
756 reserved book has been found and given to the patron who reserved it.
758 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
759 whose keys are fields from the reserves table in the Koha database.
765 my $dbh = C4::Context->dbh;
766 # fill in a reserve record....
767 my $biblionumber = $res->{'biblionumber'};
768 my $borrowernumber = $res->{'borrowernumber'};
769 my $resdate = $res->{'reservedate'};
771 # get the priority on this record....
773 my $query = "SELECT priority
775 WHERE biblionumber = ?
776 AND borrowernumber = ?
777 AND reservedate = ?";
778 my $sth = $dbh->prepare($query);
779 $sth->execute( $biblionumber, $borrowernumber, $resdate );
780 ($priority) = $sth->fetchrow_array;
783 # update the database...
784 $query = "UPDATE reserves
787 WHERE biblionumber = ?
789 AND borrowernumber = ?
791 $sth = $dbh->prepare($query);
792 $sth->execute( $biblionumber, $resdate, $borrowernumber );
795 # now fix the priority on the others (if the priority wasn't
796 # already sorted!)....
797 unless ( $priority == 0 ) {
798 _FixPriority( $priority, $biblionumber );
802 =item ModReserveStatus
804 &ModReserveStatus($itemnumber, $newstatus);
806 Update the reserve status for the active (priority=0) reserve.
808 $itemnumber is the itemnumber the reserve is on
810 $newstatus is the new status.
814 sub ModReserveStatus {
816 #first : check if we have a reservation for this item .
817 my ($itemnumber, $newstatus) = @_;
818 my $dbh = C4::Context->dbh;
819 my $query = " UPDATE reserves
820 SET found=?,waitingdate = now()
825 my $sth_set = $dbh->prepare($query);
826 $sth_set->execute( $newstatus, $itemnumber );
830 =item ModReserveAffect
832 &ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend);
834 This function affect an item and a status for a given reserve
835 The itemnumber parameter is used to find the biblionumber.
836 with the biblionumber & the borrowernumber, we can affect the itemnumber
837 to the correct reserve.
839 if $transferToDo is set, then the status is set to "Waiting" as well.
840 otherwise, a transfer is on the way, and the end of the transfer will
841 take care of the waiting status
844 sub ModReserveAffect {
845 my ( $itemnumber, $borrowernumber,$transferToDo ) = @_;
846 my $dbh = C4::Context->dbh;
848 # we want to attach $itemnumber to $borrowernumber, find the biblionumber
849 # attached to $itemnumber
850 my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?");
851 $sth->execute($itemnumber);
852 my ($biblionumber) = $sth->fetchrow;
853 # If we affect a reserve that has to be transfered, don't set to Waiting
860 WHERE borrowernumber = ?
862 AND reserves.cancellationdate IS NULL
863 AND (reserves.found <> 'F' OR reserves.found IS NULL)
867 # affect the reserve to Waiting as well.
874 WHERE borrowernumber = ?
876 AND reserves.cancellationdate IS NULL
877 AND (reserves.found <> 'F' OR reserves.found IS NULL)
880 $sth = $dbh->prepare($query);
881 $sth->execute( $itemnumber, $borrowernumber,$biblionumber);
884 # now fix up the remaining priorities....
885 # _FixPriority( $data->{'priority'}, $biblio ); # can't work, 1st parameter should be $biblionumbern NOT priority. FIXME : remove this line if no problem seen once it is commented.
889 =item ModReserveCancelAll
891 ($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber);
893 function to cancel reserv,check other reserves, and transfer document if it's necessary
897 sub ModReserveCancelAll {
900 my ( $itemnumber, $borrowernumber ) = @_;
902 #step 1 : cancel the reservation
903 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
905 #step 2 launch the subroutine of the others reserves
906 ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
908 return ( $messages, $nextreservinfo );
911 =item ModReserveMinusPriority
913 &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber)
915 Reduce the values of queuded list
919 sub ModReserveMinusPriority {
920 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
922 #first step update the value of the first person on reserv
923 my $dbh = C4::Context->dbh;
926 SET priority = 0 , itemnumber = ?
927 WHERE cancellationdate IS NULL
931 my $sth_upd = $dbh->prepare($query);
932 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
934 # second step update all others reservs
937 SET priority = priority-1
938 WHERE biblionumber = ?
940 AND cancellationdate IS NULL
942 $sth_upd = $dbh->prepare($query);
943 $sth_upd->execute( $biblionumber );
950 &_FixPriority($biblio,$borrowernumber,$rank);
952 Only used internally (so don't export it)
953 Changed how this functions works #
954 Now just gets an array of reserves in the rank order and updates them with
955 the array index (+1 as array starts from 0)
956 and if $rank is supplied will splice item from the array and splice it back in again
962 my ( $biblio, $borrowernumber, $rank ) = @_;
963 my $dbh = C4::Context->dbh;
964 if ( $rank eq "del" ) {
965 CancelReserve( $biblio, undef, $borrowernumber );
967 if ( $rank eq "W" || $rank eq "0" ) {
969 # make sure priority for waiting items is 0
973 WHERE biblionumber = ?
974 AND borrowernumber = ?
975 AND cancellationdate IS NULL
978 my $sth = $dbh->prepare($query);
979 $sth->execute( $biblio, $borrowernumber );
985 # FIXME adding a new security in returned elements for changing priority,
986 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
988 SELECT borrowernumber, reservedate, constrainttype
990 WHERE biblionumber = ?
991 AND cancellationdate IS NULL
992 AND itemnumber IS NULL
993 AND ((found <> 'F' and found <> 'W') or found is NULL)
994 ORDER BY priority ASC
996 my $sth = $dbh->prepare($query);
997 $sth->execute($biblio);
998 while ( my $line = $sth->fetchrow_hashref ) {
999 push( @reservedates, $line );
1000 push( @priority, $line );
1003 # To find the matching index
1005 my $key = -1; # to allow for 0 to be a valid result
1006 for ( $i = 0 ; $i < @priority ; $i++ ) {
1007 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
1008 $key = $i; # save the index
1013 # if index exists in array then move it to new position
1014 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1015 my $new_rank = $rank -
1016 1; # $new_rank is what you want the new index to be in the array
1017 my $moving_item = splice( @priority, $key, 1 );
1018 splice( @priority, $new_rank, 0, $moving_item );
1021 # now fix the priority on those that are left....
1025 WHERE biblionumber = ?
1026 AND borrowernumber = ?
1030 $sth = $dbh->prepare($query);
1031 for ( my $j = 0 ; $j < @priority ; $j++ ) {
1034 $priority[$j]->{'borrowernumber'},
1035 $priority[$j]->{'reservedate'}
1041 =item _Findgroupreserve
1043 @results = &_Findgroupreserve($biblioitemnumber, $biblionumber);
1046 I don't know what this does, because I don't understand how reserve
1047 constraints work. I think the idea is that you reserve a particular
1048 biblio, and the constraint allows you to restrict it to a given
1049 biblioitem (e.g., if you want to borrow the audio book edition of "The
1050 Prophet", rather than the first available publication).
1052 C<&_Findgroupreserve> returns :
1053 C<@results> is an array of references-to-hash whose keys are mostly
1054 fields from the reserves table of the Koha database, plus
1055 C<biblioitemnumber>.
1059 sub _Findgroupreserve {
1060 my ( $bibitem, $biblio ) = @_;
1061 my $dbh = C4::Context->dbh;
1063 SELECT reserves.biblionumber AS biblionumber,
1064 reserves.borrowernumber AS borrowernumber,
1065 reserves.reservedate AS reservedate,
1066 reserves.branchcode AS branchcode,
1067 reserves.cancellationdate AS cancellationdate,
1068 reserves.found AS found,
1069 reserves.reservenotes AS reservenotes,
1070 reserves.priority AS priority,
1071 reserves.timestamp AS timestamp,
1072 reserveconstraints.biblioitemnumber AS biblioitemnumber,
1073 reserves.itemnumber AS itemnumber
1075 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
1076 WHERE reserves.biblionumber = ?
1077 AND ( ( reserveconstraints.biblioitemnumber = ?
1078 AND reserves.borrowernumber = reserveconstraints.borrowernumber
1079 AND reserves.reservedate =reserveconstraints.reservedate )
1080 OR reserves.constrainttype='a' )
1081 AND reserves.cancellationdate is NULL
1082 AND (reserves.found <> 'F' or reserves.found is NULL)
1084 my $sth = $dbh->prepare($query);
1085 $sth->execute( $biblio, $bibitem );
1087 while ( my $data = $sth->fetchrow_hashref ) {
1088 push( @results, $data );
1096 $fee = GetReserveFee($borrowernumber,$biblionumber,$constraint,$biblionumber);
1098 Calculate the fee for a reserve
1106 Koha Developement team <info@koha.org>