1473c235d70c5121929d602b7a5d844bde7b2a50
[koha-equinox.git] / t / db_dependent / Koha / CirculationRules.t
1 #!/usr/bin/perl
2
3 # Copyright 2020 Koha Development team
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 use Test::Exception;
24
25 use Koha::CirculationRules;
26 use Koha::Database;
27
28 use t::lib::Mocks;
29 use t::lib::TestBuilder;
30 use t::lib::Mocks;
31
32 my $schema = Koha::Database->new->schema;
33 my $builder = t::lib::TestBuilder->new;
34
35 subtest 'set_rule + get_effective_rule' => sub {
36     plan tests => 14;
37
38     $schema->storage->txn_begin;
39
40     my $categorycode = $builder->build_object( { class => 'Koha::Patron::Categories' } )->categorycode;
41     my $itemtype     = $builder->build_object( { class => 'Koha::ItemTypes' } )->itemtype;
42     my $branchcode   = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode;
43     my $branchcode_2 = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode;
44     my $rule_name    = 'maxissueqty';
45     my $default_rule_value = 1;
46
47     my $rule;
48     Koha::CirculationRules->delete;
49
50     throws_ok { Koha::CirculationRules->get_effective_rule }
51     'Koha::Exceptions::MissingParameter',
52     "Exception should be raised if get_effective_rule is called without rule_name parameter";
53
54     $rule = Koha::CirculationRules->get_effective_rule(
55         {
56             branchcode   => $branchcode,
57             categorycode => $categorycode,
58             itemtype     => $itemtype,
59             rule_name    => $rule_name,
60         }
61     );
62     is( $rule, undef, 'Undef should be returned if no rule exist' );
63
64     Koha::CirculationRules->set_rule(
65         {
66             branchcode   => '*',
67             categorycode => '*',
68             itemtype     => '*',
69             rule_name    => $rule_name,
70             rule_value   => $default_rule_value,
71         }
72     );
73
74     $rule = Koha::CirculationRules->get_effective_rule(
75         {
76             branchcode   => undef,
77             categorycode => undef,
78             itemtype     => undef,
79             rule_name    => $rule_name,
80         }
81     );
82     is( $rule->rule_value, $default_rule_value, 'undef means default' );
83     $rule = Koha::CirculationRules->get_effective_rule(
84         {
85             branchcode   => '*',
86             categorycode => '*',
87             itemtype     => '*',
88             rule_name    => $rule_name,
89         }
90     );
91
92     is( $rule->rule_value, $default_rule_value, '* means default' );
93
94     Koha::CirculationRules->set_rule(
95         {
96             branchcode   => '*',
97             categorycode => '*',
98             itemtype     => $itemtype,
99             rule_name    => $rule_name,
100             rule_value   => 2,
101         }
102     );
103
104     $rule = Koha::CirculationRules->get_effective_rule(
105         {
106             branchcode   => $branchcode,
107             categorycode => $categorycode,
108             itemtype     => $itemtype,
109             rule_name    => $rule_name,
110         }
111     );
112     is( $rule->rule_value, 2,
113         'More specific rule is returned when itemtype is given' );
114
115     $rule = Koha::CirculationRules->get_effective_rule(
116         {
117             branchcode   => $branchcode_2,
118             categorycode => '*',
119             itemtype     => '*',
120             rule_name    => $rule_name,
121         }
122     );
123     is( $rule->rule_value, 1,
124         'Default rule is returned if there is no rule for this branchcode' );
125
126     Koha::CirculationRules->set_rule(
127         {
128             branchcode   => '*',
129             categorycode => $categorycode,
130             itemtype     => '*',
131             rule_name    => $rule_name,
132             rule_value   => 3,
133         }
134     );
135
136     $rule = Koha::CirculationRules->get_effective_rule(
137         {
138
139             branchcode   => $branchcode,
140             categorycode => $categorycode,
141             itemtype     => $itemtype,
142             rule_name    => $rule_name,
143         }
144     );
145     is( $rule->rule_value, 3,
146         'More specific rule is returned when categorycode exists' );
147
148     Koha::CirculationRules->set_rule(
149         {
150             branchcode   => '*',
151             categorycode => $categorycode,
152             itemtype     => $itemtype,
153             rule_name    => $rule_name,
154             rule_value   => 4,
155         }
156     );
157     $rule = Koha::CirculationRules->get_effective_rule(
158         {
159             branchcode   => $branchcode,
160             categorycode => $categorycode,
161             itemtype     => $itemtype,
162             rule_name    => $rule_name,
163         }
164     );
165     is( $rule->rule_value, 4,
166         'More specific rule is returned when categorycode and itemtype exist' );
167
168     Koha::CirculationRules->set_rule(
169         {
170             branchcode   => $branchcode,
171             categorycode => '*',
172             itemtype     => '*',
173             rule_name    => $rule_name,
174             rule_value   => 5,
175         }
176     );
177     $rule = Koha::CirculationRules->get_effective_rule(
178         {
179             branchcode   => $branchcode,
180             categorycode => $categorycode,
181             itemtype     => $itemtype,
182             rule_name    => $rule_name,
183         }
184     );
185     is( $rule->rule_value, 5,
186         'More specific rule is returned when branchcode exists' );
187
188     Koha::CirculationRules->set_rule(
189         {
190             branchcode   => $branchcode,
191             categorycode => '*',
192             itemtype     => $itemtype,
193             rule_name    => $rule_name,
194             rule_value   => 6,
195         }
196     );
197     $rule = Koha::CirculationRules->get_effective_rule(
198         {
199             branchcode   => $branchcode,
200             categorycode => $categorycode,
201             itemtype     => $itemtype,
202             rule_name    => $rule_name,
203         }
204     );
205     is( $rule->rule_value, 6,
206         'More specific rule is returned when branchcode and itemtype exists' );
207
208     Koha::CirculationRules->set_rule(
209         {
210             branchcode   => $branchcode,
211             categorycode => $categorycode,
212             itemtype     => '*',
213             rule_name    => $rule_name,
214             rule_value   => 7,
215         }
216     );
217     $rule = Koha::CirculationRules->get_effective_rule(
218         {
219             branchcode   => $branchcode,
220             categorycode => $categorycode,
221             itemtype     => $itemtype,
222             rule_name    => $rule_name,
223         }
224     );
225     is( $rule->rule_value, 7,
226         'More specific rule is returned when branchcode and categorycode exist'
227     );
228
229     Koha::CirculationRules->set_rule(
230         {
231             branchcode   => $branchcode,
232             categorycode => $categorycode,
233             itemtype     => $itemtype,
234             rule_name    => $rule_name,
235             rule_value   => 8,
236         }
237     );
238     $rule = Koha::CirculationRules->get_effective_rule(
239         {
240             branchcode   => $branchcode,
241             categorycode => $categorycode,
242             itemtype     => $itemtype,
243             rule_name    => $rule_name,
244         }
245     );
246     is( $rule->rule_value, 8,
247         'More specific rule is returned when branchcode, categorycode and itemtype exist'
248     );
249
250     my $our_branch_rules = Koha::CirculationRules->search({branchcode => $branchcode});
251     is( $our_branch_rules->count, 4, "We added 8 rules");
252     $our_branch_rules->delete;
253     is( $our_branch_rules->count, 0, "We deleted 8 rules");
254
255     $schema->storage->txn_rollback;
256 };
257
258 subtest 'get_onshelfholds_policy() tests' => sub {
259
260     plan tests => 2;
261
262     $schema->storage->txn_begin;
263
264     my $item = $builder->build_sample_item();
265
266     my $circ_rules = Koha::CirculationRules->new;
267     # Cleanup
268     $circ_rules->search({ rule_name => 'onshelfholds' })->delete;
269
270     $circ_rules->set_rule(
271         {
272             branchcode   => '*',
273             categorycode => '*',
274             itemtype     => '*',
275             rule_name    => 'onshelfholds',
276             rule_value   => 1,
277         }
278     );
279
280     is( $circ_rules->get_onshelfholds_policy({ item => $item }), 1, 'If rule_value is set on a matching rule, return it' );
281     # Delete the rule (i.e. get_effective_rule returns undef)
282     $circ_rules->delete;
283     is( $circ_rules->get_onshelfholds_policy({ item => $item }), 0, 'If no matching rule, fallback to 0' );
284
285     $schema->storage->txn_rollback;
286 };
287
288 subtest 'get_effective_daysmode' => sub {
289     plan tests => 4;
290
291     $schema->storage->txn_begin;
292
293     my $item_1 = $builder->build_sample_item();
294     my $item_2 = $builder->build_sample_item();
295
296     my $circ_rules =
297       Koha::CirculationRules->search( { rule_name => 'daysmode' } )->delete;
298
299     # Default value 'Datedue' at pref level
300     t::lib::Mocks::mock_preference( 'useDaysMode', 'Datedue' );
301
302     is(
303         Koha::CirculationRules->get_effective_daysmode(
304             {
305                 categorycode => undef,
306                 itemtype     => $item_1->effective_itemtype,
307                 branchcode   => undef
308             }
309         ),
310         'Datedue',
311         'daysmode default to pref value if the rule does not exist'
312     );
313
314     Koha::CirculationRules->set_rule(
315         {
316             branchcode   => '*',
317             categorycode => '*',
318             itemtype     => '*',
319             rule_name    => 'daysmode',
320             rule_value   => 'Calendar',
321         }
322     );
323     Koha::CirculationRules->set_rule(
324         {
325             branchcode   => '*',
326             categorycode => '*',
327             itemtype     => $item_1->effective_itemtype,
328             rule_name    => 'daysmode',
329             rule_value   => 'Days',
330         }
331     );
332
333     is(
334         Koha::CirculationRules->get_effective_daysmode(
335             {
336                 categorycode => undef,
337                 itemtype     => $item_1->effective_itemtype,
338                 branchcode   => undef
339             }
340         ),
341         'Days',
342         "daysmode for item_1 is the specific rule"
343     );
344     is(
345         Koha::CirculationRules->get_effective_daysmode(
346             {
347                 categorycode => undef,
348                 itemtype     => $item_2->effective_itemtype,
349                 branchcode   => undef
350             }
351         ),
352         'Calendar',
353         "daysmode for item_2 is the one defined for the default circ rule"
354     );
355
356     Koha::CirculationRules->set_rule(
357         {
358             branchcode   => '*',
359             categorycode => '*',
360             itemtype     => $item_2->effective_itemtype,
361             rule_name    => 'daysmode',
362             rule_value   => '',
363         }
364     );
365
366     is(
367         Koha::CirculationRules->get_effective_daysmode(
368             {
369                 categorycode => undef,
370                 itemtype     => $item_2->effective_itemtype,
371                 branchcode   => undef
372             }
373         ),
374         'Datedue',
375         'daysmode default to pref value if the rule exists but set to""'
376     );
377
378     $schema->storage->txn_rollback;
379 };
380
381 subtest 'get_lostreturn_policy() tests' => sub {
382     plan tests => 6;
383
384     $schema->storage->txn_begin;
385
386     $schema->resultset('CirculationRule')->search()->delete;
387
388     my $default_rule = $builder->build(
389         {
390             source => 'CirculationRule',
391             value  => {
392                 branchcode   => undef,
393                 categorycode => undef,
394                 itemtype     => undef,
395                 rule_name    => 'refund',
396                 rule_value   => 1
397             }
398         }
399     );
400     my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
401     my $specific_rule_false = $builder->build(
402         {
403             source => 'CirculationRule',
404             value  => {
405                 branchcode   => $branchcode,
406                 categorycode => undef,
407                 itemtype     => undef,
408                 rule_name    => 'refund',
409                 rule_value   => 0
410             }
411         }
412     );
413     my $branchcode2 = $builder->build( { source => 'Branch' } )->{branchcode};
414     my $specific_rule_true = $builder->build(
415         {
416             source => 'CirculationRule',
417             value  => {
418                 branchcode   => $branchcode2,
419                 categorycode => undef,
420                 itemtype     => undef,
421                 rule_name    => 'refund',
422                 rule_value   => 1
423             }
424         }
425     );
426     # Make sure we have an unused branchcode
427     my $branchcode3 = $builder->build( { source => 'Branch' } )->{branchcode};
428     my $specific_rule_dummy = $builder->build(
429         {
430             source => 'CirculationRule',
431             value  => {
432                 branchcode   => $branchcode3,
433                 categorycode => undef,
434                 itemtype     => undef,
435                 rule_name    => 'refund',
436             }
437         }
438     );
439     my $branch_without_rule = $specific_rule_dummy->{ branchcode };
440     Koha::CirculationRules
441         ->search(
442             {
443                 branchcode   => $branch_without_rule,
444                 categorycode => undef,
445                 itemtype     => undef,
446                 rule_name    => 'refund'
447             }
448           )
449         ->next
450         ->delete;
451
452     my $item = $builder->build_sample_item(
453         {
454             homebranch    => $specific_rule_true->{branchcode},
455             holdingbranch => $specific_rule_false->{branchcode}
456         }
457     );
458     my $params = {
459         return_branch => $specific_rule_true->{ branchcode },
460         item          => $item
461     };
462
463     # Specific rules
464     t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
465     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
466           1,'Specific rule for checkin branch is applied (true)');
467
468     t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHomeBranch' );
469     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
470          1,'Specific rule for home branch is applied (true)');
471
472     t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHoldingBranch' );
473     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
474          0,'Specific rule for holoding branch is applied (false)');
475
476     # Default rule check
477     t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
478     $params->{return_branch} = $branch_without_rule;
479     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
480          1,'No rule for branch, global rule applied (true)');
481
482     # Change the default value just to try
483     Koha::CirculationRules->search({ branchcode => undef, rule_name => 'refund' })->next->rule_value(0)->store;
484     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
485          0,'No rule for branch, global rule applied (false)');
486
487     # No default rule defined check
488     Koha::CirculationRules
489         ->search(
490             {
491                 branchcode   => undef,
492                 categorycode => undef,
493                 itemtype     => undef,
494                 rule_name    => 'refund'
495             }
496           )
497         ->next
498         ->delete;
499     is( Koha::CirculationRules->get_lostreturn_policy( $params ),
500          1,'No rule for branch, no default rule, fallback default (true)');
501
502     $schema->storage->txn_rollback;
503 };