]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
LP 1780660: Add more workstation functions to OpenILS::Utils::TestUtils.
[Evergreen.git] / Open-ILS / src / perlmods / live_t / 09-lp1198465_neg_balances.t
1 #!perl
2
3 use Test::More tests => 133;
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 ### adjust to zero, manually
481 $apputils->simplereq(
482     'open-ils.circ',
483     'open-ils.circ.money.billable_xact.adjust_to_zero',
484     $script->authtoken,
485     [$xact_id]
486 );
487
488 ### verify 2nd ending state
489 $summary = fetch_billable_xact_summary($xact_id);
490 is(
491     $summary->balance_owed,
492     '0.00',
493     'Case 13 (bonus): Patron has a balance of 0.00 (after manual adjustment of negative balance)'
494 );
495
496
497 ##############################
498 # 14. RERUN of Case 1. No Prohibit Negative Balance Settings Are Enabled, Payment Made
499 # SETTINGS: Prohibit negative balances on bills for overdue materials
500 ##############################
501
502 ### Setup use case variables
503 $xact_id = 15;
504 $item_id = 16;
505 $item_barcode = 'CONC4000051';
506
507 # Setup Org Unit Settings
508 $settings = {
509     'bill.prohibit_negative_balance_on_lost' => 0, #unset from previous test
510     'bill.prohibit_negative_balance_on_overdues' => 1
511 };
512 $apputils->simplereq(
513     'open-ils.actor',
514     'open-ils.actor.org_unit.settings.update',
515     $script->authtoken,
516     $org_id,
517     $settings
518 );
519
520 $summary = fetch_billable_xact_summary($xact_id);
521 ok( $summary, 'CASE 14a: Found the transaction summary');
522 is(
523     $summary->balance_owed,
524     '50.00',
525     'Starting balance owed is 50.00 for lost item'
526 );
527
528 ### pay the whole bill
529 $payment_blob = {
530     userid => $patron_id,
531     note => '09-lp1198465_neg_balances.t',
532     payment_type => 'cash_payment',
533     patron_credit => '0.00',
534     payments => [ [ $xact_id, '50.00' ] ]
535 };
536 $pay_resp = pay_bills($payment_blob);
537
538 is(
539     scalar( @{ $pay_resp->{payments} } ),
540     1,
541     'Payment response included one payment id'
542 );
543
544 $summary = fetch_billable_xact_summary($xact_id);
545 is(
546     $summary->balance_owed,
547     '0.00',
548     'Remaining balance of 0.00 after payment'
549 );
550
551 ok(
552     $summary->xact_finish ne '',
553     'xact_finish is set due to 0.00 balance'
554 );
555
556 ### check-in the lost copy
557
558 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
559 if (my $item_resp = $item_req->recv) {
560     if (my $item = $item_resp->content) {
561         is(
562             ref $item,
563             'Fieldmapper::asset::copy',
564             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
565         );
566         is(
567             $item->status,
568             3,
569             'Item with id = ' . $item_id . ' has status of LOST'
570         );
571     }
572 }
573
574 $checkin_resp = $script->do_checkin_override({
575     barcode => $item_barcode});
576 is(
577     $checkin_resp->{ilsevent},
578     0,
579     'Checkin returned a SUCCESS event'
580 );
581
582 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
583 if (my $item_resp = $item_req->recv) {
584     if (my $item = $item_resp->content) {
585         ok(
586             $item->status == 7 || $item->status == 0,
587             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
588         );
589     }
590 }
591
592 ### verify ending state
593
594 $summary = fetch_billable_xact_summary($xact_id);
595 is(
596     $summary->balance_owed,
597     '-50.00',
598     'Patron has a negative balance (credit) of 50.00 due to overpayment'
599 );
600
601 ok(
602     !defined($summary->xact_finish),
603     'xact_finish is not set due to non-zero balance'
604 );
605
606
607 ##############################
608 # 14. RERUN of Case 12. Test negative balance settings on fines
609 # SETTINGS: Prohibit negative balances on bills for overdue materials
610 ##############################
611
612 ### Setup use case variables
613 $xact_id = 16;
614 $item_id = 17;
615 $item_barcode = 'CONC4000052';
616
617 # Setup Org Unit Settings
618 # ALREADY SET:
619 #    'bill.prohibit_negative_balance_on_overdues' => 1
620
621 $summary = fetch_billable_xact_summary($xact_id);
622 ok( $summary, 'CASE 14b: Found the transaction summary');
623 is(
624     $summary->balance_owed,
625     '0.70',
626     'Starting balance owed is 0.70 for overdue fines'
627 );
628
629 ### partially pay the bill
630 $payment_blob = {
631     userid => $patron_id,
632     note => '09-lp1198465_neg_balances.t',
633     payment_type => 'cash_payment',
634     patron_credit => '0.00',
635     payments => [ [ $xact_id, '0.20' ] ]
636 };
637 $pay_resp = pay_bills($payment_blob);
638
639 is(
640     scalar( @{ $pay_resp->{payments} } ),
641     1,
642     'Payment response included one payment id'
643 );
644
645 $summary = fetch_billable_xact_summary($xact_id);
646 is(
647     $summary->balance_owed,
648     '0.50',
649     'Remaining balance of 0.50 after payment'
650 );
651
652 ### Check in using Amnesty Mode
653 $checkin_resp = $script->do_checkin_override({
654     barcode => $item_barcode,
655     void_overdues => 1
656 });
657 is(
658     $checkin_resp->{ilsevent},
659     0,
660     'Checkin returned a SUCCESS event'
661 );
662
663 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
664 if (my $item_resp = $item_req->recv) {
665     if (my $item = $item_resp->content) {
666         ok(
667             $item->status == 7 || $item->status == 0,
668             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
669         );
670     }
671 }
672
673 ### verify ending state
674 $summary = fetch_billable_xact_summary($xact_id);
675 is(
676     $summary->balance_owed,
677     '0.00',
678     'Patron has a balance of 0.00 (negative balance prevented)'
679 );
680
681
682 ##############################
683 # 3. Basic No Negative Balance Test
684 ##############################
685
686 # Re-setup first patron
687 $patron_id = 4;
688 $patron_usrname = '99999355250';
689
690 # Look up the patron
691 if ($user_obj = retrieve_patron($patron_id)) {
692     is(
693         ref $user_obj,
694         'Fieldmapper::actor::user',
695         'open-ils.storage.direct.actor.user.retrieve returned aou object'
696     );
697     is(
698         $user_obj->usrname,
699         $patron_usrname,
700         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
701     );
702 }
703
704
705 ### Setup use case variables
706 $xact_id = 3;
707 $item_id = 4;
708 $item_barcode = 'CONC4000039';
709
710 # Setup Org Unit Settings
711 $settings = {
712     'bill.prohibit_negative_balance_on_overdues' => 0, #unset from previous test
713     'bill.prohibit_negative_balance_default' => 1
714 };
715 $apputils->simplereq(
716     'open-ils.actor',
717     'open-ils.actor.org_unit.settings.update',
718     $script->authtoken,
719     $org_id,
720     $settings
721 );
722
723 $summary = fetch_billable_xact_summary($xact_id);
724 ok( $summary, 'CASE 3: Found the transaction summary');
725 is(
726     $summary->balance_owed,
727     '50.00',
728     'Starting balance owed is 50.00 for lost item'
729 );
730
731 ### check-in the lost copy
732
733 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
734 if (my $item_resp = $item_req->recv) {
735     if (my $item = $item_resp->content) {
736         is(
737             $item->status,
738             3,
739             'Item with id = ' . $item_id . ' has status of LOST'
740         );
741     }
742 }
743
744 $checkin_resp = $script->do_checkin_override({
745     barcode => $item_barcode});
746 is(
747     $checkin_resp->{ilsevent},
748     0,
749     'Checkin returned a SUCCESS event'
750 );
751
752 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
753 if (my $item_resp = $item_req->recv) {
754     if (my $item = $item_resp->content) {
755         ok(
756             $item->status == 7 || $item->status == 0,
757             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
758         );
759     }
760 }
761
762 ### verify ending state
763
764 $summary = fetch_billable_xact_summary($xact_id);
765 is(
766     $summary->balance_owed,
767     '0.00',
768     'Patron has a balance of 0.00 (negative balance prevented)'
769 );
770
771 ##############################
772 # 4. Prohibit Negative Balances with Partial Payment
773 ##############################
774
775 ### Setup use case variables
776 $xact_id = 4;
777 $item_id = 5;
778 $item_barcode = 'CONC4000040';
779
780 # Setup Org Unit Settings
781 # ALREADY SET:
782 #     'bill.prohibit_negative_balance_default' => 1
783
784 $summary = fetch_billable_xact_summary($xact_id);
785 ok( $summary, 'CASE 4: Found the transaction summary');
786 is(
787     $summary->balance_owed,
788     '50.00',
789     'Starting balance owed is 50.00 for lost item'
790 );
791
792 ### confirm the copy is lost
793 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
794 if (my $item_resp = $item_req->recv) {
795     if (my $item = $item_resp->content) {
796         is(
797             $item->status,
798             3,
799             'Item with id = ' . $item_id . ' has status of LOST'
800         );
801     }
802 }
803
804 ### partially pay the bill
805 $payment_blob = {
806     userid => $patron_id,
807     note => '09-lp1198465_neg_balances.t',
808     payment_type => 'cash_payment',
809     patron_credit => '0.00',
810     payments => [ [ $xact_id, '10.00' ] ]
811 };
812 $pay_resp = pay_bills($payment_blob);
813
814 is(
815     scalar( @{ $pay_resp->{payments} } ),
816     1,
817     'Payment response included one payment id'
818 );
819
820 $summary = fetch_billable_xact_summary($xact_id);
821 is(
822     $summary->balance_owed,
823     '40.00',
824     'Remaining balance of 40.00 after payment'
825 );
826
827 ### check-in the lost copy
828 $checkin_resp = $script->do_checkin_override({
829     barcode => $item_barcode});
830 is(
831     $checkin_resp->{ilsevent},
832     0,
833     'Checkin returned a SUCCESS event'
834 );
835
836 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
837 if (my $item_resp = $item_req->recv) {
838     if (my $item = $item_resp->content) {
839         ok(
840             $item->status == 7 || $item->status == 0,
841             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
842         );
843     }
844 }
845
846 ### verify ending state
847
848 $summary = fetch_billable_xact_summary($xact_id);
849 is(
850     $summary->balance_owed,
851     '0.00',
852     'Patron has a balance of 0.00 (negative balance prevented)'
853 );
854
855
856 ##############################
857 # Restore then generate new overdues on xact with adjustments
858 ##############################
859
860 ### Setup use case variables
861 $xact_id = 5;
862 $item_id = 6;
863 $item_barcode = 'CONC4000041';
864
865 # Setup Org Unit Settings
866 # ALREADY SET:
867 #     'bill.prohibit_negative_balance_default' => 1
868 $settings = {
869     'circ.restore_overdue_on_lost_return' => 1,
870     'circ.lost.generate_overdue_on_checkin' => 1
871 };
872
873 $apputils->simplereq(
874     'open-ils.actor',
875     'open-ils.actor.org_unit.settings.update',
876     $script->authtoken,
877     $org_id,
878     $settings
879 );
880
881 $summary = fetch_billable_xact_summary($xact_id);
882 is(
883     $summary->balance_owed,
884     '50.00',
885     'Starting balance owed is 50.00 for lost item'
886 );
887
888 $checkin_resp = $script->do_checkin_override({
889     barcode => $item_barcode
890 });
891 is(
892     $checkin_resp->{ilsevent},
893     0,
894     'Checkin returned a SUCCESS event'
895 );
896
897 ### verify ending state
898 $summary = fetch_billable_xact_summary($xact_id);
899 is(
900     $summary->balance_owed,
901     '3.00',
902     'Patron has a balance of 3.00 (newly generated fines, up to maxfines)'
903 );
904
905
906 ##############################
907 # 12. Test negative balance settings on fines
908 ##############################
909
910 # Setup next patron
911 $patron_id = 5;
912 $patron_usrname = '99999387993';
913
914 # Look up the patron
915 if ($user_obj = retrieve_patron($patron_id)) {
916     is(
917         ref $user_obj,
918         'Fieldmapper::actor::user',
919         'open-ils.storage.direct.actor.user.retrieve returned aou object'
920     );
921     is(
922         $user_obj->usrname,
923         $patron_usrname,
924         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
925     );
926 }
927
928 ### Setup use case variables
929 $xact_id = 7;
930 $item_id = 8;
931 $item_barcode = 'CONC4000043';
932
933 # Setup Org Unit Settings
934 # ALREADY SET:
935 #     'bill.prohibit_negative_balance_default' => 1
936
937 $summary = fetch_billable_xact_summary($xact_id);
938 ok( $summary, 'CASE 12: Found the transaction summary');
939 is(
940     $summary->balance_owed,
941     '0.70',
942     'Starting balance owed is 0.70 for overdue fines'
943 );
944
945 ### partially pay the bill
946 $payment_blob = {
947     userid => $patron_id,
948     note => '09-lp1198465_neg_balances.t',
949     payment_type => 'cash_payment',
950     patron_credit => '0.00',
951     payments => [ [ $xact_id, '0.20' ] ]
952 };
953 $pay_resp = pay_bills($payment_blob);
954
955 is(
956     scalar( @{ $pay_resp->{payments} } ),
957     1,
958     'Payment response included one payment id'
959 );
960
961 $summary = fetch_billable_xact_summary($xact_id);
962 is(
963     $summary->balance_owed,
964     '0.50',
965     'Remaining balance of 0.50 after payment'
966 );
967
968 ### Check in using Amnesty Mode
969 $checkin_resp = $script->do_checkin_override({
970     barcode => $item_barcode,
971     void_overdues => 1
972 });
973 is(
974     $checkin_resp->{ilsevent},
975     0,
976     'Checkin returned a SUCCESS event'
977 );
978
979 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
980 if (my $item_resp = $item_req->recv) {
981     if (my $item = $item_resp->content) {
982         ok(
983             $item->status == 7 || $item->status == 0,
984             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
985         );
986     }
987 }
988
989 ### verify ending state
990 $summary = fetch_billable_xact_summary($xact_id);
991 is(
992     $summary->balance_owed,
993     '0.00',
994     'Patron has a balance of 0.00 (remaining fines forgiven)'
995 );
996
997
998 ##############################
999 # 10. Interval Testing
1000 ##############################
1001
1002 # Setup Org Unit Settings
1003 # ALREADY SET:
1004 #     'bill.prohibit_negative_balance_default' => 1
1005
1006 # Setup Org Unit Settings
1007 $settings = {
1008     'bill.negative_balance_interval_default' => '1 hour'
1009 };
1010
1011 $apputils->simplereq(
1012     'open-ils.actor',
1013     'open-ils.actor.org_unit.settings.update',
1014     $script->authtoken,
1015     $org_id,
1016     $settings
1017 );
1018
1019 ### Setup use case variables
1020 $xact_id = 8;
1021 $item_id = 9;
1022 $item_barcode = 'CONC4000044';
1023
1024 $summary = fetch_billable_xact_summary($xact_id);
1025 ok( $summary, 'CASE 10.1: Found the transaction summary');
1026 is(
1027     $summary->balance_owed,
1028     '0.00',
1029     'Starting balance owed is 0.00 (LOST fee paid)'
1030 );
1031
1032 ### Check in first item (right after its payment)
1033 $checkin_resp = $script->do_checkin_override({
1034     barcode => $item_barcode,
1035 });
1036 is(
1037     $checkin_resp->{ilsevent},
1038     0,
1039     'Checkin returned a SUCCESS event'
1040 );
1041
1042 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1043 if (my $item_resp = $item_req->recv) {
1044     if (my $item = $item_resp->content) {
1045         ok(
1046             $item->status == 7 || $item->status == 0,
1047             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1048         );
1049     }
1050 }
1051
1052 ### verify ending state for 10.1
1053 $summary = fetch_billable_xact_summary($xact_id);
1054 is(
1055     $summary->balance_owed,
1056     '-50.00',
1057     'Patron has a balance of -50.00 (lost item returned during interval)'
1058 );
1059
1060 ### Setup use case variables
1061 $xact_id = 9;
1062 $item_id = 10;
1063 $item_barcode = 'CONC4000045';
1064
1065 $summary = fetch_billable_xact_summary($xact_id);
1066 ok( $summary, 'CASE 10.2: Found the transaction summary');
1067 is(
1068     $summary->balance_owed,
1069     '0.00',
1070     'Starting balance owed is 0.00 (LOST fee paid)'
1071 );
1072
1073 ### Check in second item (2 hours after its payment)
1074 $checkin_resp = $script->do_checkin_override({
1075     barcode => $item_barcode,
1076 });
1077 is(
1078     $checkin_resp->{ilsevent},
1079     0,
1080     'Checkin returned a SUCCESS event'
1081 );
1082
1083 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1084 if (my $item_resp = $item_req->recv) {
1085     if (my $item = $item_resp->content) {
1086         ok(
1087             $item->status == 7 || $item->status == 0,
1088             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1089         );
1090     }
1091 }
1092
1093 ### verify ending state
1094 $summary = fetch_billable_xact_summary($xact_id);
1095 is(
1096     $summary->balance_owed,
1097     '0.00',
1098     'Patron has a balance of 0.00 (lost item returned after interval)'
1099 );
1100
1101
1102 #############################
1103 # 6. Restores Overdue Fines Appropriately, No Previous "Voids", Patron Will Not Owe On Lost Item Return
1104 #############################
1105
1106 ### Setup use case variables
1107 $xact_id = 10;
1108 $item_id = 11;
1109 $item_barcode = 'CONC4000046';
1110
1111 # Setup Org Unit Settings
1112 $settings = {
1113     'bill.negative_balance_interval_default' => 0, #unset previous setting
1114     'circ.void_overdue_on_lost' => 1,
1115     'circ.restore_overdue_on_lost_return' => 1,
1116     'circ.lost.generate_overdue_on_checkin' => 1
1117 };
1118
1119 $apputils->simplereq(
1120     'open-ils.actor',
1121     'open-ils.actor.org_unit.settings.update',
1122     $script->authtoken,
1123     $org_id,
1124     $settings
1125 );
1126
1127 $summary = fetch_billable_xact_summary($xact_id);
1128 ok( $summary, 'CASE 6: Found the transaction summary');
1129 is(
1130     $summary->balance_owed,
1131     '40.00',
1132     'Starting balance owed is 40.00 for partially paid lost item'
1133 );
1134
1135 ### check-in the lost copy
1136
1137 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1138 if (my $item_resp = $item_req->recv) {
1139     if (my $item = $item_resp->content) {
1140         is(
1141             ref $item,
1142             'Fieldmapper::asset::copy',
1143             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1144         );
1145         is(
1146             $item->status,
1147             3,
1148             'Item with id = ' . $item_id . ' has status of LOST'
1149         );
1150     }
1151 }
1152
1153 $checkin_resp = $script->do_checkin_override({
1154     barcode => $item_barcode});
1155 is(
1156     $checkin_resp->{ilsevent},
1157     0,
1158     'Checkin returned a SUCCESS event'
1159 );
1160
1161 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1162 if (my $item_resp = $item_req->recv) {
1163     if (my $item = $item_resp->content) {
1164         ok(
1165             $item->status == 7 || $item->status == 0,
1166             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1167         );
1168     }
1169 }
1170
1171 ### verify ending state
1172
1173 $summary = fetch_billable_xact_summary($xact_id);
1174 is(
1175     $summary->balance_owed,
1176     '0.00',
1177     'Patron has a balance of 0.00 (negative balance prevented)'
1178 );
1179
1180
1181 #############################
1182 # 7. Restores Overdue Fines Appropriately, No Previous "Voids", Patron Will Still Owe On Lost Item Return
1183 #############################
1184
1185 ### Setup use case variables
1186 $xact_id = 11;
1187 $item_id = 12;
1188 $item_barcode = 'CONC4000047';
1189
1190 # Setup Org Unit Settings
1191 # ALREADY SET:
1192 #     'bill.prohibit_negative_balance_default' => 1
1193 #     'circ.void_overdue_on_lost' => 1,
1194 #     'circ.restore_overdue_on_lost_return' => 1,
1195 #     'circ.lost.generate_overdue_on_checkin' => 1
1196
1197 $apputils->simplereq(
1198     'open-ils.actor',
1199     'open-ils.actor.org_unit.settings.update',
1200     $script->authtoken,
1201     $org_id,
1202     $settings
1203 );
1204
1205 $summary = fetch_billable_xact_summary($xact_id);
1206 ok( $summary, 'CASE 7: Found the transaction summary');
1207 is(
1208     $summary->balance_owed,
1209     '0.70',
1210     'Starting balance owed is 0.70 for overdues'
1211 );
1212
1213 ### mark item as LOST
1214 $apputils->simplereq(
1215     'open-ils.circ',
1216     'open-ils.circ.circulation.set_lost',
1217     $script->authtoken,
1218     {barcode => $item_barcode}
1219 );
1220
1221 $summary = fetch_billable_xact_summary($xact_id);
1222 ok( $summary, 'Found the transaction summary');
1223 is(
1224     $summary->balance_owed,
1225     '50.00',
1226     'New balance owed is 50.00 for LOST fee'
1227 );
1228
1229 ### partially pay the bill
1230 $payment_blob = {
1231     userid => $patron_id,
1232     note => '09-lp1198465_neg_balances.t',
1233     payment_type => 'cash_payment',
1234     patron_credit => '0.00',
1235     payments => [ [ $xact_id, '0.10' ] ]
1236 };
1237 $pay_resp = pay_bills($payment_blob);
1238
1239 is(
1240     scalar( @{ $pay_resp->{payments} } ),
1241     1,
1242     'Payment response included one payment id'
1243 );
1244
1245 $summary = fetch_billable_xact_summary($xact_id);
1246 is(
1247     $summary->balance_owed,
1248     '49.90',
1249     'Remaining balance of 49.90 after payment'
1250 );
1251
1252 ### check-in the lost copy
1253
1254 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1255 if (my $item_resp = $item_req->recv) {
1256     if (my $item = $item_resp->content) {
1257         is(
1258             ref $item,
1259             'Fieldmapper::asset::copy',
1260             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1261         );
1262         is(
1263             $item->status,
1264             3,
1265             'Item with id = ' . $item_id . ' has status of LOST'
1266         );
1267     }
1268 }
1269
1270 $checkin_resp = $script->do_checkin_override({
1271     barcode => $item_barcode});
1272 is(
1273     $checkin_resp->{ilsevent},
1274     0,
1275     'Checkin returned a SUCCESS event'
1276 );
1277
1278 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1279 if (my $item_resp = $item_req->recv) {
1280     if (my $item = $item_resp->content) {
1281         ok(
1282             $item->status == 7 || $item->status == 0,
1283             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1284         );
1285     }
1286 }
1287
1288 ### verify ending state
1289
1290 $summary = fetch_billable_xact_summary($xact_id);
1291 is(
1292     $summary->balance_owed,
1293     '0.60',
1294     'Patron has a balance of 0.60 due to reinstated overdue fines'
1295 );
1296
1297
1298 #############################
1299 # 9. Restore Overdue Fines Appropriately, Previous Voids, Negative Balance Allowed
1300 #############################
1301
1302 ### Setup use case variables
1303 $xact_id = 12;
1304 $item_id = 13;
1305 $item_barcode = 'CONC4000048';
1306
1307 # Setup Org Unit Settings
1308 # ALREADY SET:
1309 #     'bill.prohibit_negative_balance_default' => 1
1310 #     'circ.void_overdue_on_lost' => 1,
1311 #     'circ.restore_overdue_on_lost_return' => 1,
1312 #     'circ.lost.generate_overdue_on_checkin' => 1
1313
1314 $apputils->simplereq(
1315     'open-ils.actor',
1316     'open-ils.actor.org_unit.settings.update',
1317     $script->authtoken,
1318     $org_id,
1319     $settings
1320 );
1321
1322 $summary = fetch_billable_xact_summary($xact_id);
1323 ok( $summary, 'CASE 9: Found the transaction summary');
1324 is(
1325     $summary->balance_owed,
1326     '50.00',
1327     'Starting balance owed is 50.00 for lost item'
1328 );
1329
1330 ### partially pay the bill
1331 $payment_blob = {
1332     userid => $patron_id,
1333     note => '09-lp1198465_neg_balances.t',
1334     payment_type => 'cash_payment',
1335     patron_credit => '0.00',
1336     payments => [ [ $xact_id, '10.00' ] ]
1337 };
1338 $pay_resp = pay_bills($payment_blob);
1339
1340 is(
1341     scalar( @{ $pay_resp->{payments} } ),
1342     1,
1343     'Payment response included one payment id'
1344 );
1345
1346 $summary = fetch_billable_xact_summary($xact_id);
1347 is(
1348     $summary->balance_owed,
1349     '40.00',
1350     'Remaining balance of 40.00 after payment'
1351 );
1352
1353 ### check-in the lost copy
1354
1355 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1356 if (my $item_resp = $item_req->recv) {
1357     if (my $item = $item_resp->content) {
1358         is(
1359             ref $item,
1360             'Fieldmapper::asset::copy',
1361             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1362         );
1363         is(
1364             $item->status,
1365             3,
1366             'Item with id = ' . $item_id . ' has status of LOST'
1367         );
1368     }
1369 }
1370
1371 $checkin_resp = $script->do_checkin_override({
1372     barcode => $item_barcode});
1373 is(
1374     $checkin_resp->{ilsevent},
1375     0,
1376     'Checkin returned a SUCCESS event'
1377 );
1378
1379 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1380 if (my $item_resp = $item_req->recv) {
1381     if (my $item = $item_resp->content) {
1382         ok(
1383             $item->status == 7 || $item->status == 0,
1384             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1385         );
1386     }
1387 }
1388
1389 ### verify ending state
1390
1391 $summary = fetch_billable_xact_summary($xact_id);
1392 is(
1393     $summary->balance_owed,
1394     '0.00',
1395     'Patron has a balance of 0.00 (negative balance prevented)'
1396 );
1397
1398
1399 #############################
1400 # 8. Restore Overdue Fines Appropriately, Previous Voids, Negative Balance Allowed
1401 #############################
1402
1403 ## TODO: consider using a later xact_id/item_id, instead of reverting back to user 4
1404
1405 # Setup first patron (again)
1406 $patron_id = 4;
1407 $patron_usrname = '99999355250';
1408
1409 # Look up the patron
1410 if ($user_obj = retrieve_patron($patron_id)) {
1411     is(
1412         ref $user_obj,
1413         'Fieldmapper::actor::user',
1414         'open-ils.storage.direct.actor.user.retrieve returned aou object'
1415     );
1416     is(
1417         $user_obj->usrname,
1418         $patron_usrname,
1419         'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
1420     );
1421 }
1422
1423 ### Setup use case variables
1424 $xact_id = 6;
1425 $item_id = 7;
1426 $item_barcode = 'CONC4000042';
1427
1428 # Setup Org Unit Settings
1429 # ALREADY SET:
1430 #     'circ.void_overdue_on_lost' => 1,
1431 #     'circ.restore_overdue_on_lost_return' => 1,
1432 #     'circ.lost.generate_overdue_on_checkin' => 1
1433 $settings = {
1434     'bill.prohibit_negative_balance_default' => 0
1435 };
1436
1437 $apputils->simplereq(
1438     'open-ils.actor',
1439     'open-ils.actor.org_unit.settings.update',
1440     $script->authtoken,
1441     $org_id,
1442     $settings
1443 );
1444
1445 $summary = fetch_billable_xact_summary($xact_id);
1446 ok( $summary, 'CASE 8: Found the transaction summary');
1447 is(
1448     $summary->balance_owed,
1449     '50.00',
1450     'Starting balance owed is 50.00 for lost item'
1451 );
1452
1453 ### partially pay the bill
1454 $payment_blob = {
1455     userid => $patron_id,
1456     note => '09-lp1198465_neg_balances.t',
1457     payment_type => 'cash_payment',
1458     patron_credit => '0.00',
1459     payments => [ [ $xact_id, '10.00' ] ]
1460 };
1461 $pay_resp = pay_bills($payment_blob);
1462
1463 is(
1464     scalar( @{ $pay_resp->{payments} } ),
1465     1,
1466     'Payment response included one payment id'
1467 );
1468
1469 $summary = fetch_billable_xact_summary($xact_id);
1470 is(
1471     $summary->balance_owed,
1472     '40.00',
1473     'Remaining balance of 40.00 after payment'
1474 );
1475
1476 ### check-in the lost copy
1477
1478 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1479 if (my $item_resp = $item_req->recv) {
1480     if (my $item = $item_resp->content) {
1481         is(
1482             ref $item,
1483             'Fieldmapper::asset::copy',
1484             'open-ils.storage.direct.asset.copy.retrieve returned acp object'
1485         );
1486         is(
1487             $item->status,
1488             3,
1489             'Item with id = ' . $item_id . ' has status of LOST'
1490         );
1491     }
1492 }
1493
1494 $checkin_resp = $script->do_checkin_override({
1495     barcode => $item_barcode});
1496 is(
1497     $checkin_resp->{ilsevent},
1498     0,
1499     'Checkin returned a SUCCESS event'
1500 );
1501
1502 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
1503 if (my $item_resp = $item_req->recv) {
1504     if (my $item = $item_resp->content) {
1505         ok(
1506             $item->status == 7 || $item->status == 0,
1507             'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
1508         );
1509     }
1510 }
1511
1512 ### verify ending state
1513
1514 $summary = fetch_billable_xact_summary($xact_id);
1515 is(
1516     $summary->balance_owed,
1517     '-7.00',
1518     'Patron has a negative balance of 7.00 due to overpayment'
1519 );
1520
1521
1522
1523 $script->logout();
1524
1525