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
30 use C4::Circulation::Circ2;
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::Reserves2 - Koha functions for dealing with reservation.
48 this modules provides somes functions to deal with reservations.
58 # FIXME Take out CalcReserveFee after it can be removed from opac-reserves.pl
75 &GetFirstReserveDateFromItem
76 &CountReservesFromBorrower
81 # make all your functions, whether exported or not;
85 ($messages,$nextreservinfo) = &GlobalCancel($itemnumber,$borrowernumber);
87 New op dev for the circulation based on item, global is a function to cancel reserv,check other reserves, and transfer document if it's necessary
95 my ( $itemnumber, $borrowernumber ) = @_;
97 #step 1 : cancel the reservation
98 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
100 #step 2 launch the subroutine of the others reserves
101 ( $messages, $nextreservinfo ) = OtherReserves($itemnumber);
103 return ( $messages, $nextreservinfo );
108 ($messages,$nextreservinfo)=$OtherReserves(itemnumber);
110 Check queued list of this document and check if this document must be transfered
116 my ($itemnumber) = @_;
119 my ( $restype, $checkreserves ) = CheckReserves($itemnumber);
120 if ($checkreserves) {
121 my $iteminfo = C4::Circulation::Circ2::getiteminformation($itemnumber,undef);
122 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
123 $messages->{'transfert'} = $checkreserves->{'branchcode'};
124 #minus priorities of others reservs
127 $checkreserves->{'borrowernumber'},
128 $iteminfo->{'biblionumber'}
131 #launch the subroutine dotransfer
132 C4::Circulation::Circ2::dotransfer(
134 $iteminfo->{'holdingbranch'},
135 $checkreserves->{'branchcode'}
140 #step 2b : case of a reservation on the same branch, set the waiting status
142 $messages->{'waiting'} = 1;
145 $checkreserves->{'borrowernumber'},
146 $iteminfo->{'biblionumber'}
148 SetWaitingStatus($itemnumber);
151 $nextreservinfo = $checkreserves->{'borrowernumber'};
154 return ( $messages, $nextreservinfo );
159 &MinusPriority($itemnumber,$borrowernumber,$biblionumber)
161 Reduce the values of queuded list
167 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
169 #first step update the value of the first person on reserv
170 my $dbh = C4::Context->dbh;
173 SET priority = 0 , itemnumber = ?
174 WHERE cancellationdate IS NULL
178 my $sth_upd = $dbh->prepare($query);
179 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
181 # second step update all others reservs
183 SELECT priority,borrowernumber,biblionumber,reservedate
187 AND cancellationdate IS NULL
189 my $sth_oth = $dbh->prepare($query);
190 $sth_oth->execute($biblionumber);
191 while ( my ( $priority, $borrowernumber, $biblionumber, $reservedate ) =
192 $sth_oth->fetchrow_array )
198 WHERE biblionumber = ?
199 AND borrowernumber = ?
202 my $sth_upd_oth = $dbh->prepare($query);
203 $sth_upd_oth->execute( $priority, $biblionumber, $borrowernumber,
205 $sth_upd_oth->finish;
210 =item SetWaitingStatus
212 &SetWaitingStatus($itemnumber);
214 we check if we have a reserves with itemnumber (New op system of reserves), if we found one, we update the status of the reservation when we have : 'priority' = 0, and we have an itemnumber
218 sub SetWaitingStatus {
220 #first : check if we have a reservation for this item .
221 my ($itemnumber) = @_;
222 my $dbh = C4::Context->dbh;
224 SELECT priority,borrowernumber
227 AND cancellationdate IS NULL
228 AND found IS NULL AND priority='0'
230 my $sth_find = $dbh->prepare($query);
231 $sth_find->execute($itemnumber);
232 my ( $priority, $borrowernumber ) = $sth_find->fetchrow_array;
234 return unless $borrowernumber;
236 # step 2 : if we have a borrowernumber, we update the value found to 'W' to notify the borrower
239 SET found='W',waitingdate = now()
240 WHERE borrowernumber=?
244 my $sth_set = $dbh->prepare($query);
245 $sth_set->execute( $borrowernumber, $itemnumber );
249 =item GetReservations
251 @borrowerreserv=&GetReservations($itemnumber,$borrowernumber);
253 this function get the list of reservation for an C<$itemnumber> or C<$borrowernumber>
254 given on input arg. You should give $itemnumber OR $borrowernumber but not both.
258 sub GetReservations {
259 my ( $itemnumber, $borrowernumber ) = @_;
261 my $dbh = C4::Context->dbh;
263 SELECT reservedate,borrowernumber
266 AND cancellationdate IS NULL
267 AND (found <> 'F' OR found IS NULL)
269 my $sth_res = $dbh->prepare($query);
270 $sth_res->execute($itemnumber);
271 my ( $reservedate, $borrowernumber ) = $sth_res->fetchrow_array;
272 return ( $reservedate, $borrowernumber );
274 if ($borrowernumber) {
275 my $dbh = C4::Context->dbh;
279 WHERE borrowernumber=?
280 AND cancellationdate IS NULL
281 AND (found != 'F' or found is null)
285 my $sth_find = $dbh->prepare($query);
286 $sth_find->execute($borrowernumber);
288 while ( my $data = $sth_find->fetchrow_hashref ) {
289 push @borrowerreserv, $data;
291 return @borrowerreserv;
297 $results = &FindReserves($biblionumber, $borrowernumber);
299 Looks books up in the reserves. C<$biblionumber> is the biblionumber
300 of the book to look up. C<$borrowernumber> is the borrower number of a
301 patron whose books to look up.
303 Either C<$biblionumber> or C<$borrowernumber> may be the empty string,
304 but not both. If both are specified, C<&FindReserves> looks up the
305 given book for the given patron. If only C<$biblionumber> is
306 specified, C<&FindReserves> looks up that book for all patrons. If
307 only C<$borrowernumber> is specified, C<&FindReserves> looks up all of
308 that patron's reserves. If neither is specified, C<&FindReserves>
311 For each book thus found, C<&FindReserves> checks the reserve
312 constraints and does something I don't understand.
314 C<&FindReserves> returns a two-element array:
316 C<$results> is a reference to an array of references of hashes. Each hash
317 has for keys a list of column from reserves table (see details in function).
323 my ( $biblionumber, $bor ) = @_;
324 my $dbh = C4::Context->dbh;
327 # Find the desired items in the reserves
330 timestamp AS rtimestamp,
339 WHERE cancellationdate IS NULL
340 AND (found <> \'F\' OR found IS NULL)
343 if ( $biblionumber ne '' ) {
347 push @bind, $biblionumber;
352 AND borrowernumber = ?
360 my $sth = $dbh->prepare($query);
361 $sth->execute(@bind);
364 while ( my $data = $sth->fetchrow_hashref ) {
366 # FIXME - What is this if-statement doing? How do constraints work?
367 if ( $data->{constrainttype} eq 'o' ) {
369 SELECT biblioitemnumber
370 FROM reserveconstraints
371 WHERE biblionumber = ?
372 AND borrowernumber = ?
375 my $csth = $dbh->prepare($query);
376 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
377 $data->{reservedate}, );
380 while ( my $bibitemnos = $csth->fetchrow_array ) {
381 push( @bibitemno, $bibitemnos );
383 my $count = @bibitemno;
385 # if we have two or more different specific itemtypes
386 # reserved by same person on same day
389 $bdata = GetBiblioItemData( $bibitemno[$i] );
394 # Look up the book we just found.
395 $bdata = GetBiblioItemData( $bibitemno[0] );
399 # Add the results of this latest search to the current
401 # FIXME - An 'each' would probably be more efficient.
402 foreach my $key ( keys %$bdata ) {
403 $data->{$key} = $bdata->{$key};
406 push @results, $data;
410 return ( $#results + 1, \@results );
413 #-------------------------------------------------------------------------------------
415 =item CountReservesFromBorrower
417 $number = &CountReservesFromBorrower($borrowernumber);
419 this function returns the number of reservation for a borrower given on input arg.
423 sub CountReservesFromBorrower {
424 my ($borrowernumber) = @_;
426 my $dbh = C4::Context->dbh;
429 SELECT COUNT(*) AS counter
431 WHERE borrowernumber = ?
432 AND cancellationdate IS NULL
433 AND (found != \'F\' OR found IS NULL)
435 my $sth = $dbh->prepare($query);
436 $sth->execute($borrowernumber);
437 my $row = $sth->fetchrow_hashref;
440 return $row->{counter};
443 #-------------------------------------------------------------------------------------
445 =item GetFirstReserveDateFromItem
447 $date = GetFirstReserveDateFromItem($itemnumber)
449 this function returns the first date a item has been reserved.
453 sub GetFirstReserveDateFromItem {
454 my ($itemnumber) = @_;
456 my $dbh = C4::Context->dbh;
464 AND cancellationdate IS NULL
465 AND (found != \'F\' OR found IS NULL)
467 my $sth = $dbh->prepare($query);
468 $sth->execute($itemnumber);
469 my $row = $sth->fetchrow_hashref;
471 return ($row->{reservedate},$row->{borrowernumber},$row->{branchcode});
474 #-------------------------------------------------------------------------------------
478 ($status, $reserve) = &CheckReserves($itemnumber, $barcode);
480 Find a book in the reserves.
482 C<$itemnumber> is the book's item number. C<$barcode> is its barcode.
483 Either one, but not both, may be false. If both are specified,
484 C<&CheckReserves> uses C<$itemnumber>.
486 $itemnubmer can be false, in which case uses the barcode. (Never uses
487 both. $itemnumber gets priority).
489 As I understand it, C<&CheckReserves> looks for the given item in the
490 reserves. If it is found, that's a match, and C<$status> is set to
493 Otherwise, it finds the most important item in the reserves with the
494 same biblio number as this book (I'm not clear on this) and returns it
495 with C<$status> set to C<Reserved>.
497 C<&CheckReserves> returns a two-element list:
499 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
501 C<$reserve> is the reserve item that matched. It is a
502 reference-to-hash whose keys are mostly the fields of the reserves
503 table in the Koha database.
509 my ( $item, $barcode ) = @_;
510 my $dbh = C4::Context->dbh;
513 my $qitem = $dbh->quote($item);
514 # Look up the item by itemnumber
516 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
517 FROM items, biblioitems, itemtypes
518 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
519 AND biblioitems.itemtype = itemtypes.itemtype
520 AND itemnumber=$qitem
522 $sth = $dbh->prepare($query);
525 my $qbc = $dbh->quote($barcode);
526 # Look up the item by barcode
528 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
529 FROM items, biblioitems, itemtypes
530 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
531 AND biblioitems.itemtype = itemtypes.itemtype
534 $sth = $dbh->prepare($query);
536 # FIXME - This function uses $item later on. Ought to set it here.
539 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
542 # if item is not for loan it cannot be reserved either.....
543 return ( 0, 0 ) if $notforloan;
545 # get the reserves...
546 # Find this item in the reserves
547 my @reserves = Findgroupreserve( $bibitem, $biblio );
548 my $count = scalar @reserves;
550 # $priority and $highest are used to find the most important item
551 # in the list returned by &Findgroupreserve. (The lower $priority,
552 # the more important the item.)
553 # $highest is the most important item we've seen so far.
554 my $priority = 10000000;
557 foreach my $res (@reserves) {
558 # FIXME - $item might be undefined or empty: the caller
559 # might be searching by barcode.
560 if ( $res->{'itemnumber'} == $item ) {
562 return ( "Waiting", $res );
565 # See if this item is more important than what we've got
567 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
569 $priority = $res->{'priority'};
576 # If we get this far, then no exact match was found. Print the
577 # most important item on the list. I think this tells us who's
578 # next in line to get this book.
579 if ($highest) { # FIXME - $highest might be undefined
580 $highest->{'itemnumber'} = $item;
581 return ( "Reserved", $highest );
588 #-------------------------------------------------------------------------------------
592 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
596 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
597 cancel, but not both: if both are given, C<&CancelReserve> does
600 C<$borrowernumber> is the borrower number of the patron on whose
601 behalf the book was reserved.
603 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
604 priorities of the other people who are waiting on the book.
610 my ( $biblio, $item, $borr ) = @_;
611 my $dbh = C4::Context->dbh;
612 if ( ( $item and $borr ) and ( not $biblio ) ) {
613 # removing a waiting reserve record....
614 # update the database...
617 SET cancellationdate = now(),
621 AND borrowernumber = ?
623 my $sth = $dbh->prepare($query);
624 $sth->execute( $item, $borr );
627 if ( ( $biblio and $borr ) and ( not $item ) ) {
628 # removing a reserve record....
629 # get the prioritiy on this record....
632 SELECT priority FROM reserves
633 WHERE biblionumber = ?
634 AND borrowernumber = ?
635 AND cancellationdate IS NULL
636 AND itemnumber IS NULL
637 AND (found <> 'F' OR found IS NULL)
639 my $sth = $dbh->prepare($query);
640 $sth->execute( $biblio, $borr );
641 ($priority) = $sth->fetchrow_array;
645 SET cancellationdate = now(),
648 WHERE biblionumber = ?
649 AND borrowernumber = ?
650 AND cancellationdate IS NULL
651 AND (found <> 'F' or found IS NULL)
654 # update the database, removing the record...
655 $sth = $dbh->prepare($query);
656 $sth->execute( $biblio, $borr );
659 # now fix the priority on the others....
660 FixPriority( $priority, $biblio );
664 #-------------------------------------------------------------------------------------
668 &FillReserve($reserve);
670 Fill a reserve. If I understand this correctly, this means that the
671 reserved book has been found and given to the patron who reserved it.
673 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
674 whose keys are fields from the reserves table in the Koha database.
681 my $dbh = C4::Context->dbh;
682 # fill in a reserve record....
683 my $qbiblio = $res->{'biblionumber'};
684 my $borr = $res->{'borrowernumber'};
685 my $resdate = $res->{'reservedate'};
687 # get the priority on this record....
689 my $query = "SELECT priority
691 WHERE biblionumber = ?
692 AND borrowernumber = ?
693 AND reservedate = ?";
694 my $sth = $dbh->prepare($query);
695 $sth->execute( $qbiblio, $borr, $resdate );
696 ($priority) = $sth->fetchrow_array;
699 # update the database...
700 $query = "UPDATE reserves
703 WHERE biblionumber = ?
705 AND borrowernumber = ?
707 $sth = $dbh->prepare($query);
708 $sth->execute( $qbiblio, $resdate, $borr );
711 # now fix the priority on the others (if the priority wasn't
712 # already sorted!)....
713 unless ( $priority == 0 ) {
714 FixPriority( $priority, $qbiblio );
718 #-------------------------------------------------------------------------------------
722 &FixPriority($biblio,$borrowernumber,$rank);
724 Only used internally (so don't export it)
725 Changed how this functions works #
726 Now just gets an array of reserves in the rank order and updates them with
727 the array index (+1 as array starts from 0)
728 and if $rank is supplied will splice item from the array and splice it back in again
734 my ( $biblio, $borrowernumber, $rank ) = @_;
735 my $dbh = C4::Context->dbh;
736 if ( $rank eq "del" ) {
737 CancelReserve( $biblio, undef, $borrowernumber );
739 if ( $rank eq "W" || $rank eq "0" ) {
741 # make sure priority for waiting items is 0
745 WHERE biblionumber = ?
746 AND borrowernumber = ?
747 AND cancellationdate IS NULL
750 my $sth = $dbh->prepare($query);
751 $sth->execute( $biblio, $borrowernumber );
757 # FIXME adding a new security in returned elements for changing priority,
758 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
760 SELECT borrowernumber, reservedate, constrainttype
762 WHERE biblionumber = ?
763 AND cancellationdate IS NULL
764 AND itemnumber IS NULL
765 AND ((found <> 'F' and found <> 'W') or found is NULL)
766 ORDER BY priority ASC
768 my $sth = $dbh->prepare($query);
769 $sth->execute($biblio);
770 while ( my $line = $sth->fetchrow_hashref ) {
771 push( @reservedates, $line );
772 push( @priority, $line );
775 # To find the matching index
777 my $key = -1; # to allow for 0 to be a valid result
778 for ( $i = 0 ; $i < @priority ; $i++ ) {
779 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
780 $key = $i; # save the index
785 # if index exists in array then move it to new position
786 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
787 my $new_rank = $rank -
788 1; # $new_rank is what you want the new index to be in the array
789 my $moving_item = splice( @priority, $key, 1 );
790 splice( @priority, $new_rank, 0, $moving_item );
793 # now fix the priority on those that are left....
797 WHERE biblionumber = ?
798 AND borrowernumber = ?
802 $sth = $dbh->prepare($query);
803 for ( my $j = 0 ; $j < @priority ; $j++ ) {
806 $priority[$j]->{'borrowernumber'},
807 $priority[$j]->{'reservedate'}
813 #-------------------------------------------------------------------------------------
817 branchcode = &ReserveWaiting($item,$borr);
818 this function set FOUND to 'W' for Waiting into the database.
823 my ( $item, $borr,$diffBranchSend ) = @_;
824 my $dbh = C4::Context->dbh;
826 # get priority and biblionumber....
828 SELECT reserves.priority as priority,
829 reserves.biblionumber as biblionumber,
830 reserves.branchcode as branchcode,
831 reserves.timestamp as timestamp
833 WHERE reserves.biblionumber = items.biblionumber
834 AND items.itemnumber = ?
835 AND reserves.borrowernumber = ?
836 AND reserves.cancellationdate IS NULL
837 AND (reserves.found <> 'F' OR reserves.found IS NULL)
839 my $sth = $dbh->prepare($query);
840 $sth->execute( $item, $borr );
841 my $data = $sth->fetchrow_hashref;
843 my $biblio = $data->{'biblionumber'};
844 my $timestamp = $data->{'timestamp'};
846 # update reserves record....
847 if ($diffBranchSend) {
852 WHERE borrowernumber = ?
864 WHERE borrowernumber = ?
869 $sth = $dbh->prepare($query);
870 $sth->execute( $item, $borr, $biblio, $timestamp );
873 # now fix up the remaining priorities....
874 FixPriority( $data->{'priority'}, $biblio );
875 my $branchcode = $data->{'branchcode'};
879 #-------------------------------------------------------------------------------------
881 =item GetWaitingReserves
883 \@itemswaiting=GetWaitingReserves($borr);
885 this funtion fetch the list of waiting reserves from database.
889 sub GetWaitingReserves {
891 my $dbh = C4::Context->dbh;
896 WHERE borrowernumber = ?
897 AND reserves.found = 'W'
898 AND cancellationdate IS NULL
900 my $sth = $dbh->prepare($query);
901 $sth->execute($borr);
902 while ( my $data = $sth->fetchrow_hashref ) {
903 push( @itemswaiting, $data );
906 return \@itemswaiting;
909 #-------------------------------------------------------------------------------------
911 =item Findgroupreserve
913 @results = &Findgroupreserve($biblioitemnumber, $biblionumber);
916 I don't know what this does, because I don't understand how reserve
917 constraints work. I think the idea is that you reserve a particular
918 biblio, and the constraint allows you to restrict it to a given
919 biblioitem (e.g., if you want to borrow the audio book edition of "The
920 Prophet", rather than the first available publication).
922 C<&Findgroupreserve> returns :
923 C<@results> is an array of references-to-hash whose keys are mostly
924 fields from the reserves table of the Koha database, plus
930 sub Findgroupreserve {
931 my ( $bibitem, $biblio ) = @_;
932 my $dbh = C4::Context->dbh;
934 SELECT reserves.biblionumber AS biblionumber,
935 reserves.borrowernumber AS borrowernumber,
936 reserves.reservedate AS reservedate,
937 reserves.branchcode AS branchcode,
938 reserves.cancellationdate AS cancellationdate,
939 reserves.found AS found,
940 reserves.reservenotes AS reservenotes,
941 reserves.priority AS priority,
942 reserves.timestamp AS timestamp,
943 reserveconstraints.biblioitemnumber AS biblioitemnumber,
944 reserves.itemnumber AS itemnumber
946 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
947 WHERE reserves.biblionumber = ?
948 AND ( ( reserveconstraints.biblioitemnumber = ?
949 AND reserves.borrowernumber = reserveconstraints.borrowernumber
950 AND reserves.reservedate =reserveconstraints.reservedate )
951 OR reserves.constrainttype='a' )
952 AND reserves.cancellationdate is NULL
953 AND (reserves.found <> 'F' or reserves.found is NULL)
955 my $sth = $dbh->prepare($query);
956 $sth->execute( $biblio, $bibitem );
958 while ( my $data = $sth->fetchrow_hashref ) {
959 push( @results, $data );
967 CreateReserve($env,$branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$notes,$title,$checkitem,$found)
969 FIXME - A somewhat different version of this function appears in
970 C4::Reserves. Pick one and stick with it.
976 $env, $branch, $borrowernumber, $biblionumber,
977 $constraint, $bibitems, $priority, $notes,
978 $title, $checkitem, $found
981 if ( $library_name =~ /Horowhenua/ ) {
983 CalcHLTReserveFee( $env, $borrowernumber, $biblionumber, $constraint,
988 CalcReserveFee( $env, $borrowernumber, $biblionumber, $constraint,
991 my $dbh = C4::Context->dbh;
992 my $const = lc substr( $constraint, 0, 1 );
993 my @datearr = localtime(time);
995 ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
998 # If the reserv had the waiting status, we had the value of the resdate
999 if ( $found eq 'W' ) {
1000 $waitingdate = $resdate;
1004 # updates take place here
1006 my $nextacctno = &getnextacctno( $env, $borrowernumber, $dbh );
1008 INSERT INTO accountlines
1009 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
1011 (?,?,now(),?,?,'Res',?)
1013 my $usth = $dbh->prepare($query);
1014 $usth->execute( $borrowernumber, $nextacctno, $fee,
1015 "Reserve Charge - $title", $fee );
1019 #if ($const eq 'a'){
1021 INSERT INTO reserves
1022 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
1023 priority,reservenotes,itemnumber,found,waitingdate)
1028 my $sth = $dbh->prepare($query);
1030 $borrowernumber, $biblionumber, $resdate, $branch,
1031 $const, $priority, $notes, $checkitem,
1032 $found, $waitingdate
1037 if ( ( $const eq "o" ) || ( $const eq "e" ) ) {
1038 my $numitems = @$bibitems;
1040 while ( $i < $numitems ) {
1041 my $biblioitem = @$bibitems[$i];
1043 INSERT INTO reserveconstraints
1044 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
1048 my $sth = $dbh->prepare("");
1049 $sth->execute( $borrowernumber, $biblionumber, $resdate,
1058 # FIXME - A functionally identical version of this function appears in
1059 # C4::Reserves. Pick one and stick with it.
1060 # XXX - Internal use only
1061 # FIXME - opac-reserves.pl need to use it, temporarily put into @EXPORT
1063 sub CalcReserveFee {
1064 my ( $env, $borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
1067 my $dbh = C4::Context->dbh;
1068 my $const = lc substr( $constraint, 0, 1 );
1070 SELECT * FROM borrowers,categories
1071 WHERE borrowernumber = ?
1072 AND borrowers.categorycode = categories.categorycode
1074 my $sth = $dbh->prepare($query);
1075 $sth->execute($borrowernumber);
1076 my $data = $sth->fetchrow_hashref;
1078 my $fee = $data->{'reservefee'};
1079 my $cntitems = @- > $bibitems;
1083 # check for items on issue
1084 # first find biblioitem records
1086 my $sth1 = $dbh->prepare(
1087 "SELECT * FROM biblio,biblioitems
1088 WHERE (biblio.biblionumber = ?)
1089 AND (biblio.biblionumber = biblioitems.biblionumber)"
1091 $sth1->execute($biblionumber);
1092 while ( my $data1 = $sth1->fetchrow_hashref ) {
1093 if ( $const eq "a" ) {
1094 push @biblioitems, $data1;
1099 while ( $x < $cntitems ) {
1100 if ( @$bibitems->{'biblioitemnumber'} ==
1101 $data->{'biblioitemnumber'} )
1107 if ( $const eq 'o' ) {
1108 if ( $found == 1 ) {
1109 push @biblioitems, $data1;
1113 if ( $found == 0 ) {
1114 push @biblioitems, $data1;
1120 my $cntitemsfound = @biblioitems;
1124 while ( $x < $cntitemsfound ) {
1125 my $bitdata = $biblioitems[$x];
1126 my $sth2 = $dbh->prepare(
1127 "SELECT * FROM items
1128 WHERE biblioitemnumber = ?"
1130 $sth2->execute( $bitdata->{'biblioitemnumber'} );
1131 while ( my $itdata = $sth2->fetchrow_hashref ) {
1132 my $sth3 = $dbh->prepare(
1133 "SELECT * FROM issues
1134 WHERE itemnumber = ?
1135 AND returndate IS NULL"
1137 $sth3->execute( $itdata->{'itemnumber'} );
1138 if ( my $isdata = $sth3->fetchrow_hashref ) {
1146 if ( $allissued == 0 ) {
1148 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
1149 $rsth->execute($biblionumber);
1150 if ( my $rdata = $rsth->fetchrow_hashref ) {
1162 # The following are junior and young adult item types that should not incur a
1165 # Juniors: BJC, BJCN, BJF, BJK, BJM, BJN, BJP, BJSF, BJSN, DJ, DJP, FJ, JVID,
1166 # VJ, VJP, PJ, TJ, TJP, VJ, VJP.
1168 # Young adults: BYF, BYN, BYP, DY, DYP, PY, PYP, TY, TYP, VY, VYP.
1170 # All other item types should incur a reserve charge.
1171 sub CalcHLTReserveFee {
1172 my ( $env, $borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
1173 my $dbh = C4::Context->dbh;
1174 my $sth = $dbh->prepare(
1175 "SELECT * FROM borrowers,categories
1176 WHERE (borrowernumber = ?)
1177 AND (borrowers.categorycode = categories.categorycode)"
1179 $sth->execute($borrowernumber);
1180 my $data = $sth->fetchrow_hashref;
1182 my $fee = $data->{'reservefee'};
1186 qw/BJC BJCN BJF BJK BJM BJN BJP BJSF BJSN DJ DJP FJ NJ CJ VJ VJP PJ TJ TJP BYF BYN BYP DY DYP PY PYP TY TYP VY VYP/;
1187 $sth = $dbh->prepare(
1188 "SELECT * FROM biblio,biblioitems
1189 WHERE (biblio.biblionumber = ?)
1190 AND (biblio.biblionumber = biblioitems.biblionumber)"
1192 $sth->execute($biblionumber);
1193 $data = $sth->fetchrow_hashref;
1194 my $itemtype = $data->{'itemtype'};
1195 for ( my $i = 0 ; $i < @nocharge ; $i++ ) {
1196 if ( $itemtype eq $nocharge[$i] ) {
1202 if ( $matchno > 0 ) {
1208 =item GetNextAccountNumber
1210 GetNextAccountNumber()
1214 sub GetNextAccountNumber {
1215 my ( $env, $borrowernumber, $dbh ) = @_;
1216 my $nextaccntno = 1;
1217 my $sth = $dbh->prepare(
1218 "select * from accountlines
1219 where (borrowernumber = ?)
1220 order by accountno desc"
1222 $sth->execute($borrowernumber);
1223 if ( my $accdata = $sth->fetchrow_hashref ) {
1224 $nextaccntno = $accdata->{'accountno'} + 1;
1227 return ($nextaccntno);
1230 #-------------------------------------------------------------------------------------
1234 &UpdateReserve($rank,$biblio,$borrower,$branch)
1239 #subroutine to update a reserve
1240 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
1241 return if $rank eq "W";
1242 return if $rank eq "n";
1243 my $dbh = C4::Context->dbh;
1244 if ( $rank eq "del" ) {
1247 SET cancellationdate=now()
1248 WHERE biblionumber = ?
1249 AND borrowernumber = ?
1250 AND cancellationdate is NULL
1251 AND (found <> 'F' or found is NULL)
1253 my $sth = $dbh->prepare($query);
1254 $sth->execute( $biblio, $borrower );
1260 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
1261 WHERE biblionumber = ?
1262 AND borrowernumber = ?
1263 AND cancellationdate is NULL
1264 AND (found <> 'F' or found is NULL)
1266 my $sth = $dbh->prepare($query);
1267 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
1269 FixPriority( $biblio, $borrower, $rank);
1273 =item GetReserveTitle
1275 $data = GetReserveTitle($biblio,$bor,$date,$timestamp);
1279 sub GetReserveTitle {
1280 my ( $biblio, $bor, $date, $timestamp ) = @_;
1281 my $dbh = C4::Context->dbh;
1284 FROM reserveconstraints,biblioitems
1285 WHERE reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber
1286 AND reserveconstraints.biblionumber=?
1287 AND reserveconstraints.borrowernumber = ?
1288 AND reserveconstraints.reservedate=?
1289 AND reserveconstraints.timestamp=?
1291 my $sth = $dbh->prepare($query);
1292 $sth->execute( $biblio, $bor, $date, $timestamp );
1293 my $data = $sth->fetchrow_hashref;
1298 =item FindReservesInQueue
1300 $results = &FindReservesInQueue($biblionumber);
1302 Simple variant of FindReserves, exept the result is now displaying only the queue list of reservations with the same biblionumber (At this time only displayed in request.pl)
1304 C<&FindReservesInQueue> returns a two-element array:
1306 C<$results> is a reference to an array of references of hashes. Each hash
1307 has for keys a list of column from reserves table (see details in function).
1313 sub FindReservesInQueue {
1314 my ($biblionumber) = @_;
1315 my $dbh = C4::Context->dbh;
1317 # Find the desired items in the reserves
1320 timestamp AS rtimestamp,
1329 WHERE cancellationdate IS NULL
1330 AND biblionumber = ?
1331 AND (found <> \'F\' OR found IS NULL)
1332 AND priority <> \'0\'
1335 my $sth = $dbh->prepare($query);
1336 $sth->execute($biblionumber);
1339 while ( my $data = $sth->fetchrow_hashref ) {
1341 # FIXME - What is this if-statement doing? How do constraints work?
1342 if ( $data->{constrainttype} eq 'o' ) {
1344 SELECT biblioitemnumber
1345 FROM reserveconstraints
1346 WHERE biblionumber = ?
1347 AND borrowernumber = ?
1350 my $csth = $dbh->prepare($query);
1351 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
1352 $data->{reservedate}, );
1355 while ( my $bibitemnos = $csth->fetchrow_array ) {
1356 push( @bibitemno, $bibitemnos );
1358 my $count = @bibitemno;
1360 # if we have two or more different specific itemtypes
1361 # reserved by same person on same day
1364 $bdata = GetBiblioItemData( $bibitemno[$i] );
1368 # Look up the book we just found.
1369 $bdata = GetBiblioItemData( $bibitemno[0] );
1373 # Add the results of this latest search to the current
1375 # FIXME - An 'each' would probably be more efficient.
1376 foreach my $key ( keys %$bdata ) {
1377 $data->{$key} = $bdata->{$key};
1380 push @results, $data;
1384 return ( $#results + 1, \@results );
1391 Koha Developement team <info@koha.org>