Bug 19532: (follow-up) aria-hidden attr on OPAC, and more
[koha.git] / t / db_dependent / Koha / Charges / Fees.t
1 #!/usr/bin/perl
2 #
3 # Copyright 2018 ByWater Solutions
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 => 8;
23 use Test::Exception;
24 use Test::Warn;
25
26 use t::lib::Mocks;
27 use t::lib::TestBuilder;
28 use t::lib::Dates;
29
30 use Time::Fake;
31 use C4::Calendar qw( new insert_week_day_holiday delete_holiday );
32 use Koha::DateUtils qw(dt_from_string);
33
34 BEGIN {
35     use_ok('Koha::Charges::Fees');
36 }
37
38 my $schema  = Koha::Database->new->schema;
39 my $builder = t::lib::TestBuilder->new();
40 $schema->storage->txn_begin;
41
42 my $patron_category = $builder->build_object(
43     {
44         class => 'Koha::Patron::Categories',
45         value => {
46             category_type => 'P',
47             enrolmentfee  => 0,
48         }
49     }
50 );
51 my $library = $builder->build_object(
52     {
53         class => 'Koha::Libraries',
54     }
55 );
56 my $biblio = $builder->build_object(
57     {
58         class => 'Koha::Biblios',
59     }
60 );
61 my $itemtype = $builder->build_object(
62     {
63         class => 'Koha::ItemTypes',
64         value => {
65             rentalcharge_daily           => '0.00',
66             rentalcharge_daily_calendar  => 1,
67             rentalcharge_hourly          => '0.00',
68             rentalcharge_hourly_calendar => 1,
69             rentalcharge                 => '0.00',
70             processfee                   => '0.00',
71             defaultreplacecost           => '0.00',
72           },
73     }
74 );
75 my $item = $builder->build_object(
76     {
77         class => 'Koha::Items',
78         value => {
79             biblionumber  => $biblio->id,
80             homebranch    => $library->id,
81             holdingbranch => $library->id,
82             itype         => $itemtype->id,
83         }
84     }
85 );
86 my $patron = $builder->build_object(
87     {
88         class => 'Koha::Patrons',
89         value => {
90             dateexpiry   => '9999-12-31',
91             categorycode => $patron_category->id,
92         }
93     }
94 );
95
96 my $now = dt_from_string()->set_time_zone('floating');
97 Time::Fake->offset( $now->epoch );
98
99 my $dt_from = $now->clone->subtract( days => 2 );
100 my $dt_to = $now->clone->add( days => 4 );
101
102 subtest 'new' => sub {
103     plan tests => 9;
104
105     # Mandatory parameters missing
106     throws_ok {
107         Koha::Charges::Fees->new(
108             {
109                 library => $library,
110                 item    => $item,
111                 to_date => $dt_to,
112             }
113           )
114     }
115     'Koha::Exceptions::MissingParameter', 'MissingParameter thrown for patron';
116     throws_ok {
117         Koha::Charges::Fees->new(
118             {
119                 patron  => $patron,
120                 item    => $item,
121                 to_date => $dt_to,
122             }
123           )
124     }
125     'Koha::Exceptions::MissingParameter', 'MissingParameter thrown for library';
126     throws_ok {
127         Koha::Charges::Fees->new(
128             {
129                 patron  => $patron,
130                 library => $library,
131                 to_date => $dt_to,
132             }
133           )
134     }
135     'Koha::Exceptions::MissingParameter', 'MissingParameter thrown for item';
136     throws_ok {
137         Koha::Charges::Fees->new(
138             {
139                 patron  => $patron,
140                 library => $library,
141                 item    => $item,
142             }
143           )
144     }
145     'Koha::Exceptions::MissingParameter', 'MissingParameter thrown for to_date';
146
147     # Mandatory parameter bad
148     dies_ok {
149         Koha::Charges::Fees->new(
150             {
151                 patron  => '12345',
152                 library => $library,
153                 item    => $item,
154                 to_date => $dt_to,
155             }
156           )
157     }
158     'dies for bad patron';
159     dies_ok {
160         Koha::Charges::Fees->new(
161             {
162                 patron  => $patron,
163                 library => '12345',
164                 item    => $item,
165                 to_date => $dt_to,
166             }
167           )
168     }
169     'dies for bad library';
170     dies_ok {
171         Koha::Charges::Fees->new(
172             {
173                 patron  => $patron,
174                 library => $library,
175                 item    => '12345',
176                 to_date => $dt_to,
177             }
178           )
179     }
180     'dies for bad item';
181     dies_ok {
182         Koha::Charges::Fees->new(
183             {
184                 patron  => $patron,
185                 library => $library,
186                 item    => $item,
187                 to_date => 12345
188             }
189           )
190     }
191     'dies for bad to_date';
192
193     # Defaults
194     my $fees = Koha::Charges::Fees->new(
195         {
196             patron  => $patron,
197             library => $library,
198             item    => $item,
199             to_date => $dt_to,
200         }
201     );
202     is( t::lib::Dates::compare($fees->from_date, dt_from_string()), 0,
203         'from_date default set correctly to today' );
204 };
205
206 subtest 'patron accessor' => sub {
207     plan tests => 2;
208
209     my $fees = Koha::Charges::Fees->new(
210         {
211             patron  => $patron,
212             library => $library,
213             item    => $item,
214             to_date => $dt_to,
215         }
216     );
217
218     ok(
219         $fees->patron->isa('Koha::Patron'),
220         'patron accessor returns a Koha::Patron'
221     );
222     warning_is { $fees->patron('12345') }
223     { carped =>
224 "Setting 'patron' to something other than a Koha::Patron is not supported!"
225     }, "Warning thrown when attempting to set patron to string";
226
227 };
228
229 subtest 'library accessor' => sub {
230     plan tests => 2;
231
232     my $fees = Koha::Charges::Fees->new(
233         {
234             patron  => $patron,
235             library => $library,
236             item    => $item,
237             to_date => $dt_to,
238         }
239     );
240
241     ok(
242         $fees->library->isa('Koha::Library'),
243         'library accessor returns a Koha::Library'
244     );
245     warning_is { $fees->library('12345') }
246     { carped =>
247 "Setting 'library' to something other than a Koha::Library is not supported!"
248     }, "Warning thrown when attempting to set library to string";
249 };
250
251 subtest 'item accessor' => sub {
252     plan tests => 2;
253
254     my $fees = Koha::Charges::Fees->new(
255         {
256             patron  => $patron,
257             library => $library,
258             item    => $item,
259             to_date => $dt_to,
260         }
261     );
262
263     ok( $fees->item->isa('Koha::Item'), 'item accessor returns a Koha::Item' );
264     warning_is { $fees->item('12345') }
265     { carped =>
266 "Setting 'item' to something other than a Koha::Item is not supported!"
267     }, "Warning thrown when attempting to set item to string";
268 };
269
270 subtest 'to_date accessor' => sub {
271     plan tests => 2;
272
273     my $fees = Koha::Charges::Fees->new(
274         {
275             patron  => $patron,
276             library => $library,
277             item    => $item,
278             to_date => $dt_to,
279         }
280     );
281
282     ok( $fees->to_date->isa('DateTime'),
283         'to_date accessor returns a DateTime' );
284     warning_is { $fees->to_date(12345) }
285     { carped =>
286 "Setting 'to_date' to something other than a DateTime is not supported!"
287     }, "Warning thrown when attempting to set to_date to integer";
288 };
289
290 subtest 'from_date accessor' => sub {
291     plan tests => 2;
292
293     my $fees = Koha::Charges::Fees->new(
294         {
295             patron  => $patron,
296             library => $library,
297             item    => $item,
298             to_date => $dt_to,
299         }
300     );
301
302     ok(
303         $fees->from_date->isa('DateTime'),
304         'from_date accessor returns a DateTime'
305     );
306     warning_is { $fees->from_date(12345) }
307     { carped =>
308 "Setting 'from_date' to something other than a DateTime is not supported!"
309     }, "Warning thrown when attempting to set from_date to integer";
310 };
311
312 subtest 'accumulate_rentalcharge tests' => sub {
313     plan tests => 9;
314
315     my $fees = Koha::Charges::Fees->new(
316         {
317             patron    => $patron,
318             library   => $library,
319             item      => $item,
320             to_date   => $dt_to,
321             from_date => $dt_from,
322         }
323     );
324
325     # Daily tests
326     Koha::CirculationRules->set_rules({
327             categorycode => $patron->categorycode,
328             itemtype     => $itemtype->id,
329             branchcode   => $library->id,
330             rules => {
331                 lengthunit => 'days',
332             }
333         }
334     );
335
336     $itemtype->rentalcharge_daily(1.00);
337     $itemtype->store();
338     is( $itemtype->rentalcharge_daily,
339         1.00, 'Daily return charge stored correctly' );
340
341     t::lib::Mocks::mock_preference( 'finesCalendar', 'ignoreCalendar' );
342     my $charge = $fees->accumulate_rentalcharge();
343     is( $charge, 6.00,
344 'Daily rental charge calculated correctly with finesCalendar = ignoreCalendar'
345     );
346
347     t::lib::Mocks::mock_preference( 'finesCalendar', 'noFinesWhenClosed' );
348     $charge = $fees->accumulate_rentalcharge();
349     is( $charge, 6.00,
350 'Daily rental charge calculated correctly with finesCalendar = noFinesWhenClosed'
351     );
352
353     $itemtype->rentalcharge_daily_calendar(0)->store();
354     $charge = $fees->accumulate_rentalcharge();
355     is( $charge, 6.00,
356 'Daily rental charge calculated correctly with finesCalendar = noFinesWhenClosed and rentalcharge_daily_calendar = 0'
357     );
358     $itemtype->rentalcharge_daily_calendar(1)->store();
359
360     my $calendar = C4::Calendar->new( branchcode => $library->id );
361     # DateTime 1..7 (Mon..Sun), C4::Calender 0..6 (Sun..Sat)
362     my $closed_day =
363         ( $dt_from->day_of_week == 6 ) ? 0
364       : ( $dt_from->day_of_week == 7 ) ? 1
365       :                                  $dt_from->day_of_week + 1;
366     $calendar->insert_week_day_holiday(
367         weekday     => $closed_day,
368         title       => 'Test holiday',
369         description => 'Test holiday'
370     );
371     $charge = $fees->accumulate_rentalcharge();
372     my $day_names = {
373         0 => 'Sunday',
374         1 => 'Monday',
375         2 => 'Tuesday',
376         3 => 'Wednesday',
377         4 => 'Thursday',
378         5 => 'Friday',
379         6 => 'Saturday'
380     };
381     my $dayname = $day_names->{$closed_day};
382     is( $charge, 5.00,
383 "Daily rental charge calculated correctly with finesCalendar = noFinesWhenClosed and closed $dayname"
384     );
385
386     # Hourly tests
387     Koha::CirculationRules->set_rules({
388             categorycode => $patron->categorycode,
389             itemtype     => $itemtype->id,
390             branchcode   => $library->id,
391             rules => {
392                 lengthunit => 'hours',
393             }
394         }
395
396     );
397
398     $itemtype->rentalcharge_hourly("0.25");
399     $itemtype->store();
400
401     $dt_to   = $dt_from->clone->add( hours => 96 );
402     $fees    = Koha::Charges::Fees->new(
403         {
404             patron    => $patron,
405             library   => $library,
406             item      => $item,
407             to_date   => $dt_to,
408             from_date => $dt_from,
409         }
410     );
411
412     $itemtype->rentalcharge_hourly_calendar(0)->store();
413     $charge = $fees->accumulate_rentalcharge();
414     is( $charge, 24.00, 'Hourly rental charge calculated correctly (96h * 0.25u)' );
415
416     $itemtype->rentalcharge_hourly_calendar(1)->store();
417     $charge = $fees->accumulate_rentalcharge();
418     is( $charge, 18.00,
419 "Hourly rental charge calculated correctly with finesCalendar = noFinesWhenClosed and closed $dayname (96h - 24h * 0.25u)"
420     );
421
422     $itemtype->rentalcharge_hourly_calendar(0)->store();
423     $charge = $fees->accumulate_rentalcharge();
424     is( $charge, 24.00,
425 "Hourly rental charge calculated correctly with finesCalendar = noFinesWhenClosed and closed $dayname (96h - 24h * 0.25u) and rentalcharge_hourly_calendar = 0"
426     );
427
428     $itemtype->rentalcharge_hourly_calendar(1)->store();
429     $calendar->delete_holiday( weekday => $closed_day );
430     $charge = $fees->accumulate_rentalcharge();
431     is( $charge, 24.00, 'Hourly rental charge calculated correctly with finesCalendar = noFinesWhenClosed (96h - 0h * 0.25u)' );
432 };
433
434 $schema->storage->txn_rollback;
435 Time::Fake->reset;