Bug 28931: Use EXPORT_OK from Koha::DateUtils
[koha.git] / t / db_dependent / StockRotationItems.t
1 #!/usr/bin/perl
2
3 # Copyright PTFS Europe 2016
4 #
5 # This file is part of Koha.
6 #
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.
11 #
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.
16 #
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>.
19
20 use Modern::Perl;
21
22 use DateTime;
23 use DateTime::Duration;
24 use Koha::Database;
25 use Koha::DateUtils qw( dt_from_string );
26 use Koha::Item::Transfer;
27
28 use Test::Warn;
29 use t::lib::TestBuilder;
30 use t::lib::Mocks;
31
32 use Test::More tests => 9;
33
34 my $schema = Koha::Database->new->schema;
35
36 use_ok('Koha::StockRotationItems');
37 use_ok('Koha::StockRotationItem');
38
39 my $builder = t::lib::TestBuilder->new;
40
41 subtest 'Basic object tests' => sub {
42
43     plan tests => 5;
44
45     $schema->storage->txn_begin;
46
47     my $itm = $builder->build_sample_item;
48     my $stage = $builder->build({ source => 'Stockrotationstage' });
49
50     my $item = $builder->build({
51         source => 'Stockrotationitem',
52         value  => {
53             itemnumber_id => $itm->itemnumber,
54             stage_id      => $stage->{stage_id},
55         },
56     });
57
58     my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
59     isa_ok(
60         $sritem,
61         'Koha::StockRotationItem',
62         "Correctly create and load a stock rotation item."
63     );
64
65     # Relationship to rota
66     isa_ok( $sritem->itemnumber, 'Koha::Item', "Fetched related item." );
67     is( $sritem->itemnumber->itemnumber, $itm->itemnumber, "Related rota OK." );
68
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." );
72
73
74     $schema->storage->txn_rollback;
75 };
76
77 subtest 'Tests for needs_repatriating' => sub {
78
79     plan tests => 4;
80
81     $schema->storage->txn_begin;
82
83     # Setup a pristine stockrotation context.
84     my $sritem = $builder->build(
85         {
86             source => 'Stockrotationitem',
87             value =>
88               { itemnumber_id => $builder->build_sample_item->itemnumber }
89         }
90     );
91     my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
92     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
93     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
94     $dbitem->stage->position(1);
95
96     my $dbrota = $dbitem->stage->rota;
97     my $newstage = $builder->build({
98         source => 'Stockrotationstage',
99         value => {
100             rota_id => $dbrota->rota_id,
101             position => 2,
102         }
103     });
104
105     # - homebranch == holdingbranch [0]
106     is(
107         $dbitem->needs_repatriating, 0,
108         "Homebranch == Holdingbranch."
109     );
110
111     my $branch = $builder->build({ source => 'Branch' });
112     $dbitem->itemnumber->holdingbranch($branch->{branchcode});
113
114     # - homebranch != holdingbranch [1]
115     is(
116         $dbitem->needs_repatriating, 1,
117         "Homebranch != holdingbranch."
118     );
119
120     # Set to incorrect homebranch.
121     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
122     $dbitem->itemnumber->homebranch($branch->{branchcode});
123     # - homebranch != stockrotationstage.branch & not in transit [1]
124     is(
125         $dbitem->needs_repatriating, 1,
126         "Homebranch != StockRotationStage.Branchcode_id & not in transit."
127     );
128
129     # Set to in transit (by implication).
130     $dbitem->stage($newstage->{stage_id});
131     # - homebranch != stockrotaitonstage.branch & in transit [0]
132     is(
133         $dbitem->needs_repatriating, 1,
134         "homebranch != stockrotaitonstage.branch & in transit."
135     );
136
137     $schema->storage->txn_rollback;
138 };
139
140 subtest "Tests for repatriate." => sub {
141     plan tests => 9;
142     $schema->storage->txn_begin;
143
144     my $sritem_1 = $builder->build_object(
145         {
146             class => 'Koha::StockRotationItems',
147             value  => {
148                 itemnumber_id => $builder->build_sample_item->itemnumber
149             }
150         }
151     );
152     my $item_id = $sritem_1->itemnumber->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->itemnumber->holdingbranch($branch->{branchcode});
159
160     # Test a straight up repatriate
161     ok($sritem_1->repatriate, "Repatriation done.");
162     my $intransfer = $sritem_1->itemnumber->get_transfer;
163     is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
164     is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");
165
166     # Reset
167     $intransfer->datearrived(dt_from_string())->store;
168     $sritem_1->itemnumber->holdingbranch($branch->{branchcode});
169
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'");
176
177     # Stockrotation should handle transfer clashes
178     is($sritem_1->repatriate, 0, "Repatriation skipped if transfer in progress.");
179
180     # Reset
181     $intransfer->datearrived(dt_from_string())->store;
182     $sritem_1->itemnumber->holdingbranch($branch->{branchcode});
183
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(
188         {
189             fromBranch => $branch->{branchcode},
190             toBranch   => $srstage_1->branchcode_id,
191             itemtype   => $sritem_1->itemnumber->effective_itemtype,
192         }
193     )->store;
194
195     # Stockrotation should overrule transfer limits
196     ok($sritem_1->repatriate, "Repatriation done regardless of transfer limits.");
197     $intransfer = $sritem_1->itemnumber->get_transfer;
198     is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
199     is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");
200
201     $schema->storage->txn_rollback;
202 };
203
204 subtest "Tests for needs_advancing." => sub {
205     plan tests => 7;
206     $schema->storage->txn_begin;
207
208     # Test behaviour of item freshly added to rota.
209     my $sritem = $builder->build(
210         {
211             source => 'Stockrotationitem',
212             value  => {
213                 'fresh'       => 1,
214                 itemnumber_id => $builder->build_sample_item->itemnumber
215             },
216         }
217     );
218     my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
219     is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");
220
221     # Setup a pristine stockrotation context.
222     $sritem = $builder->build(
223         {
224             source => 'Stockrotationitem',
225             value  => {
226                 'fresh'       => 0,
227                 itemnumber_id => $builder->build_sample_item->itemnumber
228             }
229         }
230     );
231     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
232     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
233     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
234     $dbitem->stage->position(1);
235     $dbitem->stage->duration(50);
236
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",
244     })->store;
245
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;
252
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;
260
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 )
264     )->store;
265     $dbtransfer->datearrived(   # And arrived 75 days ago.
266         dt_from_string() - DateTime::Duration->new( days => 75 )
267     )->store;
268     is($dbitem->needs_advancing, 1, "Ready to be advanced.");
269     $dbtransfer->delete;
270     warning_is {$dbitem->needs_advancing} "We have no historical branch transfer for itemnumber " . $dbitem->itemnumber->itemnumber . "; This should not have happened!", "Missing transfer is warned.";
271
272     $schema->storage->txn_rollback;
273 };
274
275 subtest "Tests for advance." => sub {
276     plan tests => 44;
277     $schema->storage->txn_begin;
278
279     my $sritem_1 = $builder->build_object(
280         {
281             class => 'Koha::StockRotationItems',
282             value  => {
283                 'fresh'       => 1,
284                 itemnumber_id => $builder->build_sample_item->itemnumber
285             }
286         }
287     );
288     $sritem_1->discard_changes;
289     $sritem_1->itemnumber->holdingbranch($sritem_1->stage->branchcode_id);
290     my $item_id = $sritem_1->itemnumber->itemnumber;
291     my $srstage_1 = $sritem_1->stage;
292     $srstage_1->position(1)->duration(50)->store; # Configure stage.
293     # Configure item
294     $sritem_1->itemnumber->holdingbranch($srstage_1->branchcode_id)->store;
295     $sritem_1->itemnumber->homebranch($srstage_1->branchcode_id)->store;
296     # Sanity check
297     is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage sanity check.");
298
299     # Test if an item is fresh, always move to first stage.
300     is($sritem_1->fresh, 1, "Fresh is correct.");
301     $sritem_1->advance;
302     is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage is first stage after fresh advance.");
303     is($sritem_1->fresh, 0, "Fresh reset after advance.");
304
305     # Test cases of single stage
306     $srstage_1->rota->cyclical(1)->store;         # Set Rota to cyclical.
307     ok($sritem_1->advance, "Single stage cyclical advance done.");
308     ## Refetch sritem_1
309     $sritem_1->discard_changes;
310     is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Single stage cyclical stage OK.");
311
312     # Test with indemand advance
313     $sritem_1->indemand(1)->store;
314     ok($sritem_1->advance, "Indemand item advance done.");
315     ## Refetch sritem_1
316     $sritem_1->discard_changes;
317     is($sritem_1->indemand, 0, "Indemand OK.");
318     is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Indemand item advance stage OK.");
319
320     # Multi stages
321     my $srstage_2 = $builder->build_object({
322         class => 'Koha::StockRotationStages',
323         value => { duration => 50 }
324     });
325     $srstage_2->discard_changes;
326     $srstage_2->move_to_group($sritem_1->stage->rota_id);
327     $srstage_2->move_last;
328
329     # Test a straight up advance
330     ok($sritem_1->advance, "Advancement done.");
331     ## Refetch sritem_1
332     $sritem_1->discard_changes;
333     ## Test results
334     is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated.");
335     is(
336         $sritem_1->itemnumber->homebranch,
337         $srstage_2->branchcode_id,
338         "Item homebranch updated"
339     );
340     my $transfer_request = $sritem_1->itemnumber->get_transfer;
341     is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
342     is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target Correct.");
343     is($transfer_request->datesent, undef, "Transfer requested, but not sent.");
344
345     # Arrive at new branch
346     $transfer_request->datearrived(dt_from_string())->store;
347     $sritem_1->itemnumber->holdingbranch($srstage_2->branchcode_id)->store;
348
349     # Test a cyclical advance
350     ok($sritem_1->advance, "Cyclical advancement done.");
351     ## Refetch sritem_1
352     $sritem_1->discard_changes;
353     ## Test results
354     is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage updated.");
355     is(
356         $sritem_1->itemnumber->homebranch,
357         $srstage_1->branchcode_id,
358         "Item homebranch updated"
359     );
360     $transfer_request = $sritem_1->itemnumber->get_transfer;
361     is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
362     is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
363
364     # Arrive at new branch
365     $transfer_request->datearrived(dt_from_string())->store;
366     $sritem_1->itemnumber->holdingbranch($srstage_1->branchcode_id)->store;
367
368     # Confirm that stockrotation ignores transfer limits
369     t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
370     t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
371     my $limit = Koha::Item::Transfer::Limit->new(
372         {
373             fromBranch => $srstage_1->branchcode_id,
374             toBranch   => $srstage_2->branchcode_id,
375             itemtype   => $sritem_1->itemnumber->effective_itemtype,
376         }
377     )->store;
378
379     ok($sritem_1->advance, "Advancement overrules transfer limits.");
380     ## Refetch sritem_1
381     $sritem_1->discard_changes;
382     ## Test results
383     is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated ignoring transfer limits.");
384     is(
385         $sritem_1->itemnumber->homebranch,
386         $srstage_2->branchcode_id,
387         "Item homebranch updated ignoring transfer limits"
388     );
389     $transfer_request = $sritem_1->itemnumber->get_transfer;
390     is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct ignoring transfer limits.");
391     is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct ignoring transfer limits.");
392
393     # Arrive at new branch
394     $transfer_request->datearrived(dt_from_string())->store;
395     $sritem_1->itemnumber->holdingbranch($srstage_2->branchcode_id)->store;
396
397     # Setup a conflicting manual transfer
398     my $item = Koha::Items->find($item_id);
399     $item->request_transfer({ to => $srstage_1->branchcode, reason => "Manual" });
400     $transfer_request = $item->get_transfer;
401     is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
402     is ($transfer_request->reason, 'Manual', "Conflicting transfer reason is 'Manual'");
403
404     # Advance item whilst conflicting manual transfer exists
405     ok($sritem_1->advance, "Advancement done.");
406     ## Refetch sritem_1
407     $sritem_1->discard_changes;
408
409     ## Refetch conflicted transfer
410     $transfer_request->discard_changes;
411
412     # Conflicted transfer should have been cancelled
413     isnt($transfer_request->datecancelled, undef, "Conflicting manual transfer was cancelled");
414
415     # StockRotationAdvance transfer added
416     $transfer_request = $sritem_1->itemnumber->get_transfer;
417     is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer added");
418     is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
419     is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
420
421     # Arrive at new branch
422     $transfer_request->datearrived(dt_from_string())->store;
423     $sritem_1->itemnumber->holdingbranch($srstage_1->branchcode_id)->store;
424
425     # Setup a conflicting reserve transfer
426     $item->request_transfer({ to => $srstage_2->branchcode, reason => "Reserve" });
427     $transfer_request = $item->get_transfer;
428     is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
429     is ($transfer_request->reason, 'Reserve', "Conflicting transfer reason is 'Reserve'");
430
431     # Advance item whilst conflicting reserve transfer exists
432     ok($sritem_1->advance, "Advancement done.");
433     ## Refetch sritem_1
434     $sritem_1->discard_changes;
435
436     ## Refetch conflicted transfer
437     $transfer_request->discard_changes;
438
439     # Conflicted transfer should not been cancelled
440     is($transfer_request->datecancelled, undef, "Conflicting reserve transfer was not cancelled");
441
442     # StockRotationAdvance transfer added
443     my $transfer_requests = Koha::Item::Transfers->search(
444         {
445             itemnumber    => $sritem_1->itemnumber->itemnumber,
446             datearrived   => undef,
447             datecancelled => undef
448         }
449     );
450     is($transfer_requests->count, '2', "StockrotationAdvance transfer queued");
451
452     # Arrive at new branch
453     $transfer_request->datearrived(dt_from_string())->store;
454     $sritem_1->itemnumber->holdingbranch($srstage_2->branchcode_id)->store;
455
456     # StockRotationAdvance transfer added
457     $transfer_request = $sritem_1->itemnumber->get_transfer;
458     is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer remains after reserve is met");
459     is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
460     is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct.");
461
462     # Arrive at new branch
463     $transfer_request->datearrived(dt_from_string())->store;
464     $sritem_1->itemnumber->holdingbranch($srstage_2->branchcode_id)->store;
465
466     $srstage_1->rota->cyclical(0)->store;         # Set Rota to non-cyclical.
467
468     my $srstage_3 = $builder->build_object({
469         class => 'Koha::StockRotationStages',
470         value => { duration => 50 }
471     });
472     $srstage_3->discard_changes;
473     $srstage_3->move_to_group($sritem_1->stage->rota_id);
474     $srstage_3->move_last;
475
476     # Advance again, to end of rota.
477     ok($sritem_1->advance, "Non-cyclical advance to last stage.");
478
479     # Arrive at new branch
480     $transfer_request->datearrived(dt_from_string())->store;
481     $sritem_1->itemnumber->holdingbranch($srstage_3->branchcode_id)->store;
482
483     # Advance again, Remove from rota.
484     ok($sritem_1->advance, "Non-cyclical advance.");
485     ## Refetch sritem_1
486     $sritem_1 = Koha::StockRotationItems->find({ itemnumber_id => $item_id });
487     is($sritem_1, undef, "StockRotationItem has been removed.");
488     $item = Koha::Items->find($item_id);
489     is($item->homebranch, $srstage_3->branchcode_id, "Item homebranch remains");
490
491     $schema->storage->txn_rollback;
492 };
493
494 subtest "Tests for investigate (singular)." => sub {
495     plan tests => 7;
496     $schema->storage->txn_begin;
497
498     # Test brand new item's investigation ['initiation']
499     my $sritem = $builder->build(
500         {
501             source => 'Stockrotationitem',
502             value  => {
503                 fresh         => 1,
504                 itemnumber_id => $builder->build_sample_item->itemnumber
505             }
506         }
507     );
508     my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
509     is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");
510
511     # Test brand new item at stagebranch ['initiation']
512     $sritem = $builder->build(
513         {
514             source => 'Stockrotationitem',
515             value  => {
516                 fresh         => 1,
517                 itemnumber_id => $builder->build_sample_item->itemnumber
518             }
519         }
520     );
521     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
522     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
523     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
524     is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");
525
526     # Test item not at stagebranch with branchtransfer history ['repatriation']
527     $sritem = $builder->build(
528         {
529             source => 'Stockrotationitem',
530             value  => {
531                 'fresh'       => 0,
532                 itemnumber_id => $builder->build_sample_item->itemnumber
533             }
534         }
535     );
536     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
537     my $dbtransfer = Koha::Item::Transfer->new({
538         'itemnumber'  => $dbitem->itemnumber_id,
539         'frombranch'  => $dbitem->itemnumber->homebranch,
540         'tobranch'    => $dbitem->itemnumber->homebranch,
541         'datesent'    => dt_from_string(),
542         'datearrived' => dt_from_string(),
543         'reason'      => "StockrotationAdvance",
544     })->store;
545     is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");
546
547     # Test item at stagebranch with branchtransfer history ['not-ready']
548     $sritem = $builder->build(
549         {
550             source => 'Stockrotationitem',
551             value  => {
552                 'fresh'       => 0,
553                 itemnumber_id => $builder->build_sample_item->itemnumber
554             }
555         }
556     );
557     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
558     $dbtransfer = Koha::Item::Transfer->new({
559         'itemnumber'  => $dbitem->itemnumber_id,
560         'frombranch'  => $dbitem->itemnumber->homebranch,
561         'tobranch'    => $dbitem->stage->branchcode_id,
562         'datesent'    => dt_from_string(),
563         'datearrived' => dt_from_string(),
564         'reason'      => "StockrotationAdvance",
565     })->store;
566     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
567     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
568     is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");
569
570     # Test item due for advancement ['advancement']
571     $sritem = $builder->build(
572         {
573             source => 'Stockrotationitem',
574             value  => {
575                 fresh         => 0,
576                 itemnumber_id => $builder->build_sample_item->itemnumber
577             }
578         }
579     );
580     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
581     $dbitem->indemand(0)->store;
582     $dbitem->stage->duration(50)->store;
583     my $sent_duration =  DateTime::Duration->new( days => 55);
584     my $arrived_duration =  DateTime::Duration->new( days => 52);
585     $dbtransfer = Koha::Item::Transfer->new({
586         'itemnumber'  => $dbitem->itemnumber_id,
587         'frombranch'  => $dbitem->itemnumber->homebranch,
588         'tobranch'    => $dbitem->stage->branchcode_id,
589         'datesent'    => dt_from_string() - $sent_duration,
590         'datearrived' => dt_from_string() - $arrived_duration,
591         'reason'      => "StockrotationAdvance",
592     })->store;
593     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
594     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
595     is($dbitem->investigate->{reason}, 'advancement',
596        "Item ready for advancement.");
597
598     # Test item due for advancement but in-demand ['in-demand']
599     $sritem = $builder->build(
600         {
601             source => 'Stockrotationitem',
602             value  => {
603                 fresh         => 0,
604                 itemnumber_id => $builder->build_sample_item->itemnumber
605             }
606         }
607     );
608     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
609     $dbitem->indemand(1)->store;
610     $dbitem->stage->duration(50)->store;
611     $sent_duration =  DateTime::Duration->new( days => 55);
612     $arrived_duration =  DateTime::Duration->new( days => 52);
613     $dbtransfer = Koha::Item::Transfer->new({
614         'itemnumber'  => $dbitem->itemnumber_id,
615         'frombranch'  => $dbitem->itemnumber->homebranch,
616         'tobranch'    => $dbitem->stage->branchcode_id,
617         'datesent'    => dt_from_string() - $sent_duration,
618         'datearrived' => dt_from_string() - $arrived_duration,
619         'reason'      => "StockrotationAdvance",
620     })->store;
621     $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
622     $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
623     is($dbitem->investigate->{reason}, 'in-demand',
624        "Item advances, but in-demand.");
625
626     # Test item ready for advancement, but at wrong library ['repatriation']
627     $sritem = $builder->build(
628         {
629             source => 'Stockrotationitem',
630             value  => {
631                 fresh         => 0,
632                 itemnumber_id => $builder->build_sample_item->itemnumber
633             }
634         }
635     );
636     $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
637     $dbitem->indemand(0)->store;
638     $dbitem->stage->duration(50)->store;
639     $sent_duration =  DateTime::Duration->new( days => 55);
640     $arrived_duration =  DateTime::Duration->new( days => 52);
641     $dbtransfer = Koha::Item::Transfer->new({
642         'itemnumber'  => $dbitem->itemnumber_id,
643         'frombranch'  => $dbitem->itemnumber->homebranch,
644         'tobranch'    => $dbitem->stage->branchcode_id,
645         'datesent'    => dt_from_string() - $sent_duration,
646         'datearrived' => dt_from_string() - $arrived_duration,
647         'reason'      => "StockrotationAdvance",
648     })->store;
649     is($dbitem->investigate->{reason}, 'repatriation',
650        "Item advances, but not at stage branch.");
651
652     $schema->storage->txn_rollback;
653 };
654
655 subtest "Tests for toggle_indemand" => sub {
656     plan tests => 15;
657     $schema->storage->txn_begin;
658
659     my $sritem = $builder->build({
660         source => 'Stockrotationitem',
661         value => { 'fresh' => 0, 'indemand' => 0 }
662     });
663     my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
664     my $firstbranch = $dbitem->stage->branchcode_id;
665     $dbitem->itemnumber->holdingbranch($firstbranch)->store;
666     my $dbstage = $dbitem->stage;
667     $dbstage->position(1)->duration(50)->store; # Configure stage.
668     # Configure item
669     $dbitem->itemnumber->holdingbranch($firstbranch)->store;
670     $dbitem->itemnumber->homebranch($firstbranch)->store;
671     # Sanity check
672     is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");
673
674     # Test if an item is not in transfer, toggle always acts.
675     is($dbitem->indemand, 0, "Item not in transfer starts with indemand disabled.");
676     $dbitem->toggle_indemand;
677     is($dbitem->indemand, 1, "Item not in transfer toggled correctly first time.");
678     $dbitem->toggle_indemand;
679     is($dbitem->indemand, 0, "Item not in transfer toggled correctly second time.");
680
681     # Add stages
682     my $srstage = $builder->build({
683         source => 'Stockrotationstage',
684         value => { duration => 50 }
685     });
686     my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
687     $dbstage2->move_to_group($dbitem->stage->rota_id);
688     $dbstage2->position(2)->store;
689     my $secondbranch = $dbstage2->branchcode_id;
690
691     # Test an item in transfer, toggle cancels transfer and resets indemand.
692     ok($dbitem->advance, "Advancement done.");
693     $dbitem->get_from_storage;
694     my $transfer = $dbitem->itemnumber->get_transfer;
695     is(ref($transfer), 'Koha::Item::Transfer', 'Item set to in transfer as expected');
696     is($transfer->frombranch, $firstbranch, 'Transfer from set correctly');
697     is($transfer->tobranch, $secondbranch, 'Transfer to set correctly');
698     is($transfer->datearrived, undef, 'Transfer datearrived not set');
699     $dbitem->toggle_indemand;
700     my $updated_transfer = $transfer->get_from_storage;
701     is($updated_transfer->frombranch, $firstbranch, 'Transfer from retained correctly');
702     is($updated_transfer->tobranch, $firstbranch, 'Transfer to updated correctly');
703     isnt($updated_transfer->datearrived, undef, 'Transfer datearrived set as expected');
704     is($dbitem->indemand, 0, "Item retains indemand as expected.");
705     is($dbitem->stage_id, $dbstage->id, 'Item stage reset as expected.');
706     is($dbitem->itemnumber->homebranch, $firstbranch, 'Item homebranch reset as expected.');
707
708     $schema->storage->txn_rollback;
709 };
710
711 1;