From f3008090866bb699e092ec2232752352ecc29aa0 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Tue, 15 Jan 2013 10:18:03 -0500 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. Test Plan: 1) Apply patch for Bug 9394 1) Apply this patch 2) Run updatedatabase.pl 3) Attempt to place 2 holds for the same patron on the same record, you should not be able to ( default is 1 per record ) 4) Set MaxHoldsPerRecord to 3 5) Attempt to place multiple holds for one patron on one record, you should be able to place 3 holds for one patron on a given record. A 4th hold should result in a message stating the patron has placed the max number of holds allowed on this record. --- C4/Reserves.pm | 59 ++++++++++++-------- installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 6 ++ .../en/modules/admin/preferences/circulation.pref | 7 ++- .../prog/en/modules/reserve/request.tt | 25 ++++---- .../opac-tmpl/prog/en/modules/opac-reserve.tt | 6 ++- opac/opac-reserve.pl | 28 ++++++---- reserve/request.pl | 6 ++ 8 files changed, 89 insertions(+), 49 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 36777b0..4f01d77 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -373,36 +373,47 @@ sub GetReservesFromItemnumber { =head2 GetReservesFromBorrowernumber - $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber,$tatus); - -TODO :: Descritpion + $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber[,$status][,$biblionumber][,$itemnumber]); =cut sub GetReservesFromBorrowernumber { - my ( $borrowernumber, $status ) = @_; - my $dbh = C4::Context->dbh; - my $sth; - if ($status) { - $sth = $dbh->prepare(" - SELECT * - FROM reserves - WHERE borrowernumber=? - AND found =? - ORDER BY reservedate - "); - $sth->execute($borrowernumber,$status); - } else { - $sth = $dbh->prepare(" - SELECT * - FROM reserves - WHERE borrowernumber=? - ORDER BY reservedate - "); - $sth->execute($borrowernumber); + my ( $borrowernumber, $found, $biblionumber, $itemnumber ) = @_; + + my @params; + + my $sql = "SELECT * FROM reserves WHERE borrowernumber = ?"; + push( @params, $borrowernumber ); + + if ( $biblionumber ) { + $sql .= " AND biblionumber = ? "; + push( @params, $biblionumber ); + } + + if ( $itemnumber ) { + $sql .= " AND itemnumber = ? "; + push( @params, $itemnumber ); } + + if ( $found ) { + $sql .= " AND found = ? "; + push( @params, $found ); + } + + $sql .= " ORDER BY reservedate "; + + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare( $sql ); + + $sth->execute( @params ); + my $data = $sth->fetchall_arrayref({}); - return @$data; + + if ( scalar @$data ) { + return @$data; + } else { + return (); + } } #------------------------------------------------------------------------------------- =head2 CanBookBeReserved diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index ca9b6bd..032a8b1 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -416,3 +416,4 @@ INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ( INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('IntranetNumbersPreferPhrase','0', NULL, 'Control the use of phr operator in callnumber and standard number staff client searches', 'YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UNIMARCField100Language', 'fre','UNIMARC field 100 default language',NULL,'short'); INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo'); +INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('MaxHoldsPerRecord', '1', 'The maximum number of holds allowed per bibliographic record per borrower', NULL, NULL); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index a44e4e8..fa88980 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -6437,6 +6437,12 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.11.00.XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do("INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('MaxHoldsPerRecord', '1', 'The maximum number of holds allowed per bibliographic record per borrower', NULL, NULL)"); + print "Upgrade to $DBversion done (Add syspref MaxHoldsPerRecord)\n"; + SetVersion ($DBversion); +} =head1 FUNCTIONS diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 82c1c02..951b1ec 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -404,7 +404,12 @@ Circulation: - Patrons can only have - pref: maxreserves class: integer - - holds at once. + - total holds at a time. + - + - Patrons can only place + - pref: MaxHoldsPerRecord + class: integer + - holds on a single record at a time. - - pref: emailLibrarianWhenHoldIsPlaced choices: diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt index e9a5914..dae04ab 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt @@ -55,7 +55,7 @@ function check() { } if (alreadyreserved > "0"){ - msg += (_("- This patron had already placed a hold on this item") + "\n" + _("Please cancel the previous hold first") + "\n"); + msg += (_("This patron has already placed the maximum number of holds for this record.") + "\n\n" + _("Please cancel a previous hold first.") + "\n"); } if (msg == "") return(true); @@ -208,7 +208,7 @@ function checkMultiHold() {
  • Too Many Holds: [% borrowerfirstname %] [% borrowersurname %] has too many holds.
  • [% END %] [% IF ( alreadyreserved ) %] -
  • [% borrowerfirstname %] [% borrowersurname %] already has a hold on this item
  • +
  • [% borrowerfirstname %] [% borrowersurname %] has already placed the maximum allowed number of holds on this record
  • [% END %] [% IF ( none_available ) %]
  • No copies are available to be placed on hold
  • @@ -556,6 +556,7 @@ function checkMultiHold() { [% FOREACH reserveloo IN biblioloo.reserveloop %] [% UNLESS ( loop.odd ) %][% ELSE %][% END %] + + [% IF AutoResumeSuspendedHolds %] - - - Clear Date + + + Clear Date [% END %] [% ELSE %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt index 5788b38..2c021ed 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt @@ -296,7 +296,11 @@ [% IF ( bibitemloo.already_patron_possession ) %]
    This title cannot be requested because it's already in your possession.
    [% ELSE %] -
    This title cannot be requested.
    + [% IF bibitemloo.max_holds %] +
    This title cannot be requested. You have already placed the maximum number of requests allowed for this title.
    + [% ELSE %] +
    This title cannot be requested.
    + [% END %] [% END %] [% END %] [% END %] diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 07b4f76..96757f9 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -37,7 +37,8 @@ use C4::Debug; use Koha::DateUtils; # use Data::Dumper; -my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); +my $maxreserves = C4::Context->preference("maxreserves"); +my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord'); my $query = new CGI; my ( $template, $borrowernumber, $cookie ) = get_template_and_user( @@ -173,7 +174,7 @@ foreach my $biblioNumber (@biblionumbers) { if ( $query->param('place_reserve') ) { my $notes = $query->param('notes'); my $reserve_cnt = 0; - if ($MAXIMUM_NUMBER_OF_RESERVES) { + if ($maxreserves) { $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber ); } @@ -256,8 +257,8 @@ if ( $query->param('place_reserve') ) { $itemNum = undef; } - if ( $MAXIMUM_NUMBER_OF_RESERVES - && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES ) + if ( $maxreserves + && $reserve_cnt >= $maxreserves ) { $canreserve = 0; } @@ -318,7 +319,7 @@ if ( CheckBorrowerDebarred($borrowernumber) ) { my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); $template->param( RESERVES => \@reserves ); -if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) { +if ( $maxreserves && (scalar(@reserves) >= $maxreserves) ) { $template->param( message => 1 ); $noreserves = 1; $template->param( too_many_reserves => scalar(@reserves)); @@ -326,12 +327,10 @@ if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RES foreach my $res (@reserves) { foreach my $biblionumber (@biblionumbers) { if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) { -# $template->param( message => 1 ); -# $noreserves = 1; -# $template->param( already_reserved => 1 ); - $biblioDataHash{$biblionumber}->{already_reserved} = 1; + $biblioDataHash{$biblionumber}->{holds_count}++; } } + } unless ($noreserves) { @@ -373,7 +372,7 @@ foreach my $biblioNum (@biblionumbers) { $biblioLoopIter{author} = $biblioData->{author}; $biblioLoopIter{rank} = $biblioData->{rank}; $biblioLoopIter{reservecount} = $biblioData->{reservecount}; - $biblioLoopIter{already_reserved} = $biblioData->{already_reserved}; + $biblioLoopIter{holds_count} = $biblioData->{holds_count}; if (!$itemLevelTypes && $biblioData->{itemtype}) { $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description}; @@ -500,11 +499,13 @@ foreach my $biblioNum (@biblionumbers) { $policy_holdallowed = 0; } - if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) { + if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{holds_count} < $max_holds_per_record )) { $itemLoopIter->{available} = 1; $numCopiesAvailable++; } + $itemLoopIter->{available} = 0 if ( GetReservesFromBorrowernumber( $borrowernumber, undef, undef, $itemNum ) ); + # FIXME: move this to a pm my $dbh = C4::Context->dbh; my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'"); @@ -533,6 +534,11 @@ foreach my $biblioNum (@biblionumbers) { $biblioLoopIter{holdable} = undef; $anyholdable = undef; } + if ($biblioLoopIter{holds_count} >= $max_holds_per_record) { + $biblioLoopIter{holdable} = undef; + $anyholdable = undef; + $biblioLoopIter{max_holds} = 1; + } if(not CanBookBeReserved($borrowernumber,$biblioNum)){ $biblioLoopIter{holdable} = undef; $anyholdable = undef; diff --git a/reserve/request.pl b/reserve/request.pl index be1cebe..1ee5c92 100755 --- a/reserve/request.pl +++ b/reserve/request.pl @@ -495,6 +495,12 @@ foreach my $biblionumber (@biblionumbers) { $itemdata_enumchron = 1; } + # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib + if ( GetReservesFromBorrowernumber( $borrowerinfo->{borrowernumber}, undef, undef, $itemnumber) ) { + $item->{available} = 0; + $item->{override} = 0; + } + push @{ $biblioitem->{itemloop} }, $item; } -- 1.7.2.5