Bug 26250: StockRotationItems.t and StockRotationStages.t
[koha.git] / t / db_dependent / StockRotationItems.t
blob7ec621a0abd0760caa92342b66a1640113768f6a
1 #!/usr/bin/perl
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>.
20 use Modern::Perl;
22 use DateTime;
23 use DateTime::Duration;
24 use Koha::Database;
25 use Koha::Item::Transfer;
26 use t::lib::TestBuilder;
28 use Test::More tests => 8;
30 my $schema = Koha::Database->new->schema;
32 use_ok('Koha::StockRotationItems');
33 use_ok('Koha::StockRotationItem');
35 my $builder = t::lib::TestBuilder->new;
37 subtest 'Basic object tests' => sub {
39 plan tests => 5;
41 $schema->storage->txn_begin;
43 my $itm = $builder->build_sample_item;
44 my $stage = $builder->build({ source => 'Stockrotationstage' });
46 my $item = $builder->build({
47 source => 'Stockrotationitem',
48 value => {
49 itemnumber_id => $itm->itemnumber,
50 stage_id => $stage->{stage_id},
52 });
54 my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
55 isa_ok(
56 $sritem,
57 'Koha::StockRotationItem',
58 "Correctly create and load a stock rotation item."
61 # Relationship to rota
62 isa_ok( $sritem->itemnumber, 'Koha::Item', "Fetched related item." );
63 is( $sritem->itemnumber->itemnumber, $itm->itemnumber, "Related rota OK." );
65 # Relationship to stage
66 isa_ok( $sritem->stage, 'Koha::StockRotationStage', "Fetched related stage." );
67 is( $sritem->stage->stage_id, $stage->{stage_id}, "Related stage OK." );
70 $schema->storage->txn_rollback;
73 subtest 'Tests for needs_repatriating' => sub {
75 plan tests => 4;
77 $schema->storage->txn_begin;
79 # Setup a pristine stockrotation context.
80 my $sritem = $builder->build(
82 source => 'Stockrotationitem',
83 value =>
84 { itemnumber_id => $builder->build_sample_item->itemnumber }
87 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
88 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
89 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
90 $dbitem->stage->position(1);
92 my $dbrota = $dbitem->stage->rota;
93 my $newstage = $builder->build({
94 source => 'Stockrotationstage',
95 value => {
96 rota_id => $dbrota->rota_id,
97 position => 2,
99 });
101 # - homebranch == holdingbranch [0]
103 $dbitem->needs_repatriating, 0,
104 "Homebranch == Holdingbranch."
107 my $branch = $builder->build({ source => 'Branch' });
108 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
110 # - homebranch != holdingbranch [1]
112 $dbitem->needs_repatriating, 1,
113 "Homebranch != holdingbranch."
116 # Set to incorrect homebranch.
117 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
118 $dbitem->itemnumber->homebranch($branch->{branchcode});
119 # - homebranch != stockrotationstage.branch & not in transit [1]
121 $dbitem->needs_repatriating, 1,
122 "Homebranch != StockRotationStage.Branchcode_id & not in transit."
125 # Set to in transit (by implication).
126 $dbitem->stage($newstage->{stage_id});
127 # - homebranch != stockrotaitonstage.branch & in transit [0]
129 $dbitem->needs_repatriating, 1,
130 "homebranch != stockrotaitonstage.branch & in transit."
133 $schema->storage->txn_rollback;
136 subtest "Tests for repatriate." => sub {
137 plan tests => 3;
138 $schema->storage->txn_begin;
139 my $sritem = $builder->build(
141 source => 'Stockrotationitem',
142 value =>
143 { itemnumber_id => $builder->build_sample_item->itemnumber }
146 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
147 $dbitem->stage->position(1);
148 $dbitem->stage->duration(50);
149 my $branch = $builder->build({ source => 'Branch' });
150 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
152 # Test a straight up repatriate
153 ok($dbitem->repatriate, "Repatriation done.");
154 my $intransfer = $dbitem->itemnumber->get_transfer;
155 is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
156 is($intransfer->tobranch, $dbitem->stage->branchcode_id, "Target Correct.");
158 $schema->storage->txn_rollback;
161 subtest "Tests for needs_advancing." => sub {
162 plan tests => 6;
163 $schema->storage->txn_begin;
165 # Test behaviour of item freshly added to rota.
166 my $sritem = $builder->build(
168 source => 'Stockrotationitem',
169 value => {
170 'fresh' => 1,
171 itemnumber_id => $builder->build_sample_item->itemnumber
175 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
176 is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");
178 # Setup a pristine stockrotation context.
179 $sritem = $builder->build(
181 source => 'Stockrotationitem',
182 value => {
183 'fresh' => 0,
184 itemnumber_id => $builder->build_sample_item->itemnumber
188 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
189 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
190 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
191 $dbitem->stage->position(1);
192 $dbitem->stage->duration(50);
194 my $dbtransfer = Koha::Item::Transfer->new({
195 'itemnumber' => $dbitem->itemnumber_id,
196 'frombranch' => $dbitem->stage->branchcode_id,
197 'tobranch' => $dbitem->stage->branchcode_id,
198 'datesent' => DateTime->now,
199 'datearrived' => undef,
200 'reason' => "StockrotationAdvance",
201 })->store;
203 # Test item will not be advanced if in transit.
204 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer.");
205 # Test item will not be advanced if in transit even if fresh.
206 $dbitem->fresh(1)->store;
207 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer (fresh).");
208 $dbitem->fresh(0)->store;
210 # Test item will not be advanced if it has not spent enough time.
211 $dbtransfer->datearrived(DateTime->now)->store;
212 is($dbitem->needs_advancing, 0, "Not ready to advance: Not spent enough time.");
213 # Test item will be advanced if it has not spent enough time, but is fresh.
214 $dbitem->fresh(1)->store;
215 is($dbitem->needs_advancing, 1, "Advance: Not spent enough time, but fresh.");
216 $dbitem->fresh(0)->store;
218 # Test item will be advanced if it has spent enough time.
219 $dbtransfer->datesent( # Item was sent 100 days ago...
220 DateTime->now - DateTime::Duration->new( days => 100 )
221 )->store;
222 $dbtransfer->datearrived( # And arrived 75 days ago.
223 DateTime->now - DateTime::Duration->new( days => 75 )
224 )->store;
225 is($dbitem->needs_advancing, 1, "Ready to be advanced.");
227 $schema->storage->txn_rollback;
230 subtest "Tests for advance." => sub {
231 plan tests => 15;
232 $schema->storage->txn_begin;
234 my $sritem = $builder->build(
236 source => 'Stockrotationitem',
237 value => {
238 'fresh' => 1,
239 itemnumber_id => $builder->build_sample_item->itemnumber
243 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
244 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
245 my $dbstage = $dbitem->stage;
246 $dbstage->position(1)->duration(50)->store; # Configure stage.
247 # Configure item
248 $dbitem->itemnumber->holdingbranch($dbstage->branchcode_id)->store;
249 $dbitem->itemnumber->homebranch($dbstage->branchcode_id)->store;
250 # Sanity check
251 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");
253 # Test if an item is fresh, always move to first stage.
254 is($dbitem->fresh, 1, "Fresh is correct.");
255 $dbitem->advance;
256 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage is first stage after fresh advance.");
257 is($dbitem->fresh, 0, "Fresh reset after advance.");
259 # Test cases of single stage
260 $dbstage->rota->cyclical(1)->store; # Set Rota to cyclical.
261 ok($dbitem->advance, "Single stage cyclical advance done.");
262 ## Refetch dbitem
263 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
264 is($dbitem->stage->stage_id, $dbstage->stage_id, "Single stage cyclical stage OK.");
266 # Test with indemand advance
267 $dbitem->indemand(1)->store;
268 ok($dbitem->advance, "Indemand item advance done.");
269 ## Refetch dbitem
270 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
271 is($dbitem->indemand, 0, "Indemand OK.");
272 is($dbitem->stage->stage_id, $dbstage->stage_id, "Indemand item advance stage OK.");
274 # Multi stages
275 my $srstage = $builder->build({
276 source => 'Stockrotationstage',
277 value => { duration => 50 }
279 my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
280 $dbstage2->move_to_group($dbitem->stage->rota_id);
281 $dbstage2->move_last;
283 # Test a straight up advance
284 ok($dbitem->advance, "Advancement done.");
285 ## Refetch dbitem
286 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
287 ## Test results
288 is($dbitem->stage->stage_id, $dbstage2->stage_id, "Stage updated.");
289 my $intransfer = $dbitem->itemnumber->get_transfer;
290 is($intransfer->frombranch, $dbstage->branchcode_id, "Origin correct.");
291 is($intransfer->tobranch, $dbstage2->branchcode_id, "Target Correct.");
293 $dbstage->rota->cyclical(0)->store; # Set Rota to non-cyclical.
295 # Arrive at new branch
296 $intransfer->datearrived(DateTime->now)->store;
297 $dbitem->itemnumber->holdingbranch($srstage->{branchcode_id})->store;
298 $dbitem->itemnumber->homebranch($srstage->{branchcode_id})->store;
300 # Advance again, Remove from rota.
301 ok($dbitem->advance, "Non-cyclical advance.");
302 ## Refetch dbitem
303 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
304 is($dbitem, undef, "StockRotationItem has been removed.");
306 $schema->storage->txn_rollback;
309 subtest "Tests for investigate (singular)." => sub {
310 plan tests => 7;
311 $schema->storage->txn_begin;
313 # Test brand new item's investigation ['initiation']
314 my $sritem = $builder->build(
316 source => 'Stockrotationitem',
317 value => {
318 fresh => 1,
319 itemnumber_id => $builder->build_sample_item->itemnumber
323 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
324 is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");
326 # Test brand new item at stagebranch ['initiation']
327 $sritem = $builder->build(
329 source => 'Stockrotationitem',
330 value => {
331 fresh => 1,
332 itemnumber_id => $builder->build_sample_item->itemnumber
336 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
337 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
338 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
339 is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");
341 # Test item not at stagebranch with branchtransfer history ['repatriation']
342 $sritem = $builder->build(
344 source => 'Stockrotationitem',
345 value => {
346 'fresh' => 0,
347 itemnumber_id => $builder->build_sample_item->itemnumber
351 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
352 my $dbtransfer = Koha::Item::Transfer->new({
353 'itemnumber' => $dbitem->itemnumber_id,
354 'frombranch' => $dbitem->itemnumber->homebranch,
355 'tobranch' => $dbitem->itemnumber->homebranch,
356 'datesent' => DateTime->now,
357 'datearrived' => DateTime->now,
358 'reason' => "StockrotationAdvance",
359 })->store;
360 is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");
362 # Test item at stagebranch with branchtransfer history ['not-ready']
363 $sritem = $builder->build(
365 source => 'Stockrotationitem',
366 value => {
367 'fresh' => 0,
368 itemnumber_id => $builder->build_sample_item->itemnumber
372 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
373 $dbtransfer = Koha::Item::Transfer->new({
374 'itemnumber' => $dbitem->itemnumber_id,
375 'frombranch' => $dbitem->itemnumber->homebranch,
376 'tobranch' => $dbitem->stage->branchcode_id,
377 'datesent' => DateTime->now,
378 'datearrived' => DateTime->now,
379 'reason' => "StockrotationAdvance",
380 })->store;
381 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
382 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
383 is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");
385 # Test item due for advancement ['advancement']
386 $sritem = $builder->build(
388 source => 'Stockrotationitem',
389 value => {
390 fresh => 0,
391 itemnumber_id => $builder->build_sample_item->itemnumber
395 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
396 $dbitem->indemand(0)->store;
397 $dbitem->stage->duration(50)->store;
398 my $sent_duration = DateTime::Duration->new( days => 55);
399 my $arrived_duration = DateTime::Duration->new( days => 52);
400 $dbtransfer = Koha::Item::Transfer->new({
401 'itemnumber' => $dbitem->itemnumber_id,
402 'frombranch' => $dbitem->itemnumber->homebranch,
403 'tobranch' => $dbitem->stage->branchcode_id,
404 'datesent' => DateTime->now - $sent_duration,
405 'datearrived' => DateTime->now - $arrived_duration,
406 'reason' => "StockrotationAdvance",
407 })->store;
408 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
409 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
410 is($dbitem->investigate->{reason}, 'advancement',
411 "Item ready for advancement.");
413 # Test item due for advancement but in-demand ['in-demand']
414 $sritem = $builder->build(
416 source => 'Stockrotationitem',
417 value => {
418 fresh => 0,
419 itemnumber_id => $builder->build_sample_item->itemnumber
423 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
424 $dbitem->indemand(1)->store;
425 $dbitem->stage->duration(50)->store;
426 $sent_duration = DateTime::Duration->new( days => 55);
427 $arrived_duration = DateTime::Duration->new( days => 52);
428 $dbtransfer = Koha::Item::Transfer->new({
429 'itemnumber' => $dbitem->itemnumber_id,
430 'frombranch' => $dbitem->itemnumber->homebranch,
431 'tobranch' => $dbitem->stage->branchcode_id,
432 'datesent' => DateTime->now - $sent_duration,
433 'datearrived' => DateTime->now - $arrived_duration,
434 'reason' => "StockrotationAdvance",
435 })->store;
436 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
437 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
438 is($dbitem->investigate->{reason}, 'in-demand',
439 "Item advances, but in-demand.");
441 # Test item ready for advancement, but at wrong library ['repatriation']
442 $sritem = $builder->build(
444 source => 'Stockrotationitem',
445 value => {
446 fresh => 0,
447 itemnumber_id => $builder->build_sample_item->itemnumber
451 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
452 $dbitem->indemand(0)->store;
453 $dbitem->stage->duration(50)->store;
454 $sent_duration = DateTime::Duration->new( days => 55);
455 $arrived_duration = DateTime::Duration->new( days => 52);
456 $dbtransfer = Koha::Item::Transfer->new({
457 'itemnumber' => $dbitem->itemnumber_id,
458 'frombranch' => $dbitem->itemnumber->homebranch,
459 'tobranch' => $dbitem->stage->branchcode_id,
460 'datesent' => DateTime->now - $sent_duration,
461 'datearrived' => DateTime->now - $arrived_duration,
462 'reason' => "StockrotationAdvance",
463 })->store;
464 is($dbitem->investigate->{reason}, 'repatriation',
465 "Item advances, but not at stage branch.");
467 $schema->storage->txn_rollback;