@@ -, +, @@ records with available items should not be possible --- C4/Reserves.pm | 66 ++++++++++++++++++++ installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 6 ++ .../en/modules/admin/preferences/circulation.pref | 7 +++ .../prog/en/includes/opac-detail-sidebar.inc | 12 ++-- .../opac-tmpl/prog/en/modules/opac-results.tt | 10 +-- opac/opac-detail.pl | 9 ++- opac/opac-search.pl | 9 ++- 8 files changed, 109 insertions(+), 11 deletions(-) --- a/C4/Reserves.pm +++ a/C4/Reserves.pm @@ -133,6 +133,7 @@ BEGIN { &SuspendAll &GetReservesControlBranch + &PreventOPACHoldsAnyAvailableItem ); @EXPORT_OK = qw( MergeHolds ); } @@ -2214,6 +2215,71 @@ sub GetReservesControlBranch { return $branchcode; } + +=head2 PreventOPACHoldsAnyAvailableItem +Checks if an item is available to have a hold placed on it from the OPAC only. +Specifically relates to items currently on the shelf (without a datedue). +If 'AllowOnShelfHolds' syspref is allowed then this will always return false i.e +PreventOPACHoldsAnyAvailableItem will not prevent OPAC holds. + +Is controlled by the 'PreventOPACHoldsAnyAvailableItem' system preference. + +The system preference has 2 states: + +* off: Not in effect. Allowing of hold will be determined elsewhere in the system. +* on: Each bibnumber will be checked for attached items. Each item is checked for +its availability. The only status that prevents a hold is when an item is on the +shelf and available. All other status should be ignored. + +Returns true when any item attached to the bib is on the shelf and available + +=cut + +sub PreventOPACHoldsAnyAvailableItem { + my $biblionumber = shift; + + if ( C4::Context->preference('AllowOnShelfHolds') or not C4::Context->preference('PreventOPACHoldsAnyAvailableItem') ) { + return 0; # we shouldn't be in here + } + + my @items = GetItemsInfo( $biblionumber ); + my $prevent_hold = 0; + my $dbh = C4::Context->dbh; + my $notforloan_query; + if (C4::Context->preference('item-level_itypes')) { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN itemtypes ON (itemtypes.itemtype = items.itype) + WHERE itemnumber = ?"; + } else { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN biblioitems USING (biblioitemnumber) + JOIN itemtypes USING (itemtype) + WHERE itemnumber = ?"; + } + my $sth = $dbh->prepare($notforloan_query); + foreach my $item (@items) { + $sth->execute( $item->{itemnumber} ); + my $notforloan_itemtype = 0; + if (my ($notforloan) = $sth->fetchrow_array) { + $notforloan_itemtype = 1 if $notforloan; + } + + if ( not $item->{datedue} ) { + if ($item->{itemlost} + or ( $item->{notforloan} > 0 ) + or ( $item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems') ) + or $item->{wthdrawn} + or $notforloan_itemtype) { + next; + } + else {$prevent_hold++} + } + } + return $prevent_hold; +} + =head1 AUTHOR Koha Development Team --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -301,6 +301,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('Persona','0','','Use Mozilla Persona for login','YesNo'), ('PrefillItem','0','','When a new item is added, should it be prefilled with last created item values?','YesNo'), ('previousIssuesDefaultSortOrder','asc','asc|desc','Specify the sort order of Previous Issues on the circulation page','Choice'), +('PreventOPACHoldsAnyAvailableItem,'0',NULL,'Define how OPAC users can place holds on items that are checked in (on the self),'Choice'), ('printcirculationslips','1','','If ON, enable printing circulation receipts','YesNo'), ('PrintNoticesMaxLines','0','','If greater than 0, sets the maximum number of lines an overdue notice will print. If the number of items is greater than this number, the notice will end with a warning asking the borrower to check their online account for a full list of overdue items.','Integer'), ('QueryAutoTruncate','1',NULL,'If ON, query truncation is enabled by default','YesNo'), --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -7743,6 +7743,12 @@ if(CheckVersion($DBversion)) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; + if ( CheckVersion($DBversion) ) { + $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('PreventOPACHoldsAnyAvailableItem', '0', 'Define how OPAC users can place holds on items that are checked in (on the self)', NULL ,'Choice')"); + print "Upgrade to $DBversion done (Bug 6837: Enchances AllowOnShelfHolds SystemPref, give more granular control over OPAC holds )\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 @@ -370,6 +370,13 @@ Circulation: no: "Don't allow" - hold requests to be placed on items that are not checked out. - + - pref: PreventOPACHoldsAnyAvailableItem + type: choice + choices: + yes: Prevent + no: Do not explicitly prevent + - holds to be placed when ANY item is on the shelf. (Preference is ignored if AllowOnShelfHolds is ON) + - - pref: AllowHoldDateInFuture choices: yes: Allow --- a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc +++ a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc @@ -2,12 +2,14 @@ [% UNLESS ( norequests ) %] [% IF ( opacuserlogin ) %] [% IF ( RequestOnOpac ) %] - [% IF ( AllowOnShelfHolds ) %] -
  • Place hold
  • - [% ELSE %] - [% IF ( ItemsIssued ) %] + [% UNLESS (PreventOPACHoldsAnyAvailableItem) %] + [% IF ( AllowOnShelfHolds ) %]
  • Place hold
  • - [% END %] + [% ELSE %] + [% IF ( ItemsIssued ) %] +
  • Place hold
  • + [% END %] + [% END %] [% END %] [% END %] [% END %] --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt +++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt @@ -667,11 +667,13 @@ $(document).ready(function(){ [% IF ( RequestOnOpac ) %] [% UNLESS ( SEARCH_RESULT.norequests ) %] [% IF ( opacuserlogin ) %] - [% IF ( AllowOnShelfHolds ) %] - Place hold - [% ELSE %] - [% IF ( SEARCH_RESULT.itemsissued ) %] + [% UNLESS SEARCH_RESULT.prevent_holds %] + [% IF ( AllowOnShelfHolds ) %] Place hold + [% ELSE %] + [% IF ( SEARCH_RESULT.itemsissued ) %] + Place hold + [% END %] [% END %] [% END %] [% END %] --- a/opac/opac-detail.pl +++ a/opac/opac-detail.pl @@ -401,9 +401,16 @@ if ($session->param('busc')) { } +# Check if we can place a hold on this bib where there is an item out but others available +my $prevent_holds = 0; +if ( C4::Context->preference('PreventOPACHoldsAnyAvailableItem') && not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventOPACHoldsAnyAvailableItem( $biblionumber ); + print "HOLDS: $prevent_holds
    "; +} +$template->param( 'PreventOPACHoldsAnyAvailableItem' => $prevent_holds ); $template->param( 'AllowOnShelfHolds' => C4::Context->preference('AllowOnShelfHolds') ); -$template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) ); +$template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) ) if not $prevent_holds; --- a/opac/opac-search.pl +++ a/opac/opac-search.pl @@ -52,7 +52,7 @@ use C4::Branch; # GetBranches use C4::SocialData; use C4::Ratings; use C4::External::OverDrive; - +use C4::Reserves; use POSIX qw(ceil floor strftime); use URI::Escape; use JSON qw/decode_json encode_json/; @@ -675,6 +675,13 @@ for (my $i=0;$i<@servers;$i++) { my $j = 0; foreach (@newresults) { my $bibnum = ($_->{biblionumber})?$_->{biblionumber}:0; + my $prevent_holds = 0; + if ( C4::Context->preference('PreventOPACHoldsAnyAvailableItem') && not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventOPACHoldsAnyAvailableItem($bibnum) if $bibnum; + } + if ( $prevent_holds ) { + $_->{prevent_holds} =1; + } $pasarParams .= $bibnum . ','; $j++; last if ($j == $results_per_page); --