]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
LP#1686194 Account for adjustments when generating fines
[working/Evergreen.git] / Open-ILS / src / perlmods / live_t / 09-lp1198465_neg_balances.t
1 #!perl
2
3 use Test::More tests => 132;
4
5 diag("Test features of Conditional Negative Balances code.");
6
7 use constant WORKSTATION_NAME => 'BR1-test-09-lp1198465_neg_balances.t';
8 use constant WORKSTATION_LIB => 4;
9
10 use strict; use warnings;
11
12 use DateTime;
13 use DateTime::Format::ISO8601;
14 use OpenSRF::Utils qw/cleanse_ISO8601/;
15 use OpenILS::Utils::TestUtils;
16 my $script = OpenILS::Utils::TestUtils->new();
17 use Data::Dumper;
18
19 our $apputils   = "OpenILS::Application::AppUtils";
20
21 my ($patron_id, $patron_usrname, $xact_id, $item_id, $item_barcode);
22 my ($summary, $payment_blob, $pay_resp, $item_req, $checkin_resp);
23 my $user_obj;
24 my $storage_ses = $script->session('open-ils.storage');
25
26
27 sub retrieve_patron {
28     my $patron_id = shift;
29
30     my $user_req = $storage_ses->request('open-ils.storage.direct.actor.user.retrieve', $patron_id);
31     if (my $user_resp = $user_req->recv) {
32         if (my $patron_obj = $user_resp->content) {
33             return $patron_obj;
34         }
35     }
36     return 0;
37 }
38
39 sub fetch_billable_xact_summary {
40     my $xact_id = shift;
41     my $ses = $script->session('open-ils.cstore');
42     my $req = $ses->request(
43         'open-ils.cstore.direct.money.billable_transaction_summary.retrieve',
44         $xact_id);
45
46     if (my $resp = $req->recv) {
47         return $resp->content;
48     } else {
49         return 0;
50     }
51 }
52
53 sub pay_bills {
54     my $payment_blob = shift;
55     my $resp = $apputils->simplereq(
56         'open-ils.circ',
57         'open-ils.circ.money.payment',
58         $script->authtoken,
59         $payment_blob,
60         $user_obj->last_xact_id
61     );
62
63     #refetch user_obj to get latest last_xact_id
64     $user_obj = retrieve_patron($patron_id)
65         or die 'Could not refetch patron';
66
67     return $resp;
68 }
69
70 sub void_bills {
71     my $billing_ids = shift; #array ref
72     my $resp = $apputils->simplereq(
73         'open-ils.circ',
74         'open-ils.circ.money.billing.void',
75         $script->authtoken,
76         @$billing_ids
77     );
78
79     return $resp;
80 }
81
82 #----------------------------------------------------------------
83 # The tests...  assumes stock sample data, full-auto install by
84 # eg_wheezy_installer.sh, etc.
85 #----------------------------------------------------------------
86
87 # Connect to Evergreen
88 $script->authenticate({
89     username => 'admin',
90     password => 'demo123',
91     type => 'staff'});
92 ok( $script->authtoken, 'Have an authtoken');
93
94 my $ws = $script->register_workstation(WORKSTATION_NAME,WORKSTATION_LIB);
95 ok( ! ref $ws, 'Registered a new workstation');
96
97 $script->logout();
98 $script->authenticate({
99     username => 'admin',
100     password => 'demo123',
101     type => 'staff',
102     workstation => WORKSTATION_NAME});
103 ok( $script->authtoken, 'Have an authtoken associated with the workstation');
104
105
106 ### TODO: verify that stock data is ready for testing
107
108 ### Setup Org Unit Settings that apply to all test cases
109
110 my $org_id = 1; #CONS
111 my $settings = {
112     'circ.max_item_price' => 50,
113     'circ.min_item_price' => 50,
114     'circ.void_lost_on_checkin' => 1
115 };
116
117 $apputils->simplereq(
118     'open-ils.actor',
119     'open-ils.actor.org_unit.settings.update',
120     $script->authtoken,
121     $org_id,
122     $settings
123 );
124
125 # Setup first patron
126 $patron_id = 4;
127 $patron_usrname = '99999355250';
128
129 # Look up the patron
130 if ($user_obj = retrieve_patron($patron_id)) {
131     is(
132         ref $user_obj,
133         'Fieldmapper::actor::user',
134         'open-ils.storage.direct.actor.user.retrieve returned aou object'
135     );
136     is(
137         $user_obj->usrname,
138         $patron_usrname,
139         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
140     );
141 }
142
143
144 ##############################
145 # 1. No Prohibit Negative Balance Settings Are Enabled, Payment Made
146 ##############################
147
148 ### Setup use case variables
149 $xact_id = 1;
150 $item_id = 2;
151 $item_barcode = 'CONC4000037';
152
153 $summary = fetch_billable_xact_summary($xact_id);
154 ok( $summary, 'CASE 1: Found the transaction summary');
155 is(
156     $summary->balance_owed,
157     '50.00',
158     'Starting balance owed is 50.00 for lost item'
159 );
160
161 ### pay the whole bill
162 $payment_blob = {
163     userid => $patron_id,
164     note => '09-lp1198465_neg_balances.t',
165     payment_type => 'cash_payment',
166     patron_credit => '0.00',
167     payments => [ [ $xact_id, '50.00' ] ]
168 };
169 $pay_resp = pay_bills($payment_blob);
170
171 is(
172     scalar( @{ $pay_resp->{payments} } ),
173     1,
174     'Payment response included one payment id'
175 );
176
177 $summary = fetch_billable_xact_summary($xact_id);
178 is(
179     $summary->balance_owed,
180     '0.00',
181     'Remaining balance of 0.00 after payment'
182 );
183
184 ### check-in the lost copy
185
186 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
187 if (my $item_resp = $item_req->recv) {
188     if (my $item = $item_resp->content) {
189         is(
190             ref $item,
191             'Fieldmapper::asset::copy',
192             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
193         );
194         is(
195             $item->status,
196             3,
197             'Item with id = ' . $item_id . ' has status of LOST'
198         );
199     }
200 }
201
202 $checkin_resp = $script->do_checkin_override({
203     barcode => $item_barcode});
204 is(
205     $checkin_resp->{ilsevent},
206     0,
207     'Checkin returned a SUCCESS event'
208 );
209
210 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
211 if (my $item_resp = $item_req->recv) {
212     if (my $item = $item_resp->content) {
213         ok(
214             $item->status == 7 || $item->status == 0,
215             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
216         );
217     }
218 }
219
220 ### verify ending state
221
222 $summary = fetch_billable_xact_summary($xact_id);
223 is(
224     $summary->balance_owed,
225     '-50.00',
226     'Patron has a negative balance (credit) of 50.00 due to overpayment'
227 );
228
229
230 ##############################
231 # 2. Negative Balance Settings Are Unset, No Payment Made
232 ##############################
233
234 ### Setup use case variables
235 $xact_id = 2;
236 $item_id = 3;
237 $item_barcode = 'CONC4000038';
238
239 $summary = fetch_billable_xact_summary($xact_id);
240 ok( $summary, 'CASE 2: Found the transaction summary');
241 is(
242     $summary->balance_owed,
243     '50.00',
244     'Starting balance owed is 50.00 for lost item'
245 );
246
247 ### check-in the lost copy
248
249 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
250 if (my $item_resp = $item_req->recv) {
251     if (my $item = $item_resp->content) {
252         is(
253             $item->status,
254             3,
255             'Item with id = ' . $item_id . ' has status of LOST'
256         );
257     }
258 }
259
260 $checkin_resp = $script->do_checkin_override({
261     barcode => $item_barcode});
262 is(
263     $checkin_resp->{ilsevent},
264     0,
265     'Checkin returned a SUCCESS event'
266 );
267
268 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
269 if (my $item_resp = $item_req->recv) {
270     if (my $item = $item_resp->content) {
271         ok(
272             $item->status == 7 || $item->status == 0,
273             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
274         );
275     }
276 }
277
278 ### verify ending state
279
280 $summary = fetch_billable_xact_summary($xact_id);
281 is(
282     $summary->balance_owed,
283     '0.00',
284     'Patron has a balance of 0.00'
285 );
286
287
288 ##############################
289 # 13. RERUN of Case 1. No Prohibit Negative Balance Settings Are Enabled, Payment Made
290 # SETTINGS: Prohibit negative balances on bills for lost materials
291 ##############################
292
293 # Setup next patron
294 $patron_id = 6;
295 $patron_usrname = '99999335859';
296
297 # Look up the patron
298 if ($user_obj = retrieve_patron($patron_id)) {
299     is(
300         ref $user_obj,
301         'Fieldmapper::actor::user',
302         'open-ils.storage.direct.actor.user.retrieve returned aou object'
303     );
304     is(
305         $user_obj->usrname,
306         $patron_usrname,
307         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
308     );
309 }
310
311 ### Setup use case variables
312 $xact_id = 13;
313 $item_id = 14;
314 $item_barcode = 'CONC4000049';
315
316 # Setup Org Unit Settings
317 $settings = {
318     'bill.prohibit_negative_balance_on_lost' => 1
319 };
320 $apputils->simplereq(
321     'open-ils.actor',
322     'open-ils.actor.org_unit.settings.update',
323     $script->authtoken,
324     $org_id,
325     $settings
326 );
327
328 $summary = fetch_billable_xact_summary($xact_id);
329 ok( $summary, 'CASE 13a: Found the transaction summary');
330 is(
331     $summary->balance_owed,
332     '50.00',
333     'Starting balance owed is 50.00 for lost item'
334 );
335
336 ### pay the whole bill
337 $payment_blob = {
338     userid => $patron_id,
339     note => '09-lp1198465_neg_balances.t',
340     payment_type => 'cash_payment',
341     patron_credit => '0.00',
342     payments => [ [ $xact_id, '50.00' ] ]
343 };
344 $pay_resp = pay_bills($payment_blob);
345
346 is(
347     scalar( @{ $pay_resp->{payments} } ),
348     1,
349     'Payment response included one payment id'
350 );
351
352 $summary = fetch_billable_xact_summary($xact_id);
353 is(
354     $summary->balance_owed,
355     '0.00',
356     'Remaining balance of 0.00 after payment'
357 );
358
359 ### check-in the lost copy
360
361 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
362 if (my $item_resp = $item_req->recv) {
363     if (my $item = $item_resp->content) {
364         is(
365             ref $item,
366             'Fieldmapper::asset::copy',
367             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
368         );
369         is(
370             $item->status,
371             3,
372             'Item with id = ' . $item_id . ' has status of LOST'
373         );
374     }
375 }
376
377 $checkin_resp = $script->do_checkin_override({
378     barcode => $item_barcode});
379 is(
380     $checkin_resp->{ilsevent},
381     0,
382     'Checkin returned a SUCCESS event'
383 );
384
385 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
386 if (my $item_resp = $item_req->recv) {
387     if (my $item = $item_resp->content) {
388         ok(
389             $item->status == 7 || $item->status == 0,
390             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
391         );
392     }
393 }
394
395 ### verify ending state
396
397 $summary = fetch_billable_xact_summary($xact_id);
398 is(
399     $summary->balance_owed,
400     '0.00',
401     'Patron has a balance of 0.00 (negative balance prevented)'
402 );
403
404
405 ##############################
406 # 13. RERUN of Case 12. Test negative balance settings on fines
407 # SETTINGS: Prohibit negative balances on bills for lost materials
408 ##############################
409
410 ### Setup use case variables
411 $xact_id = 14;
412 $item_id = 15;
413 $item_barcode = 'CONC4000050';
414
415 # Setup Org Unit Settings
416 # ALREADY SET:
417 #    'bill.prohibit_negative_balance_on_lost' => 1
418
419 $summary = fetch_billable_xact_summary($xact_id);
420 ok( $summary, 'CASE 13b: Found the transaction summary');
421 is(
422     $summary->balance_owed,
423     '0.70',
424     'Starting balance owed is 0.70 for overdue fines'
425 );
426
427 ### partially pay the bill
428 $payment_blob = {
429     userid => $patron_id,
430     note => '09-lp1198465_neg_balances.t',
431     payment_type => 'cash_payment',
432     patron_credit => '0.00',
433     payments => [ [ $xact_id, '0.20' ] ]
434 };
435 $pay_resp = pay_bills($payment_blob);
436
437 is(
438     scalar( @{ $pay_resp->{payments} } ),
439     1,
440     'Payment response included one payment id'
441 );
442
443 $summary = fetch_billable_xact_summary($xact_id);
444 is(
445     $summary->balance_owed,
446     '0.50',
447     'Remaining balance of 0.50 after payment'
448 );
449
450 ### Check in using Amnesty Mode
451 $checkin_resp = $script->do_checkin_override({
452     barcode => $item_barcode,
453     void_overdues => 1
454 });
455 is(
456     $checkin_resp->{ilsevent},
457     0,
458     'Checkin returned a SUCCESS event'
459 );
460
461 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
462 if (my $item_resp = $item_req->recv) {
463     if (my $item = $item_resp->content) {
464         ok(
465             $item->status == 7 || $item->status == 0,
466             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
467         );
468     }
469 }
470
471 ### verify ending state
472 $summary = fetch_billable_xact_summary($xact_id);
473 is(
474     $summary->balance_owed,
475     '-0.20',
476     'Patron has a negative balance of -0.20 (refund of overdue fine payment)'
477 );
478
479
480 ##############################
481 # 14. RERUN of Case 1. No Prohibit Negative Balance Settings Are Enabled, Payment Made
482 # SETTINGS: Prohibit negative balances on bills for overdue materials
483 ##############################
484
485 ### Setup use case variables
486 $xact_id = 15;
487 $item_id = 16;
488 $item_barcode = 'CONC4000051';
489
490 # Setup Org Unit Settings
491 $settings = {
492     'bill.prohibit_negative_balance_on_lost' => 0, #unset from previous test
493     'bill.prohibit_negative_balance_on_overdues' => 1
494 };
495 $apputils->simplereq(
496     'open-ils.actor',
497     'open-ils.actor.org_unit.settings.update',
498     $script->authtoken,
499     $org_id,
500     $settings
501 );
502
503 $summary = fetch_billable_xact_summary($xact_id);
504 ok( $summary, 'CASE 14a: Found the transaction summary');
505 is(
506     $summary->balance_owed,
507     '50.00',
508     'Starting balance owed is 50.00 for lost item'
509 );
510
511 ### pay the whole bill
512 $payment_blob = {
513     userid => $patron_id,
514     note => '09-lp1198465_neg_balances.t',
515     payment_type => 'cash_payment',
516     patron_credit => '0.00',
517     payments => [ [ $xact_id, '50.00' ] ]
518 };
519 $pay_resp = pay_bills($payment_blob);
520
521 is(
522     scalar( @{ $pay_resp->{payments} } ),
523     1,
524     'Payment response included one payment id'
525 );
526
527 $summary = fetch_billable_xact_summary($xact_id);
528 is(
529     $summary->balance_owed,
530     '0.00',
531     'Remaining balance of 0.00 after payment'
532 );
533
534 ok(
535     $summary->xact_finish ne '',
536     'xact_finish is set due to 0.00 balance'
537 );
538
539 ### check-in the lost copy
540
541 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
542 if (my $item_resp = $item_req->recv) {
543     if (my $item = $item_resp->content) {
544         is(
545             ref $item,
546             'Fieldmapper::asset::copy',
547             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
548         );
549         is(
550             $item->status,
551             3,
552             'Item with id = ' . $item_id . ' has status of LOST'
553         );
554     }
555 }
556
557 $checkin_resp = $script->do_checkin_override({
558     barcode => $item_barcode});
559 is(
560     $checkin_resp->{ilsevent},
561     0,
562     'Checkin returned a SUCCESS event'
563 );
564
565 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
566 if (my $item_resp = $item_req->recv) {
567     if (my $item = $item_resp->content) {
568         ok(
569             $item->status == 7 || $item->status == 0,
570             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
571         );
572     }
573 }
574
575 ### verify ending state
576
577 $summary = fetch_billable_xact_summary($xact_id);
578 is(
579     $summary->balance_owed,
580     '-50.00',
581     'Patron has a negative balance (credit) of 50.00 due to overpayment'
582 );
583
584 ok(
585     !defined($summary->xact_finish),
586     'xact_finish is not set due to non-zero balance'
587 );
588
589
590 ##############################
591 # 14. RERUN of Case 12. Test negative balance settings on fines
592 # SETTINGS: Prohibit negative balances on bills for overdue materials
593 ##############################
594
595 ### Setup use case variables
596 $xact_id = 16;
597 $item_id = 17;
598 $item_barcode = 'CONC4000052';
599
600 # Setup Org Unit Settings
601 # ALREADY SET:
602 #    'bill.prohibit_negative_balance_on_overdues' => 1
603
604 $summary = fetch_billable_xact_summary($xact_id);
605 ok( $summary, 'CASE 14b: Found the transaction summary');
606 is(
607     $summary->balance_owed,
608     '0.70',
609     'Starting balance owed is 0.70 for overdue fines'
610 );
611
612 ### partially pay the bill
613 $payment_blob = {
614     userid => $patron_id,
615     note => '09-lp1198465_neg_balances.t',
616     payment_type => 'cash_payment',
617     patron_credit => '0.00',
618     payments => [ [ $xact_id, '0.20' ] ]
619 };
620 $pay_resp = pay_bills($payment_blob);
621
622 is(
623     scalar( @{ $pay_resp->{payments} } ),
624     1,
625     'Payment response included one payment id'
626 );
627
628 $summary = fetch_billable_xact_summary($xact_id);
629 is(
630     $summary->balance_owed,
631     '0.50',
632     'Remaining balance of 0.50 after payment'
633 );
634
635 ### Check in using Amnesty Mode
636 $checkin_resp = $script->do_checkin_override({
637     barcode => $item_barcode,
638     void_overdues => 1
639 });
640 is(
641     $checkin_resp->{ilsevent},
642     0,
643     'Checkin returned a SUCCESS event'
644 );
645
646 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
647 if (my $item_resp = $item_req->recv) {
648     if (my $item = $item_resp->content) {
649         ok(
650             $item->status == 7 || $item->status == 0,
651             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
652         );
653     }
654 }
655
656 ### verify ending state
657 $summary = fetch_billable_xact_summary($xact_id);
658 is(
659     $summary->balance_owed,
660     '0.00',
661     'Patron has a balance of 0.00 (negative balance prevented)'
662 );
663
664
665 ##############################
666 # 3. Basic No Negative Balance Test
667 ##############################
668
669 # Re-setup first patron
670 $patron_id = 4;
671 $patron_usrname = '99999355250';
672
673 # Look up the patron
674 if ($user_obj = retrieve_patron($patron_id)) {
675     is(
676         ref $user_obj,
677         'Fieldmapper::actor::user',
678         'open-ils.storage.direct.actor.user.retrieve returned aou object'
679     );
680     is(
681         $user_obj->usrname,
682         $patron_usrname,
683         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
684     );
685 }
686
687
688 ### Setup use case variables
689 $xact_id = 3;
690 $item_id = 4;
691 $item_barcode = 'CONC4000039';
692
693 # Setup Org Unit Settings
694 $settings = {
695     'bill.prohibit_negative_balance_on_overdues' => 0, #unset from previous test
696     'bill.prohibit_negative_balance_default' => 1
697 };
698 $apputils->simplereq(
699     'open-ils.actor',
700     'open-ils.actor.org_unit.settings.update',
701     $script->authtoken,
702     $org_id,
703     $settings
704 );
705
706 $summary = fetch_billable_xact_summary($xact_id);
707 ok( $summary, 'CASE 3: Found the transaction summary');
708 is(
709     $summary->balance_owed,
710     '50.00',
711     'Starting balance owed is 50.00 for lost item'
712 );
713
714 ### check-in the lost copy
715
716 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
717 if (my $item_resp = $item_req->recv) {
718     if (my $item = $item_resp->content) {
719         is(
720             $item->status,
721             3,
722             'Item with id = ' . $item_id . ' has status of LOST'
723         );
724     }
725 }
726
727 $checkin_resp = $script->do_checkin_override({
728     barcode => $item_barcode});
729 is(
730     $checkin_resp->{ilsevent},
731     0,
732     'Checkin returned a SUCCESS event'
733 );
734
735 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
736 if (my $item_resp = $item_req->recv) {
737     if (my $item = $item_resp->content) {
738         ok(
739             $item->status == 7 || $item->status == 0,
740             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
741         );
742     }
743 }
744
745 ### verify ending state
746
747 $summary = fetch_billable_xact_summary($xact_id);
748 is(
749     $summary->balance_owed,
750     '0.00',
751     'Patron has a balance of 0.00 (negative balance prevented)'
752 );
753
754 ##############################
755 # 4. Prohibit Negative Balances with Partial Payment
756 ##############################
757
758 ### Setup use case variables
759 $xact_id = 4;
760 $item_id = 5;
761 $item_barcode = 'CONC4000040';
762
763 # Setup Org Unit Settings
764 # ALREADY SET:
765 #     'bill.prohibit_negative_balance_default' => 1
766
767 $summary = fetch_billable_xact_summary($xact_id);
768 ok( $summary, 'CASE 4: Found the transaction summary');
769 is(
770     $summary->balance_owed,
771     '50.00',
772     'Starting balance owed is 50.00 for lost item'
773 );
774
775 ### confirm the copy is lost
776 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
777 if (my $item_resp = $item_req->recv) {
778     if (my $item = $item_resp->content) {
779         is(
780             $item->status,
781             3,
782             'Item with id = ' . $item_id . ' has status of LOST'
783         );
784     }
785 }
786
787 ### partially pay the bill
788 $payment_blob = {
789     userid => $patron_id,
790     note => '09-lp1198465_neg_balances.t',
791     payment_type => 'cash_payment',
792     patron_credit => '0.00',
793     payments => [ [ $xact_id, '10.00' ] ]
794 };
795 $pay_resp = pay_bills($payment_blob);
796
797 is(
798     scalar( @{ $pay_resp->{payments} } ),
799     1,
800     'Payment response included one payment id'
801 );
802
803 $summary = fetch_billable_xact_summary($xact_id);
804 is(
805     $summary->balance_owed,
806     '40.00',
807     'Remaining balance of 40.00 after payment'
808 );
809
810 ### check-in the lost copy
811 $checkin_resp = $script->do_checkin_override({
812     barcode => $item_barcode});
813 is(
814     $checkin_resp->{ilsevent},
815     0,
816     'Checkin returned a SUCCESS event'
817 );
818
819 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
820 if (my $item_resp = $item_req->recv) {
821     if (my $item = $item_resp->content) {
822         ok(
823             $item->status == 7 || $item->status == 0,
824             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
825         );
826     }
827 }
828
829 ### verify ending state
830
831 $summary = fetch_billable_xact_summary($xact_id);
832 is(
833     $summary->balance_owed,
834     '0.00',
835     'Patron has a balance of 0.00 (negative balance prevented)'
836 );
837
838
839 ##############################
840 # Restore then generate new overdues on xact with adjustments
841 ##############################
842
843 ### Setup use case variables
844 $xact_id = 5;
845 $item_id = 6;
846 $item_barcode = 'CONC4000041';
847
848 # Setup Org Unit Settings
849 # ALREADY SET:
850 #     'bill.prohibit_negative_balance_default' => 1
851 $settings = {
852     'circ.restore_overdue_on_lost_return' => 1,
853     'circ.lost.generate_overdue_on_checkin' => 1
854 };
855
856 $apputils->simplereq(
857     'open-ils.actor',
858     'open-ils.actor.org_unit.settings.update',
859     $script->authtoken,
860     $org_id,
861     $settings
862 );
863
864 $summary = fetch_billable_xact_summary($xact_id);
865 is(
866     $summary->balance_owed,
867     '50.00',
868     'Starting balance owed is 50.00 for lost item'
869 );
870
871 $checkin_resp = $script->do_checkin_override({
872     barcode => $item_barcode
873 });
874 is(
875     $checkin_resp->{ilsevent},
876     0,
877     'Checkin returned a SUCCESS event'
878 );
879
880 ### verify ending state
881 $summary = fetch_billable_xact_summary($xact_id);
882 is(
883     $summary->balance_owed,
884     '3.00',
885     'Patron has a balance of 3.00 (newly generated fines, up to maxfines)'
886 );
887
888
889 ##############################
890 # 12. Test negative balance settings on fines
891 ##############################
892
893 # Setup next patron
894 $patron_id = 5;
895 $patron_usrname = '99999387993';
896
897 # Look up the patron
898 if ($user_obj = retrieve_patron($patron_id)) {
899     is(
900         ref $user_obj,
901         'Fieldmapper::actor::user',
902         'open-ils.storage.direct.actor.user.retrieve returned aou object'
903     );
904     is(
905         $user_obj->usrname,
906         $patron_usrname,
907         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
908     );
909 }
910
911 ### Setup use case variables
912 $xact_id = 7;
913 $item_id = 8;
914 $item_barcode = 'CONC4000043';
915
916 # Setup Org Unit Settings
917 # ALREADY SET:
918 #     'bill.prohibit_negative_balance_default' => 1
919
920 $summary = fetch_billable_xact_summary($xact_id);
921 ok( $summary, 'CASE 12: Found the transaction summary');
922 is(
923     $summary->balance_owed,
924     '0.70',
925     'Starting balance owed is 0.70 for overdue fines'
926 );
927
928 ### partially pay the bill
929 $payment_blob = {
930     userid => $patron_id,
931     note => '09-lp1198465_neg_balances.t',
932     payment_type => 'cash_payment',
933     patron_credit => '0.00',
934     payments => [ [ $xact_id, '0.20' ] ]
935 };
936 $pay_resp = pay_bills($payment_blob);
937
938 is(
939     scalar( @{ $pay_resp->{payments} } ),
940     1,
941     'Payment response included one payment id'
942 );
943
944 $summary = fetch_billable_xact_summary($xact_id);
945 is(
946     $summary->balance_owed,
947     '0.50',
948     'Remaining balance of 0.50 after payment'
949 );
950
951 ### Check in using Amnesty Mode
952 $checkin_resp = $script->do_checkin_override({
953     barcode => $item_barcode,
954     void_overdues => 1
955 });
956 is(
957     $checkin_resp->{ilsevent},
958     0,
959     'Checkin returned a SUCCESS event'
960 );
961
962 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
963 if (my $item_resp = $item_req->recv) {
964     if (my $item = $item_resp->content) {
965         ok(
966             $item->status == 7 || $item->status == 0,
967             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
968         );
969     }
970 }
971
972 ### verify ending state
973 $summary = fetch_billable_xact_summary($xact_id);
974 is(
975     $summary->balance_owed,
976     '0.00',
977     'Patron has a balance of 0.00 (remaining fines forgiven)'
978 );
979
980
981 ##############################
982 # 10. Interval Testing
983 ##############################
984
985 # Setup Org Unit Settings
986 # ALREADY SET:
987 #     'bill.prohibit_negative_balance_default' => 1
988
989 # Setup Org Unit Settings
990 $settings = {
991     'bill.negative_balance_interval_default' => '1 hour'
992 };
993
994 $apputils->simplereq(
995     'open-ils.actor',
996     'open-ils.actor.org_unit.settings.update',
997     $script->authtoken,
998     $org_id,
999     $settings
1000 );
1001
1002 ### Setup use case variables
1003 $xact_id = 8;
1004 $item_id = 9;
1005 $item_barcode = 'CONC4000044';
1006
1007 $summary = fetch_billable_xact_summary($xact_id);
1008 ok( $summary, 'CASE 10.1: Found the transaction summary');
1009 is(
1010     $summary->balance_owed,
1011     '0.00',
1012     'Starting balance owed is 0.00 (LOST fee paid)'
1013 );
1014
1015 ### Check in first item (right after its payment)
1016 $checkin_resp = $script->do_checkin_override({
1017     barcode => $item_barcode,
1018 });
1019 is(
1020     $checkin_resp->{ilsevent},
1021     0,
1022     'Checkin returned a SUCCESS event'
1023 );
1024
1025 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1026 if (my $item_resp = $item_req->recv) {
1027     if (my $item = $item_resp->content) {
1028         ok(
1029             $item->status == 7 || $item->status == 0,
1030             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1031         );
1032     }
1033 }
1034
1035 ### verify ending state for 10.1
1036 $summary = fetch_billable_xact_summary($xact_id);
1037 is(
1038     $summary->balance_owed,
1039     '-50.00',
1040     'Patron has a balance of -50.00 (lost item returned during interval)'
1041 );
1042
1043 ### Setup use case variables
1044 $xact_id = 9;
1045 $item_id = 10;
1046 $item_barcode = 'CONC4000045';
1047
1048 $summary = fetch_billable_xact_summary($xact_id);
1049 ok( $summary, 'CASE 10.2: Found the transaction summary');
1050 is(
1051     $summary->balance_owed,
1052     '0.00',
1053     'Starting balance owed is 0.00 (LOST fee paid)'
1054 );
1055
1056 ### Check in second item (2 hours after its payment)
1057 $checkin_resp = $script->do_checkin_override({
1058     barcode => $item_barcode,
1059 });
1060 is(
1061     $checkin_resp->{ilsevent},
1062     0,
1063     'Checkin returned a SUCCESS event'
1064 );
1065
1066 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1067 if (my $item_resp = $item_req->recv) {
1068     if (my $item = $item_resp->content) {
1069         ok(
1070             $item->status == 7 || $item->status == 0,
1071             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1072         );
1073     }
1074 }
1075
1076 ### verify ending state
1077 $summary = fetch_billable_xact_summary($xact_id);
1078 is(
1079     $summary->balance_owed,
1080     '0.00',
1081     'Patron has a balance of 0.00 (lost item returned after interval)'
1082 );
1083
1084
1085 #############################
1086 # 6. Restores Overdue Fines Appropriately, No Previous "Voids", Patron Will Not Owe On Lost Item Return
1087 #############################
1088
1089 ### Setup use case variables
1090 $xact_id = 10;
1091 $item_id = 11;
1092 $item_barcode = 'CONC4000046';
1093
1094 # Setup Org Unit Settings
1095 $settings = {
1096     'bill.negative_balance_interval_default' => 0, #unset previous setting
1097     'circ.void_overdue_on_lost' => 1,
1098     'circ.restore_overdue_on_lost_return' => 1,
1099     'circ.lost.generate_overdue_on_checkin' => 1
1100 };
1101
1102 $apputils->simplereq(
1103     'open-ils.actor',
1104     'open-ils.actor.org_unit.settings.update',
1105     $script->authtoken,
1106     $org_id,
1107     $settings
1108 );
1109
1110 $summary = fetch_billable_xact_summary($xact_id);
1111 ok( $summary, 'CASE 6: Found the transaction summary');
1112 is(
1113     $summary->balance_owed,
1114     '40.00',
1115     'Starting balance owed is 40.00 for partially paid lost item'
1116 );
1117
1118 ### check-in the lost copy
1119
1120 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1121 if (my $item_resp = $item_req->recv) {
1122     if (my $item = $item_resp->content) {
1123         is(
1124             ref $item,
1125             'Fieldmapper::asset::copy',
1126             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1127         );
1128         is(
1129             $item->status,
1130             3,
1131             'Item with id = ' . $item_id . ' has status of LOST'
1132         );
1133     }
1134 }
1135
1136 $checkin_resp = $script->do_checkin_override({
1137     barcode => $item_barcode});
1138 is(
1139     $checkin_resp->{ilsevent},
1140     0,
1141     'Checkin returned a SUCCESS event'
1142 );
1143
1144 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1145 if (my $item_resp = $item_req->recv) {
1146     if (my $item = $item_resp->content) {
1147         ok(
1148             $item->status == 7 || $item->status == 0,
1149             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1150         );
1151     }
1152 }
1153
1154 ### verify ending state
1155
1156 $summary = fetch_billable_xact_summary($xact_id);
1157 is(
1158     $summary->balance_owed,
1159     '0.00',
1160     'Patron has a balance of 0.00 (negative balance prevented)'
1161 );
1162
1163
1164 #############################
1165 # 7. Restores Overdue Fines Appropriately, No Previous "Voids", Patron Will Still Owe On Lost Item Return
1166 #############################
1167
1168 ### Setup use case variables
1169 $xact_id = 11;
1170 $item_id = 12;
1171 $item_barcode = 'CONC4000047';
1172
1173 # Setup Org Unit Settings
1174 # ALREADY SET:
1175 #     'bill.prohibit_negative_balance_default' => 1
1176 #     'circ.void_overdue_on_lost' => 1,
1177 #     'circ.restore_overdue_on_lost_return' => 1,
1178 #     'circ.lost.generate_overdue_on_checkin' => 1
1179
1180 $apputils->simplereq(
1181     'open-ils.actor',
1182     'open-ils.actor.org_unit.settings.update',
1183     $script->authtoken,
1184     $org_id,
1185     $settings
1186 );
1187
1188 $summary = fetch_billable_xact_summary($xact_id);
1189 ok( $summary, 'CASE 7: Found the transaction summary');
1190 is(
1191     $summary->balance_owed,
1192     '0.70',
1193     'Starting balance owed is 0.70 for overdues'
1194 );
1195
1196 ### mark item as LOST
1197 $apputils->simplereq(
1198     'open-ils.circ',
1199     'open-ils.circ.circulation.set_lost',
1200     $script->authtoken,
1201     {barcode => $item_barcode}
1202 );
1203
1204 $summary = fetch_billable_xact_summary($xact_id);
1205 ok( $summary, 'Found the transaction summary');
1206 is(
1207     $summary->balance_owed,
1208     '50.00',
1209     'New balance owed is 50.00 for LOST fee'
1210 );
1211
1212 ### partially pay the bill
1213 $payment_blob = {
1214     userid => $patron_id,
1215     note => '09-lp1198465_neg_balances.t',
1216     payment_type => 'cash_payment',
1217     patron_credit => '0.00',
1218     payments => [ [ $xact_id, '0.10' ] ]
1219 };
1220 $pay_resp = pay_bills($payment_blob);
1221
1222 is(
1223     scalar( @{ $pay_resp->{payments} } ),
1224     1,
1225     'Payment response included one payment id'
1226 );
1227
1228 $summary = fetch_billable_xact_summary($xact_id);
1229 is(
1230     $summary->balance_owed,
1231     '49.90',
1232     'Remaining balance of 49.90 after payment'
1233 );
1234
1235 ### check-in the lost copy
1236
1237 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1238 if (my $item_resp = $item_req->recv) {
1239     if (my $item = $item_resp->content) {
1240         is(
1241             ref $item,
1242             'Fieldmapper::asset::copy',
1243             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1244         );
1245         is(
1246             $item->status,
1247             3,
1248             'Item with id = ' . $item_id . ' has status of LOST'
1249         );
1250     }
1251 }
1252
1253 $checkin_resp = $script->do_checkin_override({
1254     barcode => $item_barcode});
1255 is(
1256     $checkin_resp->{ilsevent},
1257     0,
1258     'Checkin returned a SUCCESS event'
1259 );
1260
1261 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1262 if (my $item_resp = $item_req->recv) {
1263     if (my $item = $item_resp->content) {
1264         ok(
1265             $item->status == 7 || $item->status == 0,
1266             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1267         );
1268     }
1269 }
1270
1271 ### verify ending state
1272
1273 $summary = fetch_billable_xact_summary($xact_id);
1274 is(
1275     $summary->balance_owed,
1276     '0.60',
1277     'Patron has a balance of 0.60 due to reinstated overdue fines'
1278 );
1279
1280
1281 #############################
1282 # 9. Restore Overdue Fines Appropriately, Previous Voids, Negative Balance Allowed
1283 #############################
1284
1285 ### Setup use case variables
1286 $xact_id = 12;
1287 $item_id = 13;
1288 $item_barcode = 'CONC4000048';
1289
1290 # Setup Org Unit Settings
1291 # ALREADY SET:
1292 #     'bill.prohibit_negative_balance_default' => 1
1293 #     'circ.void_overdue_on_lost' => 1,
1294 #     'circ.restore_overdue_on_lost_return' => 1,
1295 #     'circ.lost.generate_overdue_on_checkin' => 1
1296
1297 $apputils->simplereq(
1298     'open-ils.actor',
1299     'open-ils.actor.org_unit.settings.update',
1300     $script->authtoken,
1301     $org_id,
1302     $settings
1303 );
1304
1305 $summary = fetch_billable_xact_summary($xact_id);
1306 ok( $summary, 'CASE 9: Found the transaction summary');
1307 is(
1308     $summary->balance_owed,
1309     '50.00',
1310     'Starting balance owed is 50.00 for lost item'
1311 );
1312
1313 ### partially pay the bill
1314 $payment_blob = {
1315     userid => $patron_id,
1316     note => '09-lp1198465_neg_balances.t',
1317     payment_type => 'cash_payment',
1318     patron_credit => '0.00',
1319     payments => [ [ $xact_id, '10.00' ] ]
1320 };
1321 $pay_resp = pay_bills($payment_blob);
1322
1323 is(
1324     scalar( @{ $pay_resp->{payments} } ),
1325     1,
1326     'Payment response included one payment id'
1327 );
1328
1329 $summary = fetch_billable_xact_summary($xact_id);
1330 is(
1331     $summary->balance_owed,
1332     '40.00',
1333     'Remaining balance of 40.00 after payment'
1334 );
1335
1336 ### check-in the lost copy
1337
1338 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1339 if (my $item_resp = $item_req->recv) {
1340     if (my $item = $item_resp->content) {
1341         is(
1342             ref $item,
1343             'Fieldmapper::asset::copy',
1344             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1345         );
1346         is(
1347             $item->status,
1348             3,
1349             'Item with id = ' . $item_id . ' has status of LOST'
1350         );
1351     }
1352 }
1353
1354 $checkin_resp = $script->do_checkin_override({
1355     barcode => $item_barcode});
1356 is(
1357     $checkin_resp->{ilsevent},
1358     0,
1359     'Checkin returned a SUCCESS event'
1360 );
1361
1362 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1363 if (my $item_resp = $item_req->recv) {
1364     if (my $item = $item_resp->content) {
1365         ok(
1366             $item->status == 7 || $item->status == 0,
1367             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1368         );
1369     }
1370 }
1371
1372 ### verify ending state
1373
1374 $summary = fetch_billable_xact_summary($xact_id);
1375 is(
1376     $summary->balance_owed,
1377     '0.00',
1378     'Patron has a balance of 0.00 (negative balance prevented)'
1379 );
1380
1381
1382 #############################
1383 # 8. Restore Overdue Fines Appropriately, Previous Voids, Negative Balance Allowed
1384 #############################
1385
1386 ## TODO: consider using a later xact_id/item_id, instead of reverting back to user 4
1387
1388 # Setup first patron (again)
1389 $patron_id = 4;
1390 $patron_usrname = '99999355250';
1391
1392 # Look up the patron
1393 if ($user_obj = retrieve_patron($patron_id)) {
1394     is(
1395         ref $user_obj,
1396         'Fieldmapper::actor::user',
1397         'open-ils.storage.direct.actor.user.retrieve returned aou object'
1398     );
1399     is(
1400         $user_obj->usrname,
1401         $patron_usrname,
1402         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
1403     );
1404 }
1405
1406 ### Setup use case variables
1407 $xact_id = 6;
1408 $item_id = 7;
1409 $item_barcode = 'CONC4000042';
1410
1411 # Setup Org Unit Settings
1412 # ALREADY SET:
1413 #     'circ.void_overdue_on_lost' => 1,
1414 #     'circ.restore_overdue_on_lost_return' => 1,
1415 #     'circ.lost.generate_overdue_on_checkin' => 1
1416 $settings = {
1417     'bill.prohibit_negative_balance_default' => 0
1418 };
1419
1420 $apputils->simplereq(
1421     'open-ils.actor',
1422     'open-ils.actor.org_unit.settings.update',
1423     $script->authtoken,
1424     $org_id,
1425     $settings
1426 );
1427
1428 $summary = fetch_billable_xact_summary($xact_id);
1429 ok( $summary, 'CASE 8: Found the transaction summary');
1430 is(
1431     $summary->balance_owed,
1432     '50.00',
1433     'Starting balance owed is 50.00 for lost item'
1434 );
1435
1436 ### partially pay the bill
1437 $payment_blob = {
1438     userid => $patron_id,
1439     note => '09-lp1198465_neg_balances.t',
1440     payment_type => 'cash_payment',
1441     patron_credit => '0.00',
1442     payments => [ [ $xact_id, '10.00' ] ]
1443 };
1444 $pay_resp = pay_bills($payment_blob);
1445
1446 is(
1447     scalar( @{ $pay_resp->{payments} } ),
1448     1,
1449     'Payment response included one payment id'
1450 );
1451
1452 $summary = fetch_billable_xact_summary($xact_id);
1453 is(
1454     $summary->balance_owed,
1455     '40.00',
1456     'Remaining balance of 40.00 after payment'
1457 );
1458
1459 ### check-in the lost copy
1460
1461 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1462 if (my $item_resp = $item_req->recv) {
1463     if (my $item = $item_resp->content) {
1464         is(
1465             ref $item,
1466             'Fieldmapper::asset::copy',
1467             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1468         );
1469         is(
1470             $item->status,
1471             3,
1472             'Item with id = ' . $item_id . ' has status of LOST'
1473         );
1474     }
1475 }
1476
1477 $checkin_resp = $script->do_checkin_override({
1478     barcode => $item_barcode});
1479 is(
1480     $checkin_resp->{ilsevent},
1481     0,
1482     'Checkin returned a SUCCESS event'
1483 );
1484
1485 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1486 if (my $item_resp = $item_req->recv) {
1487     if (my $item = $item_resp->content) {
1488         ok(
1489             $item->status == 7 || $item->status == 0,
1490             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1491         );
1492     }
1493 }
1494
1495 ### verify ending state
1496
1497 $summary = fetch_billable_xact_summary($xact_id);
1498 is(
1499     $summary->balance_owed,
1500     '-7.00',
1501     'Patron has a negative balance of 7.00 due to overpayment'
1502 );
1503
1504
1505
1506 $script->logout();
1507
1508