LP#1686194 Account for adjustments when generating fines
authorDan Wells <dbw2@calvin.edu>
Mon, 24 Apr 2017 18:29:04 +0000 (14:29 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Tue, 20 Jun 2017 13:47:00 +0000 (09:47 -0400)
Fine generation stops at a predetermined 'max fines' amount, but this
does not account for possible adjustments which lower the effective
fine amount.  This situation is common in cases where lost items are
returned, and the library wants to generate additional overdues upon
that event.

With this commit, fine generation will pull in any adjustments applied
to overdue fines, and use those to offset the current total fine when
checking for max fines.

Also includes test for this condition.

Signed-off-by: Dan Wells <dbw2@calvin.edu>
Signed-off-by: Jeff Davis <jdavis@sitka.bclibraries.ca>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm
Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
Open-ILS/tests/datasets/sql/neg_bal_custom_transactions.sql

index 9da9dd8..1675712 100644 (file)
@@ -527,13 +527,16 @@ sub generate_fines {
                 { xact => $c->id,
                   btype => 1,
                   billing_ts => { '>' => $c->$due_date_method } },
-                { order_by => {mb => 'billing_ts DESC'}}
+                { order_by => {mb => 'billing_ts DESC'},
+                  flesh => 1,
+                  flesh_fields => {mb => ['adjustments']} }
             ])};
 
             my $f_idx = 0;
             my $fine = $fines[$f_idx] if (@fines);
             my $current_fine_total = 0;
             $current_fine_total += int($_->amount * 100) for (grep { $_ and !$U->is_true($_->voided) } @fines);
