From 45c2fe53ff027aeacd90dab72c411dfebd0738e6 Mon Sep 17 00:00:00 2001 From: Matthias Meusburger Date: Fri, 30 Dec 2022 14:07:13 +0000 Subject: [PATCH] Bug 33086: Allow to prevent holds at OPAC for a patron with overdues outstanding Test plan: 1) Add overdues to a patron 2) Set the OverduesBlockHolds system preference to "Don't block" 3) Check that you can place a hold for this patron, both at OPAC and Intranet 4) Set the OverduesBlockHolds system preference to "Block" 5) Check that you cannot place a hold for this patron at OPAC, with the following message: "This title cannot be requested because you have overdues" 6) Check that you can place a hold for this patron at Intranet, but with the following warning: "Patron has overdues" Signed-off-by: Lucas Gass --- C4/Reserves.pm | 7 +++ ...g33086-Allow-blocking-holds-on-overdues.pl | 12 +++++ installer/data/mysql/mandatory/sysprefs.sql | 1 + .../admin/preferences/circulation.pref | 6 +++ .../prog/en/modules/reserve/request.tt | 8 +++ .../bootstrap/en/modules/opac-reserve.tt | 2 + reserve/request.pl | 4 ++ t/db_dependent/Reserves.t | 49 ++++++++++++++++++- 8 files changed, 88 insertions(+), 1 deletion(-) create mode 100755 installer/data/mysql/atomicupdate/Bug33086-Allow-blocking-holds-on-overdues.pl diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 987543e1cd..f4290c2f50 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -341,6 +341,13 @@ sub CanBookBeReserved{ return { status =>'alreadypossession' }; } + if (C4::Context->preference("OverduesBlockHolds") && C4::Context->preference("OverduesBlockHolds") eq 'block') { + my $patron = Koha::Patrons->find($borrowernumber); + if ($patron->has_overdues) { + return { status => 'patronHasOverdues' }; + } + } + if ( $params->{itemtype} ) { # biblio-level, item type-contrained diff --git a/installer/data/mysql/atomicupdate/Bug33086-Allow-blocking-holds-on-overdues.pl b/installer/data/mysql/atomicupdate/Bug33086-Allow-blocking-holds-on-overdues.pl new file mode 100755 index 0000000000..66e37c551e --- /dev/null +++ b/installer/data/mysql/atomicupdate/Bug33086-Allow-blocking-holds-on-overdues.pl @@ -0,0 +1,12 @@ +use Modern::Perl; + +return { + bug_number => "33086", + description => "Allow blocking holds at OPAC on overdues", + up => sub { + my ($args) = @_; + my ($dbh, $out) = @$args{qw(dbh out)}; + $dbh->do(q{INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) VALUES ('OverduesBlockHolds', 'noblock', 'noblock|block', 'Allow or block placing an hold at OPAC when the patron has overdues outstanding.', 'Choice')}); + say $out "Added new system preference 'OverduesBlockHolds'"; + }, +}; diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index 7640af55c7..60b4e96c7f 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -544,6 +544,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OverdueNoticeCalendar',0,NULL,'Take the calendar into consideration when generating overdue notices','YesNo'), ('OverdueNoticeFrom', 'cron', 'cron|item-issuebranch|item-homebranch', 'Organize and send overdue notices by item home library or checkout library', 'Choice'), ('OverduesBlockCirc','noblock','noblock|confirmation|block','When checking out an item should overdues block checkout, generate a confirmation dialogue, or allow checkout','Choice'), +('OverduesBlockHolds','noblock','noblock|block','Allow or block placing an hold at OPAC when the patron has overdues outstanding.','Choice'), ('OverduesBlockRenewing','allow','allow|blockitem|block','If any of patron checked out documents is late, should renewal be allowed, blocked only on overdue items or blocked on whatever checked out document','Choice'), ('PassItemMarcToXSLT','0',NULL,'If enabled, item fields in the MARC record will be made avaiable to XSLT sheets. Otherwise they will be removed.','YesNo'), ('PatronAnonymizeDelay','',NULL,'Delay for anonymizing patrons', 'Integer'), 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 b3491e685f..17dd9ecf65 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 @@ -429,6 +429,12 @@ Circulation: noblock: "Don't block" confirmation: Ask for confirmation - "when checking out to a patron that has overdues outstanding." + - + - pref: OverduesBlockHolds + choices: + block: Block + noblock: "Don't block" + - "placing an hold at OPAC when the patron has overdues outstanding." - - "When checking out an item with rental fees, " - pref: RentalFeesCheckoutConfirmation diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt index e2d33c5415..a99010730c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt @@ -430,6 +430,14 @@ [% END %] + [% IF ( patronHasOverdues ) %] +
+
    +
  • Patron has overdues
  • +
+
+ [% END %] + [% IF ( no_reserves_allowed || exceeded_maxreserves || exceeded_holds_per_record || alreadyreserved || none_available || alreadypossession || ageRestricted || recall ) %]
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt index 61ae289193..687ad937f2 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt @@ -214,6 +214,8 @@
This title cannot be requested because you reached the daily hold limit.
[% ELSIF bibitemloo.itemAlreadyOnHold %]
This title cannot be requested because you already have hold for this item.
+ [% ELSIF bibitemloo.patronHasOverdues %] +
This title cannot be requested because you have overdues.
[% ELSE %] [% UNLESS ( bibitemloo.bib_available ) %]
There are no items that can be placed on hold.
diff --git a/reserve/request.pl b/reserve/request.pl index 0c37d6e4c1..8f2580d3a0 100755 --- a/reserve/request.pl +++ b/reserve/request.pl @@ -338,6 +338,10 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) $template->param( $canReserve->{status} => 1 ); $biblioloopiter{ $canReserve->{status} } = 1; } + elsif ( $canReserve->{status} eq 'patronHasOverdues' ) { + $template->param( $canReserve->{status} => 1 ); + $biblioloopiter{ $canReserve->{status} } = 1; + } else { $biblioloopiter{ $canReserve->{status} } = 1; } diff --git a/t/db_dependent/Reserves.t b/t/db_dependent/Reserves.t index 3371c9539d..c59a1fc94b 100755 --- a/t/db_dependent/Reserves.t +++ b/t/db_dependent/Reserves.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 77; +use Test::More tests => 78; use Test::MockModule; use Test::Warn; @@ -1735,3 +1735,50 @@ subtest 'CanItemBeReserved() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'OverduesBlockHolds tests' => sub { + plan tests => 2; + + $schema->storage->txn_begin; + + my $library = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } ); + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + my $biblio = $builder->build_sample_biblio(); + my $overdueitem = $builder->build_sample_item( + { + biblionumber => $biblio->biblionumber, + library => $library->branchcode + } + ); + + my $context = Test::MockModule->new('C4::Context'); + $context->mock( userenv => { branch => $library->id } ); + + Koha::CirculationRules->delete; + + Koha::CirculationRules->set_rules( + { branchcode => undef, + categorycode => undef, + itemtype => undef, + rules => { + reservesallowed => 2, + } + } + ); + + my $yesterday = DateTime->today( time_zone => C4::Context->tz() )->add( days => -1 ); + my $issue = AddIssue( $patron->unblessed, $overdueitem->barcode, $yesterday ); + + t::lib::Mocks::mock_preference('OverduesBlockHolds','block'); + my $res = CanBookBeReserved($patron->id, $biblio->id, $library->id); + is_deeply( $res, { status => 'patronHasOverdues' }, + 'Hold is blocked for overdue patron when OverduesBlockHolds is set to block' ); + + t::lib::Mocks::mock_preference('OverduesBlockHolds','noblock'); + $res = CanBookBeReserved($patron->id, $biblio->id, $library->id); + is_deeply( $res, { status => 'OK' }, + 'Hold is allowed for overdue patron when OverduesBlockHolds is set to allow' ); + + $schema->storage->txn_rollback; + +}; -- 2.30.2