From ebb053b3b50f67be1cb3c269b4ba74d2e633f07d Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 25 Jun 2021 11:20:15 -0400 Subject: [PATCH] LP1891369 Renewal due date extensions When an item is renewed before it's due date, libraries now have the option to extend the renewal's due date to include any time lost from the early renewal. For example, a 14 day checkout renewed after 12 days will result in a due date on the renewal of 14 days plus 2 days to cover the lost time. New Org Unit Settings * circ.renew.extend_due_date Enables this new feature * circ.renew.extend_due_date.min_duration_percent Specifies how early in a checkout a renewal will result in an extended due date. E.g. A value of 50 (percent) means no due date extension would occur if an attempt to renew occurred after 5 days of a 14 day circulation duration. In this case, the renewal would still be allowed, it just wouldn't get the extended due date. Signed-off-by: Bill Erickson --- .../lib/OpenILS/Application/Circ/Circulate.pm | 45 ++++++++++++++++++++++ Open-ILS/src/sql/Pg/950.data.seed-values.sql | 39 +++++++++++++++++++ .../upgrade/XXXX.data.renewals-use-full-time.sql | 44 +++++++++++++++++++++ .../Circulation/renewals-extend-due-date.adoc | 24 ++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.renewals-use-full-time.sql create mode 100644 docs/RELEASE_NOTES_NEXT/Circulation/renewals-extend-due-date.adoc diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm index 7a6751df3b..af3eeeb8fc 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm @@ -2346,6 +2346,8 @@ sub apply_modified_due_date { # if the due_date lands on a day when the location is closed return unless $copy and $circ->due_date; + $self->extend_renewal_due_date if $self->is_renewal; + #my $org = (ref $copy->circ_lib) ? $copy->circ_lib->id : $copy->circ_lib; # due-date overlap should be determined by the location the item @@ -2374,6 +2376,49 @@ sub apply_modified_due_date { } } +sub extend_renewal_due_date { + my $self = shift; + my $circ = $self->circ; + my $copy = $self->copy; + + my $extend = $U->ou_ancestor_setting_value( + $self->circ_lib, 'circ.renew.extend_due_date', $self->editor); + + return unless $extend; + + # No value essentially means extend due dates for all renewals. + my $percent = $U->ou_ancestor_setting_value($self->circ_lib, + 'circ.renew.extend_due_date.min_duration_percent', $self->editor) || 0.001; + + my $prev_circ = $self->editor->retrieve_action_circulation($self->parent_circ); + + my $start_time = DateTime::Format::ISO8601->new + ->parse_datetime(clean_ISO8601($prev_circ->xact_start))->epoch; + + my $end_time = DateTime::Format::ISO8601->new + ->parse_datetime(clean_ISO8601($prev_circ->due_date))->epoch; + + my $now_time = DateTime->now->epoch; + + my $total_duration = $end_time - $start_time; + my $checkout_duration = $now_time - $start_time; + my $checkout_percent = ($checkout_duration / $total_duration) * 100; + + return if $checkout_percent < $percent; + + my $remaining_duration = $end_time - $now_time; + + # $circ->due_date is already in the correct timezone. + my $due_date = DateTime::Format::ISO8601->new + ->parse_datetime(clean_ISO8601($circ->due_date)); + + $due_date->add(seconds => $remaining_duration); + + $logger->info("circulator: extended renewal due date to $due_date"); + + $circ->due_date($due_date->strftime('%FT%T%z')); +} + sub create_due_date { diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 678ed4122d..ca442e1757 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -21634,3 +21634,42 @@ VALUES 'coust', 'description'), 'integer' ); + +INSERT into config.org_unit_setting_type (name, grp, label, description, datatype) +VALUES ( + 'circ.renew.extend_due_date', + 'circ', + oils_i18n_gettext( + 'circ.renew.extend_due_date', + 'Extend Renwal Due Dates For Early Renewal', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'circ.renew.extend_due_date', + 'Due dates for renewals will be calculated as the circ duration ' || + 'plus any time lost from the previous circulation caused by ' || + 'early renewal', + 'coust', + 'description' + ), + 'interval' +), ( + 'circ.renew.extend_due_date.min_duration_percent', + 'circ', + oils_i18n_gettext( + 'circ.renew.extend_due_date.min_duration_percent', + 'Extend Renwal Due Dates Minimum Duration Percent', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'circ.renew.extend_due_date.min_duration_percent', + 'A renewal will only result in an extended due date when the ' || + 'renewal occurs after a certain percentage of the total circ ' || + 'duration has passed', + 'coust', + 'description' + ), + 'float' +); diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.renewals-use-full-time.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.renewals-use-full-time.sql new file mode 100644 index 0000000000..e934cbced4 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.renewals-use-full-time.sql @@ -0,0 +1,44 @@ +BEGIN; + +-- SELECT evergreen.upgrade_deps_block_check('TODO', :eg_version); + +INSERT into config.org_unit_setting_type (name, grp, label, description, datatype) +VALUES ( + 'circ.renew.extend_due_date', + 'circ', + oils_i18n_gettext( + 'circ.renew.extend_due_date', + 'Extend Renwal Due Dates For Early Renewal', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'circ.renew.extend_due_date', + 'Due dates for renewals will be calculated as the circ duration ' || + 'plus any time lost from the previous circulation caused by ' || + 'early renewal', + 'coust', + 'description' + ), + 'interval' +), ( + 'circ.renew.extend_due_date.min_duration_percent', + 'circ', + oils_i18n_gettext( + 'circ.renew.extend_due_date.min_duration_percent', + 'Extend Renwal Due Dates Minimum Duration Percent', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'circ.renew.extend_due_date.min_duration_percent', + 'A renewal will only result in an extended due date when the ' || + 'renewal occurs after a certain percentage of the total circ ' || + 'duration has passed', + 'coust', + 'description' + ), + 'float' +); + +COMMIT; diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/renewals-extend-due-date.adoc b/docs/RELEASE_NOTES_NEXT/Circulation/renewals-extend-due-date.adoc new file mode 100644 index 0000000000..c1a2e973b3 --- /dev/null +++ b/docs/RELEASE_NOTES_NEXT/Circulation/renewals-extend-due-date.adoc @@ -0,0 +1,24 @@ +== Renewal Due Date Extended to Cover Lost Time == + +When an item is renewed before it's due date, libraries now have the option +to extend the renewal's due date to include any time lost from the early +renewal. + +For example, a 14 day checkout renewed after 12 days will result in a due date +on the renewal of 14 days plus 2 days to cover the lost time. + +=== Org Unit Settings === + +==== circ.renew.extend_due_date ==== + +Enables this new feature + +==== circ.renew.extend_due_date.min_duration_percent ==== + +Specifies how early in a checkout a renewal will result in an extended +due date. E.g. A value of 50 (percent) means no due date extension +would occur if an attempt to renew occurred after 5 days of a 14 day +circulation duration. In this case, the renewal would still be allowed, +it just wouldn't get the extended due date. + + -- 2.11.0