Bug 23432: (QA follow-up) Add a unit test
[koha.git] / t / db_dependent / StockRotationItems.t
blob49da2cc3040b6d44f0e5e555f74e800198d33e4c
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;
27 use Test::Warn;
29 use Test::More tests => 8;
31 my $schema = Koha::Database->new->schema;
33 use_ok('Koha::StockRotationItems');
34 use_ok('Koha::StockRotationItem');
36 my $builder = t::lib::TestBuilder->new;
38 subtest 'Basic object tests' => sub {
40 plan tests => 5;
42 $schema->storage->txn_begin;
44 my $itm = $builder->build_sample_item;
45 my $stage = $builder->build({ source => 'Stockrotationstage' });
47 my $item = $builder->build({
48 source => 'Stockrotationitem',
49 value => {
50 itemnumber_id => $itm->itemnumber,
51 stage_id => $stage->{stage_id},
53 });
55 my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
56 isa_ok(
57 $sritem,
58 'Koha::StockRotationItem',
59 "Correctly create and load a stock rotation item."
62 # Relationship to rota
63 isa_ok( $sritem->itemnumber, 'Koha::Item', "Fetched related item." );
64 is( $sritem->itemnumber->itemnumber, $itm->itemnumber, "Related rota OK." );
66 # Relationship to stage
67 isa_ok( $sritem->stage, 'Koha::StockRotationStage', "Fetched related stage." );
68 is( $sritem->stage->stage_id, $stage->{stage_id}, "Related stage OK." );
71 $schema->storage->txn_rollback;
74 subtest 'Tests for needs_repatriating' => sub {
76 plan tests => 4;
78 $schema->storage->txn_begin;
80 # Setup a pristine stockrotation context.
81 my $sritem = $builder->build(
83 source => 'Stockrotationitem',
84 value =>
85 { itemnumber_id => $builder->build_sample_item->itemnumber }
88 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
89 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
90 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
91 $dbitem->stage->position(1);
93 my $dbrota = $dbitem->stage->rota;
94 my $newstage = $builder->build({
95 source => 'Stockrotationstage',
96 value => {
97 rota_id => $dbrota->rota_id,
98 position => 2,
102 # - homebranch == holdingbranch [0]
104 $dbitem->needs_repatriating, 0,
105 "Homebranch == Holdingbranch."
108 my $branch = $builder->build({ source => 'Branch' });
109 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
111 # - homebranch != holdingbranch [1]
113 $dbitem->needs_repatriating, 1,
114 "Homebranch != holdingbranch."
117 # Set to incorrect homebranch.
118 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
119 $dbitem->itemnumber->homebranch($branch->{branchcode});
120 # - homebranch != stockrotationstage.branch & not in transit [1]
122 $dbitem->needs_repatriating, 1,
123 "Homebranch != StockRotationStage.Branchcode_id & not in transit."
126 # Set to in transit (by implication).
127 $dbitem->stage($newstage->{stage_id});
128 # - homebranch != stockrotaitonstage.branch & in transit [0]
130 $dbitem->needs_repatriating, 1,
131 "homebranch != stockrotaitonstage.branch & in transit."
134 $schema->storage->txn_rollback;
137 subtest "Tests for repatriate." => sub {
138 plan tests => 3;
139 $schema->storage->txn_begin;
140 my $sritem = $builder->build(
142 source => 'Stockrotationitem',
143 value =>
144 { itemnumber_id => $builder->build_sample_item->itemnumber }
147 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
148 $dbitem->stage->position(1);
149 $dbitem->stage->duration(50);
150 my $branch = $builder->build({ source => 'Branch' });
151 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
153 # Test a straight up repatriate
154 ok($dbitem->repatriate, "Repatriation done.");
155 my $intransfer = $dbitem->itemnumber->get_transfer;
156 is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
157 is($intransfer->tobranch, $dbitem->stage->branchcode_id, "Target Correct.");
159 $schema->storage->txn_rollback;
162 subtest "Tests for needs_advancing." => sub {
163 plan tests => 7;
164 $schema->storage->txn_begin;
166 # Test behaviour of item freshly added to rota.
167 my $sritem = $builder->build(
169 source => 'Stockrotationitem',
170 value => {
171 'fresh' => 1,
172 itemnumber_id => $builder->build_sample_item->itemnumber
176 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
177 is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");
179 # Setup a pristine stockrotation context.
180 $sritem = $builder->build(
182 source => 'Stockrotationitem',
183 value => {
184 'fresh' => 0,
185 itemnumber_id => $builder->build_sample_item->itemnumber
189 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
190 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
191 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
192 $dbitem->stage->position(1);
193 $dbitem->stage->duration(50);
195 my $dbtransfer = Koha::Item::Transfer->new({
196 'itemnumber' => $dbitem->itemnumber_id,
197 'frombranch' => $dbitem->stage->branchcode_id,
198 'tobranch' => $dbitem->stage->branchcode_id,
199 'datesent' => DateTime->now,
200 'datearrived' => undef,
201 'reason' => "StockrotationAdvance",
202 })->store;
204 # Test item will not be advanced if in transit.
205 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer.");
206 # Test item will not be advanced if in transit even if fresh.
207 $dbitem->fresh(1)->store;
208 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer (fresh).");
209 $dbitem->fresh(0)->store;
211 # Test item will not be advanced if it has not spent enough time.
212 $dbtransfer->datearrived(DateTime->now)->store;
213 is($dbitem->needs_advancing, 0, "Not ready to advance: Not spent enough time.");
214 # Test item will be advanced if it has not spent enough time, but is fresh.
215 $dbitem->fresh(1)->store;
216 is($dbitem->needs_advancing, 1, "Advance: Not spent enough time, but fresh.");
217 $dbitem->fresh(0)->store;
219 # Test item will be advanced if it has spent enough time.
220 $dbtransfer->datesent( # Item was sent 100 days ago...
221 DateTime->now - DateTime::Duration->new( days => 100 )
222 )->store;
223 $dbtransfer->datearrived( # And arrived 75 days ago.
224 DateTime->now - DateTime::Duration->new( days => 75 )
225 )->store;
226 is($dbitem->needs_advancing, 1, "Ready to be advanced.");
227 $dbtransfer->delete;
228 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.";
230 $schema->storage->txn_rollback;
233 subtest "Tests for advance." => sub {
234 plan tests => 15;
235 $schema->storage->txn_begin;
237 my $sritem = $builder->build(
239 source => 'Stockrotationitem',
240 value => {
241 'fresh' => 1,
242 itemnumber_id => $builder->build_sample_item->itemnumber
246 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
247 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
248 my $dbstage = $dbitem->stage;
249 $dbstage->position(1)->duration(50)->store; # Configure stage.
250 # Configure item
251 $dbitem->itemnumber->holdingbranch($dbstage->branchcode_id)->store;
252 $dbitem->itemnumber->homebranch($dbstage->branchcode_id)->store;
253 # Sanity check
254 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");
256 # Test if an item is fresh, always move to first stage.
257 is($dbitem->fresh, 1, "Fresh is correct.");
258 $dbitem->advance;
259 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage is first stage after fresh advance.");
260 is($dbitem->fresh, 0, "Fresh reset after advance.");
262 # Test cases of single stage
263 $dbstage->rota->cyclical(1)->store; # Set Rota to cyclical.
264 ok($dbitem->advance, "Single stage cyclical advance done.");
265 ## Refetch dbitem
266 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
267 is($dbitem->stage->stage_id, $dbstage->stage_id, "Single stage cyclical stage OK.");
269 # Test with indemand advance
270 $dbitem->indemand(1)->store;
271 ok($dbitem->advance, "Indemand item advance done.");
272 ## Refetch dbitem
273 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
274 is($dbitem->indemand, 0, "Indemand OK.");
275 is($dbitem->stage->stage_id, $dbstage->stage_id, "Indemand item advance stage OK.");
277 # Multi stages
278 my $srstage = $builder->build({
279 source => 'Stockrotationstage',
280 value => { duration => 50 }
282 my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
283 $dbstage2->move_to_group($dbitem->stage->rota_id);
284 $dbstage2->move_last;
286 # Test a straight up advance
287 ok($dbitem->advance, "Advancement done.");
288 ## Refetch dbitem
289 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
290 ## Test results
291 is($dbitem->stage->stage_id, $dbstage2->stage_id, "Stage updated.");
292 my $intransfer = $dbitem->itemnumber->get_transfer;
293 is($intransfer->frombranch, $dbstage->branchcode_id, "Origin correct.");
294 is($intransfer->tobranch, $dbstage2->branchcode_id, "Target Correct.");
296 $dbstage->rota->cyclical(0)->store; # Set Rota to non-cyclical.
298 # Arrive at new branch
299 $intransfer->datearrived(DateTime->now)->store;
300 $dbitem->itemnumber->holdingbranch($srstage->{branchcode_id})->store;
301 $dbitem->itemnumber->homebranch($srstage->{branchcode_id})->store;
303 # Advance again, Remove from rota.
304 ok($dbitem->advance, "Non-cyclical advance.");
305 ## Refetch dbitem
306 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
307 is($dbitem, undef, "StockRotationItem has been removed.");
309 $schema->storage->txn_rollback;
312 subtest "Tests for investigate (singular)." => sub {
313 plan tests => 7;
314 $schema->storage->txn_begin;
316 # Test brand new item's investigation ['initiation']
317 my $sritem = $builder->build(
319 source => 'Stockrotationitem',
320 value => {
321 fresh => 1,
322 itemnumber_id => $builder->build_sample_item->itemnumber
326 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
327 is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");
329 # Test brand new item at stagebranch ['initiation']
330 $sritem = $builder->build(
332 source => 'Stockrotationitem',
333 value => {
334 fresh => 1,
335 itemnumber_id => $builder->build_sample_item->itemnumber
339 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
340 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
341 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
342 is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");
344 # Test item not at stagebranch with branchtransfer history ['repatriation']
345 $sritem = $builder->build(
347 source => 'Stockrotationitem',
348 value => {
349 'fresh' => 0,
350 itemnumber_id => $builder->build_sample_item->itemnumber
354 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
355 my $dbtransfer = Koha::Item::Transfer->new({
356 'itemnumber' => $dbitem->itemnumber_id,
357 'frombranch' => $dbitem->itemnumber->homebranch,
358 'tobranch' => $dbitem->itemnumber->homebranch,
359 'datesent' => DateTime->now,
360 'datearrived' => DateTime->now,
361 'reason' => "StockrotationAdvance",
362 })->store;
363 is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");
365 # Test item at stagebranch with branchtransfer history ['not-ready']
366 $sritem = $builder->build(
368 source => 'Stockrotationitem',
369 value => {
370 'fresh' => 0,
371 itemnumber_id => $builder->build_sample_item->itemnumber
375 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
376 $dbtransfer = Koha::Item::Transfer->new({
377 'itemnumber' => $dbitem->itemnumber_id,
378 'frombranch' => $dbitem->itemnumber->homebranch,
379 'tobranch' => $dbitem->stage->branchcode_id,
380 'datesent' => DateTime->now,
381 'datearrived' => DateTime->now,
382 'reason' => "StockrotationAdvance",
383 })->store;
384 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
385 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
386 is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");
388 # Test item due for advancement ['advancement']
389 $sritem = $builder->build(
391 source => 'Stockrotationitem',
392 value => {
393 fresh => 0,
394 itemnumber_id => $builder->build_sample_item->itemnumber
398 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
399 $dbitem->indemand(0)->store;
400 $dbitem->stage->duration(50)->store;
401 my $sent_duration = DateTime::Duration->new( days => 55);
402 my $arrived_duration = DateTime::Duration->new( days => 52);
403 $dbtransfer = Koha::Item::Transfer->new({
404 'itemnumber' => $dbitem->itemnumber_id,
405 'frombranch' => $dbitem->itemnumber->homebranch,
406 'tobranch' => $dbitem->stage->branchcode_id,
407 'datesent' => DateTime->now - $sent_duration,
408 'datearrived' => DateTime->now - $arrived_duration,
409 'reason' => "StockrotationAdvance",
410 })->store;
411 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
412 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
413 is($dbitem->investigate->{reason}, 'advancement',
414 "Item ready for advancement.");
416 # Test item due for advancement but in-demand ['in-demand']
417 $sritem = $builder->build(
419 source => 'Stockrotationitem',
420 value => {
421 fresh => 0,
422 itemnumber_id => $builder->build_sample_item->itemnumber
426 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
427 $dbitem->indemand(1)->store;
428 $dbitem->stage->duration(50)->store;
429 $sent_duration = DateTime::Duration->new( days => 55);
430 $arrived_duration = DateTime::Duration->new( days => 52);
431 $dbtransfer = Koha::Item::Transfer->new({
432 'itemnumber' => $dbitem->itemnumber_id,
433 'frombranch' => $dbitem->itemnumber->homebranch,
434 'tobranch' => $dbitem->stage->branchcode_id,
435 'datesent' => DateTime->now - $sent_duration,
436 'datearrived' => DateTime->now - $arrived_duration,
437 'reason' => "StockrotationAdvance",
438 })->store;
439 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
440 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
441 is($dbitem->investigate->{reason}, 'in-demand',
442 "Item advances, but in-demand.");
444 # Test item ready for advancement, but at wrong library ['repatriation']
445 $sritem = $builder->build(
447 source => 'Stockrotationitem',
448 value => {
449 fresh => 0,
450 itemnumber_id => $builder->build_sample_item->itemnumber
454 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
455 $dbitem->indemand(0)->store;
456 $dbitem->stage->duration(50)->store;
457 $sent_duration = DateTime::Duration->new( days => 55);
458 $arrived_duration = DateTime::Duration->new( days => 52);
459 $dbtransfer = Koha::Item::Transfer->new({
460 'itemnumber' => $dbitem->itemnumber_id,
461 'frombranch' => $dbitem->itemnumber->homebranch,
462 'tobranch' => $dbitem->stage->branchcode_id,
463 'datesent' => DateTime->now - $sent_duration,
464 'datearrived' => DateTime->now - $arrived_duration,
465 'reason' => "StockrotationAdvance",
466 })->store;
467 is($dbitem->investigate->{reason}, 'repatriation',
468 "Item advances, but not at stage branch.");
470 $schema->storage->txn_rollback;