From 53dfa997276348f70c2924bc588b3668f2dfb519 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 13 Jan 2016 19:17:49 +0000 Subject: [PATCH] Bug 15581: Add a circ rule to limit the auto renewals given a delay This patch adds a new circulation rule (no_auto_renewal_after) to block/allow auto renewals after a given delay. For instance, if the issue date is 10 days before today, and no_auto_renewal_after is set to 10, tomorrow the issue won't be auto renewed. Test plan: 0/ Execute the update DB entry Note: You will have to manually change data in your DB, make sure you have access to the sql cli. 1/ Define a rule with no_auto_renewal_after (10 for instance) and norenewalbefore (5 for instance). (This new rule will behave the same as norenewalbefore: the unit depends on the lengthunit value). The automatic renewals will be done from 5 to 10 days ahead. 2/ Modify the issues.issuedate, to simulate a checkout in the past: UPDATE issues SET issuedate = "yyyy-mm-dd hh:mm:ss" WHERE itemnumber = YOUR_ITEMNUMBER; with issuedate = 2 days before for instance 3/ Execute the automatic renewals cronjob script (misc/cronjobs/automatic_renewals.pl) Confirm that the issue has not been renewed (too soon) 4/ Repeat step 2 with a due date set as 11 days before 5/ Execute the automatic renewals cronjob script (misc/cronjobs/automatic_renewals.pl) Confirm that the issue has not been renewed (too late) 6/ Repeat step 2 with a due date set as 7 days before 7/ Execute the automatic renewals cronjob script (misc/cronjobs/automatic_renewals.pl) Confirm that the issue has been renewed (issues.renewals has been incremented and date_due has been updated according your circ rules). Sponsored-by: University of the Arts London Signed-off-by: Jonathan Field Signed-off-by: Katrin Fischer Signed-off-by: Kyle M Hall --- C4/Circulation.pm | 18 +++++++- admin/smart-rules.pl | 3 ++ .../data/mysql/atomicupdate/bug_15581.sql | 1 + installer/data/mysql/kohastructure.sql | 1 + .../prog/en/modules/admin/smart-rules.tt | 4 ++ .../prog/en/modules/circ/renew.tt | 12 +++++ t/db_dependent/Circulation.t | 44 ++++++++++++++++++- 7 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_15581.sql diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 40fdcfdc5e..46ff960fec 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -2853,6 +2853,22 @@ sub CanBookBeRenewed { return ( 0, 'overdue'); } + if ( $itemissue->{auto_renew} + and defined $issuingrule->{no_auto_renewal_after} + and $issuingrule->{no_auto_renewal_after} ne "" ) { + + # Get issue_date and add no_auto_renewal_after + # If this is greater than today, it's too late for renewal. + my $maximum_renewal_date = dt_from_string($itemissue->{issuedate}); + $maximum_renewal_date->add( + $issuingrule->{lengthunit} => $issuingrule->{no_auto_renewal_after} + ); + my $now = dt_from_string; + if ( $now >= $maximum_renewal_date ) { + return ( 0, "auto_too_late" ); + } + } + if ( defined $issuingrule->{norenewalbefore} and $issuingrule->{norenewalbefore} ne "" ) { @@ -2882,7 +2898,7 @@ sub CanBookBeRenewed { # Fallback for automatic renewals: # If norenewalbefore is undef, don't renew before due date. - elsif ( $itemissue->{auto_renew} ) { + if ( $itemissue->{auto_renew} ) { my $now = dt_from_string; return ( 0, "auto_renew" ) if $now >= $itemissue->{date_due}; diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl index 2ceda62f88..ba8b5bf08b 100755 --- a/admin/smart-rules.pl +++ b/admin/smart-rules.pl @@ -136,6 +136,8 @@ elsif ($op eq 'add') { my $norenewalbefore = $input->param('norenewalbefore'); $norenewalbefore = undef if $norenewalbefore =~ /^\s*$/; my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0; + my $no_auto_renewal_after = $input->param('no_auto_renewal_after'); + $no_auto_renewal_after = undef if $no_auto_renewal_after =~ /^\s*$/; my $reservesallowed = $input->param('reservesallowed'); my $holds_per_record = $input->param('holds_per_record'); my $onshelfholds = $input->param('onshelfholds') || 0; @@ -173,6 +175,7 @@ elsif ($op eq 'add') { renewalperiod => $renewalperiod, norenewalbefore => $norenewalbefore, auto_renew => $auto_renew, + no_auto_renewal_after => $no_auto_renewal_after, reservesallowed => $reservesallowed, holds_per_record => $holds_per_record, issuelength => $issuelength, diff --git a/installer/data/mysql/atomicupdate/bug_15581.sql b/installer/data/mysql/atomicupdate/bug_15581.sql new file mode 100644 index 0000000000..854896870f --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15581.sql @@ -0,0 +1 @@ +ALTER TABLE issuingrules ADD COLUMN no_auto_renewal_after INT(4) DEFAULT NULL AFTER auto_renew; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 6893d6bd4a..514c13dc05 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -869,6 +869,7 @@ CREATE TABLE `issuingrules` ( -- circulation and fine rules `renewalperiod` int(4) default NULL, -- renewal period in the unit set in issuingrules.lengthunit `norenewalbefore` int(4) default NULL, -- no renewal allowed until X days or hours before due date. `auto_renew` BOOLEAN default FALSE, -- automatic renewal + `no_auto_renewal_after` int(4) default NULL, -- no auto renewal allowed after X days or hours after the issue date `reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed `holds_per_record` SMALLINT(6) NOT NULL DEFAULT 1, -- How many holds a patron can have on a given bib `branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt index e0b92eb9ec..3ee5e5f896 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt @@ -185,6 +185,7 @@ $(document).ready(function() { Renewal period No renewal before Automatic renewal + No automatic renewal after Holds allowed (count) Holds per record (count) On shelf holds allowed @@ -265,6 +266,7 @@ $(document).ready(function() { No [% END %] + [% rule.no_auto_renewal_after %] [% rule.reservesallowed %] [% rule.holds_per_record %] @@ -351,6 +353,7 @@ $(document).ready(function() { + @@ -403,6 +406,7 @@ $(document).ready(function() { Renewal period No renewal before Automatic renewal + No automatic renewal after Holds allowed (count) Holds per record (count) On shelf holds allowed diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt index 947767dadd..edbaaf1360 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt @@ -77,6 +77,18 @@ [% END %] + [% ELSIF error == "auto_too_late" %] + +

[% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] ) has been scheduled for automatic renewal and cannot be renewed since [% latestrenewdate | $KohaDates %].

+ + [% IF Koha.Preference('AllowRenewalLimitOverride') %] +
+ + + +
+ [% END %] + [% ELSIF error == "auto_renew" %]

[% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] ) has been scheduled for automatic renewal.