+            $current_fine_total -= int($_->amount * 100) for (map { @{$_->adjustments} } @fines);
     
             my $last_fine;
             if ($fine) {
index 0190f28..33b4023 100644 (file)
@@ -1,6 +1,6 @@
 #!perl
 
-use Test::More tests => 129;
+use Test::More tests => 132;
 
 diag("Test features of Conditional Negative Balances code.");
 
@@ -836,81 +836,54 @@ is(
 );
 
 
-###############################
-## 11. Manually voiding lost book fee does not result in negative balances
-###############################
-#
-#### Setup use case variables
-#$xact_id = 5;
-#$item_id = 6;
-#$item_barcode = 'CONC4000040';
-#
-## Setup Org Unit Settings
+##############################
+# Restore then generate new overdues on xact with adjustments
+##############################
+
+### Setup use case variables
+$xact_id = 5;
+$item_id = 6;
+$item_barcode = 'CONC4000041';
+
+# Setup Org Unit Settings
 # ALREADY SET:
 #     'bill.prohibit_negative_balance_default' => 1
-#
-#$summary = fetch_billable_xact_summary($xact_id);
-#ok( $summary, 'CASE 11: Found the transaction summary');
-#is(
-#    $summary->balance_owed,
-#    '50.00',
-#    'Starting balance owed is 50.00 for lost item'
-#);
-#
-#### confirm the copy is lost
-#$item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
-#if (my $item_resp = $item_req->recv) {
-#    if (my $item = $item_resp->content) {
-#        is(
-#            $item->status,
-#            3,
-#            'Item with id = ' . $item_id . ' has status of LOST'
-#        );
-#    }
-#}
-#
-#### partially pay the bill
-#$payment_blob = {
-#    userid => $patron_id,
-#    note => '09-lp1198465_neg_balances.t',
-#    payment_type => 'cash_payment',
-#    patron_credit => '0.00',
-#    payments => [ [ $xact_id, '10.00' ] ]
-#};
-#$pay_resp = pay_bills($payment_blob);
-#
-#is(
-#    scalar( @{ $pay_resp->{payments} } ),
-#    1,
-#    'Payment response included one payment id'
-#);
-#
-#$summary = fetch_billable_xact_summary($xact_id);
-#is(
-#    $summary->balance_owed,
-#    '40.00',
-#    'Remaining balance of 40.00 after payment'
-#);
-#
-#### TODO: manually void "the rest" of the bill (i.e. prevent neg bal)
-#### XXX: HARDCODING billing id for now; should look up the LOST bill for this xact?
-#my @billing_ids = (6);
-#my $void_resp = void_bills(\@billing_ids);
-#
-#is(
-#    $void_resp,
-#    '1',
-#    'Voiding was successful'
-#);
-#
-#### verify ending state
-#
-#$summary = fetch_billable_xact_summary($xact_id);
-#is(
-#    $summary->balance_owed,
-#    '0.00',
-#    'Patron has a balance of 0.00 (negative balance prohibited)'
-#);
+$settings = {
+    'circ.restore_overdue_on_lost_return' => 1,
+    'circ.lost.generate_overdue_on_checkin' => 1
+};
+
+$apputils->simplereq(
+    'open-ils.actor',
+    'open-ils.actor.org_unit.settings.update',
+    $script->authtoken,
+    $org_id,
+    $settings
+);
+
+$summary = fetch_billable_xact_summary($xact_id);
+is(
+    $summary->balance_owed,
+    '50.00',
+    'Starting balance owed is 50.00 for lost item'
+);
+
+$checkin_resp = $script->do_checkin_override({
+    barcode => $item_barcode
+});
+is(
+    $checkin_resp->{ilsevent},
+    0,
+    'Checkin returned a SUCCESS event'
+);
+
+### verify ending state
+$summary = fetch_billable_xact_summary($xact_id);
+is(
+    $summary->balance_owed,
+    '3.00',
+    'Patron has a balance of 3.00 (newly generated fines, up to maxfines)'
+);
 
 
 ##############################
index c6a2083..6df7fd0 100644 (file)
@@ -140,7 +140,14 @@ INSERT INTO money.billing (id, xact, billing_ts, voided, voider, void_time, amou
     (DEFAULT, 16, '2014-05-26 23:59:59-04', false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
     (DEFAULT, 16, '2014-05-27 23:59:59-04', false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
     (DEFAULT, 16, '2014-05-28 23:59:59-04', false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
-    -- XACT 10 must be last, because we use CURRVAL() to put their IDs in the account adjustments
+    -- XACTS 5 and 10 must be last, because we use CURRVAL() to put their IDs in the account adjustments
+    (DEFAULT, 5, '2014-05-22 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-23 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-24 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-25 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-26 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-27 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
+    (DEFAULT, 5, '2014-05-28 23:59:59-04', false, NULL, '2014-05-28 08:39:13.070326-04', 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
     (DEFAULT, 10, (DATE(NOW() - '9 days'::interval) || ' 23:59:59')::TIMESTAMP, false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
     (DEFAULT, 10, (DATE(NOW() - '8 days'::interval) || ' 23:59:59')::TIMESTAMP, false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
     (DEFAULT, 10, (DATE(NOW() - '7 days'::interval) || ' 23:59:59')::TIMESTAMP, false, NULL, NULL, 0.10, 'Overdue materials', 1, 'System Generated Overdue Fine'),
@@ -152,6 +159,13 @@ INSERT INTO money.billing (id, xact, billing_ts, voided, voider, void_time, amou
 
 
 INSERT INTO money.account_adjustment (id, xact, payment_ts, voided, amount, note, amount_collected, accepting_usr, billing) VALUES
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 14),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 13),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 12),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 11),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 10),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 9),
+    (DEFAULT, 5, '2014-05-28 08:39:13.070326-04', false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 8),
     (DEFAULT, 10, NOW() - '3 days'::interval, false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 7),
     (DEFAULT, 10, NOW() - '3 days'::interval, false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 6),
     (DEFAULT, 10, NOW() - '3 days'::interval, false, 0.10, '', 0.10, 1, CURRVAL('money.billing_id_seq') - 5),