From f3034e5a1439deba2a891cbb217ec91f3952ff28 Mon Sep 17 00:00:00 2001 From: Nahuel ANGELINETTI Date: Fri, 12 Jun 2009 17:53:43 +0200 Subject: [PATCH] [HEAD] (bug #3323) allow rules for reserves in issuing rules. This patch move reserves to issuing rules, and check reserves from branchcode/categorycode/itemtype when it's possible. In some case we cannot know the branchcode or the itemtype of the document needed to be reserved, so default values(in issuing rules) are used. It introduce a new syspref : ReservesControlBranch that define which branch should be used to control the user reserves rights and a new column in issuingrules table to store reserves rules. --- C4/Circulation.pm | 2 +- C4/Reserves.pm | 176 ++++++++++++++++++ admin/smart-rules.pl | 9 +- .../data/mysql/en/mandatory/sysprefs.sql | 2 +- .../unimarc_standard_systemprefs.sql | 2 +- installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/updatedatabase.pl | 16 ++ .../prog/en/modules/admin/smart-rules.tmpl | 3 + opac/opac-reserve.pl | 20 +- reserve/request.pl | 22 ++- 10 files changed, 227 insertions(+), 26 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 7ed516f230..e33828b6e5 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -712,7 +712,7 @@ sub CanBookBeIssued { if ( $borrower->{'dateexpiry'} eq '0000-00-00') { $issuingimpossible{EXPIRED} = 1; } else { - my @expirydate= split /-/,$borrower->{'dateexpiry'}; + my @expirydate= split (/-/,$borrower->{'dateexpiry'}); if($expirydate[0]==0 || $expirydate[1]==0|| $expirydate[2]==0 || Date_to_Days(Today) > Date_to_Days( @expirydate )) { $issuingimpossible{EXPIRED} = 1; diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 90c6fd7694..bd6bd8c360 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -112,6 +112,8 @@ BEGIN { &ModReserveCancelAll &ModReserveMinusPriority + &CanBookBeReserved + &CanItemBeReserved &CheckReserves &CancelReserve @@ -326,6 +328,180 @@ sub GetReservesFromBorrowernumber { } #------------------------------------------------------------------------------------- +=item CanBookBeReserved + +$error = &CanBookBeReserved($borrowernumber, $biblionumber) + +=cut + +sub CanBookBeReserved{ + my ($borrowernumber, $biblionumber) = @_; + + my $dbh = C4::Context->dbh; + my $biblio = GetBiblioData($biblionumber); + my $borrower = C4::Members::GetMember($borrowernumber); + my $controlbranch = C4::Context->preference('ReservesControlBranch'); + my $itype = C4::Context->preference('item-level_itypes'); + my $reservesrights= 0; + my $reservescount = 0; + + # we retrieve the user rights + my @args; + my $rightsquery = "SELECT categorycode, itemtype, branchcode, reservesallowed + FROM issuingrules + WHERE categorycode = ?"; + push @args,$borrower->{categorycode}; + + if($controlbranch eq "ItemHomeLibrary"){ + $rightsquery .= " AND branchcode = '*'"; + }elsif($controlbranch eq "PatronLibrary"){ + $rightsquery .= " AND branchcode IN (?,'*')"; + push @args, $borrower->{branchcode}; + } + + if(not $itype){ + $rightsquery .= " AND itemtype IN (?,'*')"; + push @args, $biblio->{itemtype}; + }else{ + $rightsquery .= " AND itemtype = '*'"; + } + + $rightsquery .= " ORDER BY categorycode DESC, itemtype DESC, branchcode DESC"; + + my $sthrights = $dbh->prepare($rightsquery); + $sthrights->execute(@args); + + if(my $row = $sthrights->fetchrow_hashref()){ + $reservesrights = $row->{reservesallowed}; + } + + @args = (); + # we count how many reserves the borrower have + my $countquery = "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 = ? + "; + push @args, $borrowernumber; + + if(not $itype){ + $countquery .= "AND itemtype = ?"; + push @args, $biblio->{itemtype}; + } + + if($controlbranch eq "PatronLibrary"){ + $countquery .= " AND borrowers.branchcode = ? "; + push @args, $borrower->{branchcode}; + } + + my $sthcount = $dbh->prepare($countquery); + $sthcount->execute(@args); + + if(my $row = $sthcount->fetchrow_hashref()){ + $reservescount = $row->{count}; + } + + if($reservescount < $reservesrights){ + return 1; + }else{ + return 0; + } + +} + +=item CanItemBeReserved + +$error = &CanItemBeReserved($borrowernumber, $itemnumber) + +this function return 1 if an item can be issued by this borrower. + +=cut + +sub CanItemBeReserved{ + my ($borrowernumber, $itemnumber) = @_; + + my $dbh = C4::Context->dbh; + my $allowedreserves = 0; + + my $controlbranch = C4::Context->preference('ReservesControlBranch'); + my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; + + # we retrieve borrowers and items informations # + my $item = GetItem($itemnumber); + my $borrower = C4::Members::GetMember($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 $itemtype = $item->{$itype}; + my $categorycode = $borrower->{categorycode}; + my $branchcode = ""; + my $branchfield = "reserves.branchcode"; + + if( $controlbranch eq "ItemHomeLibrary" ){ + $branchfield = "items.homebranch"; + $branchcode = $item->{homebranch}; + }elsif( $controlbranch eq "PatronLibrary" ){ + $branchfield = "borrowers.branchcode"; + $branchcode = $borrower->{branchcode}; + } + + # we retrieve rights + $sth->execute($categorycode, $itemtype, $branchcode); + if(my $rights = $sth->fetchrow_hashref()){ + $itemtype = $rights->{itemtype}; + $allowedreserves = $rights->{reservesallowed}; + }else{ + $itemtype = '*'; + } + + # we retrieve count + + $querycount .= "AND $branchfield = ?"; + + $querycount .= " AND $itype = ?" if ($itemtype ne "*"); + my $sthcount = $dbh->prepare($querycount); + + if($itemtype eq "*"){ + $sthcount->execute($borrowernumber, $branchcode); + }else{ + $sthcount->execute($borrowernumber, $branchcode, $itemtype); + } + + my $reservecount = "0"; + if(my $rowcount = $sthcount->fetchrow_hashref()){ + $reservecount = $rowcount->{count}; + } + + # we check if it's ok or not + if( $reservecount < $allowedreserves ){ + return 1; + }else{ + return 0; + } +} + =item GetReserveCount $number = &GetReserveCount($borrowernumber); diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl index db5bca905a..79cd0af200 100755 --- a/admin/smart-rules.pl +++ b/admin/smart-rules.pl @@ -99,8 +99,8 @@ elsif ($op eq 'delete-branch-item') { # save the values entered elsif ($op eq 'add') { my $sth_search = $dbh->prepare("SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?"); - my $sth_insert = $dbh->prepare("INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, issuelength, fine, finedays, firstremind, chargeperiod) VALUES(?,?,?,?,?,?,?,?,?)"); - my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, issuelength=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); + my $sth_insert = $dbh->prepare("INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, fine, finedays,firstremind, chargeperiod) VALUES(?,?,?,?,?,?,?,?,?,?)"); + my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); my $br = $branch; # branch my $bor = $input->param('categorycode'); # borrower category @@ -111,6 +111,7 @@ elsif ($op eq 'add') { my $chargeperiod = $input->param('chargeperiod'); my $maxissueqty = $input->param('maxissueqty'); my $renewalsallowed = $input->param('renewalsallowed'); + my $reservesallowed = $input->param('reservesallowed'); $maxissueqty =~ s/\s//g; $maxissueqty = undef if $maxissueqty !~ /^\d+/; my $issuelength = $input->param('issuelength'); @@ -119,9 +120,9 @@ elsif ($op eq 'add') { $sth_search->execute($br,$bor,$cat); my $res = $sth_search->fetchrow_hashref(); if ($res->{total}) { - $sth_update->execute($fine, $finedays, $firstremind, $chargeperiod, $maxissueqty,$renewalsallowed,$issuelength,$br,$bor,$cat); + $sth_update->execute($fine, $finedays, $firstremind, $chargeperiod, $maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$br,$bor,$cat); } else { - $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$issuelength,$fine, $finedays,$firstremind,$chargeperiod); + $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$fine,$finedays,$firstremind,$chargeperiod); } } elsif ($op eq "set-branch-defaults") { diff --git a/installer/data/mysql/en/mandatory/sysprefs.sql b/installer/data/mysql/en/mandatory/sysprefs.sql index a978fad3d1..771e56e565 100644 --- a/installer/data/mysql/en/mandatory/sysprefs.sql +++ b/installer/data/mysql/en/mandatory/sysprefs.sql @@ -56,7 +56,6 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MARCOrgCode','OSt','Define MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html','','free'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MaxFine',9999,'Maximum fine a patron can have for a single late return','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxoutstanding',5,'maximum amount withstanding to be able make holds','','Integer'); -INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxreserves',50,'Define maximum number of holds a patron can place','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('memberofinstitution',0,'If ON, patrons can be linked to institutions',NULL,'YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MIME','EXCEL','Define the default application for exporting report data','EXCEL|OPENOFFICE.ORG','Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('noissuescharge',5,'Define maximum amount withstanding before check outs are blocked','','Integer'); @@ -245,3 +244,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('v INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('viewLabeledMARC','0','Allow display of labeled MARC view of bibiographic records','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('viewMARC','1','Allow display of MARC view of bibiographic records','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('FilterBeforeOverdueReport','0','Do not run overdue report until filter selected','','YesNo'); +INSERT INTO systempreferences (variable,value, options, explanation, type) VALUES('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Branch checked for members reservations rights','Choice'); diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql index b9b616e566..64daa4fa8c 100644 --- a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql @@ -57,7 +57,6 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MARCOrgCode', '0', 'Ce paramètre définit votre code organisme MARC. Utilisé en MARC21. Voir - http://www.loc.gov/marc/organizations/orgshome.html', '', ''); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MaxFine','9999','Amende maximum qu''un ahdérent peut avoir pour un retour en retard','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxoutstanding', '5', 'Ce paramètre définit le montant maximal des dettes au dela duquel le lecteur ne peut plus faire de réservation', '', 'Integer'); -INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxreserves', '2', 'Ce paramètre définit le nombre maximal de réservations qu''un lecteur peut faire.', '', 'Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('memberofinstitution', '0', 'Vos adhérents sont ils membres d''une institution ?', NULL, 'YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MIME', 'OPENOFFICE.ORG', 'Ce paramètre définit l''application par défaut à ouvrir lorsqu''on télécharge un fichier (OpenOffice.org ou MS-Excel habituellement)', 'EXCEL|OPENOFFICE.ORG', 'Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('noissuescharge', '5', 'Ce paramètre définit le montant maximal des dettes au delà duquel le lecteur ne peut plus emprunter', '', 'Integer'); @@ -250,3 +249,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('v INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('viewLabeledMARC','0','Autoriser l''affichage MARC labellis des notices bibliographiques','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('viewMARC','1','Autoriser l''affichage de la vue MARC des notices bibliographiques','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type)VALUES('FilterBeforeOverdueReport','0','Ne pas lancer le rapport sur les retards tant qu''il n''y a pas de filtre','','YesNo'); +INSERT INTO systempreferences (variable,value, options, explanation, type) VALUES('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Site de controle pour les reservations','Choice'); diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index e2b62afa4e..6c037e35ca 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1143,6 +1143,7 @@ CREATE TABLE `issuingrules` ( `maxissueqty` int(4) default NULL, `issuelength` int(4) default NULL, `renewalsallowed` smallint(6) NOT NULL default "0", + `reservesallowed` smallint(6) NOT NULL default "0", `branchcode` varchar(10) NOT NULL default '', PRIMARY KEY (`branchcode`,`categorycode`,`itemtype`), KEY `categorycode` (`categorycode`), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index dd0cf7d006..d05dedb2a3 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -2192,6 +2192,22 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { print "Upgrade to $DBversion done (Moving allowed renewals from itemtypes to issuingrule)\n"; } +$DBversion = '3.01.00.040'; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do('ALTER TABLE issuingrules ADD COLUMN `reservesallowed` smallint(6) NOT NULL default "0" AFTER `renewalsallowed`;'); + + my $maxreserves = C4::Context->preference('maxreserves'); + $sth = $dbh->prepare('UPDATE issuingrules SET reservesallowed = ?;'); + $sth->execute($maxreserves); + + $dbh->do('DELETE FROM systempreferences WHERE variable = "maxreserves";'); + + $dbh->do("INSERT INTO systempreferences (variable,value, options, explanation, type) VALUES('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Branch checked for members reservations rights','Choice')"); + + SetVersion ($DBversion); + print "Upgrade to $DBversion done (Moving max allowed reserves from system preference to issuingrule)\n"; +} + =item DropAllForeignKeys($table) Drop all foreign keys of the table $table diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl index 4f9aa992f7..f74b24261e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl @@ -70,6 +70,7 @@ $(document).ready(function() { Fine Charging Interval Current Checkouts Allowed Renewals Allowed + Reserves Allowed Loan Period  @@ -105,6 +106,7 @@ $(document).ready(function() { time(s) + time(s) day(s) &categorycode=&branch=">Delete @@ -134,6 +136,7 @@ $(document).ready(function() { day(s) + day(s) "/> diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 4395f38145..1cfaa0b1bf 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -32,8 +32,6 @@ use C4::Branch; # GetBranches use C4::Debug; # use Data::Dumper; -my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); - my $query = new CGI; my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { @@ -190,11 +188,13 @@ if ( $query->param('place_reserve') ) { my $biblioData = $biblioDataHash{$biblioNum}; my $found; + my $canreserve = 0; # If a specific item was selected and the pickup branch is the same as the # holdingbranch, force the value $rank and $found. my $rank = $biblioData->{rank}; if ($itemNum ne ''){ + $canreserve = 1 if CanItemBeReserved($borrowernumber,$itemNum); $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); my $item = GetItem($itemNum); if ( $item->{'holdingbranch'} eq $branch ){ @@ -203,12 +203,13 @@ if ( $query->param('place_reserve') ) { } else { # Inserts a null into the 'itemnumber' field of 'reserves' table. + $canreserve = 1 if CanBookBeReserved($borrowernumber,$biblioNum); $itemNum = undef; } # Here we actually do the reserveration. Stage 3. AddReserve($branch, $borrowernumber, $biblioNum, 'a', [$biblioNum], $rank, $notes, - $biblioData->{'title'}, $itemNum, $found); + $biblioData->{'title'}, $itemNum, $found) if $canreserve; } print $query->redirect("/cgi-bin/koha/opac-user.pl#opac-user-holds"); @@ -253,11 +254,8 @@ if ( $borr->{debarred} && ($borr->{debarred} eq 1) ) { my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); $template->param( RESERVES => \@reserves ); -if ( scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) { - $template->param( message => 1 ); - $noreserves = 1; - $template->param( too_many_reserves => scalar(@reserves)); -} + + foreach my $res (@reserves) { foreach my $biblionumber (@biblionumbers) { if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) { @@ -421,7 +419,7 @@ foreach my $biblioNum (@biblionumbers) { $policy_holdallowed = 0; } - if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed) { + if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum)) { $itemLoopIter->{available} = 1; $numCopiesAvailable++; } @@ -447,6 +445,10 @@ foreach my $biblioNum (@biblionumbers) { $biblioLoopIter{holdable} = undef; } + if(not CanBookBeReserved($borrowernumber,$biblioNum)){ + $biblioLoopIter{holdable} = undef; + } + push @$biblioLoop, \%biblioLoopIter; } diff --git a/reserve/request.pl b/reserve/request.pl index 9898a86393..2b2c43241a 100755 --- a/reserve/request.pl +++ b/reserve/request.pl @@ -88,6 +88,7 @@ my $borrowerslist; my $messageborrower; my $warnings; my $messages; +my $maxreserves; my $date = C4::Dates->today('iso'); @@ -115,24 +116,20 @@ if ($cardnumber) { my $diffbranch; my @getreservloop; my $count_reserv = 0; - my $maxreserves; # we check the reserves of the borrower, and if he can reserv a document # FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ... + + my $number_reserves = GetReserveCount( $borrowerinfo->{'borrowernumber'} ); - - if ( $number_reserves > C4::Context->preference('maxreserves') ) { - $warnings = 1; - $maxreserves = 1; - } - + # we check the date expiry of the borrower (only if there is an expiry date, otherwise, set to 1 (warn) my $expiry_date = $borrowerinfo->{dateexpiry}; my $expiry = 0; # flag set if patron account has expired if ($expiry_date and $expiry_date ne '0000-00-00' and - Date_to_Days(split /-/,$date) > Date_to_Days(split /-/,$expiry_date)) { + Date_to_Days(split (/-/,$date)) > Date_to_Days(split (/-/,$expiry_date))) { $messages = $expiry = 1; }else{ $expiry = 0; @@ -159,7 +156,6 @@ if ($cardnumber) { borroweremailpro => $borrowerinfo->{'emailpro'}, borrowercategory => $borrowerinfo->{'category'}, borrowerreservs => $count_reserv, - maxreserves => $maxreserves, expiry => $expiry, diffbranch => $diffbranch, messages => $messages, @@ -215,6 +211,11 @@ if ($multihold) { my @biblioloop = (); foreach my $biblionumber (@biblionumbers) { + if ( not CanBookBeReserved($borrowerinfo->{borrowernumber}, $biblionumber) ) { + $warnings = 1; + $maxreserves = 1; + } + my %biblioloopiter = (); my $dat = GetBiblioData($biblionumber); @@ -401,7 +402,7 @@ foreach my $biblionumber (@biblionumbers) { $policy_holdallowed = 0; } - if (IsAvailableForItemLevelRequest($itemnumber) and not $item->{cantreserve}) { + if (IsAvailableForItemLevelRequest($itemnumber) and not $item->{cantreserve} and CanItemBeReserved($borrowerinfo->{borrowernumber}, $itemnumber) ) { if ( not $policy_holdallowed and C4::Context->preference( 'AllowHoldPolicyOverride' ) ) { $item->{override} = 1; $num_override++; @@ -547,6 +548,7 @@ foreach my $biblionumber (@biblionumbers) { $template->param( biblioloop => \@biblioloop ); $template->param( biblionumbers => $biblionumbers ); +$template->param( maxreserves => $maxreserves ); if ($multihold) { $template->param( multi_hold => 1 ); -- 2.20.1