LP#1282751 Credit card payment balance owed rounding fix
authorBill Erickson <berickxx@gmail.com>
Thu, 15 Sep 2016 19:13:47 +0000 (15:13 -0400)
committerMike Rylander <mrylander@gmail.com>
Tue, 25 Oct 2016 20:26:06 +0000 (16:26 -0400)
Avoid using Perl's int() when summing owed/paid totals for display in
the TPAC credit card payment form, since this can lead to rounding
errors.

A simple example of why we should not use int() when summing floating
point numbers:

perl -e 'print "no match\n" unless ((8.29 * 100) == int(8.29 * 100))';

Furthermore, use the relatively new fpsum() utility function for summing
floating point numbers so we can avoid having multiple versions of the
summing logic floating (*cough*) around (*cough cough*).

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm

index d2be12d..9896ff2 100644 (file)
@@ -1947,8 +1947,8 @@ sub prepare_fines {
         }
     );
 
-    my @total_keys = qw/total_paid total_owed balance_owed/;
-    $self->ctx->{"fines"}->{@total_keys} = (0, 0, 0);
+    # Collect $$ amounts from each transaction for summing below.
+    my (@paid_amounts, @owed_amounts, @balance_amounts);
 
     while(my $resp = $req->recv) {
         my $mobts = $resp->content;
@@ -1960,10 +1960,9 @@ sub prepare_fines {
             $last_billing = pop(@billings);
         }
 
-        # XXX TODO confirm that the following, and the later division by 100.0
-        # to get a floating point representation once again, is sufficiently
-        # "money-safe" math.
-        $self->ctx->{"fines"}->{$_} += int($mobts->$_ * 100) for (@total_keys);
+        push(@paid_amounts, $mobts->total_paid);
+        push(@owed_amounts, $mobts->total_owed);
+        push(@balance_amounts, $mobts->balance_owed);
 
         my $marc_xml = undef;
         if ($mobts->xact_type eq 'reservation' and
@@ -1990,7 +1989,10 @@ sub prepare_fines {
 
     $cstore->kill_me;
 
-    $self->ctx->{"fines"}->{$_} /= 100.0 for (@total_keys);
+    $self->ctx->{"fines"}->{total_paid}   = $U->fpsum(@paid_amounts);
+    $self->ctx->{"fines"}->{total_owed}   = $U->fpsum(@owed_amounts);
+    $self->ctx->{"fines"}->{balance_owed} = $U->fpsum(@balance_amounts);
+
     return;
 }