From 86bf4bd211b1722c46e702417e0e726ef066a0be Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Mon, 9 Sep 2019 12:23:01 +0200 Subject: [PATCH] Bug 29505: Add syspref to allow to place multiple holds on same item Test plan: 1. Run installer/data/mysql/updatedatabase.pl 2. Enable syspref AllowMultipleHoldsOnSameItem 3. Try to place multiple holds for the same patron on the same item. Unless another circulation rule forbid this (like the maximum number of holds per record), it should work 4. Run `prove t/db_dependent/Holds/AllowMultipleHoldsOnSameItem.t` --- C4/Reserves.pm | 6 +- .../data/mysql/atomicupdate/bug-29505.pl | 15 ++++ installer/data/mysql/mandatory/sysprefs.sql | 1 + .../admin/preferences/circulation.pref | 7 ++ .../Holds/AllowMultipleHoldsOnSameItem.t | 78 +++++++++++++++++++ 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug-29505.pl create mode 100755 t/db_dependent/Holds/AllowMultipleHoldsOnSameItem.t diff --git a/C4/Reserves.pm b/C4/Reserves.pm index a42168bc72..c9b5751d09 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -396,8 +396,10 @@ sub CanItemBeReserved { return { status => 'ageRestricted' } if $daysToAgeRestriction && $daysToAgeRestriction > 0; # Check that the patron doesn't have an item level hold on this item already - return { status =>'itemAlreadyOnHold' } - if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count() ); + unless (C4::Context->preference('AllowMultipleHoldsOnSameItem')) { + return { status =>'itemAlreadyOnHold' } + if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count() ); + } # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set) if ( !C4::Context->preference('AllowHoldsOnPatronsPossessions') diff --git a/installer/data/mysql/atomicupdate/bug-29505.pl b/installer/data/mysql/atomicupdate/bug-29505.pl new file mode 100644 index 0000000000..5cde44e9a2 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug-29505.pl @@ -0,0 +1,15 @@ +use Modern::Perl; + +return { + bug_number => "29505", + description => "Add system preference AllowMultipleHoldsOnSameItem", + up => sub { + my ($args) = @_; + my ($dbh, $out) = @$args{qw(dbh out)}; + + $dbh->do(q{ + INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type) + VALUES ('AllowMultipleHoldsOnSameItem', 0, NULL, 'Allow/Don\'t allow patrons to place multiple holds on the same item', 'YesNo') + }); + }, +} diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index 06f98cb04f..935c5319aa 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -33,6 +33,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('AllowItemsOnHoldCheckoutSCO','0','','Do not generate RESERVE_WAITING and RESERVED warning in the SCO module when checking out items reserved to someone else. This allows self checkouts for those items.','YesNo'), ('AllowMultipleCovers','0','1','Allow multiple cover images to be attached to each bibliographic record.','YesNo'), ('AllowMultipleIssuesOnABiblio',1,'Allow/Don\'t allow patrons to check out multiple items from one biblio','','YesNo'), +('AllowMultipleHoldsOnSameItem', 0, NULL, 'Allow/Don\'t allow patrons to place multiple holds on the same item', 'YesNo'), ('AllowNotForLoanOverride','0','','If ON, Koha will allow the librarian to loan a not for loan item.','YesNo'), ('AllowOfflineCirculation','0','','If on, enables HTML5 offline circulation functionality.','YesNo'), ('AllowPatronToControlAutorenewal','0',NULL,'If enabled, patrons will have a field in their account to choose whether their checkouts are auto renewed or not','YesNo'), 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 6c2a33bc6c..69648de0a6 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 @@ -915,6 +915,13 @@ Circulation: months: months years: years - from reserve date. + - + - pref: AllowMultipleHoldsOnSameItem + choices: + no: "Do not allow" + yes: "Allow" + - patrons to place multiple holds on the same item. + - This can be useful if AllowHoldDateInFuture is enabled too Interlibrary loans: - - pref: ILLModule diff --git a/t/db_dependent/Holds/AllowMultipleHoldsOnSameItem.t b/t/db_dependent/Holds/AllowMultipleHoldsOnSameItem.t new file mode 100755 index 0000000000..20fccffe5c --- /dev/null +++ b/t/db_dependent/Holds/AllowMultipleHoldsOnSameItem.t @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +use Modern::Perl; + +use t::lib::Mocks; +use t::lib::TestBuilder; + +use C4::Context; +use C4::Reserves qw( CanItemBeReserved ); +use Koha::CirculationRules; + +use Test::More tests => 1; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new(); + +t::lib::Mocks::mock_preference('item-level_itypes', '0'); + +subtest 'CanItemBeReserved AllowMultipleHoldsOnSameItem tests' => sub { + plan tests => 3; + + $schema->storage->txn_begin; + + my $library = $builder->build_object( { class => 'Koha::Libraries', value => { + pickup_location => 1, + }}); + my $item = $builder->build_sample_item({ + homebranch => $library->branchcode, + holdingbranch => $library->branchcode + }); + my $patron = $builder->build_object({ class => 'Koha::Patrons', value => { + branchcode => $library->branchcode + }}); + Koha::CirculationRules->set_rules( + { + branchcode => undef, + categorycode => undef, + itemtype => undef, + rules => { + reservesallowed => 10, + holds_per_record => 10, + } + } + ); + + is_deeply( + CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), + { status => 'OK' }, + 'Patron can place a hold on specified item' + ); + + my $hold = $builder->build_object({ class => 'Koha::Holds', value => { + biblionumber => $item->biblionumber, + itemnumber => $item->itemnumber, + found => undef, + priority => 1, + branchcode => $library->branchcode, + borrowernumber => $patron->borrowernumber, + }}); + + t::lib::Mocks::mock_preference('AllowMultipleHoldsOnSameItem', '0'); + + is_deeply( + CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), + { status => 'itemAlreadyOnHold' }, + 'When AllowMultipleHoldsOnSameItem is disabled, patron cannot place another hold on specified item' + ); + + t::lib::Mocks::mock_preference('AllowMultipleHoldsOnSameItem', '1'); + + is_deeply( + CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), + { status => 'OK' }, + 'When AllowMultipleHoldsOnSameItem is enabled, patron can place another hold on specified item' + ); + + $schema->storage->txn_rollback; +}; -- 2.30.2