@@ -, +, @@ a hold on a record with available items patron to check out 8) Attempt to place a hold for the item 9) Note you cannot place the hold 10) Check the available item out to another patron 11) Note you can now place a hold for the first patron --- C4/Reserves.pm | 26 ++++- .../prog/en/modules/admin/smart-rules.tt | 12 +- .../Holds/DisallowHoldIfItemsAvailable.t | 122 +++++++++++++++++++++ 3 files changed, 157 insertions(+), 3 deletions(-) create mode 100755 t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t --- a/C4/Reserves.pm +++ a/C4/Reserves.pm @@ -41,6 +41,8 @@ use Koha::Database; use Koha::Hold; use Koha::Holds; use Koha::Libraries; +use Koha::Items; +use Koha::Itemtypes; use List::MoreUtils qw( firstidx any ); use Carp; @@ -1493,8 +1495,30 @@ sub IsAvailableForItemLevelRequest { $item->{withdrawn} || ($item->{damaged} && !C4::Context->preference('AllowHoldsOnDamagedItems')); + my $on_shelf_holds = _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch}); + + if ( $on_shelf_holds == 1 ) { + return 1; + } elsif ( $on_shelf_holds == 2 ) { + my @items = + Koha::Items->search( { biblionumber => $item->{biblionumber} } ); + + my $any_available = 0; + + foreach my $i (@items) { + $any_available = 1 + unless $i->itemlost + || $i->{notforloan} > 0 + || $i->withdrawn + || $i->onloan + || GetReserveStatus( $i->id ) eq "Waiting" + || ( $i->damaged + && !C4::Context->preference('AllowHoldsOnDamagedItems') ) + || Koha::ItemTypes->find( $i->effective_itemtype() )->notforloan; + } - return 1 if _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch}); + return $any_available ? 0 : 1; + } return $item->{onloan} || GetReserveStatus($item->{itemnumber}) eq "Waiting"; } --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt @@ -248,7 +248,14 @@ for="tobranch">Clone these rules to: Edit @@ -318,7 +325,8 @@ for="tobranch">Clone these rules to: - + + --- a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t +++ a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t @@ -0,0 +1,122 @@ +#!/usr/bin/perl + +use Modern::Perl; + +use C4::Context; +use C4::Items; +use C4::Circulation; +use Koha::IssuingRule; + +use Test::More tests => 4; + +use t::lib::TestBuilder; + +BEGIN { + use FindBin; + use lib $FindBin::Bin; + use_ok('C4::Reserves'); +} + +my $schema = Koha::Database->schema; +$schema->storage->txn_begin; +my $dbh = C4::Context->dbh; + +my $builder = t::lib::TestBuilder->new; + +my $library1 = $builder->build({ + source => 'Branch', +}); + +# Now, set a userenv +C4::Context->_new_userenv('xxx'); +C4::Context->set_userenv(0,0,0,'firstname','surname', $library1->{branchcode}, 'Midway Public Library', '', '', ''); + +my $bib_title = "Test Title"; + +my $borrower1 = $builder->build({ + source => 'Borrower', + value => { + categorycode => 'S', + branchcode => $library1->{branchcode}, + dateexpiry => '3000-01-01', + } +}); + +my $borrower2 = $builder->build({ + source => 'Borrower', + value => { + categorycode => 'S', + branchcode => $library1->{branchcode}, + dateexpiry => '3000-01-01', + } +}); + +# Test hold_fulfillment_policy +my ( $itemtype ) = @{ $dbh->selectrow_arrayref("SELECT itemtype FROM itemtypes LIMIT 1") }; +my $borrowernumber1 = $borrower1->{borrowernumber}; +my $borrowernumber2 = $borrower2->{borrowernumber}; +my $library_A = $library1->{branchcode}; + +$dbh->do("INSERT INTO biblio (frameworkcode, author, title, datecreated) VALUES ('', 'Koha test', '$bib_title', '2011-02-01')"); + +my $biblionumber = $dbh->selectrow_array("SELECT biblionumber FROM biblio WHERE title = '$bib_title'") + or BAIL_OUT("Cannot find newly created biblio record"); + +$dbh->do("INSERT INTO biblioitems (biblionumber, marcxml, itemtype) VALUES ($biblionumber, '', '$itemtype')"); + +my $biblioitemnumber = + $dbh->selectrow_array("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber = $biblionumber") + or BAIL_OUT("Cannot find newly created biblioitems record"); + +$dbh->do(" + INSERT INTO items (barcode, biblionumber, biblioitemnumber, homebranch, holdingbranch, notforloan, damaged, itemlost, withdrawn, onloan, itype) + VALUES ('AllowHoldIf1', $biblionumber, $biblioitemnumber, '$library_A', '$library_A', 0, 0, 0, 0, NULL, '$itemtype') +"); + +my $itemnumber1 = + $dbh->selectrow_array("SELECT itemnumber FROM items WHERE biblionumber = $biblionumber") + or BAIL_OUT("Cannot find newly created item"); + +my $item1 = GetItem( $itemnumber1 ); + +$dbh->do(" + INSERT INTO items (barcode, biblionumber, biblioitemnumber, homebranch, holdingbranch, notforloan, damaged, itemlost, withdrawn, onloan, itype) + VALUES ('AllowHoldIf2', $biblionumber, $biblioitemnumber, '$library_A', '$library_A', 0, 0, 0, 0, NULL, '$itemtype') +"); + +my $itemnumber2 = + $dbh->selectrow_array("SELECT itemnumber FROM items WHERE biblionumber = $biblionumber ORDER BY itemnumber DESC") + or BAIL_OUT("Cannot find newly created item"); + +my $item2 = GetItem( $itemnumber2 ); + +$dbh->do("DELETE FROM issuingrules"); +my $rule = Koha::IssuingRule->new( + { + categorycode => '*', + itemtype => '*', + branchcode => '*', + maxissueqty => 99, + issuelength => 7, + lengthunit => 8, + reservesallowed => 99, + onshelfholds => 2, + } +); +$rule->store(); + +my $is = IsAvailableForItemLevelRequest( $item1, $borrower1); +is( $is, 0, "Item cannot be held, 2 items available" ); + +AddIssue( $borrower2, $item1->{barcode} ); + +$is = IsAvailableForItemLevelRequest( $item1, $borrower1); +is( $is, 0, "Item cannot be held, 1 item available" ); + +AddIssue( $borrower2, $item2->{barcode} ); + +$is = IsAvailableForItemLevelRequest( $item1, $borrower1); +is( $is, 1, "Item can be held, no items available" ); + +# Cleanup +$schema->storage->txn_rollback; --