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 under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 3 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 use DateTime::Duration;
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 {
41 $schema->storage->txn_begin;
43 my $itm = $builder->build({ source => 'Item' });
44 my $stage = $builder->build({ source => 'Stockrotationstage' });
46 my $item = $builder->build({
47 source => 'Stockrotationitem',
49 itemnumber_id => $itm->{itemnumber},
50 stage_id => $stage->{stage_id},
54 my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
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 {
77 $schema->storage->txn_begin;
79 # Setup a pristine stockrotation context.
80 my $sritem = $builder->build({ source => 'Stockrotationitem' });
81 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
82 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
83 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
84 $dbitem->stage->position(1);
86 my $dbrota = $dbitem->stage->rota;
87 my $newstage = $builder->build({
88 source => 'Stockrotationstage',
90 rota_id => $dbrota->rota_id,
95 # - homebranch == holdingbranch [0]
97 $dbitem->needs_repatriating, 0,
98 "Homebranch == Holdingbranch."
101 my $branch = $builder->build({ source => 'Branch' });
102 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
104 # - homebranch != holdingbranch [1]
106 $dbitem->needs_repatriating, 1,
107 "Homebranch != holdingbranch."
110 # Set to incorrect homebranch.
111 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
112 $dbitem->itemnumber->homebranch($branch->{branchcode});
113 # - homebranch != stockrotationstage.branch & not in transit [1]
115 $dbitem->needs_repatriating, 1,
116 "Homebranch != StockRotationStage.Branchcode_id & not in transit."
119 # Set to in transit (by implication).
120 $dbitem->stage($newstage->{stage_id});
121 # - homebranch != stockrotaitonstage.branch & in transit [0]
123 $dbitem->needs_repatriating, 1,
124 "homebranch != stockrotaitonstage.branch & in transit."
127 $schema->storage->txn_rollback;
130 subtest "Tests for repatriate." => sub {
132 $schema->storage->txn_begin;
133 my $sritem = $builder->build({ source => 'Stockrotationitem' });
134 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
135 $dbitem->stage->position(1);
136 $dbitem->stage->duration(50);
137 my $branch = $builder->build({ source => 'Branch' });
138 $dbitem->itemnumber->holdingbranch($branch->{branchcode});
140 # Test a straight up repatriate
141 ok($dbitem->repatriate, "Repatriation done.");
142 my $intransfer = $dbitem->itemnumber->get_transfer;
143 is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
144 is($intransfer->tobranch, $dbitem->stage->branchcode_id, "Target Correct.");
146 $schema->storage->txn_rollback;
149 subtest "Tests for needs_advancing." => sub {
151 $schema->storage->txn_begin;
153 # Test behaviour of item freshly added to rota.
154 my $sritem = $builder->build({
155 source => 'Stockrotationitem',
156 value => { 'fresh' => 1, },
158 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
159 is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");
161 # Setup a pristine stockrotation context.
162 $sritem = $builder->build({
163 source => 'Stockrotationitem',
164 value => { 'fresh' => 0,}
166 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
167 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id);
168 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
169 $dbitem->stage->position(1);
170 $dbitem->stage->duration(50);
172 my $dbtransfer = Koha::Item::Transfer->new({
173 'itemnumber' => $dbitem->itemnumber_id,
174 'frombranch' => $dbitem->stage->branchcode_id,
175 'tobranch' => $dbitem->stage->branchcode_id,
176 'datesent' => DateTime->now,
177 'datearrived' => undef,
178 'comments' => "StockrotationAdvance",
181 # Test item will not be advanced if in transit.
182 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer.");
183 # Test item will not be advanced if in transit even if fresh.
184 $dbitem->fresh(1)->store;
185 is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer (fresh).");
186 $dbitem->fresh(0)->store;
188 # Test item will not be advanced if it has not spent enough time.
189 $dbtransfer->datearrived(DateTime->now)->store;
190 is($dbitem->needs_advancing, 0, "Not ready to advance: Not spent enough time.");
191 # Test item will be advanced if it has not spent enough time, but is fresh.
192 $dbitem->fresh(1)->store;
193 is($dbitem->needs_advancing, 1, "Advance: Not spent enough time, but fresh.");
194 $dbitem->fresh(0)->store;
196 # Test item will be advanced if it has spent enough time.
197 $dbtransfer->datesent( # Item was sent 100 days ago...
198 DateTime->now - DateTime::Duration->new( days => 100 )
200 $dbtransfer->datearrived( # And arrived 75 days ago.
201 DateTime->now - DateTime::Duration->new( days => 75 )
203 is($dbitem->needs_advancing, 1, "Ready to be advanced.");
205 $schema->storage->txn_rollback;
208 subtest "Tests for advance." => sub {
210 $schema->storage->txn_begin;
212 my $sritem = $builder->build({
213 source => 'Stockrotationitem',
214 value => { 'fresh' => 1 }
216 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
217 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id);
218 my $dbstage = $dbitem->stage;
219 $dbstage->position(1)->duration(50)->store; # Configure stage.
221 $dbitem->itemnumber->holdingbranch($dbstage->branchcode_id)->store;
222 $dbitem->itemnumber->homebranch($dbstage->branchcode_id)->store;
224 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");
226 # Test if an item is fresh, always move to first stage.
227 is($dbitem->fresh, 1, "Fresh is correct.");
229 is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage is first stage after fresh advance.");
230 is($dbitem->fresh, 0, "Fresh reset after advance.");
232 # Test cases of single stage
233 $dbstage->rota->cyclical(1)->store; # Set Rota to cyclical.
234 ok($dbitem->advance, "Single stage cyclical advance done.");
236 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
237 is($dbitem->stage->stage_id, $dbstage->stage_id, "Single stage cyclical stage OK.");
239 # Test with indemand advance
240 $dbitem->indemand(1)->store;
241 ok($dbitem->advance, "Indemand item advance done.");
243 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
244 is($dbitem->indemand, 0, "Indemand OK.");
245 is($dbitem->stage->stage_id, $dbstage->stage_id, "Indemand item advance stage OK.");
248 my $srstage = $builder->build({
249 source => 'Stockrotationstage',
250 value => { duration => 50 }
252 my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
253 $dbstage2->move_to_group($dbitem->stage->rota_id);
254 $dbstage2->move_last;
256 # Test a straight up advance
257 ok($dbitem->advance, "Advancement done.");
259 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
261 is($dbitem->stage->stage_id, $dbstage2->stage_id, "Stage updated.");
262 my $intransfer = $dbitem->itemnumber->get_transfer;
263 is($intransfer->frombranch, $dbstage->branchcode_id, "Origin correct.");
264 is($intransfer->tobranch, $dbstage2->branchcode_id, "Target Correct.");
266 $dbstage->rota->cyclical(0)->store; # Set Rota to non-cyclical.
268 # Arrive at new branch
269 $intransfer->datearrived(DateTime->now)->store;
270 $dbitem->itemnumber->holdingbranch($srstage->{branchcode_id})->store;
271 $dbitem->itemnumber->homebranch($srstage->{branchcode_id})->store;
273 # Advance again, Remove from rota.
274 ok($dbitem->advance, "Non-cyclical advance.");
276 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
277 is($dbitem, undef, "StockRotationItem has been removed.");
279 $schema->storage->txn_rollback;
282 subtest "Tests for investigate (singular)." => sub {
284 $schema->storage->txn_begin;
286 # Test brand new item's investigation ['initiation']
287 my $sritem = $builder->build({ source => 'Stockrotationitem', value => { fresh => 1 } });
288 my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
289 is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");
291 # Test brand new item at stagebranch ['initiation']
292 $sritem = $builder->build({ source => 'Stockrotationitem', value => { fresh => 1 } });
293 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
294 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
295 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
296 is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");
298 # Test item not at stagebranch with branchtransfer history ['repatriation']
299 $sritem = $builder->build({
300 source => 'Stockrotationitem',
301 value => { 'fresh' => 0,}
303 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
304 my $dbtransfer = Koha::Item::Transfer->new({
305 'itemnumber' => $dbitem->itemnumber_id,
306 'frombranch' => $dbitem->itemnumber->homebranch,
307 'tobranch' => $dbitem->itemnumber->homebranch,
308 'datesent' => DateTime->now,
309 'datearrived' => DateTime->now,
310 'comments' => "StockrotationAdvance",
312 is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");
314 # Test item at stagebranch with branchtransfer history ['not-ready']
315 $sritem = $builder->build({
316 source => 'Stockrotationitem',
317 value => { 'fresh' => 0,}
319 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
320 $dbtransfer = Koha::Item::Transfer->new({
321 'itemnumber' => $dbitem->itemnumber_id,
322 'frombranch' => $dbitem->itemnumber->homebranch,
323 'tobranch' => $dbitem->stage->branchcode_id,
324 'datesent' => DateTime->now,
325 'datearrived' => DateTime->now,
326 'comments' => "StockrotationAdvance",
328 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
329 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
330 is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");
332 # Test item due for advancement ['advancement']
333 $sritem = $builder->build({ source => 'Stockrotationitem', value => { fresh => 0 } });
334 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
335 $dbitem->indemand(0)->store;
336 $dbitem->stage->duration(50)->store;
337 my $sent_duration = DateTime::Duration->new( days => 55);
338 my $arrived_duration = DateTime::Duration->new( days => 52);
339 $dbtransfer = Koha::Item::Transfer->new({
340 'itemnumber' => $dbitem->itemnumber_id,
341 'frombranch' => $dbitem->itemnumber->homebranch,
342 'tobranch' => $dbitem->stage->branchcode_id,
343 'datesent' => DateTime->now - $sent_duration,
344 'datearrived' => DateTime->now - $arrived_duration,
345 'comments' => "StockrotationAdvance",
347 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
348 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
349 is($dbitem->investigate->{reason}, 'advancement',
350 "Item ready for advancement.");
352 # Test item due for advancement but in-demand ['in-demand']
353 $sritem = $builder->build({ source => 'Stockrotationitem', value => { fresh => 0 } });
354 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
355 $dbitem->indemand(1)->store;
356 $dbitem->stage->duration(50)->store;
357 $sent_duration = DateTime::Duration->new( days => 55);
358 $arrived_duration = DateTime::Duration->new( days => 52);
359 $dbtransfer = Koha::Item::Transfer->new({
360 'itemnumber' => $dbitem->itemnumber_id,
361 'frombranch' => $dbitem->itemnumber->homebranch,
362 'tobranch' => $dbitem->stage->branchcode_id,
363 'datesent' => DateTime->now - $sent_duration,
364 'datearrived' => DateTime->now - $arrived_duration,
365 'comments' => "StockrotationAdvance",
367 $dbitem->itemnumber->homebranch($dbitem->stage->branchcode_id)->store;
368 $dbitem->itemnumber->holdingbranch($dbitem->stage->branchcode_id)->store;
369 is($dbitem->investigate->{reason}, 'in-demand',
370 "Item advances, but in-demand.");
372 # Test item ready for advancement, but at wrong library ['repatriation']
373 $sritem = $builder->build({ source => 'Stockrotationitem', value => { fresh => 0 } });
374 $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
375 $dbitem->indemand(0)->store;
376 $dbitem->stage->duration(50)->store;
377 $sent_duration = DateTime::Duration->new( days => 55);
378 $arrived_duration = DateTime::Duration->new( days => 52);
379 $dbtransfer = Koha::Item::Transfer->new({
380 'itemnumber' => $dbitem->itemnumber_id,
381 'frombranch' => $dbitem->itemnumber->homebranch,
382 'tobranch' => $dbitem->stage->branchcode_id,
383 'datesent' => DateTime->now - $sent_duration,
384 'datearrived' => DateTime->now - $arrived_duration,
385 'comments' => "StockrotationAdvance",
387 is($dbitem->investigate->{reason}, 'repatriation',
388 "Item advances, but not at stage branch.");
390 $schema->storage->txn_rollback;