LP#1422379 Move money.billing timestamps back to moment of fine
authorDan Wells <dbw2@calvin.edu>
Thu, 29 Jan 2015 21:07:27 +0000 (16:07 -0500)
committerDan Wells <dbw2@calvin.edu>
Thu, 3 Mar 2016 20:27:12 +0000 (15:27 -0500)
Current code stamps billings into the future, with the underlying
concept that the time represents when the billing ends, not when it
begins.  This is hard to understand, and requires frequent explanation
to those not familiar with it.

Let's instead do the more natural thing and have the first billing come
one second after the due time, then every fine interval after that.

Signed-off-by: Dan Wells <dbw2@calvin.edu>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm

index 4947a19..449466e 100644 (file)
@@ -8,7 +8,7 @@ use OpenILS::Event;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenILS::Utils::CStoreEditor q/:funcs/;
 use OpenILS::Const qw/:const/;
-use POSIX qw(ceil);
+use POSIX qw(floor);
 use List::MoreUtils qw(uniq);
 
 my $U = "OpenILS::Application::AppUtils";
@@ -535,22 +535,21 @@ sub generate_fines {
             my $current_fine_total = 0;
             $current_fine_total += int($_->amount * 100) for (grep { $_ and !$U->is_true($_->voided) } @fines);
     
-            my $last_fine;
+            my $next_fine;
             if ($fine) {
                 $conn->respond( "Last billing time: ".$fine->billing_ts." (clensed format: ".cleanse_ISO8601( $fine->billing_ts ).")") if $conn;
-                $last_fine = $parser->parse_datetime( cleanse_ISO8601( $fine->billing_ts ) )->epoch;
+                my $last_fine = $parser->parse_datetime( cleanse_ISO8601( $fine->billing_ts ) )->epoch;
+                $next_fine = $last_fine + $fine_interval;
             } else {
                 $logger->info( "Potential first billing for circ ".$c->id );
-                $last_fine = $due;
+                $next_fine = $due + 1; # first fine comes one second after due time
 
                 $grace_period = extend_grace_period($class, $c->$circ_lib_method,$c->$due_date_method,$grace_period,undef,$hoo{$c->$circ_lib_method});
             }
 
-            return if ($last_fine > $now);
+            return if ($next_fine > $now);
             # Generate fines for each past interval, including the one we are inside
-            my $pending_fine_count = ceil( ($now - $last_fine) / $fine_interval );
-
-            if ( $last_fine == $due                         # we have no fines yet
+            if ( $next_fine == $due + 1                     # we have no fines yet
                  && $grace_period                           # and we have a grace period
                  && $now < $due + $grace_period             # and some date math says were are within the grace period
             ) {
@@ -559,6 +558,7 @@ sub generate_fines {
                 return;
             }
 
+            my $pending_fine_count = 1 + floor( ($now - $next_fine) / $fine_interval ); # next fine + every fine interval after that
             $conn->respond( "\t$pending_fine_count pending fine(s)\n" ) if $conn;
             return unless ($pending_fine_count);
 
@@ -590,9 +590,9 @@ sub generate_fines {
                 }
                 
                 # XXX Use org time zone (or default to 'local') once we have the ou setting built for that
-                my $billing_ts = DateTime->from_epoch( epoch => $last_fine, time_zone => 'local' );
+                my $billing_ts = DateTime->from_epoch( epoch => $next_fine, time_zone => 'local' );
                 my $current_bill_count = $bill;
-                while ( $current_bill_count ) {
+                while ( $current_bill_count > 1 ) {
                     $billing_ts->add( seconds_to_interval_hash( $fine_interval ) );
                     $current_bill_count--;
                 }