3 use Test::More tests => 64;
5 diag("Test features of Conditional Negative Balances code.");
7 use constant WORKSTATION_NAME => 'BR1-test-09-lp1198465_neg_balances.t';
8 use constant WORKSTATION_LIB => 4;
10 use strict; use warnings;
13 use DateTime::Format::ISO8601;
14 use OpenSRF::Utils qw/cleanse_ISO8601/;
15 use OpenILS::Utils::TestUtils;
16 my $script = OpenILS::Utils::TestUtils->new();
19 our $apputils = "OpenILS::Application::AppUtils";
21 my ($patron_id, $patron_usrname, $xact_id, $item_id, $item_barcode);
22 my ($summary, $payment_blob, $pay_resp, $item_req, $checkin_resp);
24 my $storage_ses = $script->session('open-ils.storage');
28 my $patron_id = shift;
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) {
39 sub fetch_billable_xact_summary {
41 my $ses = $script->session('open-ils.cstore');
42 my $req = $ses->request(
43 'open-ils.cstore.direct.money.billable_transaction_summary.retrieve',
46 if (my $resp = $req->recv) {
47 return $resp->content;
54 my $payment_blob = shift;
55 my $resp = $apputils->simplereq(
57 'open-ils.circ.money.payment',
60 $user_obj->last_xact_id
63 #refetch user_obj to get latest last_xact_id
64 $user_obj = retrieve_patron($patron_id)
65 or die 'Could not refetch patron';
71 my $billing_ids = shift; #array ref
72 my $resp = $apputils->simplereq(
74 'open-ils.circ.money.billing.void',
82 #----------------------------------------------------------------
83 # The tests... assumes stock sample data, full-auto install by
84 # eg_wheezy_installer.sh, etc.
85 #----------------------------------------------------------------
87 # Connect to Evergreen
88 $script->authenticate({
90 password => 'demo123',
92 ok( $script->authtoken, 'Have an authtoken');
94 my $ws = $script->register_workstation(WORKSTATION_NAME,WORKSTATION_LIB);
95 ok( ! ref $ws, 'Registered a new workstation');
98 $script->authenticate({
100 password => 'demo123',
102 workstation => WORKSTATION_NAME});
103 ok( $script->authtoken, 'Have an authtoken associated with the workstation');
106 ### TODO: verify that stock data is ready for testing
108 ### Setup Org Unit Settings that apply to all test cases
110 my $org_id = 1; #CONS
112 'circ.max_item_price' => 50,
113 'circ.min_item_price' => 50,
114 'circ.void_lost_on_checkin' => 1
117 $apputils->simplereq(
119 'open-ils.actor.org_unit.settings.update',
127 $patron_usrname = '99999355250';
130 if ($user_obj = retrieve_patron($patron_id)) {
133 'Fieldmapper::actor::user',
134 'open-ils.storage.direct.actor.user.retrieve returned aou object'
139 'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
144 ##############################
145 # 1. No Prohibit Negative Balance Settings Are Enabled, Payment Made
146 ##############################
148 ### Setup use case variables
151 $item_barcode = 'CONC4000037';
154 $summary = fetch_billable_xact_summary($xact_id);
155 ok( $summary, 'CASE 1: Found the transaction summary');
157 $summary->balance_owed,
159 'Starting balance owed is 50.00 for lost item'
162 ### pay the whole bill
164 userid => $patron_id,
165 note => '09-lp1198465_neg_balances.t',
166 payment_type => 'cash_payment',
167 patron_credit => '0.00',
168 payments => [ [ $xact_id, '50.00' ] ]
170 $pay_resp = pay_bills($payment_blob);
173 scalar( @{ $pay_resp->{payments} } ),
175 'Payment response included one payment id'
178 $summary = fetch_billable_xact_summary($xact_id);
180 $summary->balance_owed,
182 'Remaining balance of 0.00 after payment'
185 ### check-in the lost copy
187 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
188 if (my $item_resp = $item_req->recv) {
189 if (my $item = $item_resp->content) {
192 'Fieldmapper::asset::copy',
193 'open-ils.storage.direct.asset.copy.retrieve returned acp object'
198 'Item with id = ' . $item_id . ' has status of LOST'
203 $checkin_resp = $script->do_checkin_override({
204 barcode => $item_barcode});
206 $checkin_resp->{ilsevent},
208 'Checkin returned a SUCCESS event'
211 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
212 if (my $item_resp = $item_req->recv) {
213 if (my $item = $item_resp->content) {
215 $item->status == 7 || $item->status == 0,
216 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
221 ### verify ending state
223 $summary = fetch_billable_xact_summary($xact_id);
225 $summary->balance_owed,
227 'Patron has a negative balance (credit) of 50.00 due to overpayment'
231 ##############################
232 # 2. Negative Balance Settings Are Unset, No Payment Made
233 ##############################
235 ### Setup use case variables
238 $item_barcode = 'CONC4000038';
241 $summary = fetch_billable_xact_summary($xact_id);
242 ok( $summary, 'CASE 2: Found the transaction summary');
244 $summary->balance_owed,
246 'Starting balance owed is 50.00 for lost item'
249 ### check-in the lost copy
251 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
252 if (my $item_resp = $item_req->recv) {
253 if (my $item = $item_resp->content) {
257 'Item with id = ' . $item_id . ' has status of LOST'
262 $checkin_resp = $script->do_checkin_override({
263 barcode => $item_barcode});
265 $checkin_resp->{ilsevent},
267 'Checkin returned a SUCCESS event'
270 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
271 if (my $item_resp = $item_req->recv) {
272 if (my $item = $item_resp->content) {
274 $item->status == 7 || $item->status == 0,
275 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
280 ### verify ending state
282 $summary = fetch_billable_xact_summary($xact_id);
284 $summary->balance_owed,
286 'Patron has a balance of 0.00'
290 ##############################
291 # 3. Basic No Negative Balance Test
292 ##############################
294 ### Setup use case variables
297 $item_barcode = 'CONC4000039';
300 # Setup Org Unit Settings
302 'bill.prohibit_negative_balance_default' => 1
304 $apputils->simplereq(
306 'open-ils.actor.org_unit.settings.update',
312 $summary = fetch_billable_xact_summary($xact_id);
313 ok( $summary, 'CASE 3: Found the transaction summary');
315 $summary->balance_owed,
317 'Starting balance owed is 50.00 for lost item'
320 ### check-in the lost copy
322 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
323 if (my $item_resp = $item_req->recv) {
324 if (my $item = $item_resp->content) {
328 'Item with id = ' . $item_id . ' has status of LOST'
333 $checkin_resp = $script->do_checkin_override({
334 barcode => $item_barcode});
336 $checkin_resp->{ilsevent},
338 'Checkin returned a SUCCESS event'
341 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
342 if (my $item_resp = $item_req->recv) {
343 if (my $item = $item_resp->content) {
345 $item->status == 7 || $item->status == 0,
346 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
351 ### verify ending state
353 $summary = fetch_billable_xact_summary($xact_id);
355 $summary->balance_owed,
357 'Patron has a balance of 0.00 (negative balance prohibited)'
360 ##############################
361 # 4. Prohibit Negative Balances with Partial Payment
362 ##############################
364 ### Setup use case variables
367 $item_barcode = 'CONC4000040';
370 # Setup Org Unit Settings
371 # already set: 'bill.prohibit_negative_balance_default' => 1
373 $summary = fetch_billable_xact_summary($xact_id);
374 ok( $summary, 'CASE 4: Found the transaction summary');
376 $summary->balance_owed,
378 'Starting balance owed is 50.00 for lost item'
381 ### confirm the copy is lost
382 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
383 if (my $item_resp = $item_req->recv) {
384 if (my $item = $item_resp->content) {
388 'Item with id = ' . $item_id . ' has status of LOST'
393 ### partially pay the bill
395 userid => $patron_id,
396 note => '09-lp1198465_neg_balances.t',
397 payment_type => 'cash_payment',
398 patron_credit => '0.00',
399 payments => [ [ $xact_id, '10.00' ] ]
401 $pay_resp = pay_bills($payment_blob);
404 scalar( @{ $pay_resp->{payments} } ),
406 'Payment response included one payment id'
409 $summary = fetch_billable_xact_summary($xact_id);
411 $summary->balance_owed,
413 'Remaining balance of 40.00 after payment'
416 ### check-in the lost copy
417 $checkin_resp = $script->do_checkin_override({
418 barcode => $item_barcode});
420 $checkin_resp->{ilsevent},
422 'Checkin returned a SUCCESS event'
425 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
426 if (my $item_resp = $item_req->recv) {
427 if (my $item = $item_resp->content) {
429 $item->status == 7 || $item->status == 0,
430 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
435 ### verify ending state
437 $summary = fetch_billable_xact_summary($xact_id);
439 $summary->balance_owed,
441 'Patron has a balance of 0.00 (negative balance prohibited)'
445 ###############################
446 ## 11. Manually voiding lost book fee does not result in negative balances
447 ###############################
449 #### Setup use case variables
452 #$item_barcode = 'CONC4000040';
455 ## Setup Org Unit Settings
456 ## already set: 'bill.prohibit_negative_balance_default' => 1
458 #$summary = fetch_billable_xact_summary($xact_id);
459 #ok( $summary, 'CASE 11: Found the transaction summary');
461 # $summary->balance_owed,
463 # 'Starting balance owed is 50.00 for lost item'
466 #### confirm the copy is lost
467 #$item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
468 #if (my $item_resp = $item_req->recv) {
469 # if (my $item = $item_resp->content) {
473 # 'Item with id = ' . $item_id . ' has status of LOST'
478 #### partially pay the bill
480 # userid => $patron_id,
481 # note => '09-lp1198465_neg_balances.t',
482 # payment_type => 'cash_payment',
483 # patron_credit => '0.00',
484 # payments => [ [ $xact_id, '10.00' ] ]
486 #$pay_resp = pay_bills($payment_blob);
489 # scalar( @{ $pay_resp->{payments} } ),
491 # 'Payment response included one payment id'
494 #$summary = fetch_billable_xact_summary($xact_id);
496 # $summary->balance_owed,
498 # 'Remaining balance of 40.00 after payment'
501 #### TODO: manually void "the rest" of the bill (i.e. prevent neg bal)
502 #### XXX: HARDCODING billing id for now; should look up the LOST bill for this xact?
503 #my @billing_ids = (6);
504 #my $void_resp = void_bills(\@billing_ids);
509 # 'Voiding was successful'
512 #### verify ending state
514 #$summary = fetch_billable_xact_summary($xact_id);
516 # $summary->balance_owed,
518 # 'Patron has a balance of 0.00 (negative balance prohibited)'
522 ##############################
523 # 12. Test negative balance settings on fines
524 ##############################
528 $patron_usrname = '99999387993';
531 if ($user_obj = retrieve_patron($patron_id)) {
534 'Fieldmapper::actor::user',
535 'open-ils.storage.direct.actor.user.retrieve returned aou object'
540 'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
544 ### Setup use case variables
547 $item_barcode = 'CONC4000043';
550 # Setup Org Unit Settings
551 # already set: 'bill.prohibit_negative_balance_default' => 1
553 $summary = fetch_billable_xact_summary($xact_id);
554 ok( $summary, 'CASE 12: Found the transaction summary');
556 $summary->balance_owed,
558 'Starting balance owed is 0.70 for overdue fines'
561 ### partially pay the bill
563 userid => $patron_id,
564 note => '09-lp1198465_neg_balances.t',
565 payment_type => 'cash_payment',
566 patron_credit => '0.00',
567 payments => [ [ $xact_id, '0.20' ] ]
569 $pay_resp = pay_bills($payment_blob);
572 scalar( @{ $pay_resp->{payments} } ),
574 'Payment response included one payment id'
577 $summary = fetch_billable_xact_summary($xact_id);
579 $summary->balance_owed,
581 'Remaining balance of 0.50 after payment'
584 ### Check in using Amnesty Mode
585 $checkin_resp = $script->do_checkin_override({
586 barcode => $item_barcode,
590 $checkin_resp->{ilsevent},
592 'Checkin returned a SUCCESS event'
595 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
596 if (my $item_resp = $item_req->recv) {
597 if (my $item = $item_resp->content) {
599 $item->status == 7 || $item->status == 0,
600 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
605 ### verify ending state
606 $summary = fetch_billable_xact_summary($xact_id);
608 $summary->balance_owed,
610 'Patron has a balance of 0.00 (remaining fines forgiven)'
614 ##############################
615 # 10. Interval Testing
616 ##############################
618 # Setup Org Unit Settings
619 # already set: 'bill.prohibit_negative_balance_default' => 1
621 # Setup Org Unit Settings
624 'bill.negative_balance_interval_default' => '1 hour'
627 $apputils->simplereq(
629 'open-ils.actor.org_unit.settings.update',
635 ### Setup use case variables
638 $item_barcode = 'CONC4000044';
640 $summary = fetch_billable_xact_summary($xact_id);
641 ok( $summary, 'CASE 10.1: Found the transaction summary');
643 $summary->balance_owed,
645 'Starting balance owed is 0.00 (LOST fee paid)'
648 ### Check in first item (right after its payment)
649 $checkin_resp = $script->do_checkin_override({
650 barcode => $item_barcode,
653 $checkin_resp->{ilsevent},
655 'Checkin returned a SUCCESS event'
658 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
659 if (my $item_resp = $item_req->recv) {
660 if (my $item = $item_resp->content) {
662 $item->status == 7 || $item->status == 0,
663 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
668 ### verify ending state for 10.1
669 $summary = fetch_billable_xact_summary($xact_id);
671 $summary->balance_owed,
673 'Patron has a balance of -50.00 (lost item returned during interval)'
676 ### Setup use case variables
679 $item_barcode = 'CONC4000045';
681 $summary = fetch_billable_xact_summary($xact_id);
682 ok( $summary, 'CASE 10.2: Found the transaction summary');
684 $summary->balance_owed,
686 'Starting balance owed is 0.00 (LOST fee paid)'
689 ### Check in second item (2 hours after its payment)
690 $checkin_resp = $script->do_checkin_override({
691 barcode => $item_barcode,
694 $checkin_resp->{ilsevent},
696 'Checkin returned a SUCCESS event'
699 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
700 if (my $item_resp = $item_req->recv) {
701 if (my $item = $item_resp->content) {
703 $item->status == 7 || $item->status == 0,
704 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
709 ### verify ending state
710 $summary = fetch_billable_xact_summary($xact_id);
712 $summary->balance_owed,
714 'Patron has a balance of 0.00 (lost item returned after interval)'
718 #############################
719 # 8. Restore Overdue Fines Appropriately, Previous Voids, Negative Balance Allowed
720 #############################
722 ## TODO: consider using a later xact_id/item_id, instead of reverting back to user 4
724 # Setup first patron (again)
726 $patron_usrname = '99999355250';
729 if ($user_obj = retrieve_patron($patron_id)) {
732 'Fieldmapper::actor::user',
733 'open-ils.storage.direct.actor.user.retrieve returned aou object'
738 'Patron with id = ' . $patron_id . ' has username ' . $patron_usrname
742 ### Setup use case variables
745 $item_barcode = 'CONC4000042';
748 # Setup Org Unit Settings
750 'bill.prohibit_negative_balance_default' => 0,
751 'circ.restore_overdue_on_lost_return' => 1,
752 'circ.lost.generate_overdue_on_checkin' => 1
755 $apputils->simplereq(
757 'open-ils.actor.org_unit.settings.update',
763 $summary = fetch_billable_xact_summary($xact_id);
764 ok( $summary, 'CASE 8: Found the transaction summary');
766 $summary->balance_owed,
768 'Starting balance owed is 50.00 for lost item'
771 ### partially pay the bill
773 userid => $patron_id,
774 note => '09-lp1198465_neg_balances.t',
775 payment_type => 'cash_payment',
776 patron_credit => '0.00',
777 payments => [ [ $xact_id, '10.00' ] ]
779 $pay_resp = pay_bills($payment_blob);
782 scalar( @{ $pay_resp->{payments} } ),
784 'Payment response included one payment id'
787 $summary = fetch_billable_xact_summary($xact_id);
789 $summary->balance_owed,
791 'Remaining balance of 40.00 after payment'
794 ### check-in the lost copy
796 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
797 if (my $item_resp = $item_req->recv) {
798 if (my $item = $item_resp->content) {
801 'Fieldmapper::asset::copy',
802 'open-ils.storage.direct.asset.copy.retrieve returned acp object'
807 'Item with id = ' . $item_id . ' has status of LOST'
812 $checkin_resp = $script->do_checkin_override({
813 barcode => $item_barcode});
815 $checkin_resp->{ilsevent},
817 'Checkin returned a SUCCESS event'
820 $item_req = $storage_ses->request('open-ils.storage.direct.asset.copy.retrieve', $item_id);
821 if (my $item_resp = $item_req->recv) {
822 if (my $item = $item_resp->content) {
824 $item->status == 7 || $item->status == 0,
825 'Item with id = ' . $item_id . ' has status of Reshelving or Available after fresh Storage request'
830 ### verify ending state
832 $summary = fetch_billable_xact_summary($xact_id);
834 $summary->balance_owed,
836 'Patron has a negative balance of 7.00 due to overpayment'