Bug 34279: Unit tests
[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 subtest 'Test with fine amount empty' => sub {
183     plan tests => 1;
184
185     Koha::CirculationRules->set_rules(
186         {
187             branchcode   => undef,
188             categorycode => undef,
189             itemtype     => undef,
190             rules        => {
191                 fine                          => '',
192                 lengthunit                    => 'days',
193                 finedays                      => 0,
194                 firstremind                   => 0,
195                 chargeperiod                  => 1,
196                 overduefinescap               => undef,
197                 cap_fine_to_replacement_price => 1,
198             },
199         }
200     );
201
202     my $start_dt = DateTime->new(
203         year       => 2000,
204         month      => 1,
205         day        => 1,
206     );
207
208     my $end_dt = DateTime->new(
209         year       => 2000,
210         month      => 1,
211         day        => 30,
212     );
213
214     warning_is {
215     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
216     }
217     undef, "No warning when fine amount is ''";
218
219     teardown();
220 };
221
222 subtest 'Test cap_fine_to_replacement_price' => sub {
223     plan tests => 2;
224
225     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
226     Koha::CirculationRules->set_rules(
227         {
228             branchcode   => undef,
229             categorycode => undef,
230             itemtype     => undef,
231             rules        => {
232                 fine                          => '1.00',
233                 lengthunit                    => 'days',
234                 finedays                      => 0,
235                 firstremind                   => 0,
236                 chargeperiod                  => 1,
237                 overduefinescap               => undef,
238                 cap_fine_to_replacement_price => 1,
239             },
240         }
241     );
242
243     my $start_dt = DateTime->new(
244         year       => 2000,
245         month      => 1,
246         day        => 1,
247     );
248
249     my $end_dt = DateTime->new(
250         year       => 2000,
251         month      => 1,
252         day        => 30,
253     );
254
255     my $item = $builder->build_sample_item(
256         {
257             library          => $branch->{branchcode},
258             replacementprice => 5,
259             itype            => $itemtype->{itemtype},
260         }
261     );
262
263     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
264
265     is( int($amount), 5, 'Amount is calculated correctly' );
266
267     # Use default replacement cost (useDefaultReplacementCost) is item's replacement price is 0
268     $item->replacementprice(0)->store;
269     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
270     is( int($amount), 6, 'Amount is calculated correctly' );
271
272     teardown();
273 };
274
275 subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub {
276     plan tests => 2;
277
278     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
279     Koha::CirculationRules->set_rules(
280         {
281             branchcode   => undef,
282             categorycode => undef,
283             itemtype     => undef,
284             rules        => {
285                 fine                          => '1.00',
286                 lengthunit                    => 'days',
287                 finedays                      => 0,
288                 firstremind                   => 0,
289                 chargeperiod                  => 1,
290                 overduefinescap               => 3,
291                 cap_fine_to_replacement_price => 1,
292             },
293         }
294     );
295
296     my $start_dt = DateTime->new(
297         year       => 2000,
298         month      => 1,
299         day        => 1,
300     );
301
302     my $end_dt = DateTime->new(
303         year       => 2000,
304         month      => 1,
305         day        => 30,
306     );
307
308     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
309     is( int($amount), 3, 'Got the lesser of overduefinescap and replacement price where overduefinescap < replacement price' );
310
311     Koha::CirculationRules->set_rule({ rule_name => 'overduefinescap', rule_value => 6, branchcode => undef, categorycode => undef, itemtype => undef });
312     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
313     is( int($amount), 5, 'Get the lesser of overduefinescap and replacement price where overduefinescap > replacement price' );
314
315     teardown();
316 };
317
318 subtest 'Recall overdue fines' => sub {
319     plan tests => 2;
320
321     Koha::CirculationRules->set_rules(
322         {
323             branchcode   => undef,
324             categorycode => undef,
325             itemtype     => undef,
326             rules        => {
327                 fine                          => '1.00',
328                 lengthunit                    => 'days',
329                 finedays                      => 0,
330                 firstremind                   => 0,
331                 chargeperiod                  => 1,
332                 recall_overdue_fine           => '5.00',
333             },
334         }
335     );
336
337     my $start_dt = DateTime->new(
338         year       => 2000,
339         month      => 1,
340         day        => 1,
341     );
342
343     my $end_dt = DateTime->new(
344         year       => 2000,
345         month      => 1,
346         day        => 6,
347     );
348
349     my $recall = Koha::Recall->new({
350         patron_id => $patron->{borrowernumber},
351         created_date => dt_from_string,
352         biblio_id => $item->biblionumber,
353         pickup_library_id => $branch->{branchcode},
354         item_id => $item->itemnumber,
355         expiration_date => undef,
356         item_level => 1
357     })->store;
358     $recall->set_overdue;
359
360     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
361     is( int($amount), 25, 'Use recall fine amount specified in circulation rules' );
362
363     $recall->set_fulfilled;
364     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
365     is( int($amount), 5, 'With no recall, use normal fine amount' );
366
367
368     teardown();
369 };
370
371 sub teardown {
372     $dbh->do(q|DELETE FROM circulation_rules|);
373 }