diff --git a/t/db_dependent/Circulation.t b/t/db_dependent/Circulation.t index 8350ac0490..443cf3c4e4 100755 --- a/t/db_dependent/Circulation.t +++ b/t/db_dependent/Circulation.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 88; +use Test::More tests => 90; BEGIN { require_ok('C4::Circulation'); @@ -37,7 +37,6 @@ use C4::Overdues qw(UpdateFine CalcFine); use Koha::DateUtils; use Koha::Database; - my $schema = Koha::Database->schema; $schema->storage->txn_begin; my $builder = t::lib::TestBuilder->new; @@ -553,6 +552,47 @@ C4::Context->dbh->do("DELETE FROM accountlines"); 'Bug 14101: Cannot renew, renewal is automatic (returned code is auto_renew)' ); + subtest "too_late_renewal / no_auto_renewal_after" => sub { + plan tests => 8; + my $item_to_auto_renew = $builder->build( + { source => 'Item', + value => { + biblionumber => $biblionumber, + homebranch => $branch, + holdingbranch => $branch, + } + } + ); + + my $ten_days_before = dt_from_string->add( days => -10 ); + my $ten_days_ahead = dt_from_string->add( days => 10 ); + AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } ); + + $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9'); + ( $renewokay, $error ) = + CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' ); + + $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10'); + ( $renewokay, $error ) = + CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' ); + + $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11'); + ( $renewokay, $error ) = + CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' ); + + $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11'); + ( $renewokay, $error ) = + CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} ); + is( $renewokay, 0, 'Do not renew, renewal is automatic' ); + is( $error, 'auto_renew', 'Cannot renew, renew is automatic' ); + }; + # Too many renewals # set policy to forbid renewals -- 2.39.5