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