LP1891369 Renewal due date extensions user/berick/lp1891369-renewal-extend-due-date
authorBill Erickson <berickxx@gmail.com>
Fri, 25 Jun 2021 15:20:15 +0000 (11:20 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 25 Jun 2021 15:22:01 +0000 (11:22 -0400)
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 <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.renewals-use-full-time.sql [new file with mode: 0644]
docs/RELEASE_NOTES_NEXT/Circulation/renewals-extend-due-date.adoc [new file with mode: 0644]

index 7a6751d..af3eeeb 100644 (file)
@@ -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 {
index 678ed41..ca442e1 100644 (file)
@@ -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 (file)
index 0000000..e934cbc
--- /dev/null
@@ -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 (file)
index 0000000..c1a2e97
--- /dev/null
@@ -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.
+
+