Bug 25723: Update cache flushing calls
[koha-equinox.git] / t / db_dependent / Circulation / CalcDateDue.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4
5 use Test::More tests => 17;
6 use Test::MockModule;
7 use DBI;
8 use DateTime;
9 use t::lib::Mocks;
10 use t::lib::TestBuilder;
11 use C4::Calendar;
12
13 use Koha::CirculationRules;
14
15 use_ok('C4::Circulation');
16
17 my $schema = Koha::Database->new->schema;
18 $schema->storage->txn_begin;
19 my $builder = t::lib::TestBuilder->new;
20
21 my $categorycode = 'B';
22 my $itemtype = 'MX';
23 my $branchcode = 'FPL';
24 my $issuelength = 10;
25 my $renewalperiod = 5;
26 my $lengthunit = 'days';
27
28 Koha::CirculationRules->search()->delete();
29 Koha::CirculationRules->set_rules(
30     {
31         categorycode => $categorycode,
32         itemtype     => $itemtype,
33         branchcode   => $branchcode,
34         rules        => {
35             issuelength   => $issuelength,
36             renewalperiod => $renewalperiod,
37             lengthunit    => $lengthunit,
38         }
39     }
40 );
41
42 #Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
43 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
44 t::lib::Mocks::mock_preference('useDaysMode', 'Days');
45
46 my $cache = Koha::Caches->get_instance();
47 my $key   = $branchcode . "_holidays";
48 $cache->clear_from_cache($key);
49
50 my $dateexpiry = '2013-01-01';
51
52 my $borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
53 my $start_date = DateTime->new({year => 2013, month => 2, day => 9});
54 my $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
55 is($date, $dateexpiry . 'T23:59:00', 'date expiry');
56 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
57
58
59 #Set syspref ReturnBeforeExpiry = 1 and useDaysMode != 'Days'
60 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
61 t::lib::Mocks::mock_preference('useDaysMode', 'noDays');
62
63 $borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
64 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
65 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
66 is($date, $dateexpiry . 'T23:59:00', 'date expiry with useDaysMode to noDays');
67
68 # Let's add a special holiday on 2013-01-01. With ReturnBeforeExpiry and
69 # useDaysMode different from 'Days', return should forward the dateexpiry.
70 my $calendar = C4::Calendar->new(branchcode => $branchcode);
71 $calendar->insert_single_holiday(
72     day             => 1,
73     month           => 1,
74     year            => 2013,
75     title           =>'holidayTest',
76     description     => 'holidayDesc'
77 );
78 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
79 is($date, '2012-12-31T23:59:00', 'date expiry should be 2013-01-01 -1 day');
80 $calendar->insert_single_holiday(
81     day             => 31,
82     month           => 12,
83     year            => 2012,
84     title           =>'holidayTest',
85     description     => 'holidayDesc'
86 );
87 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
88 is($date, '2012-12-30T23:59:00', 'date expiry should be 2013-01-01 -2 day');
89
90
91 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
92
93
94 #Set syspref ReturnBeforeExpiry = 0 and useDaysMode = 'Days'
95 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 0);
96 t::lib::Mocks::mock_preference('useDaysMode', 'Days');
97
98 $borrower = {categorycode => 'B', dateexpiry => $dateexpiry};
99 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
100 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
101 is($date, '2013-02-' . (9 + $issuelength) . 'T23:59:00', "date expiry ( 9 + $issuelength )");
102
103 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
104 is($date, '2013-02-' . (9 + $renewalperiod) . 'T23:59:00', "date expiry ( 9 + $renewalperiod )");
105
106
107 # Now we want to test the Dayweek useDaysMode option
108 # For this we need a loan period that is a mutiple of 7 days
109 # But, since we currently don't have that, let's test it does the
110 # right thing in that case, it should act as though useDaysMode is set to
111 # Datedue
112 #Set syspref ReturnBeforeExpiry = 0 and useDaysMode = 'Dayweek'
113 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 0);
114 t::lib::Mocks::mock_preference('useDaysMode', 'Dayweek');
115
116 # No closed day interfering, so we should get the regular due date
117 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
118 is($date, '2013-02-' . (9 + $issuelength) . 'T23:59:00', "useDaysMode = Dayweek, no closed days, issue date expiry ( start + $issuelength )");
119
120 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
121 is($date, '2013-02-' . (9 + $renewalperiod) . 'T23:59:00', "useDaysMode = Dayweek, no closed days, renewal date expiry ( start + $renewalperiod )");
122
123 # Now let's add a closed day on the expected renewal date, it should
124 # roll forward as per Datedue (i.e. one day at a time)
125 # For issues...
126 $calendar->insert_single_holiday(
127     day             => 9 + $issuelength,
128     month           => 2,
129     year            => 2013,
130     title           =>'DayweekTest1',
131     description     => 'DayweekTest1'
132 );
133 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower );
134 is($date, '2013-02-' . (9 + $issuelength + 1) . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 10 day loan (should not trigger 7 day roll forward), issue date expiry ( start + $issuelength  + 1 )");
135 # Remove the holiday we just created
136 $calendar->delete_holiday(
137     day             => 9 + $issuelength,
138     month           => 2,
139     year            => 2013
140 );
141
142 # ...and for renewals...
143 $calendar->insert_single_holiday(
144     day             => 9 + $renewalperiod,
145     month           => 2,
146     year            => 2013,
147     title           =>'DayweekTest2',
148     description     => 'DayweekTest2'
149 );
150 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
151 is($date, '2013-02-' . (9 + $renewalperiod + 1) . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 5 day renewal (should not trigger 7 day roll forward), renewal date expiry ( start + $renewalperiod  + 1 )");
152 # Remove the holiday we just created
153 $calendar->delete_holiday(
154     day             => 9 + $renewalperiod,
155     month           => 2,
156     year            => 2013,
157 );
158
159 # Now we test it does the right thing if the loan and renewal periods
160 # are a multiple of 7 days
161 my $dayweek_categorycode = 'K';
162 my $dayweek_itemtype = 'MX';
163 my $dayweek_branchcode = 'FPL';
164 my $dayweek_issuelength = 14;
165 my $dayweek_renewalperiod = 7;
166 my $dayweek_lengthunit = 'days';
167
168 Koha::CirculationRules->set_rules(
169     {
170         categorycode => $dayweek_categorycode,
171         itemtype     => $dayweek_itemtype,
172         branchcode   => $dayweek_branchcode,
173         rules        => {
174             issuelength   => $dayweek_issuelength,
175             renewalperiod => $dayweek_renewalperiod,
176             lengthunit    => $dayweek_lengthunit,
177         }
178     }
179 );
180
181 my $dayweek_borrower = {categorycode => 'K', dateexpiry => $dateexpiry};
182
183 # For issues...
184 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
185 $calendar->insert_single_holiday(
186     day             => 9 + $dayweek_issuelength,
187     month           => 2,
188     year            => 2013,
189     title           =>'DayweekTest3',
190     description     => 'DayweekTest3'
191 );
192 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower );
193 my $issue_should_add = $dayweek_issuelength + 7;
194 my $dayweek_issue_expected = $start_date->add( days => $issue_should_add );
195 is($date, $dayweek_issue_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 14 day loan (should trigger 7 day roll forward), issue date expiry ( start + $issue_should_add )");
196 # Remove the holiday we just created
197 $calendar->delete_holiday(
198     day             => 9 + $dayweek_issuelength,
199     month           => 2,
200     year            => 2013,
201 );
202
203 # ...and for renewals...
204 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
205 $calendar->insert_single_holiday(
206     day             => 9 + $dayweek_renewalperiod,
207     month           => 2,
208     year            => 2013,
209     title           => 'DayweekTest4',
210     description     => 'DayweekTest4'
211 );
212 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower, 1 );
213 my $renewal_should_add = $dayweek_renewalperiod + 7;
214 my $dayweek_renewal_expected = $start_date->add( days => $renewal_should_add );
215 is($date, $dayweek_renewal_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date, 7 day renewal (should trigger 7 day roll forward), renewal date expiry ( start + $renewal_should_add )");
216 # Remove the holiday we just created
217 $calendar->delete_holiday(
218     day             => 9 + $dayweek_renewalperiod,
219     month           => 2,
220     year            => 2013,
221 );
222
223 # Now test it continues to roll forward by 7 days until it finds
224 # an open day, so we create a 3 week period of closed Saturdays
225 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
226 my $expected_rolled_date = DateTime->new({year => 2013, month => 3, day => 9});
227 my $holiday = $start_date->clone();
228 $holiday->add(days => 7);
229 $calendar->insert_single_holiday(
230     day             => $holiday->day,
231     month           => $holiday->month,
232     year            => 2013,
233     title           =>'DayweekTest5',
234     description     => 'DayweekTest5'
235 );
236 $holiday->add(days => 7);
237 $calendar->insert_single_holiday(
238     day             => $holiday->day,
239     month           => $holiday->month,
240     year            => 2013,
241     title           =>'DayweekTest6',
242     description     => 'DayweekTest6'
243 );
244 $holiday->add(days => 7);
245 $calendar->insert_single_holiday(
246     day             => $holiday->day,
247     month           => $holiday->month,
248     year            => 2013,
249     title           =>'DayweekTest7',
250     description     => 'DayweekTest7'
251 );
252 # For issues...
253 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower );
254 $dayweek_issue_expected = $start_date->add( days => $issue_should_add );
255 is($date, $expected_rolled_date->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date and two subequent due dates, 14 day loan (should trigger 2 x 7 day roll forward), issue date expiry ( start + 28 )");
256 # ...and for renewals...
257 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
258 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower, 1 );
259 $dayweek_issue_expected = $start_date->add( days => $renewal_should_add );
260 is($date, $expected_rolled_date->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, closed on due date and three subsequent due dates, 7 day renewal (should trigger 3 x 7 day roll forward), issue date expiry ( start + 28 )");
261 # Remove the holidays we just created
262 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
263 my $del_holiday = $start_date->clone();
264 $del_holiday->add(days => 7);
265 $calendar->delete_holiday(
266     day             => $del_holiday->day,
267     month           => $del_holiday->month,
268     year            => 2013
269 );
270 $del_holiday->add(days => 7);
271 $calendar->delete_holiday(
272     day             => $del_holiday->day,
273     month           => $del_holiday->month,
274     year            => 2013
275 );
276 $del_holiday->add(days => 7);
277 $calendar->delete_holiday(
278     day             => $del_holiday->day,
279     month           => $del_holiday->month,
280     year            => 2013
281 );
282
283 # Now test that useDaysMode "Dayweek" doesn't try to roll forward onto
284 # a permanently closed day and instead rolls forward just one day
285 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
286 # Our tests are concerned with Saturdays, so let's close on Saturdays
287 $calendar->insert_week_day_holiday(
288     weekday => 6,
289     title => "Saturday closure",
290     description => "Closed on Saturdays"
291 );
292 # For issues...
293 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower );
294 $dayweek_issue_expected = $start_date->add( days => $dayweek_issuelength + 1 );
295 is($date, $dayweek_issue_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, due on Saturday, closed on Saturdays, 14 day loan (should trigger 1 day roll forward), issue date expiry ( start + 15 )");
296 # ...and for renewals...
297 $start_date = DateTime->new({year => 2013, month => 2, day => 9});
298 $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $dayweek_borrower, 1 );
299 $dayweek_renewal_expected = $start_date->add( days => $dayweek_renewalperiod + 1 );
300 is($date, $dayweek_renewal_expected->strftime('%F') . 'T23:59:00', "useDaysMode = Dayweek, due on Saturday, closed on Saturdays, 7 day renewal (should trigger 1 day roll forward), issue date expiry ( start + 8 )");
301 # Remove the holiday we just created
302 $calendar->delete_holiday(
303     weekday => 6
304 );
305
306 $cache->clear_from_cache($key);
307 $schema->storage->txn_rollback;