Bug 22679: Delete related CirculationRules when Removing IssuingRule
[koha-equinox.git] / t / db_dependent / Koha / IssuingRules.t
1 #!/usr/bin/perl
2
3 # Copyright 2016 Koha-Suomi Oy
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 Test::More tests => 4;
23
24 use Benchmark;
25
26 use Koha::IssuingRules;
27 use Koha::CirculationRules;
28
29 use t::lib::TestBuilder;
30 use t::lib::Mocks;
31
32 my $schema = Koha::Database->new->schema;
33 $schema->storage->txn_begin;
34
35 my $builder      = t::lib::TestBuilder->new;
36
37 subtest 'get_effective_issuing_rule' => sub {
38     plan tests => 3;
39
40     my $patron       = $builder->build({ source => 'Borrower' });
41     my $item     = $builder->build({ source => 'Item' });
42
43     my $categorycode = $patron->{'categorycode'};
44     my $itemtype     = $item->{'itype'};
45     my $branchcode   = $item->{'homebranch'};
46
47     subtest 'Call with undefined values' => sub {
48         plan tests => 4;
49
50         my $rule;
51         Koha::IssuingRules->delete;
52
53         is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
54         $rule = Koha::IssuingRules->get_effective_issuing_rule({
55             branchcode   => undef,
56             categorycode => undef,
57             itemtype     => undef,
58         });
59         is($rule, undef, 'When I attempt to get effective issuing rule by'
60            .' providing undefined values, then undef is returned.');
61         ok(Koha::IssuingRule->new({
62             branchcode => '*',
63             categorycode => '*',
64             itemtype => '*',
65         })->store, 'Given I added an issuing rule branchcode => *,'
66            .' categorycode => *, itemtype => *,');
67         $rule = Koha::IssuingRules->get_effective_issuing_rule({
68             branchcode   => undef,
69             categorycode => undef,
70             itemtype     => undef,
71         });
72         ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
73            .' issuing rule by providing undefined values, then the above one is'
74            .' returned.');
75     };
76
77     subtest 'Get effective issuing rule in correct order' => sub {
78         plan tests => 18;
79
80         my $rule;
81         Koha::IssuingRules->delete;
82         is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
83         $rule = Koha::IssuingRules->get_effective_issuing_rule({
84             branchcode   => $branchcode,
85             categorycode => $categorycode,
86             itemtype     => $itemtype,
87         });
88         is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
89                         .' is returned.');
90
91         ok(Koha::IssuingRule->new({
92             branchcode => '*',
93             categorycode => '*',
94             itemtype => '*',
95         })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
96         $rule = Koha::IssuingRules->get_effective_issuing_rule({
97             branchcode   => $branchcode,
98             categorycode => $categorycode,
99             itemtype     => $itemtype,
100         });
101         ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
102            .' then the above one is returned.');
103
104         ok(Koha::IssuingRule->new({
105             branchcode => '*',
106             categorycode => '*',
107             itemtype => $itemtype,
108         })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
109         $rule = Koha::IssuingRules->get_effective_issuing_rule({
110             branchcode   => $branchcode,
111             categorycode => $categorycode,
112             itemtype     => $itemtype,
113         });
114         ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
115            .' then the above one is returned.');
116
117         ok(Koha::IssuingRule->new({
118             branchcode => '*',
119             categorycode => $categorycode,
120             itemtype => '*',
121         })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
122         $rule = Koha::IssuingRules->get_effective_issuing_rule({
123             branchcode   => $branchcode,
124             categorycode => $categorycode,
125             itemtype     => $itemtype,
126         });
127         ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
128            .' then the above one is returned.');
129
130         ok(Koha::IssuingRule->new({
131             branchcode => '*',
132             categorycode => $categorycode,
133             itemtype => $itemtype,
134         })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
135         $rule = Koha::IssuingRules->get_effective_issuing_rule({
136             branchcode   => $branchcode,
137             categorycode => $categorycode,
138             itemtype     => $itemtype,
139         });
140         ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
141            .' then the above one is returned.');
142
143         ok(Koha::IssuingRule->new({
144             branchcode => $branchcode,
145             categorycode => '*',
146             itemtype => '*',
147         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
148         $rule = Koha::IssuingRules->get_effective_issuing_rule({
149             branchcode   => $branchcode,
150             categorycode => $categorycode,
151             itemtype     => $itemtype,
152         });
153         ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
154            .' then the above one is returned.');
155
156         ok(Koha::IssuingRule->new({
157             branchcode => $branchcode,
158             categorycode => '*',
159             itemtype => $itemtype,
160         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
161         $rule = Koha::IssuingRules->get_effective_issuing_rule({
162             branchcode   => $branchcode,
163             categorycode => $categorycode,
164             itemtype     => $itemtype,
165         });
166         ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
167            .' then the above one is returned.');
168
169         ok(Koha::IssuingRule->new({
170             branchcode => $branchcode,
171             categorycode => $categorycode,
172             itemtype => '*',
173         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
174         $rule = Koha::IssuingRules->get_effective_issuing_rule({
175             branchcode   => $branchcode,
176             categorycode => $categorycode,
177             itemtype     => $itemtype,
178         });
179         ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
180            .' then the above one is returned.');
181
182         ok(Koha::IssuingRule->new({
183             branchcode => $branchcode,
184             categorycode => $categorycode,
185             itemtype => $itemtype,
186         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
187         $rule = Koha::IssuingRules->get_effective_issuing_rule({
188             branchcode   => $branchcode,
189             categorycode => $categorycode,
190             itemtype     => $itemtype,
191         });
192         ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
193            .' then the above one is returned.');
194     };
195
196     subtest 'Performance' => sub {
197         plan tests => 4;
198
199         my $worst_case = timethis(500,
200                     sub { Koha::IssuingRules->get_effective_issuing_rule({
201                             branchcode   => 'nonexistent',
202                             categorycode => 'nonexistent',
203                             itemtype     => 'nonexistent',
204                         });
205                     }
206                 );
207         my $mid_case = timethis(500,
208                     sub { Koha::IssuingRules->get_effective_issuing_rule({
209                             branchcode   => $branchcode,
210                             categorycode => 'nonexistent',
211                             itemtype     => 'nonexistent',
212                         });
213                     }
214                 );
215         my $sec_best_case = timethis(500,
216                     sub { Koha::IssuingRules->get_effective_issuing_rule({
217                             branchcode   => $branchcode,
218                             categorycode => $categorycode,
219                             itemtype     => 'nonexistent',
220                         });
221                     }
222                 );
223         my $best_case = timethis(500,
224                     sub { Koha::IssuingRules->get_effective_issuing_rule({
225                             branchcode   => $branchcode,
226                             categorycode => $categorycode,
227                             itemtype     => $itemtype,
228                         });
229                     }
230                 );
231         ok($worst_case, 'In worst case, get_effective_issuing_rule finds matching'
232            .' rule '.sprintf('%.2f', $worst_case->iters/$worst_case->cpu_a)
233            .' times per second.');
234         ok($mid_case, 'In mid case, get_effective_issuing_rule finds matching'
235            .' rule '.sprintf('%.2f', $mid_case->iters/$mid_case->cpu_a)
236            .' times per second.');
237         ok($sec_best_case, 'In second best case, get_effective_issuing_rule finds matching'
238            .' rule '.sprintf('%.2f', $sec_best_case->iters/$sec_best_case->cpu_a)
239            .' times per second.');
240         ok($best_case, 'In best case, get_effective_issuing_rule finds matching'
241            .' rule '.sprintf('%.2f', $best_case->iters/$best_case->cpu_a)
242            .' times per second.');
243     };
244 };
245
246 subtest 'get_opacitemholds_policy' => sub {
247     plan tests => 4;
248     my $itype = $builder->build_object({ class => 'Koha::ItemTypes' });
249     my $itemtype = $builder->build_object({ class => 'Koha::ItemTypes' });
250     my $library = $builder->build_object({ class => 'Koha::Libraries' });
251     my $patron = $builder->build_object({ class => 'Koha::Patrons' });
252     my $biblio = $builder->build_object({ class => 'Koha::Biblios' });
253     my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems', value => { itemtype => $itemtype->itemtype, biblionumber => $biblio->biblionumber } } );
254     my $item = $builder->build_object(
255         {   class  => 'Koha::Items',
256             value  => {
257                 homebranch    => $library->branchcode,
258                 holdingbranch => $library->branchcode,
259                 notforloan    => 0,
260                 itemlost      => 0,
261                 withdrawn     => 0,
262                 biblionumber  => $biblio->biblionumber,
263                 biblioitemnumber => $biblioitem->biblioitemnumber,
264                 itype         => $itype->itemtype,
265             }
266         }
267     );
268
269     Koha::IssuingRules->delete;
270     Koha::IssuingRule->new({categorycode => '*', itemtype => '*',                 branchcode => '*', opacitemholds => "N"})->store;
271     Koha::IssuingRule->new({categorycode => '*', itemtype => $itype->itemtype,    branchcode => '*', opacitemholds => "Y"})->store;
272     Koha::IssuingRule->new({categorycode => '*', itemtype => $itemtype->itemtype, branchcode => '*', opacitemholds => "N"})->store;
273     t::lib::Mocks::mock_preference('item-level_itypes', 1);
274     my $opacitemholds = Koha::IssuingRules->get_opacitemholds_policy( { item => $item, patron => $patron } );
275     is ( $opacitemholds, 'Y', 'Patrons can place a hold on this itype');
276     t::lib::Mocks::mock_preference('item-level_itypes', 0);
277     $opacitemholds = Koha::IssuingRules->get_opacitemholds_policy( { item => $item, patron => $patron } );
278     is ( $opacitemholds, 'N', 'Patrons cannot place a hold on this itemtype');
279
280     Koha::IssuingRules->delete;
281     Koha::IssuingRule->new({categorycode => '*', itemtype => '*',                 branchcode => '*', opacitemholds => "N"})->store;
282     Koha::IssuingRule->new({categorycode => '*', itemtype => $itype->itemtype,    branchcode => '*', opacitemholds => "N"})->store;
283     Koha::IssuingRule->new({categorycode => '*', itemtype => $itemtype->itemtype, branchcode => '*', opacitemholds => "Y"})->store;
284     t::lib::Mocks::mock_preference('item-level_itypes', 1);
285     $opacitemholds = Koha::IssuingRules->get_opacitemholds_policy( { item => $item, patron => $patron } );
286     is ( $opacitemholds, 'N', 'Patrons cannot place a hold on this itype');
287     t::lib::Mocks::mock_preference('item-level_itypes', 0);
288     $opacitemholds = Koha::IssuingRules->get_opacitemholds_policy( { item => $item, patron => $patron } );
289     is ( $opacitemholds, 'Y', 'Patrons can place a hold on this itemtype');
290
291     $patron->delete;
292 };
293
294 subtest 'get_onshelfholds_policy' => sub {
295     plan tests => 3;
296
297     t::lib::Mocks::mock_preference('item-level_itypes', 1);
298     Koha::IssuingRules->delete;
299
300     my $patron = $builder->build_object({ class => 'Koha::Patrons' });
301     my $item = $builder->build_object({ class => 'Koha::Items' });
302
303     is( Koha::IssuingRules->get_onshelfholds_policy({ item => $item, patron => $patron }), undef, 'Should return undef when no rules can be found' );
304     Koha::IssuingRule->new({ categorycode => $patron->categorycode, itemtype => $item->itype, branchcode => '*', onshelfholds => "0" })->store;
305     is( Koha::IssuingRules->get_onshelfholds_policy({ item => $item, patron => $patron }), 0, 'Should be zero' );
306     Koha::IssuingRule->new({ categorycode => $patron->categorycode, itemtype => $item->itype, branchcode => $item->holdingbranch, onshelfholds => "2" })->store;
307     is( Koha::IssuingRules->get_onshelfholds_policy({ item => $item, patron => $patron }), 2, 'Should be two now' );
308 };
309
310 subtest 'delete' => sub {
311     plan tests => 1;
312
313     my $itemtype = $builder->build_object({ class => 'Koha::ItemTypes' });
314     my $library  = $builder->build_object({ class => 'Koha::Libraries' });
315     my $category = $builder->build_object({ class => 'Koha::Patron::Categories' });
316
317     # We make an issuing rule
318     my $issue_rule = $builder->build_object({ class => 'Koha::IssuingRules', value => {
319             categorycode => $category->categorycode,
320             itemtype     => $itemtype->itemtype,
321             branchcode   => $library->branchcode
322         }
323     });
324
325     my $count = Koha::CirculationRules->search()->count;
326     # Note how many circulation rules we start with
327
328     # We make some circulation rules for the same thing
329     $builder->build_object({ class => 'Koha::CirculationRules', value => {
330             categorycode => $category->categorycode,
331             itemtype     => $itemtype->itemtype,
332             branchcode   => $library->branchcode
333         }
334     });
335     $builder->build_object({ class => 'Koha::CirculationRules', value => {
336             categorycode => $category->categorycode,
337             itemtype     => $itemtype->itemtype,
338             branchcode   => $library->branchcode
339         }
340     });
341
342     # Now we delete the issuing rule
343     $issue_rule->delete;
344     is( Koha::CirculationRules->search()->count ,$count, "We remove related circ rules with our issuing rule");
345
346 };
347
348 sub _row_match {
349     my ($rule, $branchcode, $categorycode, $itemtype) = @_;
350
351     return $rule->branchcode eq $branchcode && $rule->categorycode eq $categorycode
352             && $rule->itemtype eq $itemtype;
353 }
354
355 $schema->storage->txn_rollback;
356