3 # Copyright PTFS Europe 2016
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>.
23 use DateTime::Duration;
25 use Koha::DateUtils qw( dt_from_string );
26 use Koha::Item::Transfer;
29 use t::lib::TestBuilder;
32 use Test::More tests => 9;
34 my $schema = Koha::Database->new->schema;
36 use_ok('Koha::StockRotationItems');
37 use_ok('Koha::StockRotationItem');
39 my $builder = t::lib::TestBuilder->new;
41 subtest 'Basic object tests' => sub {
45 $schema->storage->txn_begin;
47 my $itm = $builder->build_sample_item;
48 my $stage = $builder->build({ source => 'Stockrotationstage' });
50 my $item = $builder->build({
51 source => 'Stockrotationitem',
53 itemnumber_id => $itm->itemnumber,
54 stage_id => $stage->{stage_id},
58 my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
61 'Koha::StockRotationItem',
62 "Correctly create and load a stock rotation item."
65 # Relationship to rota
66 isa_ok( $sritem->item, 'Koha::Item', "Fetched related item." );
67 is( $sritem->item->itemnumber, $itm->itemnumber, "Related rota OK." );
69 # Relationship to stage
70 isa_ok( $sritem->stage, 'Koha::StockRotationStage', "Fetched related stage." );
71 is( $sritem->stage->stage_id, $stage->{stage_id}, "Related stage OK." );
74 $schema->storage->txn_rollback;
77 subtest 'Tests for needs_repatriating' => sub {
81 $schema->storage->txn_begin;
83 # Setup a pristine stockrotation context.
84 my $sritem = $builder->build(
86 source => 'Stockrotationitem',
88 { itemnumber_id => $builder->build_sample_item->itemnumber }
91 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
92 $dbitem->item->homebranch($dbitem->stage->branchcode_id);
93 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
94 $dbitem->stage->position(1);
96 my $dbrota = $dbitem->stage->rota;
97 my $newstage = $builder->build({
98 source => 'Stockrotationstage',
100 rota_id => $dbrota->rota_id,
105 # - homebranch == holdingbranch [0]
107 $dbitem->needs_repatriating, 0,
108 "Homebranch == Holdingbranch."
111 my $branch = $builder->build({ source => 'Branch' });
112 $dbitem->item->holdingbranch($branch->{branchcode});
114 # - homebranch != holdingbranch [1]
116 $dbitem->needs_repatriating, 1,
117 "Homebranch != holdingbranch."
120 # Set to incorrect homebranch.
121 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
122 $dbitem->item->homebranch($branch->{branchcode});
123 # - homebranch != stockrotationstage.branch & not in transit [1]
125 $dbitem->needs_repatriating, 1,
126 "Homebranch != StockRotationStage.Branchcode_id & not in transit."
129 # Set to in transit (by implication).
130 $dbitem->stage($newstage->{stage_id});
131 # - homebranch != stockrotaitonstage.branch & in transit [0]
133 $dbitem->needs_repatriating, 1,
134 "homebranch != stockrotaitonstage.branch & in transit."
137 $schema->storage->txn_rollback;
140 subtest "Tests for repatriate." => sub {
142 $schema->storage->txn_begin;
144 my $sritem_1 = $builder->build_object(
146 class => 'Koha::StockRotationItems',
148 itemnumber_id => $builder->build_sample_item->itemnumber
152 my $item_id = $sritem_1->item->itemnumber;
153 my $srstage_1 = $sritem_1->stage;
154 $sritem_1->discard_changes;
155 $sritem_1->stage->position(1);
156 $sritem_1->stage->duration(50);
157 my $branch = $builder->build({ source => 'Branch' });
158 $sritem_1->item->holdingbranch($branch->{branchcode});
160 # Test a straight up repatriate
161 ok($sritem_1->repatriate, "Repatriation done.");
162 my $intransfer = $sritem_1->item->get_transfer;
163 is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
164 is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");
167 $intransfer->datearrived(dt_from_string())->store;
168 $sritem_1->item->holdingbranch($branch->{branchcode});
170 # Setup a conflicting manual transfer
171 my $item = Koha::Items->find($item_id);
172 $item->request_transfer({ to => $srstage_1->branchcode, reason => "Manual" });
173 $intransfer = $item->get_transfer;
174 is (ref($intransfer), 'Koha::Item::Transfer', "Conflicting transfer added");
175 is ($intransfer->reason, 'Manual', "Conflicting transfer reason is 'Manual'");
177 # Stockrotation should handle transfer clashes
178 is($sritem_1->repatriate, 0, "Repatriation skipped if transfer in progress.");
181 $intransfer->datearrived(dt_from_string())->store;
182 $sritem_1->item->holdingbranch($branch->{branchcode});
184 # Confirm that stockrotation ignores transfer limits
185 t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
186 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
187 my $limit = Koha::Item::Transfer::Limit->new(
189 fromBranch => $branch->{branchcode},
190 toBranch => $srstage_1->branchcode_id,
191 itemtype => $sritem_1->item->effective_itemtype,
195 # Stockrotation should overrule transfer limits
196 ok($sritem_1->repatriate, "Repatriation done regardless of transfer limits.");
197 $intransfer = $sritem_1->item->get_transfer;
198 is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
199 is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");
201 $schema->storage->txn_rollback;
204 subtest "Tests for needs_advancing." => sub {
206 $schema->storage->txn_begin;
208 # Test behaviour of item freshly added to rota.
209 my $sritem = $builder->build(
211 source => 'Stockrotationitem',
214 itemnumber_id => $builder->build_sample_item->itemnumber
218 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
219 is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");
221 # Setup a pristine stockrotation context.
222 $sritem = $builder->build(
224 source => 'Stockrotationitem',
227 itemnumber_id => $builder->build_sample_item->itemnumber
231 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
232 $dbitem->item->homebranch($dbitem->stage->branchcode_id);
233 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
234 $dbitem->stage->position(1);
235 $dbitem->stage->duration(50);
237 my $dbtransfer = Koha::Item::Transfer->new({
238 'itemnumber' => $dbitem->itemnumber_id,
239 'frombranch' => $dbitem->stage->branchcode_id,
240 'tobranch' => $dbitem->stage->branchcode_id,
241 'datesent' => dt_from_string(),
242 'datearrived' => undef,
243 'reason' => "StockrotationAdvance",
246 # Test item will not be advanced if in transit.
247 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer.");
248 # Test item will not be advanced if in transit even if fresh.
249 $dbitem->fresh(1)->store;
250 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer (fresh).");
251 $dbitem->fresh(0)->store;
253 # Test item will not be advanced if it has not spent enough time.
254 $dbtransfer->datearrived(dt_from_string())->store;
255 is($dbitem->needs_advancing, 0, "Not ready to advance: Not spent enough time.");
256 # Test item will be advanced if it has not spent enough time, but is fresh.
257 $dbitem->fresh(1)->store;
258 is($dbitem->needs_advancing, 1, "Advance: Not spent enough time, but fresh.");
259 $dbitem->fresh(0)->store;
261 # Test item will be advanced if it has spent enough time.
262 $dbtransfer->datesent( # Item was sent 100 days ago...
263 dt_from_string() - DateTime::Duration->new( days => 100 )
265 $dbtransfer->datearrived( # And arrived 75 days ago.
266 dt_from_string() - DateTime::Duration->new( days => 75 )
268 is($dbitem->needs_advancing, 1, "Ready to be advanced.");
270 # Bug 30518: Confirm that DST boundaries do not explode.
271 # mock_config does not work here, because of tz vs timezone subroutines
272 my $context = Test::MockModule->new('C4::Context');
273 $context->mock( 'tz', sub {
276 my $bad_date = dt_from_string("2020-09-29T01:15:30", 'iso');
277 $dbtransfer->datesent($bad_date)->store;
278 $dbtransfer->datearrived($bad_date)->store;
279 $dbitem->stage->duration(180)->store;
280 is( $dbitem->needs_advancing, 1, "DST boundary doesn't cause failure." );
281 $context->unmock('tz');
283 # Test that missing historical branch transfers do not crash
285 warning_is {$dbitem->needs_advancing} "We have no historical branch transfer for item " . $dbitem->item->itemnumber . "; This should not have happened!", "Missing transfer is warned.";
287 $schema->storage->txn_rollback;
290 subtest "Tests for advance." => sub {
292 $schema->storage->txn_begin;
294 my $sritem_1 = $builder->build_object(
296 class => 'Koha::StockRotationItems',
299 itemnumber_id => $builder->build_sample_item->itemnumber
303 $sritem_1->discard_changes;
304 $sritem_1->item->holdingbranch($sritem_1->stage->branchcode_id);
305 my $item_id = $sritem_1->item->itemnumber;
306 my $srstage_1 = $sritem_1->stage;
307 $srstage_1->position(1)->duration(50)->store; # Configure stage.
309 $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
310 $sritem_1->item->homebranch($srstage_1->branchcode_id)->store;
312 is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage sanity check.");
314 # Test if an item is fresh, always move to first stage.
315 is($sritem_1->fresh, 1, "Fresh is correct.");
317 is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage is first stage after fresh advance.");
318 is($sritem_1->fresh, 0, "Fresh reset after advance.");
320 # Test cases of single stage
321 $srstage_1->rota->cyclical(1)->store; # Set Rota to cyclical.
322 ok($sritem_1->advance, "Single stage cyclical advance done.");
324 $sritem_1->discard_changes;
325 is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Single stage cyclical stage OK.");
327 # Test with indemand advance
328 $sritem_1->indemand(1)->store;
329 ok($sritem_1->advance, "Indemand item advance done.");
331 $sritem_1->discard_changes;
332 is($sritem_1->indemand, 0, "Indemand OK.");
333 is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Indemand item advance stage OK.");
336 my $srstage_2 = $builder->build_object({
337 class => 'Koha::StockRotationStages',
338 value => { duration => 50 }
340 $srstage_2->discard_changes;
341 $srstage_2->move_to_group($sritem_1->stage->rota_id);
342 $srstage_2->move_last;
344 # Test a straight up advance
345 ok($sritem_1->advance, "Advancement done.");
347 $sritem_1->discard_changes;
349 is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated.");
351 $sritem_1->item->homebranch,
352 $srstage_2->branchcode_id,
353 "Item homebranch updated"
355 my $transfer_request = $sritem_1->item->get_transfer;
356 is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
357 is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target Correct.");
358 is($transfer_request->datesent, undef, "Transfer requested, but not sent.");
360 # Arrive at new branch
361 $transfer_request->datearrived(dt_from_string())->store;
362 $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;
364 # Test a cyclical advance
365 ok($sritem_1->advance, "Cyclical advancement done.");
367 $sritem_1->discard_changes;
369 is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage updated.");
371 $sritem_1->item->homebranch,
372 $srstage_1->branchcode_id,
373 "Item homebranch updated"
375 $transfer_request = $sritem_1->item->get_transfer;
376 is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
377 is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
379 # Arrive at new branch
380 $transfer_request->datearrived(dt_from_string())->store;
381 $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
383 # Confirm that stockrotation ignores transfer limits
384 t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
385 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
386 my $limit = Koha::Item::Transfer::Limit->new(
388 fromBranch => $srstage_1->branchcode_id,
389 toBranch => $srstage_2->branchcode_id,
390 itemtype => $sritem_1->item->effective_itemtype,
394 ok($sritem_1->advance, "Advancement overrules transfer limits.");
396 $sritem_1->discard_changes;
398 is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated ignoring transfer limits.");
400 $sritem_1->item->homebranch,
401 $srstage_2->branchcode_id,
402 "Item homebranch updated ignoring transfer limits"
404 $transfer_request = $sritem_1->item->get_transfer;
405 is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct ignoring transfer limits.");
406 is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct ignoring transfer limits.");
408 # Arrive at new branch
409 $transfer_request->datearrived(dt_from_string())->store;
410 $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;
412 # Setup a conflicting manual transfer
413 my $item = Koha::Items->find($item_id);
414 $item->request_transfer({ to => $srstage_1->branchcode, reason => "Manual" });
415 $transfer_request = $item->get_transfer;
416 is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
417 is ($transfer_request->reason, 'Manual', "Conflicting transfer reason is 'Manual'");
419 # Advance item whilst conflicting manual transfer exists
420 ok($sritem_1->advance, "Advancement done.");
422 $sritem_1->discard_changes;
424 ## Refetch conflicted transfer
425 $transfer_request->discard_changes;
427 # Conflicted transfer should have been cancelled
428 isnt($transfer_request->datecancelled, undef, "Conflicting manual transfer was cancelled");
430 # StockRotationAdvance transfer added
431 $transfer_request = $sritem_1->item->get_transfer;
432 is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer added");
433 is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
434 is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
436 # Arrive at new branch
437 $transfer_request->datearrived(dt_from_string())->store;
438 $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
440 # Setup a conflicting reserve transfer
441 $item->request_transfer({ to => $srstage_2->branchcode, reason => "Reserve" });
442 $transfer_request = $item->get_transfer;
443 is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
444 is ($transfer_request->reason, 'Reserve', "Conflicting transfer reason is 'Reserve'");
446 # Advance item whilst conflicting reserve transfer exists
447 ok($sritem_1->advance, "Advancement done.");
449 $sritem_1->discard_changes;
451 ## Refetch conflicted transfer
452 $transfer_request->discard_changes;
454 # Conflicted transfer should not been cancelled
455 is($transfer_request->datecancelled, undef, "Conflicting reserve transfer was not cancelled");
457 # StockRotationAdvance transfer added
458 my $transfer_requests = Koha::Item::Transfers->search(
460 itemnumber => $sritem_1->item->itemnumber,
461 datearrived => undef,
462 datecancelled => undef
465 is($transfer_requests->count, '2', "StockrotationAdvance transfer queued");
467 # Arrive at new branch
468 $transfer_request->datearrived(dt_from_string())->store;
469 $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;
471 # StockRotationAdvance transfer added
472 $transfer_request = $sritem_1->item->get_transfer;
473 is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer remains after reserve is met");
474 is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
475 is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct.");
477 # Arrive at new branch
478 $transfer_request->datearrived(dt_from_string())->store;
479 $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;
481 # Checked out item, advanced to next stage, checkedout from next stage
482 # transfer should be generated, but not initiated
483 my $issue = $builder->build_object({
484 class => 'Koha::Checkouts',
486 branchcode => $srstage_1->branchcode_id,
487 itemnumber => $sritem_1->item->itemnumber,
491 $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
492 ok($sritem_1->advance, "Advancement done.");
493 $transfer_request = $sritem_1->item->get_transfer;
494 is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
495 is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
496 is($transfer_request->datesent, undef, "Transfer waiting to initiate until return.");
498 $issue->delete; #remove issue
499 $sritem_1->advance; #advance back to second stage
501 $transfer_request->datearrived(dt_from_string())->store;
502 $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;
505 $srstage_1->rota->cyclical(0)->store; # Set Rota to non-cyclical.
507 my $srstage_3 = $builder->build_object({
508 class => 'Koha::StockRotationStages',
509 value => { duration => 50 }
511 $srstage_3->discard_changes;
512 $srstage_3->move_to_group($sritem_1->stage->rota_id);
513 $srstage_3->move_last;
515 # Advance again, to end of rota.
516 ok($sritem_1->advance, "Non-cyclical advance to last stage.");
518 # Arrive at new branch
519 $transfer_request->datearrived(dt_from_string())->store;
520 $sritem_1->item->holdingbranch($srstage_3->branchcode_id)->store;
522 # Advance again, Remove from rota.
523 ok($sritem_1->advance, "Non-cyclical advance.");
525 $sritem_1 = Koha::StockRotationItems->find({ itemnumber_id => $item_id });
526 is($sritem_1, undef, "StockRotationItem has been removed.");
527 $item = Koha::Items->find($item_id);
528 is($item->homebranch, $srstage_3->branchcode_id, "Item homebranch remains");
530 $schema->storage->txn_rollback;
533 subtest "Tests for investigate (singular)." => sub {
535 $schema->storage->txn_begin;
537 # Test brand new item's investigation ['initiation']
538 my $sritem = $builder->build(
540 source => 'Stockrotationitem',
543 itemnumber_id => $builder->build_sample_item->itemnumber
547 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
548 is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");
550 # Test brand new item at stagebranch ['initiation']
551 $sritem = $builder->build(
553 source => 'Stockrotationitem',
556 itemnumber_id => $builder->build_sample_item->itemnumber
560 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
561 $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
562 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
563 is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");
565 # Test item not at stagebranch with branchtransfer history ['repatriation']
566 $sritem = $builder->build(
568 source => 'Stockrotationitem',
571 itemnumber_id => $builder->build_sample_item->itemnumber
575 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
576 my $dbtransfer = Koha::Item::Transfer->new({
577 'itemnumber' => $dbitem->itemnumber_id,
578 'frombranch' => $dbitem->item->homebranch,
579 'tobranch' => $dbitem->item->homebranch,
580 'datesent' => dt_from_string(),
581 'datearrived' => dt_from_string(),
582 'reason' => "StockrotationAdvance",
584 is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");
586 # Test item at stagebranch with branchtransfer history ['not-ready']
587 $sritem = $builder->build(
589 source => 'Stockrotationitem',
592 itemnumber_id => $builder->build_sample_item->itemnumber
596 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
597 $dbtransfer = Koha::Item::Transfer->new({
598 'itemnumber' => $dbitem->itemnumber_id,
599 'frombranch' => $dbitem->item->homebranch,
600 'tobranch' => $dbitem->stage->branchcode_id,
601 'datesent' => dt_from_string(),
602 'datearrived' => dt_from_string(),
603 'reason' => "StockrotationAdvance",
605 $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
606 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
607 is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");
609 # Test item due for advancement ['advancement']
610 $sritem = $builder->build(
612 source => 'Stockrotationitem',
615 itemnumber_id => $builder->build_sample_item->itemnumber
619 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
620 $dbitem->indemand(0)->store;
621 $dbitem->stage->duration(50)->store;
622 my $sent_duration = DateTime::Duration->new( days => 55);
623 my $arrived_duration = DateTime::Duration->new( days => 52);
624 $dbtransfer = Koha::Item::Transfer->new({
625 'itemnumber' => $dbitem->itemnumber_id,
626 'frombranch' => $dbitem->item->homebranch,
627 'tobranch' => $dbitem->stage->branchcode_id,
628 'datesent' => dt_from_string() - $sent_duration,
629 'datearrived' => dt_from_string() - $arrived_duration,
630 'reason' => "StockrotationAdvance",
632 $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
633 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
634 is($dbitem->investigate->{reason}, 'advancement',
635 "Item ready for advancement.");
637 # Test item due for advancement but in-demand ['in-demand']
638 $sritem = $builder->build(
640 source => 'Stockrotationitem',
643 itemnumber_id => $builder->build_sample_item->itemnumber
647 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
648 $dbitem->indemand(1)->store;
649 $dbitem->stage->duration(50)->store;
650 $sent_duration = DateTime::Duration->new( days => 55);
651 $arrived_duration = DateTime::Duration->new( days => 52);
652 $dbtransfer = Koha::Item::Transfer->new({
653 'itemnumber' => $dbitem->itemnumber_id,
654 'frombranch' => $dbitem->item->homebranch,
655 'tobranch' => $dbitem->stage->branchcode_id,
656 'datesent' => dt_from_string() - $sent_duration,
657 'datearrived' => dt_from_string() - $arrived_duration,
658 'reason' => "StockrotationAdvance",
660 $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
661 $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
662 is($dbitem->investigate->{reason}, 'in-demand',
663 "Item advances, but in-demand.");
665 # Test item ready for advancement, but at wrong library ['repatriation']
666 $sritem = $builder->build(
668 source => 'Stockrotationitem',
671 itemnumber_id => $builder->build_sample_item->itemnumber
675 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
676 $dbitem->indemand(0)->store;
677 $dbitem->stage->duration(50)->store;
678 $sent_duration = DateTime::Duration->new( days => 55);
679 $arrived_duration = DateTime::Duration->new( days => 52);
680 $dbtransfer = Koha::Item::Transfer->new({
681 'itemnumber' => $dbitem->itemnumber_id,
682 'frombranch' => $dbitem->item->homebranch,
683 'tobranch' => $dbitem->stage->branchcode_id,
684 'datesent' => dt_from_string() - $sent_duration,
685 'datearrived' => dt_from_string() - $arrived_duration,
686 'reason' => "StockrotationAdvance",
688 is($dbitem->investigate->{reason}, 'repatriation',
689 "Item advances, but not at stage branch.");
691 $schema->storage->txn_rollback;
694 subtest "Tests for toggle_indemand" => sub {
696 $schema->storage->txn_begin;
698 my $sritem = $builder->build({
699 source => 'Stockrotationitem',
700 value => { 'fresh' => 0, 'indemand' => 0 }
702 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
703 my $firstbranch = $dbitem->stage->branchcode_id;
704 $dbitem->item->holdingbranch($firstbranch)->store;
705 my $dbstage = $dbitem->stage;
706 $dbstage->position(1)->duration(50)->store; # Configure stage.
708 $dbitem->item->holdingbranch($firstbranch)->store;
709 $dbitem->item->homebranch($firstbranch)->store;
711 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");
713 # Test if an item is not in transfer, toggle always acts.
714 is($dbitem->indemand, 0, "Item not in transfer starts with indemand disabled.");
715 $dbitem->toggle_indemand;
716 is($dbitem->indemand, 1, "Item not in transfer toggled correctly first time.");
717 $dbitem->toggle_indemand;
718 is($dbitem->indemand, 0, "Item not in transfer toggled correctly second time.");
721 my $srstage = $builder->build({
722 source => 'Stockrotationstage',
723 value => { duration => 50 }
725 my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
726 $dbstage2->move_to_group($dbitem->stage->rota_id);
727 $dbstage2->position(2)->store;
728 my $secondbranch = $dbstage2->branchcode_id;
730 # Test an item in transfer, toggle cancels transfer and resets indemand.
731 ok($dbitem->advance, "Advancement done.");
732 $dbitem->get_from_storage;
733 my $transfer = $dbitem->item->get_transfer;
734 is(ref($transfer), 'Koha::Item::Transfer', 'Item set to in transfer as expected');
735 is($transfer->frombranch, $firstbranch, 'Transfer from set correctly');
736 is($transfer->tobranch, $secondbranch, 'Transfer to set correctly');
737 is($transfer->datearrived, undef, 'Transfer datearrived not set');
738 $dbitem->toggle_indemand;
739 my $updated_transfer = $transfer->get_from_storage;
740 is($updated_transfer->frombranch, $firstbranch, 'Transfer from retained correctly');
741 is($updated_transfer->tobranch, $firstbranch, 'Transfer to updated correctly');
742 isnt($updated_transfer->datearrived, undef, 'Transfer datearrived set as expected');
743 is($dbitem->indemand, 0, "Item retains indemand as expected.");
744 is($dbitem->stage_id, $dbstage->id, 'Item stage reset as expected.');
745 is($dbitem->item->homebranch, $firstbranch, 'Item homebranch reset as expected.');
747 $schema->storage->txn_rollback;