@@ -, +, @@
you should not be able to ( default is 1 per 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 | 7 ++
.../en/modules/admin/preferences/circulation.pref | 7 ++-
.../prog/en/modules/reserve/request.tt | 4 +-
.../opac-tmpl/prog/en/modules/opac-reserve.tt | 6 ++-
opac/opac-reserve.pl | 28 ++++++---
reserve/request.pl | 37 +++++++++----
8 files changed, 100 insertions(+), 49 deletions(-)
--- a/C4/Reserves.pm
+++ a/C4/Reserves.pm
@@ -353,36 +353,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
--- a/installer/data/mysql/sysprefs.sql
+++ a/installer/data/mysql/sysprefs.sql
@@ -427,3 +427,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('UseCourseReserves', '0', 'Enable the course reserves feature.', NULL, 'YesNo');
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHoldNotes',0,'Show hold notes on OPAC','','YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CalculateFinesOnReturn','1','Switch to control if overdue fines are calculated on return or not', '', '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);
--- a/installer/data/mysql/updatedatabase.pl
+++ a/installer/data/mysql/updatedatabase.pl
@@ -7010,6 +7010,13 @@ CREATE TABLE IF NOT EXISTS borrower_files (
SetVersion($DBversion);
}
+$DBversion = "3.13.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
=head2 TableExists($table)
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -411,7 +411,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:
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt
+++ a/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);
@@ -240,7 +240,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
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt
+++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt
@@ -316,7 +316,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 %]
--- a/opac/opac-reserve.pl
+++ a/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(
@@ -171,7 +172,7 @@ foreach my $biblioNumber (@biblionumbers) {
#
if ( $query->param('place_reserve') ) {
my $reserve_cnt = 0;
- if ($MAXIMUM_NUMBER_OF_RESERVES) {
+ if ($maxreserves) {
$reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
}
@@ -255,8 +256,8 @@ if ( $query->param('place_reserve') ) {
}
my $notes = $query->param('notes_'.$biblioNum)||'';
- if ( $MAXIMUM_NUMBER_OF_RESERVES
- && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES )
+ if ( $maxreserves
+ && $reserve_cnt >= $maxreserves )
{
$canreserve = 0;
}
@@ -317,7 +318,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));
@@ -325,12 +326,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) {
@@ -374,6 +373,7 @@ foreach my $biblioNum (@biblionumbers) {
$biblioLoopIter{reservecount} = $biblioData->{reservecount};
$biblioLoopIter{already_reserved} = $biblioData->{already_reserved};
$biblioLoopIter{mandatorynotes}=0; #FIXME: For future use
+ $biblioLoopIter{holds_count} = $biblioData->{holds_count};
if (!$itemLevelTypes && $biblioData->{itemtype}) {
$biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
@@ -500,11 +500,14 @@ 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++;
}
+ # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib
+ $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'");
@@ -531,6 +534,11 @@ foreach my $biblioNum (@biblionumbers) {
if ($biblioLoopIter{already_reserved}) {
$biblioLoopIter{holdable} = 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;
}
--- a/reserve/request.pl
+++ a/reserve/request.pl
@@ -180,6 +180,7 @@ $template->param( messageborrower => $messageborrower );
# FIXME launch another time GetMember perhaps until
my $borrowerinfo = GetMember( borrowernumber => $borrowernumber_hold );
+my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord');
my @biblionumbers = ();
my $biblionumbers = $input->param('biblionumbers');
@@ -214,25 +215,33 @@ foreach my $biblionumber (@biblionumbers) {
my $totalcount = $count;
my $alreadyreserved;
+ my $holds_for_this_borrower_count = 0;
foreach my $res (@$reserves) {
if ( defined $res->{found} && $res->{found} eq 'W' ) {
$count--;
}
- if ( defined $borrowerinfo && ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) ) {
- $warnings = 1;
- $alreadyreserved = 1;
- $biblioloopiter{warn} = 1;
- $biblioloopiter{alreadyres} = 1;
+ if ( defined $borrowerinfo
+ && $borrowerinfo->{borrowernumber} eq $res->{borrowernumber} )
+ {
+ $holds_for_this_borrower_count++;
+
+ if ( $holds_for_this_borrower_count > $max_holds_per_record ) {
+ $warnings = 1;
+ $alreadyreserved = 1;
+ $biblioloopiter{warn} = 1;
+ $biblioloopiter{alreadyres} = 1;
+ }
}
}
- $template->param( alreadyreserved => $alreadyreserved,
- messages => $messages,
- warnings => $warnings,
- maxreserves=>$maxreserves,
- alreadypossession => $alreadypossession,
- );
+ $template->param(
+ alreadyreserved => $alreadyreserved,
+ messages => $messages,
+ warnings => $warnings,
+ maxreserves => $maxreserves,
+ alreadypossession => $alreadypossession,
+ );
# FIXME think @optionloop, is maybe obsolete, or must be switchable by a systeme preference fixed rank or not
@@ -449,6 +458,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;
}
--