LP1891369 Renewal extension never shortens previous due date
authorBill Erickson <berickxx@gmail.com>
Thu, 17 Mar 2022 14:50:06 +0000 (10:50 -0400)
committerGalen Charlton <gmc@equinoxOLI.org>
Fri, 28 Oct 2022 01:06:30 +0000 (21:06 -0400)
Ensure the calculated due date of a renewal never occurs before the due
date of the previous circulation.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Michele Morgan <mmorgan@noblenet.org>
Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm

index ca293dc..aec6471 100644 (file)
@@ -2387,32 +2387,53 @@ sub extend_renewal_due_date {
     my $start_time = DateTime::Format::ISO8601->new
         ->parse_datetime(clean_ISO8601($prev_circ->xact_start))->epoch;
 
-    my $due_time = DateTime::Format::ISO8601->new
-        ->parse_datetime(clean_ISO8601($prev_circ->due_date))->epoch;
+    my $prev_due_date = DateTime::Format::ISO8601->new
+        ->parse_datetime(clean_ISO8601($prev_circ->due_date));
+
+    my $due_date = DateTime::Format::ISO8601->new
+        ->parse_datetime(clean_ISO8601($circ->due_date));
+
+    my $prev_due_time = $prev_due_date->epoch;
 
     my $now_time = DateTime->now->epoch;
 
-    return if $due_time < $now_time; # Renewed circ was overdue.
+    return if $prev_due_time < $now_time; # Renewed circ was overdue.
 
     if (my $interval = $matchpoint->renew_extend_min_interval) {
 
         my $min_duration = OpenILS::Utils::DateTime->interval_to_seconds($interval);
         my $checkout_duration = $now_time - $start_time;
 
-        return if $checkout_duration < $min_duration;
+        if ($checkout_duration < $min_duration) {
+            # Renewal occurred too early in the cycle to result in an
+            # extension of the due date on the renewal.
+
+            # If the new due date falls before the due date of
+            # the previous circulation, use the due date of the prev.
+            # circ so the patron does not lose time.
+            my $due = $due_date < $prev_due_date ? $prev_due_date : $due_date;
+            $circ->due_date($due->strftime('%FT%T%z'));
+
+            return;
+        }
     }
 
-    my $remaining_duration = $due_time - $now_time;
+    # Item was checked out long enough during the previous circulation
+    # to consider extending the due date of the renewal to cover the gap.
 
-    my $due_date = DateTime::Format::ISO8601->new
-        ->parse_datetime(clean_ISO8601($circ->due_date));
+    # Amount of the previous duration that was left unused.
+    my $remaining_duration = $prev_due_time - $now_time;
 
     $due_date->add(seconds => $remaining_duration);
 
-    $logger->info("circulator: extended renewal due date to $due_date");
+    # If the calculated due date falls before the due date of the previous 
+    # circulation, use the due date of the prev. circ so the patron does
+    # not lose time.
+    my $due = $due_date < $prev_due_date ? $prev_due_date : $due_date;
+
+    $logger->info("circulator: renewal due date extension landed on due date: $due");
 
-    # $circ->due_date is already in the needed timezone.
-    $circ->due_date($due_date->strftime('%FT%T%z'));
+    $circ->due_date($due->strftime('%FT%T%z'));
 }