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 my $data = $sth->fetchall_arrayref({});
293 #-------------------------------------------------------------------------------------
295 =item GetReserveCount
297 $number = &GetReserveCount($borrowernumber);
299 this function returns the number of reservation for a borrower given on input arg.
303 sub GetReserveCount {
304 my ($borrowernumber) = @_;
306 my $dbh = C4::Context->dbh;
309 SELECT COUNT(*) AS counter
311 WHERE borrowernumber = ?
312 AND cancellationdate IS NULL
313 AND (found != \'F\' OR found IS NULL)
315 my $sth = $dbh->prepare($query);
316 $sth->execute($borrowernumber);
317 my $row = $sth->fetchrow_hashref;
320 return $row->{counter};
323 =item GetOtherReserves
325 ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber);
327 Check queued list of this document and check if this document must be transfered
331 sub GetOtherReserves {
332 my ($itemnumber) = @_;
335 my ( $restype, $checkreserves ) = CheckReserves($itemnumber);
336 if ($checkreserves) {
337 my $iteminfo = GetItem($itemnumber);
338 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
339 $messages->{'transfert'} = $checkreserves->{'branchcode'};
340 #minus priorities of others reservs
341 ModReserveMinusPriority(
343 $checkreserves->{'borrowernumber'},
344 $iteminfo->{'biblionumber'}
347 #launch the subroutine dotransfer
348 C4::Circulation::ModItemTransfer(
350 $iteminfo->{'holdingbranch'},
351 $checkreserves->{'branchcode'}
356 #step 2b : case of a reservation on the same branch, set the waiting status
358 $messages->{'waiting'} = 1;
359 ModReserveMinusPriority(
361 $checkreserves->{'borrowernumber'},
362 $iteminfo->{'biblionumber'}
364 ModReserveStatus($itemnumber,'W');
367 $nextreservinfo = $checkreserves->{'borrowernumber'};
370 return ( $messages, $nextreservinfo );
374 my ($borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
377 my $dbh = C4::Context->dbh;
378 my $const = lc substr( $constraint, 0, 1 );
380 SELECT * FROM borrowers,categories
381 WHERE borrowernumber = ?
382 AND borrowers.categorycode = categories.categorycode
384 my $sth = $dbh->prepare($query);
385 $sth->execute($borrowernumber);
386 my $data = $sth->fetchrow_hashref;
388 my $fee = $data->{'reservefee'};
389 my $cntitems = @- > $bibitems;
393 # check for items on issue
394 # first find biblioitem records
396 my $sth1 = $dbh->prepare(
397 "SELECT * FROM biblio,biblioitems
398 WHERE (biblio.biblionumber = ?)
399 AND (biblio.biblionumber = biblioitems.biblionumber)"
401 $sth1->execute($biblionumber);
402 while ( my $data1 = $sth1->fetchrow_hashref ) {
403 if ( $const eq "a" ) {
404 push @biblioitems, $data1;
409 while ( $x < $cntitems ) {
410 if ( @$bibitems->{'biblioitemnumber'} ==
411 $data->{'biblioitemnumber'} )
417 if ( $const eq 'o' ) {
419 push @biblioitems, $data1;
424 push @biblioitems, $data1;
430 my $cntitemsfound = @biblioitems;
434 while ( $x < $cntitemsfound ) {
435 my $bitdata = $biblioitems[$x];
436 my $sth2 = $dbh->prepare(
438 WHERE biblioitemnumber = ?"
440 $sth2->execute( $bitdata->{'biblioitemnumber'} );
441 while ( my $itdata = $sth2->fetchrow_hashref ) {
442 my $sth3 = $dbh->prepare(
443 "SELECT * FROM issues
445 AND returndate IS NULL"
447 $sth3->execute( $itdata->{'itemnumber'} );
448 if ( my $isdata = $sth3->fetchrow_hashref ) {
456 if ( $allissued == 0 ) {
458 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
459 $rsth->execute($biblionumber);
460 if ( my $rdata = $rsth->fetchrow_hashref ) {
472 =head2 GetReservesToBranch
474 @transreserv = GetReservesToBranch( $frombranch );
476 Get reserve list for a given branch
480 sub GetReservesToBranch {
481 my ( $frombranch ) = @_;
482 my $dbh = C4::Context->dbh;
483 my $sth = $dbh->prepare(
484 "SELECT borrowernumber,reservedate,itemnumber,timestamp
486 WHERE priority='0' AND cancellationdate is null
490 $sth->execute( $frombranch );
493 while ( my $data = $sth->fetchrow_hashref ) {
494 $transreserv[$i] = $data;
498 return (@transreserv);
501 =head2 GetReservesForBranch
503 @transreserv = GetReservesForBranch($frombranch);
507 sub GetReservesForBranch {
508 my ($frombranch) = @_;
509 my $dbh = C4::Context->dbh;
510 my $sth = $dbh->prepare( "
511 SELECT borrowernumber,reservedate,itemnumber,waitingdate
514 AND cancellationdate IS NULL
517 ORDER BY waitingdate" );
518 $sth->execute($frombranch);
521 while ( my $data = $sth->fetchrow_hashref ) {
522 $transreserv[$i] = $data;
526 return (@transreserv);
531 ($status, $reserve) = &CheckReserves($itemnumber);
533 Find a book in the reserves.
535 C<$itemnumber> is the book's item number.
537 As I understand it, C<&CheckReserves> looks for the given item in the
538 reserves. If it is found, that's a match, and C<$status> is set to
541 Otherwise, it finds the most important item in the reserves with the
542 same biblio number as this book (I'm not clear on this) and returns it
543 with C<$status> set to C<Reserved>.
545 C<&CheckReserves> returns a two-element list:
547 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
549 C<$reserve> is the reserve item that matched. It is a
550 reference-to-hash whose keys are mostly the fields of the reserves
551 table in the Koha database.
556 my ( $item, $barcode ) = @_;
557 my $dbh = C4::Context->dbh;
560 my $qitem = $dbh->quote($item);
561 # Look up the item by itemnumber
563 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
564 FROM items, biblioitems, itemtypes
565 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
566 AND biblioitems.itemtype = itemtypes.itemtype
567 AND itemnumber=$qitem
569 $sth = $dbh->prepare($query);
572 my $qbc = $dbh->quote($barcode);
573 # Look up the item by barcode
575 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
576 FROM items, biblioitems, itemtypes
577 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
578 AND biblioitems.itemtype = itemtypes.itemtype
581 $sth = $dbh->prepare($query);
583 # FIXME - This function uses $item later on. Ought to set it here.
586 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
589 # if item is not for loan it cannot be reserved either.....
590 return ( 0, 0 ) if $notforloan;
592 # get the reserves...
593 # Find this item in the reserves
594 my @reserves = _Findgroupreserve( $bibitem, $biblio );
595 my $count = scalar @reserves;
597 # $priority and $highest are used to find the most important item
598 # in the list returned by &_Findgroupreserve. (The lower $priority,
599 # the more important the item.)
600 # $highest is the most important item we've seen so far.
601 my $priority = 10000000;
604 foreach my $res (@reserves) {
605 # FIXME - $item might be undefined or empty: the caller
606 # might be searching by barcode.
607 if ( $res->{'itemnumber'} == $item ) {
609 return ( "Waiting", $res );
612 # See if this item is more important than what we've got
614 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
616 $priority = $res->{'priority'};
623 # If we get this far, then no exact match was found. Print the
624 # most important item on the list. I think this tells us who's
625 # next in line to get this book.
626 if ($highest) { # FIXME - $highest might be undefined
627 $highest->{'itemnumber'} = $item;
628 return ( "Reserved", $highest );
637 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
641 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
642 cancel, but not both: if both are given, C<&CancelReserve> does
645 C<$borrowernumber> is the borrower number of the patron on whose
646 behalf the book was reserved.
648 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
649 priorities of the other people who are waiting on the book.
654 my ( $biblio, $item, $borr ) = @_;
655 my $dbh = C4::Context->dbh;
656 if ( ( $item and $borr ) and ( not $biblio ) ) {
657 # removing a waiting reserve record....
658 # update the database...
661 SET cancellationdate = now(),
665 AND borrowernumber = ?
667 my $sth = $dbh->prepare($query);
668 $sth->execute( $item, $borr );
671 if ( ( $biblio and $borr ) and ( not $item ) ) {
672 # removing a reserve record....
673 # get the prioritiy on this record....
676 SELECT priority FROM reserves
677 WHERE biblionumber = ?
678 AND borrowernumber = ?
679 AND cancellationdate IS NULL
680 AND itemnumber IS NULL
681 AND (found <> 'F' OR found IS NULL)
683 my $sth = $dbh->prepare($query);
684 $sth->execute( $biblio, $borr );
685 ($priority) = $sth->fetchrow_array;
689 SET cancellationdate = now(),
692 WHERE biblionumber = ?
693 AND borrowernumber = ?
694 AND cancellationdate IS NULL
695 AND (found <> 'F' or found IS NULL)
698 # update the database, removing the record...
699 $sth = $dbh->prepare($query);
700 $sth->execute( $biblio, $borr );
703 # now fix the priority on the others....
704 _FixPriority( $priority, $biblio );
710 &ModReserve($rank,$biblio,$borrower,$branch)
715 #subroutine to update a reserve
716 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
717 return if $rank eq "W";
718 return if $rank eq "n";
719 my $dbh = C4::Context->dbh;
720 if ( $rank eq "del" ) {
723 SET cancellationdate=now()
724 WHERE biblionumber = ?
725 AND borrowernumber = ?
726 AND cancellationdate is NULL
727 AND (found <> 'F' or found is NULL)
729 my $sth = $dbh->prepare($query);
730 $sth->execute( $biblio, $borrower );
736 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
737 WHERE biblionumber = ?
738 AND borrowernumber = ?
739 AND cancellationdate is NULL
740 AND (found <> 'F' or found is NULL)
742 my $sth = $dbh->prepare($query);
743 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
745 _FixPriority( $biblio, $borrower, $rank);
751 &ModReserveFill($reserve);
753 Fill a reserve. If I understand this correctly, this means that the
754 reserved book has been found and given to the patron who reserved it.
756 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
757 whose keys are fields from the reserves table in the Koha database.
763 my $dbh = C4::Context->dbh;
764 # fill in a reserve record....
765 my $biblionumber = $res->{'biblionumber'};
766 my $borrowernumber = $res->{'borrowernumber'};
767 my $resdate = $res->{'reservedate'};
769 # get the priority on this record....
771 my $query = "SELECT priority
773 WHERE biblionumber = ?
774 AND borrowernumber = ?
775 AND reservedate = ?";
776 my $sth = $dbh->prepare($query);
777 $sth->execute( $biblionumber, $borrowernumber, $resdate );
778 ($priority) = $sth->fetchrow_array;
781 # update the database...
782 $query = "UPDATE reserves
785 WHERE biblionumber = ?
787 AND borrowernumber = ?
789 $sth = $dbh->prepare($query);
790 $sth->execute( $biblionumber, $resdate, $borrowernumber );
793 # now fix the priority on the others (if the priority wasn't
794 # already sorted!)....
795 unless ( $priority == 0 ) {
796 _FixPriority( $priority, $biblionumber );
800 =item ModReserveStatus
802 &ModReserveStatus($itemnumber, $newstatus);
804 Update the reserve status for the active (priority=0) reserve.
806 $itemnumber is the itemnumber the reserve is on
808 $newstatus is the new status.
812 sub ModReserveStatus {
814 #first : check if we have a reservation for this item .
815 my ($itemnumber, $newstatus) = @_;
816 my $dbh = C4::Context->dbh;
817 my $query = " UPDATE reserves
818 SET found=?,waitingdate = now()
823 my $sth_set = $dbh->prepare($query);
824 $sth_set->execute( $newstatus, $itemnumber );
828 =item ModReserveAffect
830 &ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend);
832 This function affect an item and a status for a given reserve
833 The itemnumber parameter is used to find the biblionumber.
834 with the biblionumber & the borrowernumber, we can affect the itemnumber
835 to the correct reserve.
837 if $transferToDo is set, then the status is set to "Waiting" as well.
838 otherwise, a transfer is on the way, and the end of the transfer will
839 take care of the waiting status
842 sub ModReserveAffect {
843 my ( $itemnumber, $borrowernumber,$transferToDo ) = @_;
844 my $dbh = C4::Context->dbh;
846 # we want to attach $itemnumber to $borrowernumber, find the biblionumber
847 # attached to $itemnumber
848 my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?");
849 $sth->execute($itemnumber);
850 my ($biblionumber) = $sth->fetchrow;
851 # If we affect a reserve that has to be transfered, don't set to Waiting
858 WHERE borrowernumber = ?
860 AND reserves.cancellationdate IS NULL
861 AND (reserves.found <> 'F' OR reserves.found IS NULL)
865 # affect the reserve to Waiting as well.
872 WHERE borrowernumber = ?
874 AND reserves.cancellationdate IS NULL
875 AND (reserves.found <> 'F' OR reserves.found IS NULL)
878 $sth = $dbh->prepare($query);
879 $sth->execute( $itemnumber, $borrowernumber,$biblionumber);
882 # now fix up the remaining priorities....
883 # _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.
887 =item ModReserveCancelAll
889 ($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber);
891 function to cancel reserv,check other reserves, and transfer document if it's necessary
895 sub ModReserveCancelAll {
898 my ( $itemnumber, $borrowernumber ) = @_;
900 #step 1 : cancel the reservation
901 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
903 #step 2 launch the subroutine of the others reserves
904 ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
906 return ( $messages, $nextreservinfo );
909 =item ModReserveMinusPriority
911 &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber)
913 Reduce the values of queuded list
917 sub ModReserveMinusPriority {
918 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
920 #first step update the value of the first person on reserv
921 my $dbh = C4::Context->dbh;
924 SET priority = 0 , itemnumber = ?
925 WHERE cancellationdate IS NULL
929 my $sth_upd = $dbh->prepare($query);
930 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
932 # second step update all others reservs
935 SET priority = priority-1
936 WHERE biblionumber = ?
938 AND cancellationdate IS NULL
940 $sth_upd = $dbh->prepare($query);
941 $sth_upd->execute( $biblionumber );
948 &_FixPriority($biblio,$borrowernumber,$rank);
950 Only used internally (so don't export it)
951 Changed how this functions works #
952 Now just gets an array of reserves in the rank order and updates them with
953 the array index (+1 as array starts from 0)
954 and if $rank is supplied will splice item from the array and splice it back in again
960 my ( $biblio, $borrowernumber, $rank ) = @_;
961 my $dbh = C4::Context->dbh;
962 if ( $rank eq "del" ) {
963 CancelReserve( $biblio, undef, $borrowernumber );
965 if ( $rank eq "W" || $rank eq "0" ) {
967 # make sure priority for waiting items is 0
971 WHERE biblionumber = ?
972 AND borrowernumber = ?
973 AND cancellationdate IS NULL
976 my $sth = $dbh->prepare($query);
977 $sth->execute( $biblio, $borrowernumber );
983 # FIXME adding a new security in returned elements for changing priority,
984 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
986 SELECT borrowernumber, reservedate, constrainttype
988 WHERE biblionumber = ?
989 AND cancellationdate IS NULL
990 AND itemnumber IS NULL
991 AND ((found <> 'F' and found <> 'W') or found is NULL)
992 ORDER BY priority ASC
994 my $sth = $dbh->prepare($query);
995 $sth->execute($biblio);
996 while ( my $line = $sth->fetchrow_hashref ) {
997 push( @reservedates, $line );
998 push( @priority, $line );
1001 # To find the matching index
1003 my $key = -1; # to allow for 0 to be a valid result
1004 for ( $i = 0 ; $i < @priority ; $i++ ) {
1005 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
1006 $key = $i; # save the index
1011 # if index exists in array then move it to new position
1012 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1013 my $new_rank = $rank -
1014 1; # $new_rank is what you want the new index to be in the array
1015 my $moving_item = splice( @priority, $key, 1 );
1016 splice( @priority, $new_rank, 0, $moving_item );
1019 # now fix the priority on those that are left....
1023 WHERE biblionumber = ?
1024 AND borrowernumber = ?
1028 $sth = $dbh->prepare($query);
1029 for ( my $j = 0 ; $j < @priority ; $j++ ) {
1032 $priority[$j]->{'borrowernumber'},
1033 $priority[$j]->{'reservedate'}
1039 =item _Findgroupreserve
1041 @results = &_Findgroupreserve($biblioitemnumber, $biblionumber);
1044 I don't know what this does, because I don't understand how reserve
1045 constraints work. I think the idea is that you reserve a particular
1046 biblio, and the constraint allows you to restrict it to a given
1047 biblioitem (e.g., if you want to borrow the audio book edition of "The
1048 Prophet", rather than the first available publication).
1050 C<&_Findgroupreserve> returns :
1051 C<@results> is an array of references-to-hash whose keys are mostly
1052 fields from the reserves table of the Koha database, plus
1053 C<biblioitemnumber>.
1057 sub _Findgroupreserve {
1058 my ( $bibitem, $biblio ) = @_;
1059 my $dbh = C4::Context->dbh;
1061 SELECT reserves.biblionumber AS biblionumber,
1062 reserves.borrowernumber AS borrowernumber,
1063 reserves.reservedate AS reservedate,
1064 reserves.branchcode AS branchcode,
1065 reserves.cancellationdate AS cancellationdate,
1066 reserves.found AS found,
1067 reserves.reservenotes AS reservenotes,
1068 reserves.priority AS priority,
1069 reserves.timestamp AS timestamp,
1070 reserveconstraints.biblioitemnumber AS biblioitemnumber,
1071 reserves.itemnumber AS itemnumber
1073 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
1074 WHERE reserves.biblionumber = ?
1075 AND ( ( reserveconstraints.biblioitemnumber = ?
1076 AND reserves.borrowernumber = reserveconstraints.borrowernumber
1077 AND reserves.reservedate =reserveconstraints.reservedate )
1078 OR reserves.constrainttype='a' )
1079 AND reserves.cancellationdate is NULL
1080 AND (reserves.found <> 'F' or reserves.found is NULL)
1082 my $sth = $dbh->prepare($query);
1083 $sth->execute( $biblio, $bibitem );
1085 while ( my $data = $sth->fetchrow_hashref ) {
1086 push( @results, $data );
1094 $fee = GetReserveFee($borrowernumber,$biblionumber,$constraint,$biblionumber);
1096 Calculate the fee for a reserve
1104 Koha Developement team <info@koha.org>