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.
74 &GetFirstReserveDateFromItem
75 &CountReservesFromBorrower
80 # make all your functions, whether exported or not;
84 ($messages,$nextreservinfo) = &GlobalCancel($itemnumber,$borrowernumber);
86 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
94 my ( $itemnumber, $borrowernumber ) = @_;
96 #step 1 : cancel the reservation
97 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
99 #step 2 launch the subroutine of the others reserves
100 ( $messages, $nextreservinfo ) = OtherReserves($itemnumber);
102 return ( $messages, $nextreservinfo );
107 ($messages,$nextreservinfo)=$OtherReserves(itemnumber);
109 Check queued list of this document and check if this document must be transfered
115 my ($itemnumber) = @_;
118 my ( $restype, $checkreserves ) = CheckReserves($itemnumber);
119 if ($checkreserves) {
120 my $iteminfo = C4::Circulation::Circ2::getiteminformation($itemnumber,undef);
121 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
122 $messages->{'transfert'} = $checkreserves->{'branchcode'};
123 #minus priorities of others reservs
126 $checkreserves->{'borrowernumber'},
127 $iteminfo->{'biblionumber'}
130 #launch the subroutine dotransfer
131 C4::Circulation::Circ2::dotransfer(
133 $iteminfo->{'holdingbranch'},
134 $checkreserves->{'branchcode'}
139 #step 2b : case of a reservation on the same branch, set the waiting status
141 $messages->{'waiting'} = 1;
144 $checkreserves->{'borrowernumber'},
145 $iteminfo->{'biblionumber'}
147 SetWaitingStatus($itemnumber);
150 $nextreservinfo = $checkreserves->{'borrowernumber'};
153 return ( $messages, $nextreservinfo );
158 &MinusPriority($itemnumber,$borrowernumber,$biblionumber)
160 Reduce the values of queuded list
166 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
168 #first step update the value of the first person on reserv
169 my $dbh = C4::Context->dbh;
172 SET priority = 0 , itemnumber = ?
173 WHERE cancellationdate IS NULL
177 my $sth_upd = $dbh->prepare($query);
178 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
180 # second step update all others reservs
182 SELECT priority,borrowernumber,biblionumber,reservedate
186 AND cancellationdate IS NULL
188 my $sth_oth = $dbh->prepare($query);
189 $sth_oth->execute($biblionumber);
190 while ( my ( $priority, $borrowernumber, $biblionumber, $reservedate ) =
191 $sth_oth->fetchrow_array )
197 WHERE biblionumber = ?
198 AND borrowernumber = ?
201 my $sth_upd_oth = $dbh->prepare($query);
202 $sth_upd_oth->execute( $priority, $biblionumber, $borrowernumber,
204 $sth_upd_oth->finish;
209 =item SetWaitingStatus
211 &SetWaitingStatus($itemnumber);
213 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
217 sub SetWaitingStatus {
219 #first : check if we have a reservation for this item .
220 my ($itemnumber) = @_;
221 my $dbh = C4::Context->dbh;
223 SELECT priority,borrowernumber
226 AND cancellationdate IS NULL
227 AND found IS NULL AND priority='0'
229 my $sth_find = $dbh->prepare($query);
230 $sth_find->execute($itemnumber);
231 my ( $priority, $borrowernumber ) = $sth_find->fetchrow_array;
233 return unless $borrowernumber;
235 # step 2 : if we have a borrowernumber, we update the value found to 'W' to notify the borrower
238 SET found='W',waitingdate = now()
239 WHERE borrowernumber=?
243 my $sth_set = $dbh->prepare($query);
244 $sth_set->execute( $borrowernumber, $itemnumber );
248 =item GetReservations
250 @borrowerreserv=&GetReservations($itemnumber,$borrowernumber);
252 this function get the list of reservation for an C<$itemnumber> or C<$borrowernumber>
253 given on input arg. You should give $itemnumber OR $borrowernumber but not both.
257 sub GetReservations {
258 my ( $itemnumber, $borrowernumber ) = @_;
260 my $dbh = C4::Context->dbh;
262 SELECT reservedate,borrowernumber
265 AND cancellationdate IS NULL
266 AND (found <> 'F' OR found IS NULL)
268 my $sth_res = $dbh->prepare($query);
269 $sth_res->execute($itemnumber);
270 my ( $reservedate, $borrowernumber ) = $sth_res->fetchrow_array;
271 return ( $reservedate, $borrowernumber );
273 if ($borrowernumber) {
274 my $dbh = C4::Context->dbh;
278 WHERE borrowernumber=?
279 AND cancellationdate IS NULL
280 AND (found != 'F' or found is null)
284 my $sth_find = $dbh->prepare($query);
285 $sth_find->execute($borrowernumber);
287 while ( my $data = $sth_find->fetchrow_hashref ) {
288 push @borrowerreserv, $data;
290 return @borrowerreserv;
296 $results = &FindReserves($biblionumber, $borrowernumber);
298 Looks books up in the reserves. C<$biblionumber> is the biblionumber
299 of the book to look up. C<$borrowernumber> is the borrower number of a
300 patron whose books to look up.
302 Either C<$biblionumber> or C<$borrowernumber> may be the empty string,
303 but not both. If both are specified, C<&FindReserves> looks up the
304 given book for the given patron. If only C<$biblionumber> is
305 specified, C<&FindReserves> looks up that book for all patrons. If
306 only C<$borrowernumber> is specified, C<&FindReserves> looks up all of
307 that patron's reserves. If neither is specified, C<&FindReserves>
310 For each book thus found, C<&FindReserves> checks the reserve
311 constraints and does something I don't understand.
313 C<&FindReserves> returns a two-element array:
315 C<$results> is a reference to an array of references of hashes. Each hash
316 has for keys a list of column from reserves table (see details in function).
322 my ( $biblionumber, $bor ) = @_;
323 my $dbh = C4::Context->dbh;
326 # Find the desired items in the reserves
329 timestamp AS rtimestamp,
338 WHERE cancellationdate IS NULL
339 AND (found <> \'F\' OR found IS NULL)
342 if ( $biblionumber ne '' ) {
346 push @bind, $biblionumber;
351 AND borrowernumber = ?
359 my $sth = $dbh->prepare($query);
360 $sth->execute(@bind);
363 while ( my $data = $sth->fetchrow_hashref ) {
365 # FIXME - What is this if-statement doing? How do constraints work?
366 if ( $data->{constrainttype} eq 'o' ) {
368 SELECT biblioitemnumber
369 FROM reserveconstraints
370 WHERE biblionumber = ?
371 AND borrowernumber = ?
374 my $csth = $dbh->prepare($query);
375 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
376 $data->{reservedate}, );
379 while ( my $bibitemnos = $csth->fetchrow_array ) {
380 push( @bibitemno, $bibitemnos );
382 my $count = @bibitemno;
384 # if we have two or more different specific itemtypes
385 # reserved by same person on same day
388 $bdata = GetBiblioItemData( $bibitemno[$i] );
393 # Look up the book we just found.
394 $bdata = GetBiblioItemData( $bibitemno[0] );
398 # Add the results of this latest search to the current
400 # FIXME - An 'each' would probably be more efficient.
401 foreach my $key ( keys %$bdata ) {
402 $data->{$key} = $bdata->{$key};
405 push @results, $data;
409 return ( $#results + 1, \@results );
412 #-------------------------------------------------------------------------------------
414 =item CountReservesFromBorrower
416 $number = &CountReservesFromBorrower($borrowernumber);
418 this function returns the number of reservation for a borrower given on input arg.
422 sub CountReservesFromBorrower {
423 my ($borrowernumber) = @_;
425 my $dbh = C4::Context->dbh;
428 SELECT COUNT(*) AS counter
430 WHERE borrowernumber = ?
431 AND cancellationdate IS NULL
432 AND (found != \'F\' OR found IS NULL)
434 my $sth = $dbh->prepare($query);
435 $sth->execute($borrowernumber);
436 my $row = $sth->fetchrow_hashref;
439 return $row->{counter};
442 #-------------------------------------------------------------------------------------
444 =item GetFirstReserveDateFromItem
446 $date = GetFirstReserveDateFromItem($itemnumber)
448 this function returns the first date a item has been reserved.
452 sub GetFirstReserveDateFromItem {
453 my ($itemnumber) = @_;
455 my $dbh = C4::Context->dbh;
463 AND cancellationdate IS NULL
464 AND (found != \'F\' OR found IS NULL)
466 my $sth = $dbh->prepare($query);
467 $sth->execute($itemnumber);
468 my $row = $sth->fetchrow_hashref;
470 return ($row->{reservedate},$row->{borrowernumber},$row->{branchcode});
473 #-------------------------------------------------------------------------------------
477 ($status, $reserve) = &CheckReserves($itemnumber, $barcode);
479 Find a book in the reserves.
481 C<$itemnumber> is the book's item number. C<$barcode> is its barcode.
482 Either one, but not both, may be false. If both are specified,
483 C<&CheckReserves> uses C<$itemnumber>.
485 $itemnubmer can be false, in which case uses the barcode. (Never uses
486 both. $itemnumber gets priority).
488 As I understand it, C<&CheckReserves> looks for the given item in the
489 reserves. If it is found, that's a match, and C<$status> is set to
492 Otherwise, it finds the most important item in the reserves with the
493 same biblio number as this book (I'm not clear on this) and returns it
494 with C<$status> set to C<Reserved>.
496 C<&CheckReserves> returns a two-element list:
498 C<$status> is either C<Waiting>, C<Reserved> (see above), or 0.
500 C<$reserve> is the reserve item that matched. It is a
501 reference-to-hash whose keys are mostly the fields of the reserves
502 table in the Koha database.
508 my ( $item, $barcode ) = @_;
509 my $dbh = C4::Context->dbh;
512 my $qitem = $dbh->quote($item);
513 # Look up the item by itemnumber
515 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
516 FROM items, biblioitems, itemtypes
517 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
518 AND biblioitems.itemtype = itemtypes.itemtype
519 AND itemnumber=$qitem
521 $sth = $dbh->prepare($query);
524 my $qbc = $dbh->quote($barcode);
525 # Look up the item by barcode
527 SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan
528 FROM items, biblioitems, itemtypes
529 WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
530 AND biblioitems.itemtype = itemtypes.itemtype
533 $sth = $dbh->prepare($query);
535 # FIXME - This function uses $item later on. Ought to set it here.
538 my ( $biblio, $bibitem, $notforloan ) = $sth->fetchrow_array;
541 # if item is not for loan it cannot be reserved either.....
542 return ( 0, 0 ) if $notforloan;
544 # get the reserves...
545 # Find this item in the reserves
546 my @reserves = Findgroupreserve( $bibitem, $biblio );
547 my $count = scalar @reserves;
549 # $priority and $highest are used to find the most important item
550 # in the list returned by &Findgroupreserve. (The lower $priority,
551 # the more important the item.)
552 # $highest is the most important item we've seen so far.
553 my $priority = 10000000;
556 foreach my $res (@reserves) {
557 # FIXME - $item might be undefined or empty: the caller
558 # might be searching by barcode.
559 if ( $res->{'itemnumber'} == $item ) {
561 return ( "Waiting", $res );
564 # See if this item is more important than what we've got
566 if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
568 $priority = $res->{'priority'};
575 # If we get this far, then no exact match was found. Print the
576 # most important item on the list. I think this tells us who's
577 # next in line to get this book.
578 if ($highest) { # FIXME - $highest might be undefined
579 $highest->{'itemnumber'} = $item;
580 return ( "Reserved", $highest );
587 #-------------------------------------------------------------------------------------
591 &CancelReserve($biblionumber, $itemnumber, $borrowernumber);
595 Use either C<$biblionumber> or C<$itemnumber> to specify the item to
596 cancel, but not both: if both are given, C<&CancelReserve> does
599 C<$borrowernumber> is the borrower number of the patron on whose
600 behalf the book was reserved.
602 If C<$biblionumber> was given, C<&CancelReserve> also adjusts the
603 priorities of the other people who are waiting on the book.
609 my ( $biblio, $item, $borr ) = @_;
610 my $dbh = C4::Context->dbh;
611 if ( ( $item and $borr ) and ( not $biblio ) ) {
612 # removing a waiting reserve record....
613 # update the database...
616 SET cancellationdate = now(),
620 AND borrowernumber = ?
622 my $sth = $dbh->prepare($query);
623 $sth->execute( $item, $borr );
626 if ( ( $biblio and $borr ) and ( not $item ) ) {
627 # removing a reserve record....
628 # get the prioritiy on this record....
631 SELECT priority FROM reserves
632 WHERE biblionumber = ?
633 AND borrowernumber = ?
634 AND cancellationdate IS NULL
635 AND itemnumber IS NULL
636 AND (found <> 'F' OR found IS NULL)
638 my $sth = $dbh->prepare($query);
639 $sth->execute( $biblio, $borr );
640 ($priority) = $sth->fetchrow_array;
644 SET cancellationdate = now(),
647 WHERE biblionumber = ?
648 AND borrowernumber = ?
649 AND cancellationdate IS NULL
650 AND (found <> 'F' or found IS NULL)
653 # update the database, removing the record...
654 $sth = $dbh->prepare($query);
655 $sth->execute( $biblio, $borr );
658 # now fix the priority on the others....
659 FixPriority( $priority, $biblio );
663 #-------------------------------------------------------------------------------------
667 &FillReserve($reserve);
669 Fill a reserve. If I understand this correctly, this means that the
670 reserved book has been found and given to the patron who reserved it.
672 C<$reserve> specifies the reserve to fill. It is a reference-to-hash
673 whose keys are fields from the reserves table in the Koha database.
680 my $dbh = C4::Context->dbh;
681 # fill in a reserve record....
682 my $qbiblio = $res->{'biblionumber'};
683 my $borr = $res->{'borrowernumber'};
684 my $resdate = $res->{'reservedate'};
686 # get the priority on this record....
688 my $query = "SELECT priority
690 WHERE biblionumber = ?
691 AND borrowernumber = ?
692 AND reservedate = ?";
693 my $sth = $dbh->prepare($query);
694 $sth->execute( $qbiblio, $borr, $resdate );
695 ($priority) = $sth->fetchrow_array;
698 # update the database...
699 $query = "UPDATE reserves
702 WHERE biblionumber = ?
704 AND borrowernumber = ?
706 $sth = $dbh->prepare($query);
707 $sth->execute( $qbiblio, $resdate, $borr );
710 # now fix the priority on the others (if the priority wasn't
711 # already sorted!)....
712 unless ( $priority == 0 ) {
713 FixPriority( $priority, $qbiblio );
717 #-------------------------------------------------------------------------------------
721 &FixPriority($biblio,$borrowernumber,$rank);
723 Only used internally (so don't export it)
724 Changed how this functions works #
725 Now just gets an array of reserves in the rank order and updates them with
726 the array index (+1 as array starts from 0)
727 and if $rank is supplied will splice item from the array and splice it back in again
733 my ( $biblio, $borrowernumber, $rank ) = @_;
734 my $dbh = C4::Context->dbh;
735 if ( $rank eq "del" ) {
736 CancelReserve( $biblio, undef, $borrowernumber );
738 if ( $rank eq "W" || $rank eq "0" ) {
740 # make sure priority for waiting items is 0
744 WHERE biblionumber = ?
745 AND borrowernumber = ?
746 AND cancellationdate IS NULL
749 my $sth = $dbh->prepare($query);
750 $sth->execute( $biblio, $borrowernumber );
756 # FIXME adding a new security in returned elements for changing priority,
757 # now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
759 SELECT borrowernumber, reservedate, constrainttype
761 WHERE biblionumber = ?
762 AND cancellationdate IS NULL
763 AND itemnumber IS NULL
764 AND ((found <> 'F' and found <> 'W') or found is NULL)
765 ORDER BY priority ASC
767 my $sth = $dbh->prepare($query);
768 $sth->execute($biblio);
769 while ( my $line = $sth->fetchrow_hashref ) {
770 push( @reservedates, $line );
771 push( @priority, $line );
774 # To find the matching index
776 my $key = -1; # to allow for 0 to be a valid result
777 for ( $i = 0 ; $i < @priority ; $i++ ) {
778 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
779 $key = $i; # save the index
784 # if index exists in array then move it to new position
785 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
786 my $new_rank = $rank -
787 1; # $new_rank is what you want the new index to be in the array
788 my $moving_item = splice( @priority, $key, 1 );
789 splice( @priority, $new_rank, 0, $moving_item );
792 # now fix the priority on those that are left....
796 WHERE biblionumber = ?
797 AND borrowernumber = ?
801 $sth = $dbh->prepare($query);
802 for ( my $j = 0 ; $j < @priority ; $j++ ) {
805 $priority[$j]->{'borrowernumber'},
806 $priority[$j]->{'reservedate'}
812 #-------------------------------------------------------------------------------------
816 branchcode = &ReserveWaiting($item,$borr);
817 this function set FOUND to 'W' for Waiting into the database.
822 my ( $item, $borr,$diffBranchSend ) = @_;
823 my $dbh = C4::Context->dbh;
825 # get priority and biblionumber....
827 SELECT reserves.priority as priority,
828 reserves.biblionumber as biblionumber,
829 reserves.branchcode as branchcode,
830 reserves.timestamp as timestamp
832 WHERE reserves.biblionumber = items.biblionumber
833 AND items.itemnumber = ?
834 AND reserves.borrowernumber = ?
835 AND reserves.cancellationdate IS NULL
836 AND (reserves.found <> 'F' OR reserves.found IS NULL)
838 my $sth = $dbh->prepare($query);
839 $sth->execute( $item, $borr );
840 my $data = $sth->fetchrow_hashref;
842 my $biblio = $data->{'biblionumber'};
843 my $timestamp = $data->{'timestamp'};
845 # update reserves record....
846 if ($diffBranchSend) {
851 WHERE borrowernumber = ?
863 WHERE borrowernumber = ?
868 $sth = $dbh->prepare($query);
869 $sth->execute( $item, $borr, $biblio, $timestamp );
872 # now fix up the remaining priorities....
873 FixPriority( $data->{'priority'}, $biblio );
874 my $branchcode = $data->{'branchcode'};
878 #-------------------------------------------------------------------------------------
880 =item GetWaitingReserves
882 \@itemswaiting=GetWaitingReserves($borr);
884 this funtion fetch the list of waiting reserves from database.
888 sub GetWaitingReserves {
890 my $dbh = C4::Context->dbh;
895 WHERE borrowernumber = ?
896 AND reserves.found = 'W'
897 AND cancellationdate IS NULL
899 my $sth = $dbh->prepare($query);
900 $sth->execute($borr);
901 while ( my $data = $sth->fetchrow_hashref ) {
902 push( @itemswaiting, $data );
905 return \@itemswaiting;
908 #-------------------------------------------------------------------------------------
910 =item Findgroupreserve
912 @results = &Findgroupreserve($biblioitemnumber, $biblionumber);
915 I don't know what this does, because I don't understand how reserve
916 constraints work. I think the idea is that you reserve a particular
917 biblio, and the constraint allows you to restrict it to a given
918 biblioitem (e.g., if you want to borrow the audio book edition of "The
919 Prophet", rather than the first available publication).
921 C<&Findgroupreserve> returns :
922 C<@results> is an array of references-to-hash whose keys are mostly
923 fields from the reserves table of the Koha database, plus
929 sub Findgroupreserve {
930 my ( $bibitem, $biblio ) = @_;
931 my $dbh = C4::Context->dbh;
933 SELECT reserves.biblionumber AS biblionumber,
934 reserves.borrowernumber AS borrowernumber,
935 reserves.reservedate AS reservedate,
936 reserves.branchcode AS branchcode,
937 reserves.cancellationdate AS cancellationdate,
938 reserves.found AS found,
939 reserves.reservenotes AS reservenotes,
940 reserves.priority AS priority,
941 reserves.timestamp AS timestamp,
942 reserveconstraints.biblioitemnumber AS biblioitemnumber,
943 reserves.itemnumber AS itemnumber
945 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
946 WHERE reserves.biblionumber = ?
947 AND ( ( reserveconstraints.biblioitemnumber = ?
948 AND reserves.borrowernumber = reserveconstraints.borrowernumber
949 AND reserves.reservedate =reserveconstraints.reservedate )
950 OR reserves.constrainttype='a' )
951 AND reserves.cancellationdate is NULL
952 AND (reserves.found <> 'F' or reserves.found is NULL)
954 my $sth = $dbh->prepare($query);
955 $sth->execute( $biblio, $bibitem );
957 while ( my $data = $sth->fetchrow_hashref ) {
958 push( @results, $data );
966 CreateReserve($env,$branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$notes,$title,$checkitem,$found)
968 FIXME - A somewhat different version of this function appears in
969 C4::Reserves. Pick one and stick with it.
975 $env, $branch, $borrowernumber, $biblionumber,
976 $constraint, $bibitems, $priority, $notes,
977 $title, $checkitem, $found
980 if ( $library_name =~ /Horowhenua/ ) {
982 CalcHLTReserveFee( $env, $borrowernumber, $biblionumber, $constraint,
987 CalcReserveFee( $env, $borrowernumber, $biblionumber, $constraint,
990 my $dbh = C4::Context->dbh;
991 my $const = lc substr( $constraint, 0, 1 );
992 my @datearr = localtime(time);
994 ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
997 # If the reserv had the waiting status, we had the value of the resdate
998 if ( $found eq 'W' ) {
999 $waitingdate = $resdate;
1003 # updates take place here
1005 my $nextacctno = &getnextacctno( $env, $borrowernumber, $dbh );
1007 INSERT INTO accountlines
1008 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
1010 (?,?,now(),?,?,'Res',?)
1012 my $usth = $dbh->prepare($query);
1013 $usth->execute( $borrowernumber, $nextacctno, $fee,
1014 "Reserve Charge - $title", $fee );
1018 #if ($const eq 'a'){
1020 INSERT INTO reserves
1021 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
1022 priority,reservenotes,itemnumber,found,waitingdate)
1027 my $sth = $dbh->prepare($query);
1029 $borrowernumber, $biblionumber, $resdate, $branch,
1030 $const, $priority, $notes, $checkitem,
1031 $found, $waitingdate
1036 if ( ( $const eq "o" ) || ( $const eq "e" ) ) {
1037 my $numitems = @$bibitems;
1039 while ( $i < $numitems ) {
1040 my $biblioitem = @$bibitems[$i];
1042 INSERT INTO reserveconstraints
1043 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
1047 my $sth = $dbh->prepare("");
1048 $sth->execute( $borrowernumber, $biblionumber, $resdate,
1057 # FIXME - A functionally identical version of this function appears in
1058 # C4::Reserves. Pick one and stick with it.
1059 # XXX - Internal use only
1060 # FIXME - opac-reserves.pl need to use it, temporarily put into @EXPORT
1062 sub CalcReserveFee {
1063 my ( $env, $borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
1066 my $dbh = C4::Context->dbh;
1067 my $const = lc substr( $constraint, 0, 1 );
1069 SELECT * FROM borrowers,categories
1070 WHERE borrowernumber = ?
1071 AND borrowers.categorycode = categories.categorycode
1073 my $sth = $dbh->prepare($query);
1074 $sth->execute($borrowernumber);
1075 my $data = $sth->fetchrow_hashref;
1077 my $fee = $data->{'reservefee'};
1078 my $cntitems = @- > $bibitems;
1082 # check for items on issue
1083 # first find biblioitem records
1085 my $sth1 = $dbh->prepare(
1086 "SELECT * FROM biblio,biblioitems
1087 WHERE (biblio.biblionumber = ?)
1088 AND (biblio.biblionumber = biblioitems.biblionumber)"
1090 $sth1->execute($biblionumber);
1091 while ( my $data1 = $sth1->fetchrow_hashref ) {
1092 if ( $const eq "a" ) {
1093 push @biblioitems, $data1;
1098 while ( $x < $cntitems ) {
1099 if ( @$bibitems->{'biblioitemnumber'} ==
1100 $data->{'biblioitemnumber'} )
1106 if ( $const eq 'o' ) {
1107 if ( $found == 1 ) {
1108 push @biblioitems, $data1;
1112 if ( $found == 0 ) {
1113 push @biblioitems, $data1;
1119 my $cntitemsfound = @biblioitems;
1123 while ( $x < $cntitemsfound ) {
1124 my $bitdata = $biblioitems[$x];
1125 my $sth2 = $dbh->prepare(
1126 "SELECT * FROM items
1127 WHERE biblioitemnumber = ?"
1129 $sth2->execute( $bitdata->{'biblioitemnumber'} );
1130 while ( my $itdata = $sth2->fetchrow_hashref ) {
1131 my $sth3 = $dbh->prepare(
1132 "SELECT * FROM issues
1133 WHERE itemnumber = ?
1134 AND returndate IS NULL"
1136 $sth3->execute( $itdata->{'itemnumber'} );
1137 if ( my $isdata = $sth3->fetchrow_hashref ) {
1145 if ( $allissued == 0 ) {
1147 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
1148 $rsth->execute($biblionumber);
1149 if ( my $rdata = $rsth->fetchrow_hashref ) {
1161 # The following are junior and young adult item types that should not incur a
1164 # Juniors: BJC, BJCN, BJF, BJK, BJM, BJN, BJP, BJSF, BJSN, DJ, DJP, FJ, JVID,
1165 # VJ, VJP, PJ, TJ, TJP, VJ, VJP.
1167 # Young adults: BYF, BYN, BYP, DY, DYP, PY, PYP, TY, TYP, VY, VYP.
1169 # All other item types should incur a reserve charge.
1170 sub CalcHLTReserveFee {
1171 my ( $env, $borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
1172 my $dbh = C4::Context->dbh;
1173 my $sth = $dbh->prepare(
1174 "SELECT * FROM borrowers,categories
1175 WHERE (borrowernumber = ?)
1176 AND (borrowers.categorycode = categories.categorycode)"
1178 $sth->execute($borrowernumber);
1179 my $data = $sth->fetchrow_hashref;
1181 my $fee = $data->{'reservefee'};
1185 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/;
1186 $sth = $dbh->prepare(
1187 "SELECT * FROM biblio,biblioitems
1188 WHERE (biblio.biblionumber = ?)
1189 AND (biblio.biblionumber = biblioitems.biblionumber)"
1191 $sth->execute($biblionumber);
1192 $data = $sth->fetchrow_hashref;
1193 my $itemtype = $data->{'itemtype'};
1194 for ( my $i = 0 ; $i < @nocharge ; $i++ ) {
1195 if ( $itemtype eq $nocharge[$i] ) {
1201 if ( $matchno > 0 ) {
1207 =item GetNextAccountNumber
1209 GetNextAccountNumber()
1213 sub GetNextAccountNumber {
1214 my ( $env, $borrowernumber, $dbh ) = @_;
1215 my $nextaccntno = 1;
1216 my $sth = $dbh->prepare(
1217 "select * from accountlines
1218 where (borrowernumber = ?)
1219 order by accountno desc"
1221 $sth->execute($borrowernumber);
1222 if ( my $accdata = $sth->fetchrow_hashref ) {
1223 $nextaccntno = $accdata->{'accountno'} + 1;
1226 return ($nextaccntno);
1229 #-------------------------------------------------------------------------------------
1233 &UpdateReserve($rank,$biblio,$borrower,$branch)
1238 #subroutine to update a reserve
1239 my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_;
1240 return if $rank eq "W";
1241 return if $rank eq "n";
1242 my $dbh = C4::Context->dbh;
1243 if ( $rank eq "del" ) {
1246 SET cancellationdate=now()
1247 WHERE biblionumber = ?
1248 AND borrowernumber = ?
1249 AND cancellationdate is NULL
1250 AND (found <> 'F' or found is NULL)
1252 my $sth = $dbh->prepare($query);
1253 $sth->execute( $biblio, $borrower );
1259 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL
1260 WHERE biblionumber = ?
1261 AND borrowernumber = ?
1262 AND cancellationdate is NULL
1263 AND (found <> 'F' or found is NULL)
1265 my $sth = $dbh->prepare($query);
1266 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
1268 FixPriority( $biblio, $borrower, $rank);
1272 =item GetReserveTitle
1274 $data = GetReserveTitle($biblio,$bor,$date,$timestamp);
1278 sub GetReserveTitle {
1279 my ( $biblio, $bor, $date, $timestamp ) = @_;
1280 my $dbh = C4::Context->dbh;
1283 FROM reserveconstraints,biblioitems
1284 WHERE reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber
1285 AND reserveconstraints.biblionumber=?
1286 AND reserveconstraints.borrowernumber = ?
1287 AND reserveconstraints.reservedate=?
1288 AND reserveconstraints.timestamp=?
1290 my $sth = $dbh->prepare($query);
1291 $sth->execute( $biblio, $bor, $date, $timestamp );
1292 my $data = $sth->fetchrow_hashref;
1297 =item FindReservesInQueue
1299 $results = &FindReservesInQueue($biblionumber);
1301 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)
1303 C<&FindReservesInQueue> returns a two-element array:
1305 C<$results> is a reference to an array of references of hashes. Each hash
1306 has for keys a list of column from reserves table (see details in function).
1312 sub FindReservesInQueue {
1313 my ($biblionumber) = @_;
1314 my $dbh = C4::Context->dbh;
1316 # Find the desired items in the reserves
1319 timestamp AS rtimestamp,
1328 WHERE cancellationdate IS NULL
1329 AND biblionumber = ?
1330 AND (found <> \'F\' OR found IS NULL)
1331 AND priority <> \'0\'
1334 my $sth = $dbh->prepare($query);
1335 $sth->execute($biblionumber);
1338 while ( my $data = $sth->fetchrow_hashref ) {
1340 # FIXME - What is this if-statement doing? How do constraints work?
1341 if ( $data->{constrainttype} eq 'o' ) {
1343 SELECT biblioitemnumber
1344 FROM reserveconstraints
1345 WHERE biblionumber = ?
1346 AND borrowernumber = ?
1349 my $csth = $dbh->prepare($query);
1350 $csth->execute( $data->{biblionumber}, $data->{borrowernumber},
1351 $data->{reservedate}, );
1354 while ( my $bibitemnos = $csth->fetchrow_array ) {
1355 push( @bibitemno, $bibitemnos );
1357 my $count = @bibitemno;
1359 # if we have two or more different specific itemtypes
1360 # reserved by same person on same day
1363 $bdata = GetBiblioItemData( $bibitemno[$i] );
1367 # Look up the book we just found.
1368 $bdata = GetBiblioItemData( $bibitemno[0] );
1372 # Add the results of this latest search to the current
1374 # FIXME - An 'each' would probably be more efficient.
1375 foreach my $key ( keys %$bdata ) {
1376 $data->{$key} = $bdata->{$key};
1379 push @results, $data;
1383 return ( $#results + 1, \@results );
1390 Koha Developement team <info@koha.org>