Bug 30788: Unit test
[koha.git] / t / db_dependent / Circulation / CalcFine.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4
5 use Test::More tests => 5;
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 'Test with fine amount empty' => 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                          => '',
114                 lengthunit                    => 'days',
115                 finedays                      => 0,
116                 firstremind                   => 0,
117                 chargeperiod                  => 1,
118                 overduefinescap               => undef,
119                 cap_fine_to_replacement_price => 1,
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     warning_is {
137     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
138     }
139     undef, "No warning when fine amount is ''";
140
141     teardown();
142 };
143
144 subtest 'Test cap_fine_to_replacement_price' => sub {
145     plan tests => 2;
146
147     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
148     Koha::CirculationRules->set_rules(
149         {
150             branchcode   => undef,
151             categorycode => undef,
152             itemtype     => undef,
153             rules        => {
154                 fine                          => '1.00',
155                 lengthunit                    => 'days',
156                 finedays                      => 0,
157                 firstremind                   => 0,
158                 chargeperiod                  => 1,
159                 overduefinescap               => undef,
160                 cap_fine_to_replacement_price => 1,
161             },
162         }
163     );
164
165     my $start_dt = DateTime->new(
166         year       => 2000,
167         month      => 1,
168         day        => 1,
169     );
170
171     my $end_dt = DateTime->new(
172         year       => 2000,
173         month      => 1,
174         day        => 30,
175     );
176
177     my $item = $builder->build_sample_item(
178         {
179             library          => $branch->{branchcode},
180             replacementprice => 5,
181             itype            => $itemtype->{itemtype},
182         }
183     );
184
185     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
186
187     is( int($amount), 5, 'Amount is calculated correctly' );
188
189     # Use default replacement cost (useDefaultReplacementCost) is item's replacement price is 0
190     $item->replacementprice(0)->store;
191     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
192     is( int($amount), 6, 'Amount is calculated correctly' );
193
194     teardown();
195 };
196
197 subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub {
198     plan tests => 2;
199
200     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
201     Koha::CirculationRules->set_rules(
202         {
203             branchcode   => undef,
204             categorycode => undef,
205             itemtype     => undef,
206             rules        => {
207                 fine                          => '1.00',
208                 lengthunit                    => 'days',
209                 finedays                      => 0,
210                 firstremind                   => 0,
211                 chargeperiod                  => 1,
212                 overduefinescap               => 3,
213                 cap_fine_to_replacement_price => 1,
214             },
215         }
216     );
217
218     my $start_dt = DateTime->new(
219         year       => 2000,
220         month      => 1,
221         day        => 1,
222     );
223
224     my $end_dt = DateTime->new(
225         year       => 2000,
226         month      => 1,
227         day        => 30,
228     );
229
230     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
231     is( int($amount), 3, 'Got the lesser of overduefinescap and replacement price where overduefinescap < replacement price' );
232
233     Koha::CirculationRules->set_rule({ rule_name => 'overduefinescap', rule_value => 6, branchcode => undef, categorycode => undef, itemtype => undef });
234     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
235     is( int($amount), 5, 'Get the lesser of overduefinescap and replacement price where overduefinescap > replacement price' );
236
237     teardown();
238 };
239
240 subtest 'Recall overdue fines' => sub {
241     plan tests => 2;
242
243     Koha::CirculationRules->set_rules(
244         {
245             branchcode   => undef,
246             categorycode => undef,
247             itemtype     => undef,
248             rules        => {
249                 fine                          => '1.00',
250                 lengthunit                    => 'days',
251                 finedays                      => 0,
252                 firstremind                   => 0,
253                 chargeperiod                  => 1,
254                 recall_overdue_fine           => '5.00',
255             },
256         }
257     );
258
259     my $start_dt = DateTime->new(
260         year       => 2000,
261         month      => 1,
262         day        => 1,
263     );
264
265     my $end_dt = DateTime->new(
266         year       => 2000,
267         month      => 1,
268         day        => 6,
269     );
270
271     my $recall = Koha::Recall->new({
272         patron_id => $patron->{borrowernumber},
273         created_date => dt_from_string,
274         biblio_id => $item->biblionumber,
275         pickup_library_id => $branch->{branchcode},
276         item_id => $item->itemnumber,
277         expiration_date => undef,
278         item_level => 1
279     })->store;
280     $recall->set_overdue;
281
282     my ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
283     is( int($amount), 25, 'Use recall fine amount specified in circulation rules' );
284
285     $recall->set_fulfilled;
286     ($amount) = CalcFine( $item->unblessed, $patron->{categorycode}, $branch->{branchcode}, $start_dt, $end_dt );
287     is( int($amount), 5, 'With no recall, use normal fine amount' );
288
289
290     teardown();
291 };
292
293 sub teardown {
294     $dbh->do(q|DELETE FROM circulation_rules|);
295 }