From 6a379038431afb1c0766c04bf65ff770498472d4 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Thu, 22 Mar 2012 12:42:32 -0400 Subject: [PATCH] Bug 7710 - multiple holds per title Adds the ability to allow multiple holds on the same record for the same borrower. Adds new system preference MaxHoldsPerRecord, which controls how many holds one person can have on items for the same record. --- C4/Biblio.pm | 2 +- C4/ILSDI/Services.pm | 2 +- C4/Reserves.pm | 490 ++++++++++---------- C4/SIP/ILS/Transaction/Hold.pm | 23 +- circ/branchtransfers.pl | 10 +- circ/circulation.pl | 2 +- installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 7 + .../en/modules/admin/preferences/circulation.pref | 7 +- .../prog/en/modules/reserve/request.tt | 25 +- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 2 +- opac/opac-modrequest.pl | 9 +- opac/opac-reserve.pl | 25 +- reserve/modrequest.pl | 28 +- reserve/request.pl | 73 ++-- serials/routing-preview.pl | 7 +- 16 files changed, 368 insertions(+), 345 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 7d28ccd..e5ed7c1 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -439,7 +439,7 @@ sub DelBiblio { require C4::Reserves; my ($count, $reserves) = C4::Reserves::GetReservesFromBiblionumber($biblionumber); foreach my $res ( @$reserves ) { - C4::Reserves::CancelReserve( $res->{'biblionumber'}, $res->{'itemnumber'}, $res->{'borrowernumber'} ); + C4::Reserves::CancelReserve({ reserve_id => $res->{'reserve_id'} }); } # Delete in Zebra. Be careful NOT to move this line after _koha_delete_biblio diff --git a/C4/ILSDI/Services.pm b/C4/ILSDI/Services.pm index 68cbdb3..75340a4 100644 --- a/C4/ILSDI/Services.pm +++ b/C4/ILSDI/Services.pm @@ -762,7 +762,7 @@ sub CancelHold { return { code => 'NotCanceled' } unless any { $itemnumber eq $_ } @reserveditems; # Cancel the reserve - CancelReserve( $itemnumber, undef, $borrowernumber ); + CancelReserve({ itemnumber => $itemnumber, borrowernumber => $borrowernumber }); return { code => 'Canceled' }; } diff --git a/C4/Reserves.pm b/C4/Reserves.pm index a380bf0..4b6f9d5 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -93,7 +93,8 @@ BEGIN { @ISA = qw(Exporter); @EXPORT = qw( &AddReserve - + + &GetReserve &GetReservesFromItemnumber &GetReservesFromBiblionumber &GetReservesFromBorrowernumber @@ -244,6 +245,24 @@ sub AddReserve { return; # FIXME: why not have a useful return value? } +=head2 GetReserve + + $res = GetReserve( $reserve_id ); + +=cut + +sub GetReserve { + my ($reserve_id) = @_; + #warn "C4::Reserves::GetReserve( $reserve_id )"; + + my $dbh = C4::Context->dbh; + my $query = "SELECT * FROM reserves WHERE reserve_id = ?"; + my $sth = $dbh->prepare( $query ); + $sth->execute( $reserve_id ); + my $res = $sth->fetchrow_hashref(); + return $res; +} + =head2 GetReservesFromBiblionumber ($count, $title_reserves) = &GetReserves($biblionumber); @@ -260,7 +279,8 @@ sub GetReservesFromBiblionumber { # Find the desired items in the reserves my $query = " - SELECT branchcode, + SELECT reserve_id, + branchcode, timestamp AS rtimestamp, priority, biblionumber, @@ -328,7 +348,7 @@ sub GetReservesFromBiblionumber { =head2 GetReservesFromItemnumber - ( $reservedate, $borrowernumber, $branchcode ) = GetReservesFromItemnumber($itemnumber); + ( $reservedate, $borrowernumber, $branchcode, $reserve_id ) = GetReservesFromItemnumber($itemnumber); TODO :: Description here @@ -338,7 +358,7 @@ sub GetReservesFromItemnumber { my ( $itemnumber, $all_dates ) = @_; my $dbh = C4::Context->dbh; my $query = " - SELECT reservedate,borrowernumber,branchcode + SELECT reservedate,borrowernumber,branchcode,reserve_id FROM reserves WHERE itemnumber=? "; @@ -417,9 +437,11 @@ This function return 1 if an item can be issued by this borrower. sub CanItemBeReserved{ my ($borrowernumber, $itemnumber) = @_; - - my $dbh = C4::Context->dbh; + + my $dbh = C4::Context->dbh; my $allowedreserves = 0; + my $multi_holds_allowed_same = 0; + my $multi_holds_allowed_diff = 0; my $controlbranch = C4::Context->preference('ReservesControlBranch'); my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; @@ -428,27 +450,14 @@ sub CanItemBeReserved{ my $item = GetItem($itemnumber); my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); - # we retrieve user rights on this itemtype and branchcode - my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed - FROM issuingrules - WHERE (categorycode in (?,'*') ) - AND (itemtype IN (?,'*')) - AND (branchcode IN (?,'*')) - ORDER BY - categorycode DESC, - itemtype DESC, - branchcode DESC;" - ); - - my $querycount ="SELECT - count(*) as count - FROM reserves - LEFT JOIN items USING (itemnumber) - LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber) - LEFT JOIN borrowers USING (borrowernumber) - WHERE borrowernumber = ? - "; - + my $querycount = " + SELECT count(*) AS count + FROM reserves + LEFT JOIN items USING (itemnumber) + LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber) + LEFT JOIN borrowers USING (borrowernumber) + WHERE borrowernumber = ? + "; my $itemtype = $item->{$itype}; my $categorycode = $borrower->{categorycode}; @@ -464,8 +473,8 @@ sub CanItemBeReserved{ } # we retrieve rights - $sth->execute($categorycode, $itemtype, $branchcode); - if(my $rights = $sth->fetchrow_hashref()){ + my $rights = C4::Circulation::GetIssuingRule( $categorycode, $itemtype, $branchcode ); + if ( defined $rights ) { $itemtype = $rights->{itemtype}; $allowedreserves = $rights->{reservesallowed}; }else{ @@ -489,12 +498,11 @@ sub CanItemBeReserved{ if(my $rowcount = $sthcount->fetchrow_hashref()){ $reservecount = $rowcount->{count}; } - # we check if it's ok or not - if( $reservecount < $allowedreserves ){ - return 1; - }else{ + if( $reservecount >= $allowedreserves ){ ## too many reserves return 0; + }else{ + return 1; } } #-------------------------------------------------------------------------------- @@ -511,11 +519,11 @@ sub GetReserveCount { my $dbh = C4::Context->dbh; - my $query = ' + my $query = " SELECT COUNT(*) AS counter FROM reserves - WHERE borrowernumber = ? - '; + WHERE borrowernumber = ? + "; my $sth = $dbh->prepare($query); $sth->execute($borrowernumber); my $row = $sth->fetchrow_hashref; @@ -542,8 +550,7 @@ sub GetOtherReserves { #minus priorities of others reservs ModReserveMinusPriority( $itemnumber, - $checkreserves->{'borrowernumber'}, - $iteminfo->{'biblionumber'} + $checkreserves->{'reserve_id'}, ); #launch the subroutine dotransfer @@ -560,8 +567,7 @@ sub GetOtherReserves { $messages->{'waiting'} = 1; ModReserveMinusPriority( $itemnumber, - $checkreserves->{'borrowernumber'}, - $iteminfo->{'biblionumber'} + $checkreserves->{'reserve_id'}, ); ModReserveStatus($itemnumber,'W'); } @@ -687,7 +693,7 @@ sub GetReservesToBranch { my ( $frombranch ) = @_; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( - "SELECT borrowernumber,reservedate,itemnumber,timestamp + "SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp FROM reserves WHERE priority='0' AND branchcode=?" @@ -710,22 +716,24 @@ sub GetReservesToBranch { sub GetReservesForBranch { my ($frombranch) = @_; - my $dbh = C4::Context->dbh; - my $query = "SELECT borrowernumber,reservedate,itemnumber,waitingdate + my $dbh = C4::Context->dbh; + + my $query = " + SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate FROM reserves WHERE priority='0' - AND found='W' "; - if ($frombranch){ - $query .= " AND branchcode=? "; - } + AND found='W' + "; + $query .= " AND branchcode=? " if ( $frombranch ); $query .= "ORDER BY waitingdate" ; + my $sth = $dbh->prepare($query); if ($frombranch){ - $sth->execute($frombranch); - } - else { - $sth->execute(); - } + $sth->execute($frombranch); + } else { + $sth->execute(); + } + my @transreserv; my $i = 0; while ( my $data = $sth->fetchrow_hashref ) { @@ -880,7 +888,7 @@ sub CancelExpiredReserves { $sth->execute(); while ( my $res = $sth->fetchrow_hashref() ) { - CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); + CancelReserve({ reserve_id => $res->{'reserve_id'} }); } # Cancel reserves that have been waiting too long @@ -897,7 +905,7 @@ sub CancelExpiredReserves { manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge); } - CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); + CancelReserve({ reserve_id => $res->{'reserve_id'} }); } } @@ -923,109 +931,60 @@ sub AutoUnsuspendReserves { =head2 CancelReserve - &CancelReserve($biblionumber, $itemnumber, $borrowernumber); + CancelReserve({ reserve_id => $reserve_id, [ biblionumber => $biblionumber, borrowernumber => $borrrowernumber, itemnumber => $itemnumber ] }); Cancels a reserve. -Use either C<$biblionumber> or C<$itemnumber> to specify the item to -cancel, but not both: if both are given, C<&CancelReserve> uses -C<$itemnumber>. - -C<$borrowernumber> is the borrower number of the patron on whose -behalf the book was reserved. - -If C<$biblionumber> was given, C<&CancelReserve> also adjusts the -priorities of the other people who are waiting on the book. - =cut sub CancelReserve { - my ( $biblio, $item, $borr ) = @_; + my ( $params ) = @_; + + my $reserve_id = $params->{'reserve_id'}; + $reserve_id = GetReserveId( $params ) unless ( $reserve_id ); + + return unless ( $reserve_id ); + my $dbh = C4::Context->dbh; - if ( $item and $borr ) { - # removing a waiting reserve record.... - # update the database... - my $query = " - UPDATE reserves - SET cancellationdate = now(), - found = Null, - priority = 0 - WHERE itemnumber = ? - AND borrowernumber = ? - "; - my $sth = $dbh->prepare($query); - $sth->execute( $item, $borr ); - $sth->finish; - $query = " - INSERT INTO old_reserves - SELECT * FROM reserves - WHERE itemnumber = ? - AND borrowernumber = ? - "; - $sth = $dbh->prepare($query); - $sth->execute( $item, $borr ); - $query = " - DELETE FROM reserves - WHERE itemnumber = ? - AND borrowernumber = ? - "; - $sth = $dbh->prepare($query); - $sth->execute( $item, $borr ); - } - else { - # removing a reserve record.... - # get the prioritiy on this record.... - my $priority; - my $query = qq/ - SELECT priority FROM reserves - WHERE biblionumber = ? - AND borrowernumber = ? - AND cancellationdate IS NULL - AND itemnumber IS NULL - /; - my $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borr ); - ($priority) = $sth->fetchrow_array; - $sth->finish; - $query = qq/ - UPDATE reserves - SET cancellationdate = now(), - found = Null, - priority = 0 - WHERE biblionumber = ? - AND borrowernumber = ? - /; - - # update the database, removing the record... - $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borr ); - $sth->finish; - $query = qq/ - INSERT INTO old_reserves - SELECT * FROM reserves - WHERE biblionumber = ? - AND borrowernumber = ? - /; - $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borr ); + my $query = " + UPDATE reserves + SET cancellationdate = now(), + found = Null, + priority = 0 + WHERE reserve_id = ? + "; + my $sth = $dbh->prepare($query); + $sth->execute( $reserve_id ); + $sth->finish; - $query = qq/ - DELETE FROM reserves - WHERE biblionumber = ? - AND borrowernumber = ? - /; - $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borr ); + $query = " + INSERT INTO old_reserves + SELECT * FROM reserves + WHERE reserve_id = ? + "; + $sth = $dbh->prepare($query); + $sth->execute( $reserve_id ); - # now fix the priority on the others.... - _FixPriority( $biblio, $borr ); - } + $query = " + DELETE FROM reserves + WHERE reserve_id = ? + "; + $sth = $dbh->prepare($query); + $sth->execute( $reserve_id ); + + # now fix the priority on the others.... + _FixPriority( $reserve_id ); } =head2 ModReserve - ModReserve($rank, $biblio, $borrower, $branch[, $itemnumber]) + ModReserve({ rank => $rank, + reserve_id => $reserve_id, + branchcode => $branchcode + [, itemnumber => $itemnumber ] + [, biblionumber => $biblionumber, $borrowernumber => $borrowernumber ] + }); Change a hold request's priority or cancel it. @@ -1055,59 +1014,67 @@ itemnumber and supplying itemnumber. =cut sub ModReserve { - #subroutine to update a reserve - my ( $rank, $biblio, $borrower, $branch , $itemnumber, $suspend_until) = @_; - return if $rank eq "W"; - return if $rank eq "n"; + my ( $params ) = @_; + + my $rank = $params->{'rank'}; + my $reserve_id = $params->{'reserve_id'}; + my $branchcode = $params->{'branchcode'}; + my $itemnumber = $params->{'itemnumber'}; + my $suspend_until = $params->{'suspend_until'}; + my $borrowernumber = $params->{'borrowernumber'}; + my $biblionumber = $params->{'biblionumber'}; + + return if $rank eq "W"; + return if $rank eq "n"; + + return unless ( $reserve_id || ( $borrowernumber && ( $biblionumber || $itemnumber ) ) ); + $reserve_id = GetReserveId({ biblionumber => $biblionumber, borrowernumber => $borrowernumber, itemnumber => $itemnumber }) unless ( $reserve_id ); + my $dbh = C4::Context->dbh; if ( $rank eq "del" ) { - my $query = qq/ + my $query = " UPDATE reserves SET cancellationdate=now() - WHERE biblionumber = ? - AND borrowernumber = ? - /; + WHERE reserve_id = ? + "; my $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borrower ); + $sth->execute( $reserve_id ); $sth->finish; - $query = qq/ + $query = " INSERT INTO old_reserves SELECT * FROM reserves - WHERE biblionumber = ? - AND borrowernumber = ? - /; + WHERE reserve_id = ? + "; $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borrower ); - $query = qq/ + $sth->execute( $reserve_id ); + $query = " DELETE FROM reserves - WHERE biblionumber = ? - AND borrowernumber = ? - /; + WHERE reserve_id = ? + "; $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borrower ); + $sth->execute( $reserve_id ); } elsif ($rank =~ /^\d+/ and $rank > 0) { my $query = " UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL, waitingdate = NULL - WHERE biblionumber = ? - AND borrowernumber = ? + WHERE reserve_id = ? "; my $sth = $dbh->prepare($query); - $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower); + $sth->execute( $rank, $branchcode, $itemnumber, $reserve_id ); $sth->finish; if ( defined( $suspend_until ) ) { if ( $suspend_until ) { $suspend_until = C4::Dates->new( $suspend_until )->output("iso"); - $dbh->do("UPDATE reserves SET suspend = 1, suspend_until = ? WHERE biblionumber = ? AND borrowernumber = ?", undef, ( $suspend_until, $biblio, $borrower ) ); + $dbh->do("UPDATE reserves SET suspend = 1, suspend_until = ? WHERE reserve_id = ?", undef, ( $suspend_until, $reserve_id ) ); } else { - $dbh->do("UPDATE reserves SET suspend_until = NULL WHERE biblionumber = ? AND borrowernumber = ?", undef, ( $biblio, $borrower ) ); + $dbh->do("UPDATE reserves SET suspend_until = NULL WHERE reserve_id = ?", undef, ( $reserve_id ) ); } } - _FixPriority( $biblio, $borrower, $rank); + _FixPriority( $reserve_id, $rank ); } } @@ -1127,6 +1094,7 @@ sub ModReserveFill { my ($res) = @_; my $dbh = C4::Context->dbh; # fill in a reserve record.... + my $reserve_id = $res->{'reserve_id'}; my $biblionumber = $res->{'biblionumber'}; my $borrowernumber = $res->{'borrowernumber'}; my $resdate = $res->{'reservedate'}; @@ -1175,7 +1143,7 @@ sub ModReserveFill { # now fix the priority on the others (if the priority wasn't # already sorted!).... unless ( $priority == 0 ) { - _FixPriority( $biblionumber, $borrowernumber ); + _FixPriority( $reserve_id ); } } @@ -1285,7 +1253,7 @@ sub ModReserveCancelAll { my ( $itemnumber, $borrowernumber ) = @_; #step 1 : cancel the reservation - my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber ); + my $CancelReserve = CancelReserve({ itemnumber => $itemnumber, borrowernumber => $borrowernumber }); #step 2 launch the subroutine of the others reserves ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber); @@ -1297,25 +1265,24 @@ sub ModReserveCancelAll { &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber) -Reduce the values of queuded list +Reduce the values of queued list =cut sub ModReserveMinusPriority { - my ( $itemnumber, $borrowernumber, $biblionumber ) = @_; + my ( $itemnumber, $reserve_id ) = @_; #first step update the value of the first person on reserv my $dbh = C4::Context->dbh; my $query = " UPDATE reserves SET priority = 0 , itemnumber = ? - WHERE borrowernumber=? - AND biblionumber=? + WHERE reserve_id = ? "; my $sth_upd = $dbh->prepare($query); - $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber ); + $sth_upd->execute( $itemnumber, $reserve_id ); # second step update all others reservs - _FixPriority($biblionumber, $borrowernumber, '0'); + _FixPriority( $reserve_id, '0'); } =head2 GetReserveInfo @@ -1328,9 +1295,9 @@ Current implementation this query should have a single result. =cut sub GetReserveInfo { - my ( $borrowernumber, $biblionumber ) = @_; + my ( $reserve_id ) = @_; my $dbh = C4::Context->dbh; - my $strsth="SELECT + my $strsth="SELECT reservedate, reservenotes, reserves.borrowernumber, @@ -1360,17 +1327,14 @@ sub GetReserveInfo { notes FROM reserves LEFT JOIN items USING(itemnumber) - LEFT JOIN borrowers USING(borrowernumber) - LEFT JOIN biblio ON (reserves.biblionumber=biblio.biblionumber) - WHERE - reserves.borrowernumber=? - AND reserves.biblionumber=?"; - my $sth = $dbh->prepare($strsth); - $sth->execute($borrowernumber,$biblionumber); - - my $data = $sth->fetchrow_hashref; - return $data; + LEFT JOIN borrowers USING(borrowernumber) + LEFT JOIN biblio ON (reserves.biblionumber=biblio.biblionumber) + WHERE reserves.reserve_id = ?"; + my $sth = $dbh->prepare($strsth); + $sth->execute($reserve_id); + my $data = $sth->fetchrow_hashref; + return $data; } =head2 IsAvailableForItemLevelRequest @@ -1455,29 +1419,25 @@ Input: $where is 'up', 'down', 'top' or 'bottom'. Biblionumber, Date reserve was =cut sub AlterPriority { - my ( $where, $borrowernumber, $biblionumber ) = @_; - + my ( $where, $reserve_id ) = @_; + #warn "C4::Reserves::AlterPriority( $where, $reserve_id )"; my $dbh = C4::Context->dbh; - ## Find this reserve - my $sth = $dbh->prepare('SELECT * FROM reserves WHERE biblionumber = ? AND borrowernumber = ? AND cancellationdate IS NULL'); - $sth->execute( $biblionumber, $borrowernumber ); - my $reserve = $sth->fetchrow_hashref(); - $sth->finish(); + my $reserve = GetReserve( $reserve_id ); if ( $where eq 'up' || $where eq 'down' ) { my $priority = $reserve->{'priority'}; $priority = $where eq 'up' ? $priority - 1 : $priority + 1; - _FixPriority( $biblionumber, $borrowernumber, $priority ) + _FixPriority( $reserve_id, $priority ) } elsif ( $where eq 'top' ) { - _FixPriority( $biblionumber, $borrowernumber, '1' ) + _FixPriority( $reserve_id, '1' ) } elsif ( $where eq 'bottom' ) { - _FixPriority( $biblionumber, $borrowernumber, '999999' ) + _FixPriority( $reserve_id, '999999' ) } } @@ -1491,27 +1451,20 @@ This function sets the lowestPriority field to true if is false, and false if it =cut sub ToggleLowestPriority { - my ( $borrowernumber, $biblionumber ) = @_; + my ( $reserve_id ) = @_; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "UPDATE reserves SET lowestPriority = NOT lowestPriority - WHERE biblionumber = ? - AND borrowernumber = ?" - ); - $sth->execute( - $biblionumber, - $borrowernumber, - ); + my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); + $sth->execute( $reserve_id ); $sth->finish; - _FixPriority( $biblionumber, $borrowernumber, '999999' ); + _FixPriority( $reserve_id, '999999' ); } =head2 ToggleSuspend - ToggleSuspend( $borrowernumber, $biblionumber ); + ToggleSuspend( $reserve_id ); This function sets the suspend field to true if is false, and false if it is true. If the reserve is currently suspended with a suspend_until date, that date will @@ -1520,7 +1473,7 @@ be cleared when it is unsuspended. =cut sub ToggleSuspend { - my ( $borrowernumber, $biblionumber, $suspend_until ) = @_; + my ( $reserve_id, $suspend_until ) = @_; $suspend_until = output_pref( dt_from_string( $suspend_until ), 'iso' ) if ( $suspend_until ); @@ -1531,14 +1484,12 @@ sub ToggleSuspend { my $sth = $dbh->prepare( "UPDATE reserves SET suspend = NOT suspend, suspend_until = CASE WHEN suspend = 0 THEN NULL ELSE $do_until END - WHERE biblionumber = ? - AND borrowernumber = ? + WHERE reserve_id = ? "); my @params; push( @params, $suspend_until ) if ( $suspend_until ); - push( @params, $biblionumber ); - push( @params, $borrowernumber ); + push( @params, $reserve_id ); $sth->execute( @params ); $sth->finish; @@ -1603,7 +1554,7 @@ sub SuspendAll { =head2 _FixPriority - &_FixPriority($biblio,$borrowernumber,$rank,$ignoreSetLowestRank); + &_FixPriority( $reserve_id, $rank, $ignoreSetLowestRank); Only used internally (so don't export it) Changed how this functions works # @@ -1615,41 +1566,39 @@ in new priority rank =cut sub _FixPriority { - my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank ) = @_; + my ( $reserve_id, $rank, $ignoreSetLowestRank ) = @_; my $dbh = C4::Context->dbh; - if ( $rank eq "del" ) { - CancelReserve( $biblio, undef, $borrowernumber ); - } - if ( $rank eq "W" || $rank eq "0" ) { + + my $res = GetReserve( $reserve_id ); + + if ( $rank eq "del" ) { + CancelReserve({ reserve_id => $reserve_id }); + } + elsif ( $rank eq "W" || $rank eq "0" ) { # make sure priority for waiting or in-transit items is 0 - my $query = qq/ + my $query = " UPDATE reserves SET priority = 0 - WHERE biblionumber = ? - AND borrowernumber = ? - AND found IN ('W', 'T') - /; + WHERE reserve_id = ? + AND found IN ('W', 'T') + "; my $sth = $dbh->prepare($query); - $sth->execute( $biblio, $borrowernumber ); + $sth->execute( $reserve_id ); } my @priority; my @reservedates; # get whats left -# FIXME adding a new security in returned elements for changing priority, -# now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve) - # This is wrong a waiting reserve has W set - # The assumption that having an itemnumber set means waiting is wrong and should be corrected any place it occurs - my $query = qq/ - SELECT borrowernumber, reservedate, constrainttype + my $query = " + SELECT reserve_id, borrowernumber, reservedate, constrainttype FROM reserves WHERE biblionumber = ? - AND ((found <> 'W' AND found <> 'T') or found is NULL) + AND ((found <> 'W' AND found <> 'T') OR found IS NULL) ORDER BY priority ASC - /; + "; my $sth = $dbh->prepare($query); - $sth->execute($biblio); + $sth->execute( $res->{'biblionumber'} ); while ( my $line = $sth->fetchrow_hashref ) { push( @reservedates, $line ); push( @priority, $line ); @@ -1659,7 +1608,7 @@ sub _FixPriority { my $i; my $key = -1; # to allow for 0 to be a valid result for ( $i = 0 ; $i < @priority ; $i++ ) { - if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) { + if ( $reserve_id == $priority[$i]->{'reserve_id'} ) { $key = $i; # save the index last; } @@ -1675,29 +1624,25 @@ sub _FixPriority { # now fix the priority on those that are left.... $query = " - UPDATE reserves - SET priority = ? - WHERE biblionumber = ? - AND borrowernumber = ? - AND reservedate = ? - AND found IS NULL + UPDATE reserves + SET priority = ? + WHERE reserve_id = ? "; $sth = $dbh->prepare($query); for ( my $j = 0 ; $j < @priority ; $j++ ) { $sth->execute( - $j + 1, $biblio, - $priority[$j]->{'borrowernumber'}, - $priority[$j]->{'reservedate'} + $j + 1, + $priority[$j]->{'reserve_id'} ); $sth->finish; } - $sth = $dbh->prepare( "SELECT borrowernumber FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); + $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); $sth->execute(); unless ( $ignoreSetLowestRank ) { while ( my $res = $sth->fetchrow_hashref() ) { - _FixPriority( $biblio, $res->{'borrowernumber'}, '999999', 1 ); + _FixPriority( $res->{'reserve_id'}, '999999', 1 ); } } } @@ -1736,7 +1681,8 @@ sub _Findgroupreserve { reserves.priority AS priority, reserves.timestamp AS timestamp, biblioitems.biblioitemnumber AS biblioitemnumber, - reserves.itemnumber AS itemnumber + reserves.itemnumber AS itemnumber, + reserves.reserve_id AS reserve_id, FROM reserves JOIN biblioitems USING (biblionumber) JOIN hold_fill_targets USING (biblionumber, borrowernumber, itemnumber) @@ -1969,7 +1915,7 @@ sub _ShiftPriorityByDateAndPriority { =head2 MoveReserve - MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) + MoveReserve( $reserve_id, $cancelreserve ) Use when checking out an item to handle reserves If $cancelreserve boolean is set to true, it will remove existing reserve @@ -2011,8 +1957,11 @@ sub MoveReserve { RevertWaitingStatus({ itemnumber => $itemnumber }); } elsif ( $cancelreserve eq 'cancel' || $cancelreserve ) { # cancel reserves on this item - CancelReserve(0, $res->{'itemnumber'}, $res->{'borrowernumber'}); - CancelReserve($res->{'biblionumber'}, 0, $res->{'borrowernumber'}); + CancelReserve({ + biblionumber => $res->{'biblionumber'}, + itemnumber => $res->{'itemnumber'}, + borrowernumber => $res->{'borrowernumber'} + }); } } } @@ -2028,7 +1977,7 @@ This shifts the holds from C<$from_biblio> to C<$to_biblio> and reorders them by sub MergeHolds { my ( $dbh, $to_biblio, $from_biblio ) = @_; my $sth = $dbh->prepare( - "SELECT count(*) as reservenumber FROM reserves WHERE biblionumber = ?" + "SELECT count(*) as reserve_id FROM reserves WHERE biblionumber = ?" ); $sth->execute($from_biblio); if ( my $data = $sth->fetchrow_hashref() ) { @@ -2121,6 +2070,41 @@ sub RevertWaitingStatus { return $sth->execute( $reserve->{'reserve_id'} ); } +=head2 GetReserveId + + $reserve_id = GetReserveId({ biblionumber => $biblionumber, borrowernumber => $borrowernumber [, itemnumber => $itemnumber ] }); + + Returnes the first reserve id that matches the given criteria + +=cut + +sub GetReserveId { + my ( $params ) = @_; + + return unless ( ( $params->{'biblionumber'} || $params->{'itemnumber'} ) && $params->{'borrowernumber'} ); + + my $dbh = C4::Context->dbh(); + + my $sql = "SELECT reserve_id FROM reserves WHERE biblionumber "; + + my @params; + my @limits; + foreach my $key ( keys %$params ) { + if ( defined( $params->{$key} ) ) { + push( @limits, "$key = ?" ); + push( @params, $params->{$key} ); + } + } + + $sql .= join( " AND ", @limits ); + + my $sth = $dbh->prepare( $sql ); + $sth->execute( @params ); + my $row = $sth->fetchrow_hashref(); + + return $row->{'reserve_id'}; +} + =head2 ReserveSlip ReserveSlip($branchcode, $borrowernumber, $biblionumber) diff --git a/C4/SIP/ILS/Transaction/Hold.pm b/C4/SIP/ILS/Transaction/Hold.pm index a2ca13e..9586272 100644 --- a/C4/SIP/ILS/Transaction/Hold.pm +++ b/C4/SIP/ILS/Transaction/Hold.pm @@ -85,10 +85,13 @@ sub drop_hold { return $self; } my $bib = GetBiblioFromItemNumber(undef, $self->{item}->id); - # FIXME: figure out if it is a item or title hold. Till then, cancel both. - CancelReserve($bib->{biblionumber}, undef, $borrower->{borrowernumber}); - CancelReserve(undef, $self->{item}->id, $borrower->{borrowernumber}); - # unfortunately no meaningful return value here either + + CancelReserve({ + biblionumber => $bib->{biblionumber}, + itemnumber => $self->{item}->id, + borrowernumber => $borrower->{borrowernumber} + }); + $self->ok(1); return $self; } @@ -119,17 +122,11 @@ sub change_hold { return $self; } my $bibno = $bib->{biblionumber}; - ModReserve($bibno, $borrower->{borrowernumber}, $branch, GetBiblioItemByBiblioNumber($bibno)); - # unfortunately no meaningful return value - # ModReserve needs to be fixed to maintain priority by iteself (Feb 2008) + ModReserve({ biblionumber => $bibno, borrowernumber => $borrower->{borrowernumber}, branchcode => $branch }); + $self->ok(1); return $self; } + 1; __END__ - -# 11 friggin arguments -AddReserve($branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$startdate,$notes,$title,$checkitem,$found) - -ModReserve($rank, $biblio, $borrower, $branch , $itemnumber) - diff --git a/circ/branchtransfers.pl b/circ/branchtransfers.pl index ad7aa9a..6ce9857 100755 --- a/circ/branchtransfers.pl +++ b/circ/branchtransfers.pl @@ -80,7 +80,10 @@ my $ignoreRs = 0; # Deal with the requests.... if ( $request eq "KillWaiting" ) { my $item = $query->param('itemnumber'); - CancelReserve( 0, $item, $borrowernumber ); + CancelReserve({ + itemnumber => $item, + borrowernumber => $borrowernumber + }); $cancelled = 1; $reqmessage = 1; } @@ -93,7 +96,10 @@ elsif ( $request eq "SetWaiting" ) { } elsif ( $request eq 'KillReserved' ) { my $biblio = $query->param('biblionumber'); - CancelReserve( $biblio, 0, $borrowernumber ); + CancelReserve({ + biblionumber => $biblio, + borrowernumber => $borrowernumber + }); $cancelled = 1; $reqmessage = 1; } diff --git a/circ/circulation.pl b/circ/circulation.pl index 91fd1a2..f9db07f 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -354,7 +354,7 @@ if ($borrowernumber) { $getreserv{nottransfered} = 0; $getreserv{reservedate} = format_date( $num_res->{'reservedate'} ); - $getreserv{reservenumber} = $num_res->{'reservenumber'}; + $getreserv{reserve_id} = $num_res->{'reserve_id'}; $getreserv{title} = $getiteminfo->{'title'}; $getreserv{itemtype} = $itemtypeinfo->{'description'}; $getreserv{author} = $getiteminfo->{'author'}; diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index d5d15d7..2d2218b 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -406,3 +406,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('NotesBlacklist','','List of notes fields that should not appear in the title notes/description separator of details',NULL,'free'); INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('SCOUserCSS', '', NULL, 'Add CSS to be included in the SCO module in an embedded