Bug 21301: add unit tests
[koha.git] / t / db_dependent / StockRotationStages.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 Koha::Database;
23 use t::lib::TestBuilder;
24
25 use Test::More tests => 6;
26
27 my $schema = Koha::Database->new->schema;
28
29 use_ok('Koha::StockRotationStages');
30 use_ok('Koha::StockRotationStage');
31
32 my $builder = t::lib::TestBuilder->new;
33
34 subtest 'Basic object tests' => sub {
35     plan tests => 5;
36
37     $schema->storage->txn_begin;
38
39     my $library = $builder->build({ source => 'Branch' });
40     my $rota = $builder->build({ source => 'Stockrotationrota' });
41     my $stage = $builder->build({
42         source => 'Stockrotationstage',
43         value  => {
44             branchcode_id => $library->{branchcode},
45             rota_id       => $rota->{rota_id},
46         },
47     });
48
49     my $srstage = Koha::StockRotationStages->find($stage->{stage_id});
50     isa_ok(
51         $srstage,
52         'Koha::StockRotationStage',
53         "Correctly create and load a stock rotation stage."
54     );
55
56     # Relationship to library
57     isa_ok( $srstage->branchcode, 'Koha::Library', "Fetched related branch." );
58     is( $srstage->branchcode->branchcode, $library->{branchcode}, "Related branch OK." );
59
60     # Relationship to rota
61     isa_ok( $srstage->rota, 'Koha::StockRotationRota', "Fetched related rota." );
62     is( $srstage->rota->rota_id, $rota->{rota_id}, "Related rota OK." );
63
64     $schema->storage->txn_rollback;
65 };
66
67 subtest 'DBIx::Class::Ordered tests' => sub {
68     plan tests => 33;
69
70     $schema->storage->txn_begin;
71
72     my $library = $builder->build({ source => 'Branch' });
73     my $rota = $builder->build({ source => 'Stockrotationrota' });
74     my $stagefirst = $builder->build({
75         source   => 'Stockrotationstage',
76         value    => { rota_id  => $rota->{rota_id}, position => 1 }
77     });
78     my $stageprevious = $builder->build({
79         source   => 'Stockrotationstage',
80         value    => { rota_id  => $rota->{rota_id}, position => 2 }
81     });
82     my $stage = $builder->build({
83         source => 'Stockrotationstage',
84         value  => { rota_id => $rota->{rota_id}, position => 3 },
85     });
86     my $stagenext = $builder->build({
87         source   => 'Stockrotationstage',
88         value    => { rota_id  => $rota->{rota_id}, position => 4 }
89     });
90     my $stagelast = $builder->build({
91         source   => 'Stockrotationstage',
92         value    => { rota_id  => $rota->{rota_id}, position => 5 }
93     });
94
95     my $srstage = Koha::StockRotationStages->find($stage->{stage_id});
96
97     is($srstage->siblings->count, 4, "Siblings works.");
98     is($srstage->previous_siblings->count, 2, "Previous Siblings works.");
99     is($srstage->next_siblings->count, 2, "Next Siblings works.");
100
101     my $map = {
102         first_sibling    => $stagefirst,
103         previous_sibling => $stageprevious,
104         next_sibling     => $stagenext,
105         last_sibling     => $stagelast,
106     };
107     # Test plain relations:
108     while ( my ( $srxsr, $check ) = each %{$map} ) {
109         my $sr = $srstage->$srxsr;
110         isa_ok($sr, 'Koha::StockRotationStage', "Fetched using '$srxsr'.");
111         is($sr->stage_id, $check->{stage_id}, "'$srxsr' data is correct.");
112     };
113
114     # Test mutators
115     ## Move Previous
116     ok($srstage->move_previous, "Previous.");
117     is($srstage->previous_sibling->stage_id, $stagefirst->{stage_id}, "Previous, correct previous.");
118     is($srstage->next_sibling->stage_id, $stageprevious->{stage_id}, "Previous, correct next.");
119     ## Move Next
120     ok($srstage->move_next, "Back to middle.");
121     is($srstage->previous_sibling->stage_id, $stageprevious->{stage_id}, "Middle, correct previous.");
122     is($srstage->next_sibling->stage_id, $stagenext->{stage_id}, "Middle, correct next.");
123     ## Move First
124     ok($srstage->move_first, "First.");
125     is($srstage->previous_sibling, 0, "First, correct previous.");
126     is($srstage->next_sibling->stage_id, $stagefirst->{stage_id}, "First, correct next.");
127     ## Move Last
128     ok($srstage->move_last, "Last.");
129     is($srstage->previous_sibling->stage_id, $stagelast->{stage_id}, "Last, correct previous.");
130     is($srstage->next_sibling, 0, "Last, correct next.");
131     ## Move To
132
133     ### Out of range moves.
134     is(
135         $srstage->move_to($srstage->siblings->count + 2),
136         0, "Move above count of stages."
137     );
138     is($srstage->move_to(0), 0, "Move to 0th position.");
139     is($srstage->move_to(-1), 0, "Move to negative position.");
140
141     ### Move To
142     ok($srstage->move_to(3), "Move.");
143     is($srstage->previous_sibling->stage_id, $stageprevious->{stage_id}, "Move, correct previous.");
144     is($srstage->next_sibling->stage_id, $stagenext->{stage_id}, "Move, correct next.");
145
146     # Group manipulation
147     my $newrota = $builder->build({ source => 'Stockrotationrota' });
148     ok($srstage->move_to_group($newrota->{rota_id}), "Move to Group.");
149     is(Koha::StockRotationStages->find($srstage->stage_id)->rota_id, $newrota->{rota_id}, "Moved correctly.");
150
151     # Delete in ordered context
152     ok($srstage->delete, "Deleted OK.");
153     is(
154         Koha::StockRotationStages->find($stageprevious)->next_sibling->stage_id,
155         $stagenext->{stage_id},
156         "Delete, correctly re-ordered."
157     );
158
159     $schema->storage->txn_rollback;
160 };
161
162 subtest 'Relationship to stockrotationitems' => sub {
163     plan tests => 2;
164
165     $schema->storage->txn_begin;
166     my $stage = $builder->build({ source => 'Stockrotationstage' });
167
168     $builder->build(
169         {
170             source => 'Stockrotationitem',
171             value  => {
172                 stage_id      => $stage->{stage_id},
173                 itemnumber_id => $builder->build_sample_item->itemnumber
174             },
175         }
176     );
177     $builder->build(
178         {
179             source => 'Stockrotationitem',
180             value  => {
181                 stage_id      => $stage->{stage_id},
182                 itemnumber_id => $builder->build_sample_item->itemnumber
183             },
184         }
185     );
186     $builder->build(
187         {
188             source => 'Stockrotationitem',
189             value  => {
190                 stage_id      => $stage->{stage_id},
191                 itemnumber_id => $builder->build_sample_item->itemnumber
192             },
193         }
194     );
195
196     my $srstage = Koha::StockRotationStages->find($stage->{stage_id});
197     my $sritems = $srstage->stockrotationitems;
198     is(
199         $sritems->count, 3,
200         'Correctly fetched stockrotationitems associated with this stage'
201     );
202
203     isa_ok(
204         $sritems->next, 'Koha::StockRotationItem',
205         "Relationship correctly creates Koha::Objects."
206     );
207
208     $schema->storage->txn_rollback;
209 };
210
211
212 subtest 'Tests for investigate (singular)' => sub {
213
214     plan tests => 3;
215
216     # In this subtest series we will primarily be testing whether items end up
217     # in the correct 'branched' section of the stage-report.  We don't care
218     # for item reasons here, as they are tested in StockRotationItems.
219
220     # We will run tests on first on an empty report (the base-case) and then
221     # on a populated report.
222
223     # We will need:
224     # - Libraries which will hold the Items
225     # - Rota Which containing the related stages
226     #   + Stages on which we run investigate
227     #     * Items on the stages
228
229     $schema->storage->txn_begin;
230
231     # Libraries
232     my $library1 = $builder->build({ source => 'Branch' });
233     my $library2 = $builder->build({ source => 'Branch' });
234     my $library3 = $builder->build({ source => 'Branch' });
235
236     my $stage1lib = $builder->build({ source => 'Branch' });
237     my $stage2lib = $builder->build({ source => 'Branch' });
238     my $stage3lib = $builder->build({ source => 'Branch' });
239     my $stage4lib = $builder->build({ source => 'Branch' });
240
241     my $libraries = [ $library1, $library2, $library3, $stage1lib, $stage2lib,
242                       $stage3lib, $stage4lib ];
243
244     # Rota
245     my $rota = $builder->build({
246         source => 'Stockrotationrota',
247         value  => { cyclical => 0 },
248     });
249
250     # Stages
251     my $stage1 = $builder->build({
252         source => 'Stockrotationstage',
253         value  => {
254             rota_id => $rota->{rota_id},
255             branchcode_id => $stage1lib->{branchcode},
256             duration => 10,
257             position => 1,
258         },
259     });
260     my $stage2 = $builder->build({
261         source => 'Stockrotationstage',
262         value  => {
263             rota_id => $rota->{rota_id},
264             branchcode_id => $stage2lib->{branchcode},
265             duration => 20,
266             position => 2,
267         },
268     });
269     my $stage3 = $builder->build({
270         source => 'Stockrotationstage',
271         value  => {
272             rota_id => $rota->{rota_id},
273             branchcode_id => $stage3lib->{branchcode},
274             duration => 10,
275             position => 3,
276         },
277     });
278     my $stage4 = $builder->build({
279         source => 'Stockrotationstage',
280         value  => {
281             rota_id => $rota->{rota_id},
282             branchcode_id => $stage4lib->{branchcode},
283             duration => 20,
284             position => 4,
285         },
286     });
287
288     # Test on an empty report.
289     my $spec =  {
290         $library1->{branchcode} => 1,
291         $library2->{branchcode} => 1,
292         $library3->{branchcode} => 1,
293         $stage1lib->{branchcode} => 2,
294         $stage2lib->{branchcode} => 1,
295         $stage3lib->{branchcode} => 3,
296         $stage4lib->{branchcode} => 4
297     };
298     while ( my ( $code, $count ) = each %{$spec} ) {
299         my $cnt = 0;
300         while ( $cnt < $count ) {
301             my $item = $builder->build(
302                 {
303                     source => 'Stockrotationitem',
304                     value  => {
305                         stage_id      => $stage1->{stage_id},
306                         indemand      => 0,
307                         fresh         => 1,
308                         itemnumber_id => $builder->build_sample_item->itemnumber
309                     }
310                 }
311             );
312             my $dbitem = Koha::StockRotationItems->find($item);
313             $dbitem->itemnumber->homebranch($code)
314                 ->holdingbranch($code)->store;
315             $cnt++;
316         }
317     }
318     my $report = Koha::StockRotationStages
319         ->find($stage1->{stage_id})->investigate;
320     my $results = [];
321     foreach my $lib ( @{$libraries} ) {
322         my $items = $report->{branched}->{$lib->{branchcode}}->{items} || [];
323         push @{$results},
324             scalar @{$items};
325     }
326
327     # Items assigned to stag1lib -> log, hence $results[4] = 0;
328     is_deeply( $results, [ 1, 1, 1, 2, 1, 3, 4 ], "Empty report test 1.");
329
330     # Now we test by adding the next stage's items to the same report.
331     $spec =  {
332         $library1->{branchcode} => 3,
333         $library2->{branchcode} => 2,
334         $library3->{branchcode} => 1,
335         $stage1lib->{branchcode} => 4,
336         $stage2lib->{branchcode} => 2,
337         $stage3lib->{branchcode} => 0,
338         $stage4lib->{branchcode} => 3
339     };
340     while ( my ( $code, $count ) = each %{$spec} ) {
341         my $cnt = 0;
342         while ( $cnt < $count ) {
343             my $item = $builder->build(
344                 {
345                     source => 'Stockrotationitem',
346                     value  => {
347                         stage_id      => $stage2->{stage_id},
348                         indemand      => 0,
349                         fresh         => 1,
350                         itemnumber_id => $builder->build_sample_item->itemnumber
351                     }
352                 }
353             );
354             my $dbitem = Koha::StockRotationItems->find($item);
355             $dbitem->itemnumber->homebranch($code)
356                 ->holdingbranch($code)->store;
357             $cnt++;
358         }
359     }
360
361     $report = Koha::StockRotationStages
362         ->find($stage2->{stage_id})->investigate($report);
363     $results = [];
364     foreach my $lib ( @{$libraries} ) {
365         my $items = $report->{branched}->{$lib->{branchcode}}->{items} || [];
366         push @{$results},
367             scalar @{$items};
368     }
369     is_deeply( $results, [ 4, 3, 2, 6, 3, 3, 7 ], "full report test.");
370
371     # Carry out db updates
372     foreach my $item (@{$report->{items}}) {
373         my $reason = $item->{reason};
374         if ( $reason eq 'repatriation' ) {
375             $item->{object}->repatriate;
376         } elsif ( grep { $reason eq $_ }
377                       qw/in-demand advancement initiation/ ) {
378             $item->{object}->advance;
379         }
380     }
381
382     $report = Koha::StockRotationStages
383         ->find($stage1->{stage_id})->investigate;
384     $results = [];
385     foreach my $lib ( @{$libraries} ) {
386         my $items = $report->{branched}->{$lib->{branchcode}}->{items} || [];
387         push @{$results},
388             scalar @{$items};
389     }
390     # All items have been 'initiated', which means they are either happily in
391     # transit or happily at the library they are supposed to be.  Either way
392     # they will register as 'not-ready' in the stock rotation report.
393     is_deeply( $results, [ 0, 0, 0, 0, 0, 0, 0 ], "All items now in logs.");
394
395     $schema->storage->txn_rollback;
396 };
397
398 1;