Bug 33237: (QA follow-up) Clarify tests and Mock
[koha.git] / t / db_dependent / Circulation / CalcFine.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4
5 use Test::More tests => 7;
6 use Test::Warn;
7
8 use C4::Context;
9 use C4::Overdues qw( CalcFine );
10
11 use Koha::DateUtils qw( dt_from_string );
12
13 use t::lib::TestBuilder;
14 use t::lib::Mocks;
15
16 my $schema = Koha::Database->schema;
17 $schema->storage->txn_begin;
18
19 our $dbh = C4::Context->dbh;
20 $dbh->do(q|DELETE FROM issues|);
21
22 t::lib::Mocks::mock_preference('item-level_itypes', '1');
23
24 my $builder = t::lib::TestBuilder->new();
25
26 my $branch = $builder->build(
27     {
28         source => 'Branch',
29     }
30 );
31
32 my $category = $builder->build(
33     {
34         source => 'Category',
35     }
36 );
37
38 my $patron = $builder->build(
39     {
40         source => 'Borrower',
41         value  => {
42             categorycode => $category->{categorycode},
43             branchcode   => $branch->{branchcode},
44         },
45     }
46 );
47
48 my $itemtype = $builder->build(
49     {
50         source => 'Itemtype',
51         value => {
52             defaultreplacecost => 6,
53         },
54     }
55 );
56
57 my $item = $builder->build_sample_item(
58     {
59         library          => $branch->{branchcode},
60         replacementprice => '5.00',
61         itype            => $itemtype->{itemtype},
62     }
63 );
64
65 subtest 'Test basic functionality' => sub {
66     plan tests => 1;
67
68     Koha::CirculationRules->set_rules(
69         {
70             branchcode   => undef,
71             categorycode => undef,
72             itemtype     => undef,
73             rules        => {
74                 fine                          => '1.00',
75                 lengthunit                    => 'days',
76                 finedays                      => 0,
77                 firstremind                   => 0,
78                 chargeperiod                  => 1,
79                 overduefinescap               => undef,
80                 cap_fine_to_replacement_price => 0,
81             }
82         },
83     );
84
85     my $start_dt = DateTime->new(
86         year       => 2000,
87         month      => 1,
88         day        => 1,
89     );
90
91     my $end_dt = DateTime->new(
92         year       => 2000,
93         month      => 1,
94         day        => 30,
95     );
96
97     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
98
99     is( $amount, 29, 'Amount is calculated correctly' );
100
101     teardown();
102 };
103
104 subtest 'Overdue fines cap should be disabled when value is 0' => sub {
105     plan tests => 1;
106
107     Koha::CirculationRules->set_rules(
108         {
109             branchcode   => undef,
110             categorycode => undef,
111             itemtype     => undef,
112             rules        => {
113                 fine                          => '1.00',
114                 lengthunit                    => 'days',
115                 finedays                      => 0,
116                 firstremind                   => 0,
117                 chargeperiod                  => 1,
118                 overduefinescap               => "0",
119                 cap_fine_to_replacement_price => 0,
120             }
121         },
122     );
123
124     my $start_dt = DateTime->new(
125         year  => 2000,
126         month => 1,
127         day   => 1,
128     );
129
130     my $end_dt = DateTime->new(
131         year  => 2000,
132         month => 1,
133         day   => 30,
134     );
135
136     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
137
138     is( $amount, 29, 'Amount is calculated correctly' );
139
140     teardown();
141 };
142
143 subtest 'Overdue fines cap should be disabled when value is 0.00' => sub {
144     plan tests => 1;
145
146     Koha::CirculationRules->set_rules(
147         {
148             branchcode   => undef,
149             categorycode => undef,
150             itemtype     => undef,
151             rules        => {
152                 fine                          => '1.00',
153                 lengthunit                    => 'days',
154                 finedays                      => 0,
155                 firstremind                   => 0,
156                 chargeperiod                  => 1,
157                 overduefinescap               => "0.00",
158                 cap_fine_to_replacement_price => 0,
159             }
160         },
161     );
162
163     my $start_dt = DateTime->new(
164         year  => 2000,
165         month => 1,
166         day   => 1,
167     );
168
169     my $end_dt = DateTime->new(
170         year  => 2000,
171         month => 1,
172         day   => 30,
173     );
174
175     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
176
177     is( $amount, 29, 'Amount is calculated correctly' );
178
179     teardown();
180 };
181
182
183 subtest 'Test with fine amount empty' => sub {
184     plan tests => 1;
185
186     Koha::CirculationRules->set_rules(
187         {
188             branchcode   => undef,
189             categorycode => undef,
190             itemtype     => undef,
191             rules        => {
192                 fine                          => '',
193                 lengthunit                    => 'days',
194                 finedays                      => 0,
195                 firstremind                   => 0,
196                 chargeperiod                  => 1,
197                 overduefinescap               => undef,
198                 cap_fine_to_replacement_price => 1,
199             },
200         }
201     );
202
203     my $start_dt = DateTime->new(
204         year       => 2000,
205         month      => 1,
206         day        => 1,
207     );
208
209     my $end_dt = DateTime->new(
210         year       => 2000,
211         month      => 1,
212         day        => 30,
213     );
214
215     warning_is {
216     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
217     }
218     undef, "No warning when fine amount is ''";
219
220     teardown();
221 };
222
223 subtest 'Test cap_fine_to_replacement_price' => sub {
224     plan tests => 2;
225
226     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
227     Koha::CirculationRules->set_rules(
228         {
229             branchcode   => undef,
230             categorycode => undef,
231             itemtype     => undef,
232             rules        => {
233                 fine                          => '1.00',
234                 lengthunit                    => 'days',
235                 finedays                      => 0,
236                 firstremind                   => 0,
237                 chargeperiod                  => 1,
238                 overduefinescap               => undef,
239                 cap_fine_to_replacement_price => 1,
240             },
241         }
242     );
243
244     my $start_dt = DateTime->new(
245         year       => 2000,
246         month      => 1,
247         day        => 1,
248     );
249
250     my $end_dt = DateTime->new(
251         year       => 2000,
252         month      => 1,
253         day        => 30,
254     );
255
256     my $item = $builder->build_sample_item(
257         {
258             library          => $branch->{branchcode},
259             replacementprice => 5,
260             itype            => $itemtype->{itemtype},
261         }
262     );
263
264     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
265
266     is( int($amount), 5, 'Amount is calculated correctly' );
267
268     # Use default replacement cost (useDefaultReplacementCost) is item's replacement price is 0
269     $item->replacementprice(0)->store;
270     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
271     is( int($amount), 6, 'Amount is calculated correctly' );
272
273     teardown();
274 };
275
276 subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub {
277     plan tests => 2;
278
279     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
280     Koha::CirculationRules->set_rules(
281         {
282             branchcode   => undef,
283             categorycode => undef,
284             itemtype     => undef,
285             rules        => {
286                 fine                          => '1.00',
287                 lengthunit                    => 'days',
288                 finedays                      => 0,
289                 firstremind                   => 0,
290                 chargeperiod                  => 1,
291                 overduefinescap               => 3,
292                 cap_fine_to_replacement_price => 1,
293             },
294         }
295     );
296
297     my $start_dt = DateTime->new(
298         year       => 2000,
299         month      => 1,
300         day        => 1,
301     );
302
303     my $end_dt = DateTime->new(
304         year       => 2000,
305         month      => 1,
306         day        => 30,
307     );
308
309     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
310     is( int($amount), 3, 'Got the lesser of overduefinescap and replacement price where overduefinescap < replacement price' );
311
312     Koha::CirculationRules->set_rule({ rule_name => 'overduefinescap', rule_value => 6, branchcode => undef, categorycode => undef, itemtype => undef });
313     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
314     is( int($amount), 5, 'Get the lesser of overduefinescap and replacement price where overduefinescap > replacement price' );
315
316     teardown();
317 };
318
319 subtest 'Recall overdue fines' => sub {
320     plan tests => 2;
321
322     Koha::CirculationRules->set_rules(
323         {
324             branchcode   => undef,
325             categorycode => undef,
326             itemtype     => undef,
327             rules        => {
328                 fine                          => '1.00',
329                 lengthunit                    => 'days',
330                 finedays                      => 0,
331                 firstremind                   => 0,
332                 chargeperiod                  => 1,
333                 recall_overdue_fine           => '5.00',
334             },
335         }
336     );
337
338     my $start_dt = DateTime->new(
339         year       => 2000,
340         month      => 1,
341         day        => 1,
342     );
343
344     my $end_dt = DateTime->new(
345         year       => 2000,
346         month      => 1,
347         day        => 6,
348     );
349
350     my $recall = Koha::Recall->new({
351         patron_id => $patron->{borrowernumber},
352         created_date => dt_from_string,
353         biblio_id => $item->biblionumber,
354         pickup_library_id => $branch->{branchcode},
355         item_id => $item->itemnumber,
356         expiration_date => undef,
357         item_level => 1
358     })->store;
359     $recall->set_overdue;
360
361     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
362     is( int($amount), 25, 'Use recall fine amount specified in circulation rules' );
363
364     $recall->set_fulfilled;
365     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
366     is( int($amount), 5, 'With no recall, use normal fine amount' );
367
368
369     teardown();
370 };
371
372 sub teardown {
373     $dbh->do(q|DELETE FROM circulation_rules|);
374 }