@@ -, +, @@ BlockExpiredPatronOpacActions is set --- C4/Circulation.pm | 5 +++ installer/data/mysql/updatedatabase.pl | 2 +- misc/cronjobs/automatic_renewals.pl | 1 + t/db_dependent/Circulation.t | 76 +++++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 3 deletions(-) --- a/C4/Circulation.pm +++ a/C4/Circulation.pm @@ -2694,6 +2694,11 @@ sub CanBookBeRenewed { } if ( $issue->auto_renew ) { + + if ( $patron->category->effective_BlockExpiredPatronOpacActions and $patron->is_expired ) { + return ( 0, 'auto_account_expired' ); + } + if ( defined $issuing_rule->no_auto_renewal_after and $issuing_rule->no_auto_renewal_after ne "" ) { # Get issue_date and add no_auto_renewal_after --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -14854,7 +14854,7 @@ if( CheckVersion( $DBversion ) ) { }); SetVersion( $DBversion ); - print "Upgrade to $DBversion done (Bug 12768 - Add 'Processing Fee' to the account_offset_types table if missing)"; + print "Upgrade to $DBversion done (Bug 12768 - Add 'Processing Fee' to the account_offset_types table if missing)\n"; } $DBversion = '17.06.00.020'; --- a/misc/cronjobs/automatic_renewals.pl +++ a/misc/cronjobs/automatic_renewals.pl @@ -85,6 +85,7 @@ while ( my $auto_renew = $auto_renews->next ) { or $error eq 'on_reserve' or $error eq 'restriction' or $error eq 'overdue' + or $error eq 'auto_account_expired' or $error eq 'auto_too_late' or $error eq 'auto_too_much_oweing' or $error eq 'auto_too_soon' ) { --- a/t/db_dependent/Circulation.t +++ a/t/db_dependent/Circulation.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 112; +use Test::More tests => 113; use DateTime; @@ -63,7 +63,17 @@ my $itemtype = $builder->build( value => { notforloan => undef, rentalcharge => 0, defaultreplacecost => undef, processfee => undef } } )->{itemtype}; -my $patron_category = $builder->build({ source => 'Category', value => { categorycode => 'NOT_X', category_type => 'P', enrolmentfee => 0 } }); +my $patron_category = $builder->build( + { + source => 'Category', + value => { + categorycode => 'NOT_X', + category_type => 'P', + enrolmentfee => 0, + BlockExpiredPatronOpacActions => -1, # Pick the pref value + } + } +); my $CircControl = C4::Context->preference('CircControl'); my $HomeOrHoldingBranch = C4::Context->preference('HomeOrHoldingBranch'); @@ -290,13 +300,23 @@ C4::Context->dbh->do("DELETE FROM accountlines"); branchcode => $branch, ); + my %expired_borrower_data = ( + firstname => 'Ça', + surname => 'Glisse', + categorycode => $patron_category->{categorycode}, + branchcode => $branch, + dateexpiry => dt_from_string->subtract( months => 1 ), + ); + my $renewing_borrowernumber = AddMember(%renewing_borrower_data); my $reserving_borrowernumber = AddMember(%reserving_borrower_data); my $hold_waiting_borrowernumber = AddMember(%hold_waiting_borrower_data); my $restricted_borrowernumber = AddMember(%restricted_borrower_data); + my $expired_borrowernumber = AddMember(%expired_borrower_data); my $renewing_borrower = Koha::Patrons->find( $renewing_borrowernumber )->unblessed; my $restricted_borrower = Koha::Patrons->find( $restricted_borrowernumber )->unblessed; + my $expired_borrower = Koha::Patrons->find( $expired_borrowernumber )->unblessed; my $bibitems = ''; my $priority = '1'; @@ -695,6 +715,58 @@ C4::Context->dbh->do("DELETE FROM accountlines"); $dbh->do('DELETE FROM accountlines WHERE borrowernumber=?', undef, $renewing_borrowernumber); }; + subtest "auto_account_expired | BlockExpiredPatronOpacActions" => sub { + plan tests => 6; + my $item_to_auto_renew = $builder->build({ + source => 'Item', + value => { + biblionumber => $biblionumber, + homebranch => $branch, + holdingbranch => $branch, + } + }); + + $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11'); + + my $ten_days_before = dt_from_string->add( days => -10 ); + my $ten_days_ahead = dt_from_string->add( days => 10 ); + + # Patron is expired and BlockExpiredPatronOpacActions=0 + # => auto renew is allowed + t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 0); + my $patron = $expired_borrower; + my $checkout = AddIssue( $patron, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } ); + ( $renewokay, $error ) = + CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_renew', 'Can auto renew, patron is expired but BlockExpiredPatronOpacActions=0' ); + Koha::Checkouts->find( $checkout->issue_id )->delete; + + + # Patron is expired and BlockExpiredPatronOpacActions=1 + # => auto renew is not allowed + t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1); + $patron = $expired_borrower; + $checkout = AddIssue( $patron, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } ); + ( $renewokay, $error ) = + CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_account_expired', 'Can not auto renew, lockExpiredPatronOpacActions=1 and patron is expired' ); + Koha::Checkouts->find( $checkout->issue_id )->delete; + + + # Patron is not expired and BlockExpiredPatronOpacActions=1 + # => auto renew is allowed + t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1); + $patron = $renewing_borrower; + $checkout = AddIssue( $patron, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } ); + ( $renewokay, $error ) = + CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_renew', 'Can auto renew, BlockExpiredPatronOpacActions=1 but patron is not expired' ); + Koha::Checkouts->find( $checkout->issue_id )->delete; + }; + subtest "GetLatestAutoRenewDate" => sub { plan tests => 5; my $item_to_auto_renew = $builder->build( --