3 # Tests for SIP::ILS::Transaction
4 # Current state is very rudimentary. Please help to extend it!
7 use Test::More tests => 17;
10 use t::lib::TestBuilder;
13 use C4::SIP::ILS::Patron;
14 use C4::SIP::ILS::Transaction::RenewAll;
15 use C4::SIP::ILS::Transaction::Checkout;
16 use C4::SIP::ILS::Transaction::FeePayment;
17 use C4::SIP::ILS::Transaction::Hold;
18 use C4::SIP::ILS::Transaction::Checkout;
19 use C4::SIP::ILS::Transaction::Checkin;
21 use C4::Reserves qw( AddReserve ModReserve ModReserveAffect RevertWaitingStatus );
22 use Koha::CirculationRules;
23 use Koha::Item::Transfer;
24 use Koha::DateUtils qw( dt_from_string output_pref );
26 my $schema = Koha::Database->new->schema;
27 $schema->storage->txn_begin;
29 my $builder = t::lib::TestBuilder->new();
30 my $borr1 = $builder->build({ source => 'Borrower' });
31 my $card = $borr1->{cardnumber};
32 my $sip_patron = C4::SIP::ILS::Patron->new( $card );
34 # Create transaction RenewAll, assign patron, and run (no items)
35 my $transaction = C4::SIP::ILS::Transaction::RenewAll->new();
36 is( ref $transaction, "C4::SIP::ILS::Transaction::RenewAll", "New transaction created" );
37 is( $transaction->patron( $sip_patron ), $sip_patron, "Patron assigned to transaction" );
38 isnt( $transaction->do_renew_all, undef, "RenewAll on zero items" );
40 subtest fill_holds_at_checkout => sub {
44 my $category = $builder->build({ source => 'Category', value => { category_type => 'A' }});
45 my $branch = $builder->build({ source => 'Branch' });
46 my $borrower = $builder->build({ source => 'Borrower', value =>{
47 branchcode => $branch->{branchcode},
48 categorycode=>$category->{categorycode}
51 t::lib::Mocks::mock_userenv({ branchcode => $branch->{branchcode}, flags => 1 });
53 my $itype = $builder->build({ source => 'Itemtype', value =>{notforloan=>0} });
54 my $item1 = $builder->build_sample_item({
55 barcode => 'barcode4test',
56 homebranch => $branch->{branchcode},
57 holdingbranch => $branch->{branchcode},
58 itype => $itype->{itemtype},
61 my $item2 = $builder->build_sample_item({
62 homebranch => $branch->{branchcode},
63 holdingbranch => $branch->{branchcode},
64 biblionumber => $item1->{biblionumber},
65 itype => $itype->{itemtype},
69 Koha::CirculationRules->set_rules(
71 categorycode => $borrower->{categorycode},
72 branchcode => $branch->{branchcode},
73 itemtype => $itype->{itemtype},
77 holds_per_record => 3,
84 my $reserve1 = AddReserve(
86 branchcode => $branch->{branchcode},
87 borrowernumber => $borrower->{borrowernumber},
88 biblionumber => $item1->{biblionumber}
91 my $reserve2 = AddReserve(
93 branchcode => $branch->{branchcode},
94 borrowernumber => $borrower->{borrowernumber},
95 biblionumber => $item1->{biblionumber}
99 my $bib = Koha::Biblios->find( $item1->{biblionumber} );
100 is( $bib->holds->count(), 2, "Bib has 2 holds");
102 my $sip_patron = C4::SIP::ILS::Patron->new( $borrower->{cardnumber} );
103 my $sip_item = C4::SIP::ILS::Item->new( $item1->{barcode} );
104 my $transaction = C4::SIP::ILS::Transaction::Checkout->new();
105 is( ref $transaction, "C4::SIP::ILS::Transaction::Checkout", "New transaction created" );
106 is( $transaction->patron( $sip_patron ), $sip_patron, "Patron assigned to transaction" );
107 is( $transaction->item( $sip_item ), $sip_item, "Item assigned to transaction" );
108 my $checkout = $transaction->do_checkout();
109 use Data::Dumper; # Temporary debug statement
110 is( $bib->holds->count(), 1, "Bib has 1 holds remaining") or diag Dumper $checkout;
112 t::lib::Mocks::mock_preference('itemBarcodeInputFilter', 'whitespace');
113 $sip_item = C4::SIP::ILS::Item->new( ' barcode 4 test ');
114 $transaction = C4::SIP::ILS::Transaction::Checkout->new();
115 is( $sip_item->{barcode}, $item1->{barcode}, "Item assigned to transaction" );
118 subtest "FeePayment->pay tests" => sub {
122 # Create a borrower and add some outstanding debts to their account
123 my $patron = $builder->build( { source => 'Borrower' } );
125 Koha::Account->new( { patron_id => $patron->{borrowernumber} } );
126 my $debt1 = $account->add_debit(
127 { type => 'ACCOUNT', amount => 100, interface => 'commandline' } );
128 my $debt2 = $account->add_debit(
129 { type => 'ACCOUNT', amount => 200, interface => 'commandline' } );
131 # Instantiate a new FeePayment transaction object
132 my $trans = C4::SIP::ILS::Transaction::FeePayment->new();
135 "C4::SIP::ILS::Transaction::FeePayment",
136 "New fee transaction created"
139 # Test the 'pay' method
140 # FIXME: pay should not require a borrowernumber
141 # (we should reach out to the transaction which should contain a patron object)
142 my $pay_type = '00'; # 00 - Cash, 01 - VISA, 02 - Creditcard
144 $trans->pay( $patron->{borrowernumber}, 100, $pay_type, $debt1->id, 0,
146 ok( $ok, "FeePayment transaction succeeded" );
147 $debt1->discard_changes;
148 is( $debt1->amountoutstanding + 0, 0,
149 "Debt1 was reduced to 0 as expected" );
150 my $offsets = Koha::Account::Offsets->search(
151 { debit_id => $debt1->id, credit_id => { '!=' => undef } } );
152 is( $offsets->count, 1, "FeePayment produced an offset line correctly" );
153 my $credit = $offsets->next->credit;
154 is( $credit->payment_type, 'SIP00', "Payment type was set correctly" );
157 subtest cancel_hold => sub {
160 my $library = $builder->build_object ({ class => 'Koha::Libraries' });
161 my $patron = $builder->build_object(
163 class => 'Koha::Patrons',
165 branchcode => $library->branchcode,
169 t::lib::Mocks::mock_userenv({ branchcode => $library->branchcode, flags => 1 });
171 my $item = $builder->build_sample_item({
172 library => $library->branchcode,
175 Koha::CirculationRules->set_rules(
177 categorycode => $patron->categorycode,
178 branchcode => $library->branchcode,
179 itemtype => $item->effective_itemtype,
182 reservesallowed => 3,
183 holds_per_record => 3,
185 lengthunit => 'days',
190 my $reserve1 = AddReserve(
192 branchcode => $library->branchcode,
193 borrowernumber => $patron->borrowernumber,
194 biblionumber => $item->biblio->biblionumber,
195 itemnumber => $item->itemnumber,
198 is( $item->biblio->holds->count(), 1, "Hold was placed on bib");
199 is( $item->holds->count(),1,"Hold was placed on specific item");
201 my $sip_patron = C4::SIP::ILS::Patron->new( $patron->cardnumber );
202 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
203 my $transaction = C4::SIP::ILS::Transaction::Hold->new();
204 is( ref $transaction, "C4::SIP::ILS::Transaction::Hold", "New transaction created" );
205 is( $transaction->patron( $sip_patron ), $sip_patron, "Patron assigned to transaction" );
206 is( $transaction->item( $sip_item ), $sip_item, "Item assigned to transaction" );
207 my $hold = $transaction->drop_hold();
208 is( $item->biblio->holds->count(), 0, "Bib has 0 holds remaining");
209 is( $item->holds->count(), 0, "Item has 0 holds remaining");
212 subtest do_hold => sub {
215 my $library = $builder->build_object(
217 class => 'Koha::Libraries',
223 my $patron_1 = $builder->build_object(
225 class => 'Koha::Patrons',
227 branchcode => $library->branchcode,
231 my $patron_2 = $builder->build_object(
233 class => 'Koha::Patrons',
235 branchcode => $library->branchcode,
236 categorycode => $patron_1->categorycode,
241 t::lib::Mocks::mock_userenv(
242 { branchcode => $library->branchcode, flags => 1 } );
244 my $item = $builder->build_sample_item(
246 library => $library->branchcode,
250 my $reserve1 = AddReserve(
252 branchcode => $library->branchcode,
253 borrowernumber => $patron_1->borrowernumber,
254 biblionumber => $item->biblio->biblionumber,
255 itemnumber => $item->itemnumber,
258 is( $item->biblio->holds->count(), 1, "Hold was placed on bib" );
259 is( $item->holds->count(), 1, "Hold was placed on specific item" );
261 my $sip_patron = C4::SIP::ILS::Patron->new( $patron_2->cardnumber );
262 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
263 my $transaction = C4::SIP::ILS::Transaction::Hold->new();
266 "C4::SIP::ILS::Transaction::Hold",
267 "New transaction created"
269 is( $transaction->patron($sip_patron),
270 $sip_patron, "Patron assigned to transaction" );
271 is( $transaction->item($sip_item),
272 $sip_item, "Item assigned to transaction" );
273 my $hold = $transaction->do_hold();
274 is( $item->biblio->holds->count(), 2, "Bib has 2 holds" );
276 my $THE_hold = $patron_2->holds->next;
277 is( $THE_hold->priority, 2, 'Hold placed from SIP should have a correct priority of 2');
278 is( $THE_hold->branchcode, $patron_2->branchcode, 'Hold placed from SIP should have the branchcode set' );
281 subtest "Placing holds via SIP check CanItemBeReserved" => sub {
284 my $library = $builder->build_object(
286 class => 'Koha::Libraries',
292 my $patron_1 = $builder->build_object(
294 class => 'Koha::Patrons',
296 branchcode => $library->branchcode,
300 my $patron_2 = $builder->build_object(
302 class => 'Koha::Patrons',
304 branchcode => $library->branchcode,
305 categorycode => $patron_1->categorycode,
310 t::lib::Mocks::mock_userenv(
311 { branchcode => $library->branchcode, flags => 1 } );
313 my $item = $builder->build_sample_item(
315 library => $library->branchcode,
319 my $sip_patron = C4::SIP::ILS::Patron->new( $patron_2->cardnumber );
320 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
321 my $transaction = C4::SIP::ILS::Transaction::Hold->new();
324 "C4::SIP::ILS::Transaction::Hold",
325 "New transaction created"
327 is( $transaction->patron($sip_patron),
328 $sip_patron, "Patron assigned to transaction" );
329 is( $transaction->item($sip_item),
330 $sip_item, "Item assigned to transaction" );
331 my $hold = $transaction->do_hold();
333 is( $transaction->ok, 0, "Hold was not allowed" );
336 subtest do_checkin => sub {
339 my $mockILS = Test::MockObject->new;
340 my $server = { ils => $mockILS };
341 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
342 my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
343 my $patron = $builder->build_object(
345 class => 'Koha::Patrons',
347 branchcode => $library->branchcode,
352 t::lib::Mocks::mock_userenv(
353 { branchcode => $library->branchcode, flags => 1 } );
355 my $item = $builder->build_sample_item(
357 library => $library->branchcode,
363 my $sip_patron = C4::SIP::ILS::Patron->new( $patron->cardnumber );
364 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
365 my $co_transaction = C4::SIP::ILS::Transaction::Checkout->new();
366 is( $co_transaction->patron($sip_patron),
367 $sip_patron, "Patron assigned to transaction" );
368 is( $co_transaction->item($sip_item),
369 $sip_item, "Item assigned to transaction" );
370 my $checkout = $co_transaction->do_checkout();
371 is( $patron->checkouts->count, 1, 'Checkout should have been done successfully');
374 my $ci_transaction = C4::SIP::ILS::Transaction::Checkin->new();
375 is( $ci_transaction->patron($sip_patron),
376 $sip_patron, "Patron assigned to transaction" );
377 is( $ci_transaction->item($sip_item),
378 $sip_item, "Item assigned to transaction" );
380 my $checkin = $ci_transaction->do_checkin($library->branchcode, C4::SIP::Sip::timestamp);
381 is( $patron->checkouts->count, 0, 'Checkin should have been done successfully');
383 # Test checkin without return date
384 $co_transaction->do_checkout;
385 is( $patron->checkouts->count, 1, 'Checkout should have been done successfully');
386 $ci_transaction->do_checkin($library->branchcode, undef);
387 is( $patron->checkouts->count, 0, 'Checkin should have been done successfully');
389 my $result = $ci_transaction->do_checkin($library2->branchcode, undef);
390 is($ci_transaction->alert_type,'04',"Checkin of item no issued at another branch succeeds");
395 'NotIssued' => $item->barcode,
396 'WasTransfered' => $library->branchcode,
397 'TransferTrigger' => 'ReturnToHome'
400 "Messages show not issued and transferred"
402 is( $ci_transaction->item->destination_loc,$library->branchcode,"Item destination correctly set");
404 subtest 'Checkin an in transit item' => sub {
408 my $library_1 = $builder->build_object({ class => 'Koha::Libraries' });
409 my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
411 my $patron = $builder->build_object({ class => 'Koha::Patrons', value => {branchcode => $library_1->branchcode, }});
412 my $sip_patron = C4::SIP::ILS::Patron->new( $patron->cardnumber );
413 my $item = $builder->build_sample_item({ library => $library_1->branchcode });
414 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
416 t::lib::Mocks::mock_userenv(
417 { branchcode => $library_1->branchcode, flags => 1 } );
419 my $reserve = AddReserve(
421 branchcode => $library_1->branchcode,
422 borrowernumber => $patron->borrowernumber,
423 biblionumber => $item->biblionumber,
427 ModReserveAffect( $item->itemnumber, $patron->borrowernumber ); # Mark waiting
429 my $ci_transaction = C4::SIP::ILS::Transaction::Checkin->new();
430 is( $ci_transaction->patron($sip_patron),
431 $sip_patron, "Patron assigned to transaction" );
432 is( $ci_transaction->item($sip_item),
433 $sip_item, "Item assigned to transaction" );
435 my $checkin = $ci_transaction->do_checkin($library_2->branchcode, C4::SIP::Sip::timestamp);
437 my $hold = Koha::Holds->find($reserve);
438 is( $hold->found, 'T', );
439 is( $hold->itemnumber, $item->itemnumber, );
440 is( Koha::Checkouts->search({itemnumber => $item->itemnumber})->count, 0, );
443 subtest 'Checkin with fines' => sub {
446 my $mockILS = Test::MockObject->new;
447 my $server = { ils => $mockILS };
448 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
451 implementation => "ILS",
460 my $ils = C4::SIP::ILS->new($institution);
461 my $item = $builder->build_sample_item(
463 library => $library->branchcode,
467 # show_outstanding_amount disabled
468 my $patron = $builder->build_object(
470 class => 'Koha::Patrons',
472 branchcode => $library->branchcode,
476 my $circ = $ils->checkout($patron->cardnumber, $item->barcode, undef, undef, $server->{account});
477 my $fee1 = $builder->build(
479 source => 'Accountline',
481 borrowernumber => $patron->borrowernumber,
482 amountoutstanding => 12,
483 debit_type_code => 'OVERDUE',
484 itemnumber => $item->itemnumber
488 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode, undef, undef, $server->{account} );
489 is( $circ->{screen_msg}, '', "The fine is not displayed on checkin when show_outstanding_amount is disabled" );
491 # show_outstanding_amount enabled
492 $patron = $builder->build_object(
494 class => 'Koha::Patrons',
496 branchcode => $library->branchcode,
500 $circ = $ils->checkout($patron->cardnumber, $item->barcode, undef, undef, $server->{account});
502 $fee1 = $builder->build(
504 source => 'Accountline',
506 borrowernumber => $patron->borrowernumber,
507 amountoutstanding => 12,
508 debit_type_code => 'OVERDUE',
509 itemnumber => $item->itemnumber
514 $server->{account}->{show_outstanding_amount} = 1;
515 $circ = $ils->checkout($patron->cardnumber, $item->barcode, undef, undef, $server->{account});
517 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode, undef, undef, $server->{account} );
518 is( $circ->{screen_msg}, 'You owe $12.00 for this item.', "The fine is displayed on checkin when show_outstanding_amount is enabled" );
523 subtest do_checkout_with_sysprefs_override => sub {
526 my $mockILS = Test::MockObject->new;
527 my $server = { ils => $mockILS };
528 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
531 implementation => "ILS",
540 my $ils = C4::SIP::ILS->new($institution);
541 my $item = $builder->build_sample_item(
543 library => $library->branchcode,
547 my $patron_under_noissuescharge = $builder->build_object(
549 class => 'Koha::Patrons',
551 branchcode => $library->branchcode,
556 my $fee_under_noissuescharge = $builder->build(
558 source => 'Accountline',
560 borrowernumber => $patron_under_noissuescharge->borrowernumber,
561 amountoutstanding => 4,
562 debit_type_code => 'OVERDUE',
567 my $patron_over_noissuescharge = $builder->build_object(
570 class => 'Koha::Patrons',
572 branchcode => $library->branchcode,
577 my $fee_over_noissuescharge = $builder->build(
579 source => 'Accountline',
581 borrowernumber => $patron_over_noissuescharge->borrowernumber,
582 amountoutstanding => 6,
583 debit_type_code => 'OVERDUE',
589 $server->{account}->{override_fine_on_checkout} = 0;
591 t::lib::Mocks::mock_preference( 'AllFinesNeedOverride', '0' );
592 t::lib::Mocks::mock_preference( 'AllowFineOverride', '0' );
593 my $circ = $ils->checkout($patron_under_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
594 is( $patron_under_noissuescharge->checkouts->count, 1, 'Checkout is allowed when the amount is under noissuecharge, AllFinesNeedOverride and AllowFineOverride disabled');
596 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
598 $circ = $ils->checkout($patron_over_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
599 is( $patron_over_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is over noissuecharge, AllFinesNeedOverride and AllowFineOverride disabled');
601 t::lib::Mocks::mock_preference( 'AllFinesNeedOverride', '0' );
602 t::lib::Mocks::mock_preference( 'AllowFineOverride', '1' );
604 $circ = $ils->checkout($patron_under_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
605 is( $patron_under_noissuescharge->checkouts->count, 1, 'Checkout is allowed when the amount is under noissuecharge, AllFinesNeedOverride disabled and AllowFineOverride enabled');
607 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
609 $circ = $ils->checkout($patron_over_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
610 is( $patron_over_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is over noissuecharge, AllFinesNeedOverride disabled and AllowFineOverride enabled');
612 t::lib::Mocks::mock_preference( 'AllFinesNeedOverride', '1' );
613 t::lib::Mocks::mock_preference( 'AllowFineOverride', '0' );
615 $circ = $ils->checkout($patron_under_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
616 is( $patron_under_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is under noissuecharge, AllFinesNeedOverride enabled and AllowFineOverride disabled');
618 $circ = $ils->checkout($patron_over_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
619 is( $patron_over_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is over noissuecharge, AllFinesNeedOverride enabled and AllowFineOverride disabled');
621 t::lib::Mocks::mock_preference( 'AllFinesNeedOverride', '1' );
622 t::lib::Mocks::mock_preference( 'AllowFineOverride', '1' );
624 $circ = $ils->checkout($patron_under_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
625 is( $patron_under_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is under noissuecharge, AllFinesNeedOverride and AllowFineOverride enabled');
627 $circ = $ils->checkout($patron_over_noissuescharge->cardnumber, $item->barcode, undef, undef, $server->{account});
628 is( $patron_over_noissuescharge->checkouts->count, 0, 'Checkout is blocked when the amount is over noissuecharge, AllFinesNeedOverride and AllowFineOverride enabled');
632 subtest do_checkout_with_patron_blocked => sub {
635 my $mockILS = Test::MockObject->new;
636 my $server = { ils => $mockILS };
637 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
640 implementation => "ILS",
649 my $ils = C4::SIP::ILS->new($institution);
650 my $item = $builder->build_sample_item(
652 library => $library->branchcode,
656 my $expired_patron = $builder->build_object(
658 class => 'Koha::Patrons',
660 branchcode => $library->branchcode,
661 dateexpiry => '2020/01/03',
665 my $circ = $ils->checkout($expired_patron->cardnumber, $item->barcode);
666 is( $circ->{screen_msg}, 'Patron expired on 01/03/2020', "Got correct expired screen message" );
668 my $fines_patron = $builder->build_object(
670 class => 'Koha::Patrons',
672 branchcode => $library->branchcode,
676 my $fee1 = $builder->build(
678 source => 'Accountline',
680 borrowernumber => $fines_patron->borrowernumber,
681 amountoutstanding => 10,
682 debit_type_code => 'OVERDUE',
687 my $fines_sip_patron = C4::SIP::ILS::Patron->new( $fines_patron->cardnumber );
689 $circ = $ils->checkout($fines_patron->cardnumber, $item->barcode, undef, undef, $server->{account});
690 is( $circ->{screen_msg}, 'Patron has fines', "Got correct fines screen message" );
692 $server->{account}->{show_outstanding_amount} = 1;
693 $circ = $ils->checkout($fines_patron->cardnumber, $item->barcode, undef, undef, $server->{account});
694 is( $circ->{screen_msg}, 'Patron has fines - You owe $10.00.', "Got correct fines with amount screen message" );
695 my $debarred_patron = $builder->build_object(
697 class => 'Koha::Patrons',
699 branchcode => $library->branchcode,
700 debarred => '9999/01/01',
704 my $debarred_sip_patron = C4::SIP::ILS::Patron->new( $debarred_patron->cardnumber );
705 $circ = $ils->checkout($debarred_patron->cardnumber, $item->barcode);
706 is( $circ->{screen_msg}, 'Patron debarred', "Got correct debarred screen message" );
708 my $overdue_patron = $builder->build_object(
710 class => 'Koha::Patrons',
712 branchcode => $library->branchcode,
717 my $odue = $builder->build({ source => 'Issue', value => {
718 borrowernumber => $overdue_patron->borrowernumber,
719 date_due => '2017-01-01',
722 t::lib::Mocks::mock_preference( 'OverduesBlockCirc', 'block' );
723 my $overdue_sip_patron = C4::SIP::ILS::Patron->new( $overdue_patron->cardnumber );
724 $circ = $ils->checkout($overdue_patron->cardnumber, $item->barcode);
725 is( $circ->{screen_msg}, 'Patron blocked', "Got correct blocked screen message" );
729 subtest do_checkout_with_noblock => sub {
732 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
733 my $patron = $builder->build_object(
735 class => 'Koha::Patrons',
737 branchcode => $library->branchcode,
738 debarred => '9999/01/01',
743 t::lib::Mocks::mock_userenv(
744 { branchcode => $library->branchcode, flags => 1 } );
746 my $item = $builder->build_sample_item(
748 library => $library->branchcode,
753 my $sip_patron = C4::SIP::ILS::Patron->new( $patron->cardnumber );
754 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
755 my $co_transaction = C4::SIP::ILS::Transaction::Checkout->new();
756 is( $co_transaction->patron($sip_patron),
757 $sip_patron, "Patron assigned to transaction" );
758 is( $co_transaction->item($sip_item),
759 $sip_item, "Item assigned to transaction" );
761 $co_transaction->do_checkout(undef, '19990102 030405');
763 is( $patron->checkouts->count, 1, 'No Block checkout was performed for debarred patron');
766 subtest do_checkout_with_holds => sub {
769 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
770 my $patron = $builder->build_object(
772 class => 'Koha::Patrons',
774 branchcode => $library->branchcode,
778 my $patron2 = $builder->build_object(
780 class => 'Koha::Patrons',
782 branchcode => $library->branchcode,
787 t::lib::Mocks::mock_userenv(
788 { branchcode => $library->branchcode, flags => 1 } );
790 my $item = $builder->build_sample_item(
792 library => $library->branchcode,
796 my $reserve = AddReserve(
798 branchcode => $library->branchcode,
799 borrowernumber => $patron2->borrowernumber,
800 biblionumber => $item->biblionumber,
804 my $sip_patron = C4::SIP::ILS::Patron->new( $patron->cardnumber );
805 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
806 my $co_transaction = C4::SIP::ILS::Transaction::Checkout->new();
807 is( $co_transaction->patron($sip_patron),
808 $sip_patron, "Patron assigned to transaction" );
809 is( $co_transaction->item($sip_item),
810 $sip_item, "Item assigned to transaction" );
812 # Test attached holds
813 ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 0, $reserve ); # Mark waiting (W)
814 my $hold = Koha::Holds->find($reserve);
815 $co_transaction->do_checkout();
816 is( $patron->checkouts->count, 0, 'Checkout was not done due to attached hold (W)');
819 $co_transaction->do_checkout();
820 is( $patron->checkouts->count, 0, 'Checkout was not done due to attached hold (T)');
822 $hold->set_processing;
823 $co_transaction->do_checkout();
824 is( $patron->checkouts->count, 0, 'Checkout was not done due to attached hold (P)');
826 # Test non-attached holds
827 C4::Reserves::RevertWaitingStatus({ itemnumber => $hold->itemnumber });
828 t::lib::Mocks::mock_preference('AllowItemsOnHoldCheckoutSIP', '0');
829 $co_transaction->do_checkout();
830 is( $patron->checkouts->count, 0, 'Checkout refused due to hold and AllowItemsOnHoldCheckoutSIP');
832 t::lib::Mocks::mock_preference('AllowItemsOnHoldCheckoutSIP', '1');
833 $co_transaction->do_checkout();
834 is( $patron->checkouts->count, 1, 'Checkout allowed due to hold and AllowItemsOnHoldCheckoutSIP');
837 subtest checkin_lost => sub {
840 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
842 t::lib::Mocks::mock_userenv(
843 { branchcode => $library->branchcode, flags => 1 } );
845 my $item = $builder->build_sample_item(
847 library => $library->branchcode,
851 $item->itemlost(1)->itemlost_on(dt_from_string)->store();
855 implementation => "ILS",
864 my $ils = C4::SIP::ILS->new( $instituation );
866 t::lib::Mocks::mock_preference('BlockReturnOfLostItems', '1');
867 my $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
868 is( $circ->{screen_msg}, 'Item lost, return not allowed', "Got correct screen message" );
870 t::lib::Mocks::mock_preference('BlockReturnOfLostItems', '0');
871 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
872 is( $circ->{screen_msg}, 'Item not checked out', "Got 'Item not checked out' screen message" );
875 subtest checkin_withdrawn => sub {
878 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
880 t::lib::Mocks::mock_userenv(
881 { branchcode => $library->branchcode, flags => 1 } );
883 my $item = $builder->build_sample_item(
885 library => $library->branchcode,
889 $item->withdrawn(1)->withdrawn_on(dt_from_string)->store();
893 implementation => "ILS",
902 my $ils = C4::SIP::ILS->new( $instituation );
904 t::lib::Mocks::mock_preference('BlockReturnOfWithdrawnItems', '1');
905 my $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
906 is( $circ->{screen_msg}, 'Item withdrawn, return not allowed', "Got correct screen message" );
908 t::lib::Mocks::mock_preference('BlockReturnOfWithdrawnItems', '0');
909 $circ = $ils->checkin( $item->barcode, C4::SIP::Sip::timestamp, undef, $library->branchcode );
910 is( $circ->{screen_msg}, 'Item not checked out', "Got 'Item not checked out' screen message" );
913 subtest _get_sort_bin => sub {
916 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
917 my $branch = $library->branchcode;
918 my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
919 my $branch2 = $library2->branchcode;
921 my $rules = <<"RULES";
922 $branch:homebranch:ne:\$holdingbranch:X\r
923 $branch:effective_itemtype:eq:CD:0\r
924 $branch:itemcallnumber:<:340:1\r
925 $branch:itemcallnumber:<:370:2\r
926 $branch:itemcallnumber:<:600:3\r
927 $branch2:homebranch:ne:\$holdingbranch:X\r
928 $branch2:effective_itemtype:eq:CD:4\r
929 $branch2:itemcallnumber:>:600:5\r
931 t::lib::Mocks::mock_preference('SIP2SortBinMapping', $rules);
933 my $item_cd = $builder->build_sample_item(
935 library => $library->branchcode,
940 my $item_book = $builder->build_sample_item(
942 library => $library->branchcode,
944 itemcallnumber => '200.01'
950 # Set holdingbranch as though item returned to library other than homebranch (As AddReturn would)
951 $item_cd->holdingbranch($library2->branchcode)->store();
952 $bin = C4::SIP::ILS::Transaction::Checkin::_get_sort_bin( $item_cd, $library2->branchcode );
953 is($bin, 'X', "Item parameter on RHS of comparison works (ne comparator)");
955 # Reset holdingbranch as though item returned to home library
956 $item_cd->holdingbranch($library->branchcode)->store();
957 $bin = C4::SIP::ILS::Transaction::Checkin::_get_sort_bin( $item_cd, $library->branchcode );
958 is($bin, '0', "Fixed value on RHS of comparison works (eq comparator)");
959 $bin = C4::SIP::ILS::Transaction::Checkin::_get_sort_bin( $item_book, $library->branchcode );
960 is($bin, '1', "Rules applied in order (< comparator)");
961 $item_book->itemcallnumber('350.20')->store();
962 $bin = C4::SIP::ILS::Transaction::Checkin::_get_sort_bin( $item_book, $library->branchcode );
963 is($bin, '2', "Rules applied in order (< comparator)");
966 subtest item_circulation_status => sub {
969 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
970 my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
972 my $patron = $builder->build_object(
974 class => 'Koha::Patrons',
976 branchcode => $library->branchcode,
981 t::lib::Mocks::mock_userenv(
982 { branchcode => $library->branchcode, flags => 1 } );
984 my $item = $builder->build_sample_item(
986 library => $library->branchcode,
990 my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
991 my $status = $sip_item->sip_circulation_status;
992 is( $status, '03', "Item circulation status is available");
994 my $transfer = Koha::Item::Transfer->new({
995 itemnumber => $item->id,
996 datesent => '2020-01-01',
997 frombranch => $library->branchcode,
998 tobranch => $library2->branchcode,
1001 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1002 $status = $sip_item->sip_circulation_status;
1003 is( $status, '10', "Item circulation status is in transit" );
1007 my $claim = Koha::Checkouts::ReturnClaim->new({
1008 itemnumber => $item->id,
1009 borrowernumber => $patron->id,
1010 created_by => $patron->id,
1013 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1014 $status = $sip_item->sip_circulation_status;
1015 is( $status, '11', "Item circulation status is claimed returned" );
1019 $item->itemlost(1)->store();
1020 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1021 $status = $sip_item->sip_circulation_status;
1022 is( $status, '12', "Item circulation status is lost" );
1023 $item->itemlost(0)->store();
1025 my $location = $item->location;
1026 $item->location("CART")->store();
1027 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1028 $status = $sip_item->sip_circulation_status;
1029 is( $status, '09', "Item circulation status is waiting to be re-shelved" );
1030 $item->location($location)->store();
1032 my $nfl = $item->notforloan;
1033 $item->notforloan(-1)->store();
1034 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1035 $status = $sip_item->sip_circulation_status;
1036 is( $status, '02', "Item circulation status is on order" );
1037 $item->notforloan($nfl)->store();
1039 my $damaged = $item->damaged;
1040 $item->damaged(1)->store();
1041 $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
1042 $status = $sip_item->sip_circulation_status;
1043 is( $status, '01', "Item circulation status is damaged" );
1044 $item->damaged(0)->store();
1046 $schema->storage->txn_rollback;