2 # NOTE: This file uses standard 8-character tabs
6 # Copyright 2000-2002 Katipo Communications
7 # 2006 SAN Ouest Provence
8 # 2007 BibLibre Paul POULAIN
10 # This file is part of Koha.
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
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.
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
34 our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,%EXPORT_TAGS);
36 my $library_name = C4::Context->preference("LibraryName");
38 # set the version for version checking
43 C4::Reserves - Koha functions for dealing with reservation.
51 this modules provides somes functions to deal with reservations.
53 Reserves are stored in reserves table.
54 The following columns contains important values :
55 - priority >0 : then the reserve is at 1st stage, and not yet affected to any item.
56 =0 : then the reserve is being dealed
57 - found : NULL : means the patron requested the 1st available, and we haven't choosen the item
58 W(aiting) : the reserve has an itemnumber affected, and is on the way
59 F(inished) : the reserve has been completed, and is done
60 - itemnumber : empty : the reserve is still unaffected to an item
61 filled: the reserve is attached to an item
62 The complete workflow is :
63 ==== 1st use case ====
64 patron request a document, 1st available : P >0, F=NULL, I=NULL
65 a library having it run "transfertodo", and clic on the list
66 if there is no transfer to do, the reserve waiting
67 patron can pick it up P =0, F=W, I=filled
68 if there is a transfer to do, write in branchtransfer P =0, F=NULL, I=filled
69 The pickup library recieve the book, it check in P =0, F=W, I=filled
70 The patron borrow the book P =0, F=F, I=filled
72 ==== 2nd use case ====
73 patron requests a document, a given item,
74 If pickup is holding branch P =0, F=W, I=filled
75 If transfer needed, write in branchtransfer P =0, F=NULL, I=filled
76 The pickup library recieve the book, it checks it in P =0, F=W, I=filled
77 The patron borrow the book P =0, F=F, I=filled
90 &GetReservesFromItemnumber
91 &GetReservesFromBiblionumber
92 &GetReservesFromBorrowernumber
105 &ModReserveMinusPriority
114 AddReserve($branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$notes,$title,$checkitem,$found)
120 $branch, $borrowernumber, $biblionumber,
121 $constraint, $bibitems, $priority, $notes,
122 $title, $checkitem, $found
125 GetReserveFee($borrowernumber, $biblionumber, $constraint,
127 my $dbh = C4::Context->dbh;
128 my $const = lc substr( $constraint, 0, 1 );
129 my @datearr = localtime(time);
131 ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
134 # If the reserv had the waiting status, we had the value of the resdate
135 if ( $found eq 'W' ) {
136 $waitingdate = $resdate;
140 # updates take place here
142 my $nextacctno = &getnextacctno( $borrowernumber );
144 INSERT INTO accountlines
145 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
147 (?,?,now(),?,?,'Res',?)
149 my $usth = $dbh->prepare($query);
150 $usth->execute( $borrowernumber, $nextacctno, $fee,
151 "Reserve Charge - $title", $fee );
158 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
159 priority,reservenotes,itemnumber,found,waitingdate)
164 my $sth = $dbh->prepare($query);
166 $borrowernumber, $biblionumber, $resdate, $branch,
167 $const, $priority, $notes, $checkitem,
173 if ( ( $const eq "o" ) || ( $const eq "e" ) ) {
174 my $numitems = @$bibitems;
176 while ( $i < $numitems ) {
177 my $biblioitem = @$bibitems[$i];
179 INSERT INTO reserveconstraints
180 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
184 my $sth = $dbh->prepare("");
185 $sth->execute( $borrowernumber, $biblionumber, $resdate,
194 =item GetReservesFromBiblionumber
196 @borrowerreserv=&GetReserves($biblionumber,$itemnumber,$borrowernumber);
198 this function get the list of reservation for an C<$biblionumber>, C<$itemnumber> or C<$borrowernumber>
200 Only 1 argument has to be passed.
204 sub GetReservesFromBiblionumber {
205 my ( $biblionumber, $itemnumber, $borrowernumber ) = @_;
206 my $dbh = C4::Context->dbh;
208 # Find the desired items in the reserves
211 timestamp AS rtimestamp,
221 WHERE cancellationdate IS NULL
222 AND (found <> \'F\' OR found IS NULL)
225 my $sth = $dbh->prepare($query);
226 $sth->execute($biblionumber);
229 while ( my $data = $sth->fetchrow_hashref ) {
231 # FIXME - What is this if-statement doing? How do constraints work?
232 if ( $data->{constrainttype} eq 'o' ) {
234 SELECT biblioitemnumber
235 FROM reserveconstraints
236 WHERE biblionumber = ?
237 AND borrowernumber = ?
240 my $csth = $dbh->prepare($query);
241 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
242 $data->{reservedate}, );
245 while ( my $bibitemnos = $csth->fetchrow_array ) {
246 push( @bibitemno, $bibitemnos );
248 my $count = @bibitemno;
250 # if we have two or more different specific itemtypes
251 # reserved by same person on same day
254 $bdata = GetBiblioItemData( $bibitemno[$i] );
259 # Look up the book we just found.
260 $bdata = GetBiblioItemData( $bibitemno[0] );
264 # Add the results of this latest search to the current
266 # FIXME - An 'each' would probably be more efficient.
267 foreach my $key ( keys %$bdata ) {
268 $data->{$key} = $bdata->{$key};
271 push @results, $data;
274 return ( $#results + 1, \@results );
277 =item GetReservesFromItemnumber
279 ( $reservedate, $borrowernumber, $branchcode ) = GetReservesFromItemnumber($itemnumber);
281 TODO :: Description here
285 sub GetReservesFromItemnumber {
286 my ( $itemnumber ) = @_;
287 my $dbh = C4::Context->dbh;
289 SELECT reservedate,borrowernumber,branchcode
292 AND cancellationdate IS NULL
293 AND (found <> 'F' OR found IS NULL)
295 my $sth_res = $dbh->prepare($query);
296 $sth_res->execute($itemnumber);
297 my ( $reservedate, $borrowernumber,$branchcode ) = $sth_res->fetchrow_array;
298 return ( $reservedate, $borrowernumber, $branchcode );
301 =item GetReservesFromBorrowernumber
303 $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber,$tatus);
309 sub GetReservesFromBorrowernumber {
310 my ( $borrowernumber, $status ) = @_;
311 my $dbh = C4::Context->dbh;
314 $sth = $dbh->prepare("
317 WHERE borrowernumber=?
318 AND cancellationdate IS NULL
322 $sth->execute($borrowernumber,$status);
324 $sth = $dbh->prepare("
327 WHERE borrowernumber=?
328 AND cancellationdate IS NULL
329 AND (found != 'F' or found is null)
332 $sth->execute($borrowernumber);
334 my $data = $sth->fetchall_arrayref({});
337 #-------------------------------------------------------------------------------------
339 =item GetReserveCount
341 $number = &GetReserveCount($borrowernumber);
343 this function returns the number of reservation for a borrower given on input arg.
347 sub GetReserveCount {
348 my ($borrowernumber) = @_;
350 my $dbh = C4::Context->dbh;
353 SELECT COUNT(*) AS counter
355 WHERE borrowernumber = ?
356 AND cancellationdate IS NULL
357 AND (found != \'F\' OR found IS NULL)
359 my $sth = $dbh->prepare($query);
360 $sth->execute($borrowernumber);
361 my $row = $sth->fetchrow_hashref;
364 return $row->{counter};
367 =item GetOtherReserves
369 ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber);
371 Check queued list of this document and check if this document must be transfered
375 sub GetOtherReserves {
376 my ($itemnumber) = @_;
379 my ( $restype, $checkreserves ) = CheckReserves($itemnumber);
380 if ($checkreserves) {
381 my $iteminfo = GetItem($itemnumber);
382 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
383 $messages->{'transfert'} = $checkreserves->{'branchcode'};
384 #minus priorities of others reservs
385 ModReserveMinusPriority(
387 $checkreserves->{'borrowernumber'},
388 $iteminfo->{'biblionumber'}
391 #launch the subroutine dotransfer
392 C4::Circulation::ModItemTransfer(
394 $iteminfo->{'holdingbranch'},
395 $checkreserves->{'branchcode'}
400 #step 2b : case of a reservation on the same branch, set the waiting status
402 $messages->{'waiting'} = 1;
403 ModReserveMinusPriority(
405 $checkreserves->{'borrowernumber'},
406 $iteminfo->{'biblionumber'}
408 ModReserveStatus($itemnumber,'W');
411 $nextreservinfo = $checkreserves->{'borrowernumber'};
414 return ( $messages, $nextreservinfo );
419 $fee = GetReserveFee($borrowernumber,$biblionumber,$constraint,$biblionumber);
421 Calculate the fee for a reserve
426 my ($borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
429 my $dbh = C4::Context->dbh;
430 my $const = lc substr( $constraint, 0, 1 );
432 SELECT * FROM borrowers
433 LEFT JOIN categories ON borrowers.categorycode = categories.categorycode
434 WHERE borrowernumber = ?
436 my $sth = $dbh->prepare($query);
437 $sth->execute($borrowernumber);
438 my $data = $sth->fetchrow_hashref;
440 my $fee = $data->{'reservefee'};
441 my $cntitems = @- > $bibitems;
445 # check for items on issue
446 # first find biblioitem records
448 my $sth1 = $dbh->prepare(
449 "SELECT * FROM biblio LEFT JOIN biblioitems on biblio.biblionumber = biblioitems.biblionumber
450 WHERE (biblio.biblionumber = ?)"
452 $sth1->execute($biblionumber);
453 while ( my $data1 = $sth1->fetchrow_hashref ) {
454 if ( $const eq "a" ) {
455 push @biblioitems, $data1;
460 while ( $x < $cntitems ) {
461 if ( @$bibitems->{'biblioitemnumber'} ==
462 $data->{'biblioitemnumber'} )
468 if ( $const eq 'o' ) {
470 push @biblioitems, $data1;
475 push @biblioitems, $data1;
481 my $cntitemsfound = @biblioitems;
485 while ( $x < $cntitemsfound ) {
486 my $bitdata = $biblioitems[$x];
487 my $sth2 = $dbh->prepare(
489 WHERE biblioitemnumber = ?"
491 $sth2->execute( $bitdata->{'biblioitemnumber'} );
492 while ( my $itdata = $sth2->fetchrow_hashref ) {
493 my $sth3 = $dbh->prepare(
494 "SELECT * FROM issues
496 AND returndate IS NULL"
498 $sth3->execute( $itdata->{'itemnumber'} );
499 if ( my $isdata = $sth3->fetchrow_hashref ) {
507 if ( $allissued == 0 ) {
509 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
510 $rsth->execute($biblionumber);
511 if ( my $rdata = $rsth->fetchrow_hashref ) {
521 =item GetReservesToBranch
523 @transreserv = GetReservesToBranch( $frombranch );
525 Get reserve list for a given branch
529 sub GetReservesToBranch {
530 my ( $frombranch ) = @_;
531 my $dbh = C4::Context->dbh;
532 my $sth = $dbh->prepare(
533 "SELECT borrowernumber,reservedate,itemnumber,timestamp
535 WHERE priority='0' AND cancellationdate is null
539 $sth->execute( $frombranch );
542 while ( my $data = $sth->fetchrow_hashref ) {
543 $transreserv[$i] = $data;
547 return (@transreserv);
550 =item GetReservesForBranch
552 @transreserv = GetReservesForBranch($frombranch);
556 sub GetReservesForBranch {
557 my ($frombranch) = @_;
558 my $dbh = C4::Context->dbh;
559 my $query = "SELECT borrowernumber,reservedate,itemnumber,waitingdate
562 AND cancellationdate IS NULL
565 $query .= " AND branchcode=? ";
567 $query .= "ORDER BY waitingdate" ;
568 my $sth = $dbh->prepare($query);
570 $sth->execute($frombranch);
577 while ( my $data = $sth->fetchrow_hashref ) {
578 $transreserv[$i] = $data;
582 return (@transreserv);
587 ($status, $reserve) = &CheckReserves($itemnumber);
589 Find a book in the reserves.
591 C<$itemnumber> is the book's item number.
593 As I understand it, C<&CheckReserves> looks for the given item in the
594 reserves. If it is found, that's a match, and C<$status> is set to
597 Otherwise, it finds the most important item in the reserves with the
598 same biblio number as this book (I'm not clear on this) and returns it
599 with C<$status> set to C<Reserved>.
601 C<&CheckReserves> returns a two-element list:
603 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
605 C<$reserve> is the reserve item that matched. It is a
606 reference-to-hash whose keys are mostly the fields of the reserves
607 table in the Koha database.
612 my ( $item, $barcode ) = @_;
613 my $dbh = C4::Context->dbh;
616 my $qitem = $dbh->quote($item);
617 # Look up the item by itemnumber
619 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
621 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
622 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
623 WHERE itemnumber=$qitem
625 $sth = $dbh->prepare($query);
628 my $qbc = $dbh->quote($barcode);
629 # Look up the item by barcode
631 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
633 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
634 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
635 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
636 AND biblioitems.itemtype = itemtypes.itemtype
639 $sth = $dbh->prepare($query);
641 # FIXME - This function uses $item later on. Ought to set it here.
644 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
647 # if item is not for loan it cannot be reserved either.....
648 return ( 0, 0 ) if $notforloan;
650 # get the reserves...
651 # Find this item in the reserves
652 my @reserves = _Findgroupreserve( $bibitem, $biblio );
653 my $count = scalar @reserves;
655 # $priority and $highest are used to find the most important item
656 # in the list returned by &_Findgroupreserve. (The lower $priority,
657 # the more important the item.)
658 # $highest is the most important item we've seen so far.
659 my $priority = 10000000;
662 foreach my $res (@reserves) {
663 # FIXME - $item might be undefined or empty: the caller
664 # might be searching by barcode.
665 if ( $res->{'itemnumber'} == $item ) {
667 return ( "Waiting", $res );
670 # See if this item is more important than what we've got
672 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
674 $priority = $res->{'priority'};
681 # If we get this far, then no exact match was found. Print the
682 # most important item on the list. I think this tells us who's
683 # next in line to get this book.
684 if ($highest) { # FIXME - $highest might be undefined
685 $highest->{'itemnumber'} = $item;
686 return ( "Reserved", $highest );
695 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
699 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
700 cancel, but not both: if both are given, C<&CancelReserve> does
703 C<$borrowernumber> is the borrower number of the patron on whose
704 behalf the book was reserved.
706 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
707 priorities of the other people who are waiting on the book.
712 my ( $biblio, $item, $borr ) = @_;
713 my $dbh = C4::Context->dbh;
714 if ( $item and $borr ) {
715 # removing a waiting reserve record....
716 # update the database...
719 SET cancellationdate = now(),
723 AND borrowernumber = ?
725 my $sth = $dbh->prepare($query);
726 $sth->execute( $item, $borr );
730 # removing a reserve record....
731 # get the prioritiy on this record....
734 SELECT priority FROM reserves
735 WHERE biblionumber = ?
736 AND borrowernumber = ?
737 AND cancellationdate IS NULL
738 AND itemnumber IS NULL
739 AND (found <> 'F' OR found IS NULL)
741 my $sth = $dbh->prepare($query);
742 $sth->execute( $biblio, $borr );
743 ($priority) = $sth->fetchrow_array;
747 SET cancellationdate = now(),
750 WHERE biblionumber = ?
751 AND borrowernumber = ?
752 AND cancellationdate IS NULL
753 AND (found <> 'F' or found IS NULL)
756 # update the database, removing the record...
757 $sth = $dbh->prepare($query);
758 $sth->execute( $biblio, $borr );
761 # now fix the priority on the others....
762 _FixPriority( $priority, $biblio );
768 &ModReserve($rank,$biblio,$borrower,$branch)
773 #subroutine to update a reserve
774 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
775 return if $rank eq "W";
776 return if $rank eq "n";
777 my $dbh = C4::Context->dbh;
778 if ( $rank eq "del" ) {
781 SET cancellationdate=now()
782 WHERE biblionumber = ?
783 AND borrowernumber = ?
784 AND cancellationdate is NULL
785 AND (found <> 'F' or found is NULL)
787 my $sth = $dbh->prepare($query);
788 $sth->execute( $biblio, $borrower );
794 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
795 WHERE biblionumber = ?
796 AND borrowernumber = ?
797 AND cancellationdate is NULL
798 AND (found <> 'F' or found is NULL)
800 my $sth = $dbh->prepare($query);
801 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
803 _FixPriority( $biblio, $borrower, $rank);
809 &ModReserveFill($reserve);
811 Fill a reserve. If I understand this correctly, this means that the
812 reserved book has been found and given to the patron who reserved it.
814 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
815 whose keys are fields from the reserves table in the Koha database.
821 my $dbh = C4::Context->dbh;
822 # fill in a reserve record....
823 my $biblionumber = $res->{'biblionumber'};
824 my $borrowernumber = $res->{'borrowernumber'};
825 my $resdate = $res->{'reservedate'};
827 # get the priority on this record....
829 my $query = "SELECT priority
831 WHERE biblionumber = ?
832 AND borrowernumber = ?
833 AND reservedate = ?";
834 my $sth = $dbh->prepare($query);
835 $sth->execute( $biblionumber, $borrowernumber, $resdate );
836 ($priority) = $sth->fetchrow_array;
839 # update the database...
840 $query = "UPDATE reserves
843 WHERE biblionumber = ?
845 AND borrowernumber = ?
847 $sth = $dbh->prepare($query);
848 $sth->execute( $biblionumber, $resdate, $borrowernumber );
851 # now fix the priority on the others (if the priority wasn't
852 # already sorted!)....
853 unless ( $priority == 0 ) {
854 _FixPriority( $priority, $biblionumber );
858 =item ModReserveStatus
860 &ModReserveStatus($itemnumber, $newstatus);
862 Update the reserve status for the active (priority=0) reserve.
864 $itemnumber is the itemnumber the reserve is on
866 $newstatus is the new status.
870 sub ModReserveStatus {
872 #first : check if we have a reservation for this item .
873 my ($itemnumber, $newstatus) = @_;
874 my $dbh = C4::Context->dbh;
875 my $query = " UPDATE reserves
876 SET found=?,waitingdate = now()
881 my $sth_set = $dbh->prepare($query);
882 $sth_set->execute( $newstatus, $itemnumber );
886 =item ModReserveAffect
888 &ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend);
890 This function affect an item and a status for a given reserve
891 The itemnumber parameter is used to find the biblionumber.
892 with the biblionumber & the borrowernumber, we can affect the itemnumber
893 to the correct reserve.
895 if $transferToDo is not set, then the status is set to "Waiting" as well.
896 otherwise, a transfer is on the way, and the end of the transfer will
897 take care of the waiting status
900 sub ModReserveAffect {
901 my ( $itemnumber, $borrowernumber,$transferToDo ) = @_;
902 my $dbh = C4::Context->dbh;
904 # we want to attach $itemnumber to $borrowernumber, find the biblionumber
905 # attached to $itemnumber
906 my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?");
907 $sth->execute($itemnumber);
908 my ($biblionumber) = $sth->fetchrow;
909 # If we affect a reserve that has to be transfered, don't set to Waiting
916 WHERE borrowernumber = ?
918 AND reserves.cancellationdate IS NULL
919 AND (reserves.found <> 'F' OR reserves.found IS NULL)
923 # affect the reserve to Waiting as well.
930 WHERE borrowernumber = ?
932 AND reserves.cancellationdate IS NULL
933 AND (reserves.found <> 'F' OR reserves.found IS NULL)
936 $sth = $dbh->prepare($query);
937 $sth->execute( $itemnumber, $borrowernumber,$biblionumber);
942 =item ModReserveCancelAll
944 ($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber);
946 function to cancel reserv,check other reserves, and transfer document if it's necessary
950 sub ModReserveCancelAll {
953 my ( $itemnumber, $borrowernumber ) = @_;
955 #step 1 : cancel the reservation
956 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
958 #step 2 launch the subroutine of the others reserves
959 ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
961 return ( $messages, $nextreservinfo );
964 =item ModReserveMinusPriority
966 &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber)
968 Reduce the values of queuded list
972 sub ModReserveMinusPriority {
973 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
975 #first step update the value of the first person on reserv
976 my $dbh = C4::Context->dbh;
979 SET priority = 0 , itemnumber = ?
980 WHERE cancellationdate IS NULL
984 my $sth_upd = $dbh->prepare($query);
985 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
987 # second step update all others reservs
990 SET priority = priority-1
991 WHERE biblionumber = ?
993 AND cancellationdate IS NULL
995 $sth_upd = $dbh->prepare($query);
996 $sth_upd->execute( $biblionumber );
1003 &_FixPriority($biblio,$borrowernumber,$rank);
1005 Only used internally (so don't export it)
1006 Changed how this functions works #
1007 Now just gets an array of reserves in the rank order and updates them with
1008 the array index (+1 as array starts from 0)
1009 and if $rank is supplied will splice item from the array and splice it back in again
1010 in new priority rank
1015 my ( $biblio, $borrowernumber, $rank ) = @_;
1016 my $dbh = C4::Context->dbh;
1017 if ( $rank eq "del" ) {
1018 CancelReserve( $biblio, undef, $borrowernumber );
1020 if ( $rank eq "W" || $rank eq "0" ) {
1022 # make sure priority for waiting items is 0
1026 WHERE biblionumber = ?
1027 AND borrowernumber = ?
1028 AND cancellationdate IS NULL
1031 my $sth = $dbh->prepare($query);
1032 $sth->execute( $biblio, $borrowernumber );
1038 # FIXME adding a new security in returned elements for changing priority,
1039 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
1041 SELECT borrowernumber, reservedate, constrainttype
1043 WHERE biblionumber = ?
1044 AND cancellationdate IS NULL
1045 AND itemnumber IS NULL
1046 AND ((found <> 'F' and found <> 'W') or found is NULL)
1047 ORDER BY priority ASC
1049 my $sth = $dbh->prepare($query);
1050 $sth->execute($biblio);
1051 while ( my $line = $sth->fetchrow_hashref ) {
1052 push( @reservedates, $line );
1053 push( @priority, $line );
1056 # To find the matching index
1058 my $key = -1; # to allow for 0 to be a valid result
1059 for ( $i = 0 ; $i < @priority ; $i++ ) {
1060 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
1061 $key = $i; # save the index
1066 # if index exists in array then move it to new position
1067 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1068 my $new_rank = $rank -
1069 1; # $new_rank is what you want the new index to be in the array
1070 my $moving_item = splice( @priority, $key, 1 );
1071 splice( @priority, $new_rank, 0, $moving_item );
1074 # now fix the priority on those that are left....
1078 WHERE biblionumber = ?
1079 AND borrowernumber = ?
1083 $sth = $dbh->prepare($query);
1084 for ( my $j = 0 ; $j < @priority ; $j++ ) {
1087 $priority[$j]->{'borrowernumber'},
1088 $priority[$j]->{'reservedate'}
1094 =item _Findgroupreserve
1096 @results = &_Findgroupreserve($biblioitemnumber, $biblionumber);
1099 I don't know what this does, because I don't understand how reserve
1100 constraints work. I think the idea is that you reserve a particular
1101 biblio, and the constraint allows you to restrict it to a given
1102 biblioitem (e.g., if you want to borrow the audio book edition of "The
1103 Prophet", rather than the first available publication).
1105 C<&_Findgroupreserve> returns :
1106 C<@results> is an array of references-to-hash whose keys are mostly
1107 fields from the reserves table of the Koha database, plus
1108 C<biblioitemnumber>.
1112 sub _Findgroupreserve {
1113 my ( $bibitem, $biblio ) = @_;
1114 my $dbh = C4::Context->dbh;
1116 SELECT reserves.biblionumber AS biblionumber,
1117 reserves.borrowernumber AS borrowernumber,
1118 reserves.reservedate AS reservedate,
1119 reserves.branchcode AS branchcode,
1120 reserves.cancellationdate AS cancellationdate,
1121 reserves.found AS found,
1122 reserves.reservenotes AS reservenotes,
1123 reserves.priority AS priority,
1124 reserves.timestamp AS timestamp,
1125 reserveconstraints.biblioitemnumber AS biblioitemnumber,
1126 reserves.itemnumber AS itemnumber
1128 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
1129 WHERE reserves.biblionumber = ?
1130 AND ( ( reserveconstraints.biblioitemnumber = ?
1131 AND reserves.borrowernumber = reserveconstraints.borrowernumber
1132 AND reserves.reservedate =reserveconstraints.reservedate )
1133 OR reserves.constrainttype='a' )
1134 AND reserves.cancellationdate is NULL
1135 AND (reserves.found <> 'F' or reserves.found is NULL)
1137 my $sth = $dbh->prepare($query);
1138 $sth->execute( $biblio, $bibitem );
1140 while ( my $data = $sth->fetchrow_hashref ) {
1141 push( @results, $data );
1151 Koha Developement team <info@koha.org>