Bug 18501: (follow-up) Test undefined userenv behaviour
[koha.git] / t / db_dependent / Koha / Items.t
blob6140139c0cd6ddb5537dfb95686ca06f62bf86c9
1 #!/usr/bin/perl
3 # Copyright 2016 Koha Development team
5 # This file is part of Koha
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Modern::Perl;
22 use Test::More tests => 11;
23 use Test::Exception;
24 use Time::Fake;
26 use C4::Circulation;
27 use C4::Context;
28 use Koha::Item;
29 use Koha::Item::Transfer::Limits;
30 use Koha::Items;
31 use Koha::Database;
32 use Koha::DateUtils qw( dt_from_string );
34 use t::lib::TestBuilder;
35 use t::lib::Mocks;
36 use t::lib::Dates;
38 my $schema = Koha::Database->new->schema;
39 $schema->storage->txn_begin;
41 my $dbh = C4::Context->dbh;
43 my $builder = t::lib::TestBuilder->new;
44 my $library = $builder->build( { source => 'Branch' } );
45 my $nb_of_items = Koha::Items->search->count;
46 my $biblio = $builder->build_sample_biblio();
47 my $new_item_1 = $builder->build_sample_item({
48 biblionumber => $biblio->biblionumber,
49 homebranch => $library->{branchcode},
50 holdingbranch => $library->{branchcode},
51 });
52 my $new_item_2 = $builder->build_sample_item({
53 biblionumber => $biblio->biblionumber,
54 homebranch => $library->{branchcode},
55 holdingbranch => $library->{branchcode},
56 });
59 t::lib::Mocks::mock_userenv({ branchcode => $library->{branchcode} });
61 like( $new_item_1->itemnumber, qr|^\d+$|, 'Adding a new item should have set the itemnumber' );
62 is( Koha::Items->search->count, $nb_of_items + 2, 'The 2 items should have been added' );
64 my $retrieved_item_1 = Koha::Items->find( $new_item_1->itemnumber );
65 is( $retrieved_item_1->barcode, $new_item_1->barcode, 'Find a item by id should return the correct item' );
67 subtest 'store' => sub {
68 plan tests => 6;
70 my $biblio = $builder->build_sample_biblio;
71 my $today = dt_from_string->set( hour => 0, minute => 0, second => 0 );
72 my $item = Koha::Item->new(
74 homebranch => $library->{branchcode},
75 holdingbranch => $library->{branchcode},
76 biblionumber => $biblio->biblionumber,
77 location => 'my_loc',
79 )->store->get_from_storage;
81 is( t::lib::Dates::compare( $item->replacementpricedate, $today ),
82 0, 'replacementpricedate must have been set to today if not given' );
83 is( t::lib::Dates::compare( $item->datelastseen, $today ),
84 0, 'datelastseen must have been set to today if not given' );
85 is(
86 $item->itype,
87 $biblio->biblioitem->itemtype,
88 'items.itype must have been set to biblioitem.itemtype is not given'
90 is( $item->permanent_location, $item->location,
91 'permanent_location must have been set to location if not given' );
92 $item->delete;
94 subtest '*_on updates' => sub {
95 plan tests => 9;
97 # Once the '_on' value is set (triggered by the related field turning from false to true)
98 # it should not be re-set for any changes outside of the related field being 'unset'.
100 my @fields = qw( itemlost withdrawn damaged );
101 my $today = dt_from_string();
102 my $yesterday = $today->clone()->subtract( days => 1 );
104 for my $field ( @fields ) {
105 my $item = $builder->build_sample_item(
107 itemlost => 0,
108 itemlost_on => undef,
109 withdrawn => 0,
110 withdrawn_on => undef,
111 damaged => 0,
112 damaged_on => undef
115 my $field_on = $field . '_on';
117 # Set field for the first time
118 Time::Fake->offset( $yesterday->epoch );
119 $item->$field(1)->store;
120 $item->get_from_storage;
121 is($item->$field_on, DateTime::Format::MySQL->format_datetime($yesterday), $field_on . " was set upon first truthy setting");
123 # Update the field to a new 'true' value
124 Time::Fake->offset( $today->epoch );
125 $item->$field(2)->store;
126 $item->get_from_storage;
127 is($item->$field_on, DateTime::Format::MySQL->format_datetime($yesterday), $field_on . " was not updated upon second truthy setting");
129 # Update the field to a new 'false' value
130 $item->$field(0)->store;
131 $item->get_from_storage;
132 is($item->$field_on, undef, $field_on . " was unset upon untruthy setting");
134 Time::Fake->reset;
138 subtest '_lost_found_trigger' => sub {
139 plan tests => 7;
141 t::lib::Mocks::mock_preference( 'WhenLostChargeReplacementFee', 1 );
142 t::lib::Mocks::mock_preference( 'WhenLostForgiveFine', 0 );
144 my $processfee_amount = 20;
145 my $replacement_amount = 99.00;
146 my $item_type = $builder->build_object(
148 class => 'Koha::ItemTypes',
149 value => {
150 notforloan => undef,
151 rentalcharge => 0,
152 defaultreplacecost => undef,
153 processfee => $processfee_amount,
154 rentalcharge_daily => 0,
158 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
160 $biblio = $builder->build_sample_biblio( { author => 'Hall, Daria' } );
162 subtest 'Full write-off tests' => sub {
164 plan tests => 12;
166 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
167 my $manager =
168 $builder->build_object( { class => "Koha::Patrons" } );
169 t::lib::Mocks::mock_userenv(
170 { patron => $manager, branchcode => $manager->branchcode } );
172 my $item = $builder->build_sample_item(
174 biblionumber => $biblio->biblionumber,
175 library => $library->branchcode,
176 replacementprice => $replacement_amount,
177 itype => $item_type->itemtype,
181 C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
183 # Simulate item marked as lost
184 $item->itemlost(3)->store;
185 C4::Circulation::LostItem( $item->itemnumber, 1 );
187 my $processing_fee_lines = Koha::Account::Lines->search(
189 borrowernumber => $patron->id,
190 itemnumber => $item->itemnumber,
191 debit_type_code => 'PROCESSING'
194 is( $processing_fee_lines->count,
195 1, 'Only one processing fee produced' );
196 my $processing_fee_line = $processing_fee_lines->next;
197 is( $processing_fee_line->amount + 0,
198 $processfee_amount,
199 'The right PROCESSING amount is generated' );
200 is( $processing_fee_line->amountoutstanding + 0,
201 $processfee_amount,
202 'The right PROCESSING amountoutstanding is generated' );
204 my $lost_fee_lines = Koha::Account::Lines->search(
206 borrowernumber => $patron->id,
207 itemnumber => $item->itemnumber,
208 debit_type_code => 'LOST'
211 is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
212 my $lost_fee_line = $lost_fee_lines->next;
213 is( $lost_fee_line->amount + 0,
214 $replacement_amount, 'The right LOST amount is generated' );
215 is( $lost_fee_line->amountoutstanding + 0,
216 $replacement_amount,
217 'The right LOST amountoutstanding is generated' );
218 is( $lost_fee_line->status, undef, 'The LOST status was not set' );
220 my $account = $patron->account;
221 my $debts = $account->outstanding_debits;
223 # Write off the debt
224 my $credit = $account->add_credit(
226 amount => $account->balance,
227 type => 'WRITEOFF',
228 interface => 'test',
231 $credit->apply(
232 { debits => [ $debts->as_list ], offset_type => 'Writeoff' } );
234 # Simulate item marked as found
235 $item->itemlost(0)->store;
236 is( $item->{_refunded}, undef, 'No LOST_FOUND account line added' );
238 $lost_fee_line->discard_changes; # reload from DB
239 is( $lost_fee_line->amountoutstanding + 0,
240 0, 'Lost fee has no outstanding amount' );
241 is( $lost_fee_line->debit_type_code,
242 'LOST', 'Lost fee now still has account type of LOST' );
243 is( $lost_fee_line->status, 'FOUND',
244 "Lost fee now has account status of FOUND - No Refund" );
246 is( $patron->account->balance,
247 -0, 'The patron balance is 0, everything was written off' );
250 subtest 'Full payment tests' => sub {
252 plan tests => 14;
254 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
256 my $item = $builder->build_sample_item(
258 biblionumber => $biblio->biblionumber,
259 library => $library->branchcode,
260 replacementprice => $replacement_amount,
261 itype => $item_type->itemtype
265 my $issue =
266 C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
268 # Simulate item marked as lost
269 $item->itemlost(1)->store;
270 C4::Circulation::LostItem( $item->itemnumber, 1 );
272 my $processing_fee_lines = Koha::Account::Lines->search(
274 borrowernumber => $patron->id,
275 itemnumber => $item->itemnumber,
276 debit_type_code => 'PROCESSING'
279 is( $processing_fee_lines->count,
280 1, 'Only one processing fee produced' );
281 my $processing_fee_line = $processing_fee_lines->next;
282 is( $processing_fee_line->amount + 0,
283 $processfee_amount,
284 'The right PROCESSING amount is generated' );
285 is( $processing_fee_line->amountoutstanding + 0,
286 $processfee_amount,
287 'The right PROCESSING amountoutstanding is generated' );
289 my $lost_fee_lines = Koha::Account::Lines->search(
291 borrowernumber => $patron->id,
292 itemnumber => $item->itemnumber,
293 debit_type_code => 'LOST'
296 is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
297 my $lost_fee_line = $lost_fee_lines->next;
298 is( $lost_fee_line->amount + 0,
299 $replacement_amount, 'The right LOST amount is generated' );
300 is( $lost_fee_line->amountoutstanding + 0,
301 $replacement_amount,
302 'The right LOST amountountstanding is generated' );
304 my $account = $patron->account;
305 my $debts = $account->outstanding_debits;
307 # Pay off the debt
308 my $credit = $account->add_credit(
310 amount => $account->balance,
311 type => 'PAYMENT',
312 interface => 'test',
315 $credit->apply(
316 { debits => [ $debts->as_list ], offset_type => 'Payment' } );
318 # Simulate item marked as found
319 $item->itemlost(0)->store;
320 is( $item->{_refunded}, 1, 'Refund triggered' );
322 my $credit_return = Koha::Account::Lines->search(
324 itemnumber => $item->itemnumber,
325 credit_type_code => 'LOST_FOUND'
327 { rows => 1 }
328 )->single;
330 ok( $credit_return, 'An account line of type LOST_FOUND is added' );
331 is( $credit_return->amount + 0,
332 -99.00,
333 'The account line of type LOST_FOUND has an amount of -99' );
335 $credit_return->amountoutstanding + 0,
336 -99.00,
337 'The account line of type LOST_FOUND has an amountoutstanding of -99'
340 $lost_fee_line->discard_changes;
341 is( $lost_fee_line->amountoutstanding + 0,
342 0, 'Lost fee has no outstanding amount' );
343 is( $lost_fee_line->debit_type_code,
344 'LOST', 'Lost fee now still has account type of LOST' );
345 is( $lost_fee_line->status, 'FOUND',
346 "Lost fee now has account status of FOUND" );
348 is( $patron->account->balance, -99,
349 'The patron balance is -99, a credit that equals the lost fee payment'
353 subtest 'Test without payment or write off' => sub {
355 plan tests => 14;
357 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
359 my $item = $builder->build_sample_item(
361 biblionumber => $biblio->biblionumber,
362 library => $library->branchcode,
363 replacementprice => 23.00,
364 replacementprice => $replacement_amount,
365 itype => $item_type->itemtype
369 my $issue =
370 C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
372 # Simulate item marked as lost
373 $item->itemlost(3)->store;
374 C4::Circulation::LostItem( $item->itemnumber, 1 );
376 my $processing_fee_lines = Koha::Account::Lines->search(
378 borrowernumber => $patron->id,
379 itemnumber => $item->itemnumber,
380 debit_type_code => 'PROCESSING'
383 is( $processing_fee_lines->count,
384 1, 'Only one processing fee produced' );
385 my $processing_fee_line = $processing_fee_lines->next;
386 is( $processing_fee_line->amount + 0,
387 $processfee_amount,
388 'The right PROCESSING amount is generated' );
389 is( $processing_fee_line->amountoutstanding + 0,
390 $processfee_amount,
391 'The right PROCESSING amountoutstanding is generated' );
393 my $lost_fee_lines = Koha::Account::Lines->search(
395 borrowernumber => $patron->id,
396 itemnumber => $item->itemnumber,
397 debit_type_code => 'LOST'
400 is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
401 my $lost_fee_line = $lost_fee_lines->next;
402 is( $lost_fee_line->amount + 0,
403 $replacement_amount, 'The right LOST amount is generated' );
404 is( $lost_fee_line->amountoutstanding + 0,
405 $replacement_amount,
406 'The right LOST amountountstanding is generated' );
408 # Simulate item marked as found
409 $item->itemlost(0)->store;
410 is( $item->{_refunded}, 1, 'Refund triggered' );
412 my $credit_return = Koha::Account::Lines->search(
414 itemnumber => $item->itemnumber,
415 credit_type_code => 'LOST_FOUND'
417 { rows => 1 }
418 )->single;
420 ok( $credit_return, 'An account line of type LOST_FOUND is added' );
421 is( $credit_return->amount + 0,
422 -99.00,
423 'The account line of type LOST_FOUND has an amount of -99' );
425 $credit_return->amountoutstanding + 0,
427 'The account line of type LOST_FOUND has an amountoutstanding of 0'
430 $lost_fee_line->discard_changes;
431 is( $lost_fee_line->amountoutstanding + 0,
432 0, 'Lost fee has no outstanding amount' );
433 is( $lost_fee_line->debit_type_code,
434 'LOST', 'Lost fee now still has account type of LOST' );
435 is( $lost_fee_line->status, 'FOUND',
436 "Lost fee now has account status of FOUND" );
438 is( $patron->account->balance,
439 20, 'The patron balance is 20, still owes the processing fee' );
442 subtest
443 'Test with partial payement and write off, and remaining debt' =>
444 sub {
446 plan tests => 17;
448 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
449 my $item = $builder->build_sample_item(
451 biblionumber => $biblio->biblionumber,
452 library => $library->branchcode,
453 replacementprice => $replacement_amount,
454 itype => $item_type->itemtype
458 my $issue =
459 C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
461 # Simulate item marked as lost
462 $item->itemlost(1)->store;
463 C4::Circulation::LostItem( $item->itemnumber, 1 );
465 my $processing_fee_lines = Koha::Account::Lines->search(
467 borrowernumber => $patron->id,
468 itemnumber => $item->itemnumber,
469 debit_type_code => 'PROCESSING'
472 is( $processing_fee_lines->count,
473 1, 'Only one processing fee produced' );
474 my $processing_fee_line = $processing_fee_lines->next;
475 is( $processing_fee_line->amount + 0,
476 $processfee_amount,
477 'The right PROCESSING amount is generated' );
478 is( $processing_fee_line->amountoutstanding + 0,
479 $processfee_amount,
480 'The right PROCESSING amountoutstanding is generated' );
482 my $lost_fee_lines = Koha::Account::Lines->search(
484 borrowernumber => $patron->id,
485 itemnumber => $item->itemnumber,
486 debit_type_code => 'LOST'
489 is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
490 my $lost_fee_line = $lost_fee_lines->next;
491 is( $lost_fee_line->amount + 0,
492 $replacement_amount, 'The right LOST amount is generated' );
493 is( $lost_fee_line->amountoutstanding + 0,
494 $replacement_amount,
495 'The right LOST amountountstanding is generated' );
497 my $account = $patron->account;
499 $account->balance,
500 $processfee_amount + $replacement_amount,
501 'Balance is PROCESSING + L'
504 # Partially pay fee
505 my $payment_amount = 27;
506 my $payment = $account->add_credit(
508 amount => $payment_amount,
509 type => 'PAYMENT',
510 interface => 'test',
514 $payment->apply(
515 { debits => [$lost_fee_line], offset_type => 'Payment' } );
517 # Partially write off fee
518 my $write_off_amount = 25;
519 my $write_off = $account->add_credit(
521 amount => $write_off_amount,
522 type => 'WRITEOFF',
523 interface => 'test',
526 $write_off->apply(
527 { debits => [$lost_fee_line], offset_type => 'Writeoff' } );
530 $account->balance,
531 $processfee_amount +
532 $replacement_amount -
533 $payment_amount -
534 $write_off_amount,
535 'Payment and write off applied'
538 # Store the amountoutstanding value
539 $lost_fee_line->discard_changes;
540 my $outstanding = $lost_fee_line->amountoutstanding;
542 # Simulate item marked as found
543 $item->itemlost(0)->store;
544 is( $item->{_refunded}, 1, 'Refund triggered' );
546 my $credit_return = Koha::Account::Lines->search(
548 itemnumber => $item->itemnumber,
549 credit_type_code => 'LOST_FOUND'
551 { rows => 1 }
552 )->single;
554 ok( $credit_return, 'An account line of type LOST_FOUND is added' );
557 $account->balance,
558 $processfee_amount - $payment_amount,
559 'Balance is PROCESSING - PAYMENT (LOST_FOUND)'
562 $lost_fee_line->discard_changes;
563 is( $lost_fee_line->amountoutstanding + 0,
564 0, 'Lost fee has no outstanding amount' );
565 is( $lost_fee_line->debit_type_code,
566 'LOST', 'Lost fee now still has account type of LOST' );
567 is( $lost_fee_line->status, 'FOUND',
568 "Lost fee now has account status of FOUND" );
571 $credit_return->amount + 0,
572 ( $payment_amount + $outstanding ) * -1,
573 'The account line of type LOST_FOUND has an amount equal to the payment + outstanding'
576 $credit_return->amountoutstanding + 0,
577 $payment_amount * -1,
578 'The account line of type LOST_FOUND has an amountoutstanding equal to the payment'
582 $account->balance,
583 $processfee_amount - $payment_amount,
584 'The patron balance is the difference between the PROCESSING and the credit'
588 subtest 'Partial payment, existing debits and AccountAutoReconcile' =>
589 sub {
591 plan tests => 10;
593 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
594 my $barcode = 'KD123456793';
595 my $replacement_amount = 100;
596 my $processfee_amount = 20;
598 my $item_type = $builder->build_object(
600 class => 'Koha::ItemTypes',
601 value => {
602 notforloan => undef,
603 rentalcharge => 0,
604 defaultreplacecost => undef,
605 processfee => 0,
606 rentalcharge_daily => 0,
610 my $item = Koha::Item->new(
612 biblionumber => $biblio->biblionumber,
613 homebranch => $library->branchcode,
614 holdingbranch => $library->branchcode,
615 barcode => $barcode,
616 replacementprice => $replacement_amount,
617 itype => $item_type->itemtype
619 )->store;
621 my $issue =
622 C4::Circulation::AddIssue( $patron->unblessed, $barcode );
624 # Simulate item marked as lost
625 $item->itemlost(1)->store;
626 C4::Circulation::LostItem( $item->itemnumber, 1 );
628 my $lost_fee_lines = Koha::Account::Lines->search(
630 borrowernumber => $patron->id,
631 itemnumber => $item->itemnumber,
632 debit_type_code => 'LOST'
635 is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
636 my $lost_fee_line = $lost_fee_lines->next;
637 is( $lost_fee_line->amount + 0,
638 $replacement_amount, 'The right LOST amount is generated' );
639 is( $lost_fee_line->amountoutstanding + 0,
640 $replacement_amount,
641 'The right LOST amountountstanding is generated' );
643 my $account = $patron->account;
644 is( $account->balance, $replacement_amount, 'Balance is L' );
646 # Partially pay fee
647 my $payment_amount = 27;
648 my $payment = $account->add_credit(
650 amount => $payment_amount,
651 type => 'PAYMENT',
652 interface => 'test',
655 $payment->apply(
656 { debits => [$lost_fee_line], offset_type => 'Payment' } );
659 $account->balance,
660 $replacement_amount - $payment_amount,
661 'Payment applied'
664 my $manual_debit_amount = 80;
665 $account->add_debit(
667 amount => $manual_debit_amount,
668 type => 'OVERDUE',
669 interface => 'test'
674 $account->balance,
675 $manual_debit_amount + $replacement_amount - $payment_amount,
676 'Manual debit applied'
679 t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
681 # Simulate item marked as found
682 $item->itemlost(0)->store;
683 is( $item->{_refunded}, 1, 'Refund triggered' );
685 my $credit_return = Koha::Account::Lines->search(
687 itemnumber => $item->itemnumber,
688 credit_type_code => 'LOST_FOUND'
690 { rows => 1 }
691 )->single;
693 ok( $credit_return, 'An account line of type LOST_FOUND is added' );
696 $account->balance,
697 $manual_debit_amount - $payment_amount,
698 'Balance is PROCESSING - payment (LOST_FOUND)'
701 my $manual_debit = Koha::Account::Lines->search(
703 borrowernumber => $patron->id,
704 debit_type_code => 'OVERDUE',
705 status => 'UNRETURNED'
707 )->next;
709 $manual_debit->amountoutstanding + 0,
710 $manual_debit_amount - $payment_amount,
711 'reconcile_balance was called'
715 subtest 'Patron deleted' => sub {
716 plan tests => 1;
718 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
719 my $barcode = 'KD123456794';
720 my $replacement_amount = 100;
721 my $processfee_amount = 20;
723 my $item_type = $builder->build_object(
725 class => 'Koha::ItemTypes',
726 value => {
727 notforloan => undef,
728 rentalcharge => 0,
729 defaultreplacecost => undef,
730 processfee => 0,
731 rentalcharge_daily => 0,
735 my $item = Koha::Item->new(
737 biblionumber => $biblio->biblionumber,
738 homebranch => $library->branchcode,
739 holdingbranch => $library->branchcode,
740 barcode => $barcode,
741 replacementprice => $replacement_amount,
742 itype => $item_type->itemtype
744 )->store;
746 my $issue =
747 C4::Circulation::AddIssue( $patron->unblessed, $barcode );
749 # Simulate item marked as lost
750 $item->itemlost(1)->store;
751 C4::Circulation::LostItem( $item->itemnumber, 1 );
753 $issue->delete();
754 $patron->delete();
756 # Simulate item marked as found
757 $item->itemlost(0)->store;
758 is( $item->{_refunded}, undef, 'No refund triggered' );
762 subtest 'Continue when userenv is not set' => sub {
763 plan tests => 1;
765 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
766 my $barcode = 'KD123456795';
767 my $replacement_amount = 100;
768 my $processfee_amount = 20;
770 my $item_type = $builder->build_object(
772 class => 'Koha::ItemTypes',
773 value => {
774 notforloan => undef,
775 rentalcharge => 0,
776 defaultreplacecost => undef,
777 processfee => 0,
778 rentalcharge_daily => 0,
782 my $item = $builder->build_sample_item(
784 biblionumber => $biblio->biblionumber,
785 homebranch => $library->branchcode,
786 holdingbranch => $library->branchcode,
787 barcode => $barcode,
788 replacementprice => $replacement_amount,
789 itype => $item_type->itemtype
793 my $issue =
794 C4::Circulation::AddIssue( $patron->unblessed, $barcode );
796 # Simulate item marked as lost
797 $item->itemlost(1)->store;
798 C4::Circulation::LostItem( $item->itemnumber, 1 );
800 # Unset the userenv
801 C4::Context->_new_userenv(undef);
803 # Simluate item marked as found
804 $item->itemlost(0)->store;
805 is( $item->{_refunded}, 1, 'No refund triggered' );
811 subtest 'get_transfer' => sub {
812 plan tests => 3;
814 my $transfer = $new_item_1->get_transfer();
815 is( $transfer, undef, 'Koha::Item->get_transfer should return undef if the item is not in transit' );
817 my $library_to = $builder->build( { source => 'Branch' } );
819 C4::Circulation::transferbook({
820 from_branch => $new_item_1->holdingbranch,
821 to_branch => $library_to->{branchcode},
822 barcode => $new_item_1->barcode,
825 $transfer = $new_item_1->get_transfer();
826 is( ref($transfer), 'Koha::Item::Transfer', 'Koha::Item->get_transfer should return a Koha::Item::Transfers object' );
828 is( $transfer->itemnumber, $new_item_1->itemnumber, 'Koha::Item->get_transfer should return a valid Koha::Item::Transfers object' );
831 subtest 'holds' => sub {
832 plan tests => 5;
834 my $biblio = $builder->build_sample_biblio();
835 my $item = $builder->build_sample_item({
836 biblionumber => $biblio->biblionumber,
838 is($item->holds->count, 0, "Nothing returned if no holds");
839 my $hold1 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'T' }});
840 my $hold2 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
841 my $hold3 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
843 is($item->holds()->count,3,"Three holds found");
844 is($item->holds({found => 'W'})->count,2,"Two waiting holds found");
845 is_deeply($item->holds({found => 'T'})->next->unblessed,$hold1,"Found transit holds matches the hold");
846 is($item->holds({found => undef})->count, 0,"Nothing returned if no matching holds");
849 subtest 'biblio' => sub {
850 plan tests => 2;
852 my $biblio = $retrieved_item_1->biblio;
853 is( ref( $biblio ), 'Koha::Biblio', 'Koha::Item->biblio should return a Koha::Biblio' );
854 is( $biblio->biblionumber, $retrieved_item_1->biblionumber, 'Koha::Item->biblio should return the correct biblio' );
857 subtest 'biblioitem' => sub {
858 plan tests => 2;
860 my $biblioitem = $retrieved_item_1->biblioitem;
861 is( ref( $biblioitem ), 'Koha::Biblioitem', 'Koha::Item->biblioitem should return a Koha::Biblioitem' );
862 is( $biblioitem->biblionumber, $retrieved_item_1->biblionumber, 'Koha::Item->biblioitem should return the correct biblioitem' );
865 # Restore userenv
866 t::lib::Mocks::mock_userenv({ branchcode => $library->{branchcode} });
867 subtest 'checkout' => sub {
868 plan tests => 5;
869 my $item = Koha::Items->find( $new_item_1->itemnumber );
870 # No checkout yet
871 my $checkout = $item->checkout;
872 is( $checkout, undef, 'Koha::Item->checkout should return undef if there is no current checkout on this item' );
874 # Add a checkout
875 my $patron = $builder->build({ source => 'Borrower' });
876 C4::Circulation::AddIssue( $patron, $item->barcode );
877 $checkout = $retrieved_item_1->checkout;
878 is( ref( $checkout ), 'Koha::Checkout', 'Koha::Item->checkout should return a Koha::Checkout' );
879 is( $checkout->itemnumber, $item->itemnumber, 'Koha::Item->checkout should return the correct checkout' );
880 is( $checkout->borrowernumber, $patron->{borrowernumber}, 'Koha::Item->checkout should return the correct checkout' );
882 # Do the return
883 C4::Circulation::AddReturn( $item->barcode );
885 # There is no more checkout on this item, making sure it will not return old checkouts
886 $checkout = $item->checkout;
887 is( $checkout, undef, 'Koha::Item->checkout should return undef if there is no *current* checkout on this item' );
890 subtest 'can_be_transferred' => sub {
891 plan tests => 5;
893 t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
894 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
896 my $biblio = $builder->build_sample_biblio();
897 my $library1 = $builder->build_object( { class => 'Koha::Libraries' } );
898 my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
899 my $item = $builder->build_sample_item({
900 biblionumber => $biblio->biblionumber,
901 homebranch => $library1->branchcode,
902 holdingbranch => $library1->branchcode,
905 is(Koha::Item::Transfer::Limits->search({
906 fromBranch => $library1->branchcode,
907 toBranch => $library2->branchcode,
908 })->count, 0, 'There are no transfer limits between libraries.');
909 ok($item->can_be_transferred({ to => $library2 }),
910 'Item can be transferred between libraries.');
912 my $limit = Koha::Item::Transfer::Limit->new({
913 fromBranch => $library1->branchcode,
914 toBranch => $library2->branchcode,
915 itemtype => $item->effective_itemtype,
916 })->store;
917 is(Koha::Item::Transfer::Limits->search({
918 fromBranch => $library1->branchcode,
919 toBranch => $library2->branchcode,
920 })->count, 1, 'Given we have added a transfer limit,');
921 is($item->can_be_transferred({ to => $library2 }), 0,
922 'Item can no longer be transferred between libraries.');
923 is($item->can_be_transferred({ to => $library2, from => $library1 }), 0,
924 'We get the same result also if we pass the from-library parameter.');
927 # Reset nb_of_items prior to testing delete
928 $nb_of_items = Koha::Items->search->count;
930 # Test delete
931 $retrieved_item_1->delete;
932 is( Koha::Items->search->count, $nb_of_items - 1, 'Delete should have deleted the item' );
934 $schema->storage->txn_rollback;