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
106 &ModReserveMinusPriority
115 AddReserve($branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$notes,$title,$checkitem,$found)
121 $branch, $borrowernumber, $biblionumber,
122 $constraint, $bibitems, $priority, $notes,
123 $title, $checkitem, $found
126 GetReserveFee($borrowernumber, $biblionumber, $constraint,
128 my $dbh = C4::Context->dbh;
129 my $const = lc substr( $constraint, 0, 1 );
130 my @datearr = localtime(time);
132 ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
135 # If the reserv had the waiting status, we had the value of the resdate
136 if ( $found eq 'W' ) {
137 $waitingdate = $resdate;
141 # updates take place here
143 my $nextacctno = &getnextacctno( $borrowernumber );
145 INSERT INTO accountlines
146 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
148 (?,?,now(),?,?,'Res',?)
150 my $usth = $dbh->prepare($query);
151 $usth->execute( $borrowernumber, $nextacctno, $fee,
152 "Reserve Charge - $title", $fee );
159 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
160 priority,reservenotes,itemnumber,found,waitingdate)
165 my $sth = $dbh->prepare($query);
167 $borrowernumber, $biblionumber, $resdate, $branch,
168 $const, $priority, $notes, $checkitem,
174 if ( ( $const eq "o" ) || ( $const eq "e" ) ) {
175 my $numitems = @$bibitems;
177 while ( $i < $numitems ) {
178 my $biblioitem = @$bibitems[$i];
180 INSERT INTO reserveconstraints
181 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
185 my $sth = $dbh->prepare("");
186 $sth->execute( $borrowernumber, $biblionumber, $resdate,
195 =item GetReservesFromBiblionumber
197 @borrowerreserv=&GetReserves($biblionumber,$itemnumber,$borrowernumber);
199 this function get the list of reservation for an C<$biblionumber>, C<$itemnumber> or C<$borrowernumber>
201 Only 1 argument has to be passed.
205 sub GetReservesFromBiblionumber {
206 my ( $biblionumber, $itemnumber, $borrowernumber ) = @_;
207 my $dbh = C4::Context->dbh;
209 # Find the desired items in the reserves
212 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 $sth = $dbh->prepare( "
560 SELECT borrowernumber,reservedate,itemnumber,waitingdate
563 AND cancellationdate IS NULL
566 ORDER BY waitingdate" );
567 $sth->execute($frombranch);
570 while ( my $data = $sth->fetchrow_hashref ) {
571 $transreserv[$i] = $data;
575 return (@transreserv);
580 ($status, $reserve) = &CheckReserves($itemnumber);
582 Find a book in the reserves.
584 C<$itemnumber> is the book's item number.
586 As I understand it, C<&CheckReserves> looks for the given item in the
587 reserves. If it is found, that's a match, and C<$status> is set to
590 Otherwise, it finds the most important item in the reserves with the
591 same biblio number as this book (I'm not clear on this) and returns it
592 with C<$status> set to C<Reserved>.
594 C<&CheckReserves> returns a two-element list:
596 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
598 C<$reserve> is the reserve item that matched. It is a
599 reference-to-hash whose keys are mostly the fields of the reserves
600 table in the Koha database.
605 my ( $item, $barcode ) = @_;
606 my $dbh = C4::Context->dbh;
609 my $qitem = $dbh->quote($item);
610 # Look up the item by itemnumber
612 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
614 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
615 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
616 WHERE itemnumber=$qitem
618 $sth = $dbh->prepare($query);
621 my $qbc = $dbh->quote($barcode);
622 # Look up the item by barcode
624 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
626 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
627 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
628 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
629 AND biblioitems.itemtype = itemtypes.itemtype
632 $sth = $dbh->prepare($query);
634 # FIXME - This function uses $item later on. Ought to set it here.
637 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
640 # if item is not for loan it cannot be reserved either.....
641 return ( 0, 0 ) if $notforloan;
643 # get the reserves...
644 # Find this item in the reserves
645 my @reserves = _Findgroupreserve( $bibitem, $biblio );
646 my $count = scalar @reserves;
648 # $priority and $highest are used to find the most important item
649 # in the list returned by &_Findgroupreserve. (The lower $priority,
650 # the more important the item.)
651 # $highest is the most important item we've seen so far.
652 my $priority = 10000000;
655 foreach my $res (@reserves) {
656 # FIXME - $item might be undefined or empty: the caller
657 # might be searching by barcode.
658 if ( $res->{'itemnumber'} == $item ) {
660 return ( "Waiting", $res );
663 # See if this item is more important than what we've got
665 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
667 $priority = $res->{'priority'};
674 # If we get this far, then no exact match was found. Print the
675 # most important item on the list. I think this tells us who's
676 # next in line to get this book.
677 if ($highest) { # FIXME - $highest might be undefined
678 $highest->{'itemnumber'} = $item;
679 return ( "Reserved", $highest );
688 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
692 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
693 cancel, but not both: if both are given, C<&CancelReserve> does
696 C<$borrowernumber> is the borrower number of the patron on whose
697 behalf the book was reserved.
699 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
700 priorities of the other people who are waiting on the book.
705 my ( $biblio, $item, $borr ) = @_;
706 my $dbh = C4::Context->dbh;
707 if ( $item and $borr ) {
708 # removing a waiting reserve record....
709 # update the database...
712 SET cancellationdate = now(),
716 AND borrowernumber = ?
718 my $sth = $dbh->prepare($query);
719 $sth->execute( $item, $borr );
723 # removing a reserve record....
724 # get the prioritiy on this record....
727 SELECT priority FROM reserves
728 WHERE biblionumber = ?
729 AND borrowernumber = ?
730 AND cancellationdate IS NULL
731 AND itemnumber IS NULL
732 AND (found <> 'F' OR found IS NULL)
734 my $sth = $dbh->prepare($query);
735 $sth->execute( $biblio, $borr );
736 ($priority) = $sth->fetchrow_array;
740 SET cancellationdate = now(),
743 WHERE biblionumber = ?
744 AND borrowernumber = ?
745 AND cancellationdate IS NULL
746 AND (found <> 'F' or found IS NULL)
749 # update the database, removing the record...
750 $sth = $dbh->prepare($query);
751 $sth->execute( $biblio, $borr );
754 # now fix the priority on the others....
755 _FixPriority( $priority, $biblio );
761 &ModReserve($rank,$biblio,$borrower,$branch)
766 #subroutine to update a reserve
767 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
768 return if $rank eq "W";
769 return if $rank eq "n";
770 my $dbh = C4::Context->dbh;
771 if ( $rank eq "del" ) {
774 SET cancellationdate=now()
775 WHERE biblionumber = ?
776 AND borrowernumber = ?
777 AND cancellationdate is NULL
778 AND (found <> 'F' or found is NULL)
780 my $sth = $dbh->prepare($query);
781 $sth->execute( $biblio, $borrower );
787 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
788 WHERE biblionumber = ?
789 AND borrowernumber = ?
790 AND cancellationdate is NULL
791 AND (found <> 'F' or found is NULL)
793 my $sth = $dbh->prepare($query);
794 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
796 _FixPriority( $biblio, $borrower, $rank);
802 &ModReserveFill($reserve);
804 Fill a reserve. If I understand this correctly, this means that the
805 reserved book has been found and given to the patron who reserved it.
807 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
808 whose keys are fields from the reserves table in the Koha database.
814 my $dbh = C4::Context->dbh;
815 # fill in a reserve record....
816 my $biblionumber = $res->{'biblionumber'};
817 my $borrowernumber = $res->{'borrowernumber'};
818 my $resdate = $res->{'reservedate'};
820 # get the priority on this record....
822 my $query = "SELECT priority
824 WHERE biblionumber = ?
825 AND borrowernumber = ?
826 AND reservedate = ?";
827 my $sth = $dbh->prepare($query);
828 $sth->execute( $biblionumber, $borrowernumber, $resdate );
829 ($priority) = $sth->fetchrow_array;
832 # update the database...
833 $query = "UPDATE reserves
836 WHERE biblionumber = ?
838 AND borrowernumber = ?
840 $sth = $dbh->prepare($query);
841 $sth->execute( $biblionumber, $resdate, $borrowernumber );
844 # now fix the priority on the others (if the priority wasn't
845 # already sorted!)....
846 unless ( $priority == 0 ) {
847 _FixPriority( $priority, $biblionumber );
851 =item ModReserveStatus
853 &ModReserveStatus($itemnumber, $newstatus);
855 Update the reserve status for the active (priority=0) reserve.
857 $itemnumber is the itemnumber the reserve is on
859 $newstatus is the new status.
863 sub ModReserveStatus {
865 #first : check if we have a reservation for this item .
866 my ($itemnumber, $newstatus) = @_;
867 my $dbh = C4::Context->dbh;
868 my $query = " UPDATE reserves
869 SET found=?,waitingdate = now()
874 my $sth_set = $dbh->prepare($query);
875 $sth_set->execute( $newstatus, $itemnumber );
879 =item ModReserveAffect
881 &ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend);
883 This function affect an item and a status for a given reserve
884 The itemnumber parameter is used to find the biblionumber.
885 with the biblionumber & the borrowernumber, we can affect the itemnumber
886 to the correct reserve.
888 if $transferToDo is not set, then the status is set to "Waiting" as well.
889 otherwise, a transfer is on the way, and the end of the transfer will
890 take care of the waiting status
893 sub ModReserveAffect {
894 my ( $itemnumber, $borrowernumber,$transferToDo ) = @_;
895 my $dbh = C4::Context->dbh;
897 # we want to attach $itemnumber to $borrowernumber, find the biblionumber
898 # attached to $itemnumber
899 my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?");
900 $sth->execute($itemnumber);
901 my ($biblionumber) = $sth->fetchrow;
902 # If we affect a reserve that has to be transfered, don't set to Waiting
909 WHERE borrowernumber = ?
911 AND reserves.cancellationdate IS NULL
912 AND (reserves.found <> 'F' OR reserves.found IS NULL)
916 # affect the reserve to Waiting as well.
923 WHERE borrowernumber = ?
925 AND reserves.cancellationdate IS NULL
926 AND (reserves.found <> 'F' OR reserves.found IS NULL)
929 $sth = $dbh->prepare($query);
930 $sth->execute( $itemnumber, $borrowernumber,$biblionumber);
935 =item ModReserveCancelAll
937 ($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber);
939 function to cancel reserv,check other reserves, and transfer document if it's necessary
943 sub ModReserveCancelAll {
946 my ( $itemnumber, $borrowernumber ) = @_;
948 #step 1 : cancel the reservation
949 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
951 #step 2 launch the subroutine of the others reserves
952 ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
954 return ( $messages, $nextreservinfo );
957 =item ModReserveMinusPriority
959 &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber)
961 Reduce the values of queuded list
965 sub ModReserveMinusPriority {
966 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
968 #first step update the value of the first person on reserv
969 my $dbh = C4::Context->dbh;
972 SET priority = 0 , itemnumber = ?
973 WHERE cancellationdate IS NULL
977 my $sth_upd = $dbh->prepare($query);
978 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
980 # second step update all others reservs
983 SET priority = priority-1
984 WHERE biblionumber = ?
986 AND cancellationdate IS NULL
988 $sth_upd = $dbh->prepare($query);
989 $sth_upd->execute( $biblionumber );
996 &_FixPriority($biblio,$borrowernumber,$rank);
998 Only used internally (so don't export it)
999 Changed how this functions works #
1000 Now just gets an array of reserves in the rank order and updates them with
1001 the array index (+1 as array starts from 0)
1002 and if $rank is supplied will splice item from the array and splice it back in again
1003 in new priority rank
1008 my ( $biblio, $borrowernumber, $rank ) = @_;
1009 my $dbh = C4::Context->dbh;
1010 if ( $rank eq "del" ) {
1011 CancelReserve( $biblio, undef, $borrowernumber );
1013 if ( $rank eq "W" || $rank eq "0" ) {
1015 # make sure priority for waiting items is 0
1019 WHERE biblionumber = ?
1020 AND borrowernumber = ?
1021 AND cancellationdate IS NULL
1024 my $sth = $dbh->prepare($query);
1025 $sth->execute( $biblio, $borrowernumber );
1031 # FIXME adding a new security in returned elements for changing priority,
1032 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
1034 SELECT borrowernumber, reservedate, constrainttype
1036 WHERE biblionumber = ?
1037 AND cancellationdate IS NULL
1038 AND itemnumber IS NULL
1039 AND ((found <> 'F' and found <> 'W') or found is NULL)
1040 ORDER BY priority ASC
1042 my $sth = $dbh->prepare($query);
1043 $sth->execute($biblio);
1044 while ( my $line = $sth->fetchrow_hashref ) {
1045 push( @reservedates, $line );
1046 push( @priority, $line );
1049 # To find the matching index
1051 my $key = -1; # to allow for 0 to be a valid result
1052 for ( $i = 0 ; $i < @priority ; $i++ ) {
1053 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
1054 $key = $i; # save the index
1059 # if index exists in array then move it to new position
1060 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1061 my $new_rank = $rank -
1062 1; # $new_rank is what you want the new index to be in the array
1063 my $moving_item = splice( @priority, $key, 1 );
1064 splice( @priority, $new_rank, 0, $moving_item );
1067 # now fix the priority on those that are left....
1071 WHERE biblionumber = ?
1072 AND borrowernumber = ?
1076 $sth = $dbh->prepare($query);
1077 for ( my $j = 0 ; $j < @priority ; $j++ ) {
1080 $priority[$j]->{'borrowernumber'},
1081 $priority[$j]->{'reservedate'}
1087 =item _Findgroupreserve
1089 @results = &_Findgroupreserve($biblioitemnumber, $biblionumber);
1092 I don't know what this does, because I don't understand how reserve
1093 constraints work. I think the idea is that you reserve a particular
1094 biblio, and the constraint allows you to restrict it to a given
1095 biblioitem (e.g., if you want to borrow the audio book edition of "The
1096 Prophet", rather than the first available publication).
1098 C<&_Findgroupreserve> returns :
1099 C<@results> is an array of references-to-hash whose keys are mostly
1100 fields from the reserves table of the Koha database, plus
1101 C<biblioitemnumber>.
1105 sub _Findgroupreserve {
1106 my ( $bibitem, $biblio ) = @_;
1107 my $dbh = C4::Context->dbh;
1109 SELECT reserves.biblionumber AS biblionumber,
1110 reserves.borrowernumber AS borrowernumber,
1111 reserves.reservedate AS reservedate,
1112 reserves.branchcode AS branchcode,
1113 reserves.cancellationdate AS cancellationdate,
1114 reserves.found AS found,
1115 reserves.reservenotes AS reservenotes,
1116 reserves.priority AS priority,
1117 reserves.timestamp AS timestamp,
1118 reserveconstraints.biblioitemnumber AS biblioitemnumber,
1119 reserves.itemnumber AS itemnumber
1121 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
1122 WHERE reserves.biblionumber = ?
1123 AND ( ( reserveconstraints.biblioitemnumber = ?
1124 AND reserves.borrowernumber = reserveconstraints.borrowernumber
1125 AND reserves.reservedate =reserveconstraints.reservedate )
1126 OR reserves.constrainttype='a' )
1127 AND reserves.cancellationdate is NULL
1128 AND (reserves.found <> 'F' or reserves.found is NULL)
1130 my $sth = $dbh->prepare($query);
1131 $sth->execute( $biblio, $bibitem );
1133 while ( my $data = $sth->fetchrow_hashref ) {
1134 push( @results, $data );
1144 Koha Developement team <info@koha.org>