Bug 15029: Make the IssueSlip tests pass even if launched after 23:00
[koha.git] / t / db_dependent / Members / IssueSlip.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4
5 use Test::More tests => 3;
6 use Test::MockModule;
7
8 use C4::Biblio;
9 use C4::Items;
10 use C4::Members;
11 use C4::Branch;
12 use C4::Category;
13 use C4::Circulation;
14
15 use Koha::DateUtils qw( dt_from_string output_pref );
16 use DateTime::Duration;
17
18 use MARC::Record;
19
20 my $dbh = C4::Context->dbh;
21 $dbh->{AutoCommit} = 0;
22 $dbh->{RaiseError} = 1;
23
24 $dbh->do(q|DELETE FROM issues|);
25 $dbh->do(q|DELETE FROM borrowers|);
26 $dbh->do(q|DELETE FROM items|);
27 $dbh->do(q|DELETE FROM branches|);
28 $dbh->do(q|DELETE FROM biblio|);
29 $dbh->do(q|DELETE FROM categories|);
30 $dbh->do(q|DELETE FROM letter|);
31
32 my $branchcode = 'B';
33 ModBranch( { add => 1, branchcode => $branchcode, branchname => 'Branch' } );
34
35 my $categorycode = 'C';
36 $dbh->do( "INSERT INTO categories(categorycode) VALUES(?)",
37     undef, $categorycode );
38
39 my %item_branch_infos = (
40     homebranch    => $branchcode,
41     holdingbranch => $branchcode,
42 );
43
44 my $slip_content = <<EOS;
45 Checked out:
46 <checkedout>
47 Title: <<biblio.title>>
48 Barcode: <<items.barcode>>
49 Date due: <<issues.date_due>>
50 </checkedout>
51
52 Overdues:
53 <overdue>
54 Title: <<biblio.title>>
55 Barcode: <<items.barcode>>
56 Date due: <<issues.date_due>>
57 </overdue>
58 EOS
59
60 $dbh->do(q|
61     INSERT INTO letter( module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('circulation', 'ISSUESLIP', '', 'Issue Slip', 0, 'Issue Slip', ?, 'email')
62 |, {}, $slip_content);
63
64 my $quick_slip_content = <<EOS;
65 Checked out today:
66 <checkedout>
67 Title: <<biblio.title>>
68 Barcode: <<items.barcode>>
69 Date due: <<issues.date_due>>
70 </checkedout>
71 EOS
72
73 $dbh->do(q|
74     INSERT INTO letter( module, code, branchcode, name, is_html, title, content, message_transport_type) VALUES ('circulation', 'ISSUEQSLIP', '', 'Issue Quick Slip', 0, 'Issue Quick Slip', ?, 'email')
75 |, {}, $quick_slip_content);
76
77 my ( $title1, $title2 ) = ( 'My title 1', 'My title 2' );
78 my ( $barcode1, $barcode2 ) = ('BC0101', 'BC0202' );
79 my $record = MARC::Record->new;
80 $record->append_fields(
81     MARC::Field->new(
82         245, '1', '4',
83             a => $title1,
84     ),
85 );
86 my ($biblionumber1) = AddBiblio( $record, '' );
87 my $itemnumber1 =
88   AddItem( { barcode => $barcode1, %item_branch_infos }, $biblionumber1 );
89
90 $record = MARC::Record->new;
91 $record->append_fields(
92     MARC::Field->new(
93         245, '1', '4',
94             a => $title2,
95     ),
96 );
97 my ($biblionumber2) = AddBiblio( $record, '' );
98 my $itemnumber2 =
99   AddItem( { barcode => $barcode2, %item_branch_infos }, $biblionumber2 );
100
101 my $borrowernumber =
102   AddMember( categorycode => $categorycode, branchcode => $branchcode );
103 my $borrower = GetMember( borrowernumber => $borrowernumber );
104
105 my $module = new Test::MockModule('C4::Context');
106 $module->mock( 'userenv', sub { { branch => $branchcode } } );
107
108 my $today = dt_from_string;
109 my $yesterday = dt_from_string->subtract_duration( DateTime::Duration->new( days => 1 ) );
110
111 subtest 'Issue slip' => sub {
112     plan tests => 3;
113
114     subtest 'Empty slip' => sub {
115         plan tests => 1;
116         my $slip = IssueSlip( $branchcode, $borrowernumber );
117         my $empty_slip = <<EOS;
118 Checked out:
119
120
121 Overdues:
122
123 EOS
124         is( $slip->{content}, $empty_slip, 'No checked out or overdues return an empty slip, it should return undef (FIXME)' );
125     };
126
127     subtest 'Daily loans' => sub {
128         plan tests => 2;
129         skip "It's 23:59!", 2 if $today->hour == 23 and $today->minute == 59;
130         # Test 1: No overdue
131         my $today_daily = $today->clone->set( hour => 23, minute => 59 );
132         my $today_daily_as_formatted = output_pref( $today_daily );
133         my $yesterday_daily = $yesterday->clone->set( hour => 23, minute => 59 );
134         my $yesterday_daily_as_formatted = output_pref( $yesterday_daily );
135
136         my ( $date_due, $issue_date, $slip, $expected_slip );
137         $date_due = $today_daily;
138         $issue_date = $today_daily->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
139         AddIssue( $borrower, $barcode1, $date_due, undef, $issue_date );
140         $date_due = $today_daily;
141         $issue_date = $yesterday_daily;
142         AddIssue( $borrower, $barcode2, $date_due, undef, $issue_date );
143
144         $expected_slip = <<EOS;
145 Checked out:
146
147 Title: $title1
148 Barcode: $barcode1
149 Date due: $today_daily_as_formatted
150
151
152 Title: $title2
153 Barcode: $barcode2
154 Date due: $today_daily_as_formatted
155
156
157 Overdues:
158
159 EOS
160         $slip = IssueSlip( $branchcode, $borrowernumber );
161         is( $slip->{content}, $expected_slip , 'IssueSlip should return a slip with 2 checkouts');
162
163         AddReturn( $barcode1, $branchcode );
164         AddReturn( $barcode2, $branchcode );
165
166         # Test 2: 1 Overdue
167         $date_due = $today_daily;
168         $issue_date = $today_daily->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
169         AddIssue( $borrower, $barcode1, $date_due, undef, $issue_date );
170         $date_due = $yesterday_daily;
171         $issue_date = $yesterday_daily;
172         AddIssue( $borrower, $barcode2, $date_due, undef, $issue_date );
173
174         $expected_slip = <<EOS;
175 Checked out:
176
177 Title: $title1
178 Barcode: $barcode1
179 Date due: $today_daily_as_formatted
180
181
182 Overdues:
183
184 Title: $title2
185 Barcode: $barcode2
186 Date due: $yesterday_daily_as_formatted
187
188 EOS
189         $slip = IssueSlip( $branchcode, $borrowernumber );
190         is( $slip->{content}, $expected_slip, 'IssueSlip should return a slip with 1 checkout and 1 overdue');
191
192         AddReturn( $barcode1, $branchcode );
193         AddReturn( $barcode2, $branchcode );
194     };
195
196     subtest 'Hourly loans' => sub {
197         plan tests => 2;
198         skip "It's 23:59!", 2 if $today->hour == 23 and $today->minute == 59;
199         # Test 1: No overdue
200         my ( $date_due_in_time, $date_due_in_time_as_formatted, $date_due_in_late, $date_due_in_late_as_formatted, $issue_date, $slip, $expected_slip );
201         # Assuming today is not hour = 23 and minute = 59
202         $date_due_in_time = $today->clone->set(hour => ($today->hour < 23 ? $today->hour + 1 : 23), minute => 59);
203         $date_due_in_time_as_formatted = output_pref( $date_due_in_time );
204         $issue_date = $date_due_in_time->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
205         AddIssue( $borrower, $barcode1, $date_due_in_time, undef, $issue_date );
206         $issue_date = $yesterday->clone;
207         AddIssue( $borrower, $barcode2, $date_due_in_time, undef, $issue_date );
208
209         $expected_slip = <<EOS;
210 Checked out:
211
212 Title: $title1
213 Barcode: $barcode1
214 Date due: $date_due_in_time_as_formatted
215
216
217 Title: $title2
218 Barcode: $barcode2
219 Date due: $date_due_in_time_as_formatted
220
221
222 Overdues:
223
224 EOS
225         $slip = IssueSlip( $branchcode, $borrowernumber );
226         is( $slip->{content}, $expected_slip, 'IssueSlip should return a slip with 2 checkouts' );
227
228         AddReturn( $barcode1, $branchcode );
229         AddReturn( $barcode2, $branchcode );
230
231         # Test 2: 1 Overdue
232         $date_due_in_time = $today->clone->set(hour => ($today->hour < 23 ? $today->hour + 1 : 23), minute => 59);
233         $date_due_in_time_as_formatted = output_pref( $date_due_in_time );
234         $issue_date = $date_due_in_time->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
235         AddIssue( $borrower, $barcode1, $date_due_in_time, undef, $issue_date );
236         $date_due_in_late = $today->clone->set(hour => $today->hour - 1);
237         $date_due_in_late_as_formatted = output_pref( $date_due_in_late );
238         $issue_date = $yesterday->clone;
239         AddIssue( $borrower, $barcode2, $date_due_in_late, undef, $issue_date );
240
241         $expected_slip = <<EOS;
242 Checked out:
243
244 Title: $title1
245 Barcode: $barcode1
246 Date due: $date_due_in_time_as_formatted
247
248
249 Overdues:
250
251 Title: $title2
252 Barcode: $barcode2
253 Date due: $date_due_in_late_as_formatted
254
255 EOS
256         $slip = IssueSlip( $branchcode, $borrowernumber );
257         is( $slip->{content}, $expected_slip, 'IssueSlip should return a slip with 1 checkout and 1 overdue' );
258
259         AddReturn( $barcode1, $branchcode );
260         AddReturn( $barcode2, $branchcode );
261     };
262
263 };
264
265 subtest 'Quick slip' => sub {
266     plan tests => 3;
267
268     subtest 'Empty slip' => sub {
269         plan tests => 1;
270         my $slip = IssueSlip( $branchcode, $borrowernumber, 'quick slip' );
271         my $empty_slip = <<EOS;
272 Checked out today:
273
274 EOS
275         is( $slip->{content}, $empty_slip, 'No checked out or overdues return an empty slip, it should return undef (FIXME)' );
276     };
277
278     subtest 'Daily loans' => sub {
279         plan tests => 2;
280         skip "It's 23:59!", 2 if $today->hour == 23 and $today->minute == 59;
281         # Test 1: No overdue
282         my $today_daily = $today->clone->set( hour => 23, minute => 59 );
283         my $today_daily_as_formatted = output_pref( $today_daily );
284         my $yesterday_daily = $yesterday->clone->set( hour => 23, minute => 59 );
285         my $yesterday_daily_as_formatted = output_pref( $yesterday_daily );
286
287         my ( $date_due, $issue_date, $slip, $expected_slip );
288         $date_due = $today_daily;
289         $issue_date = $today_daily->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
290         AddIssue( $borrower, $barcode1, $date_due, undef, $issue_date );
291         $date_due = $today_daily;
292         $issue_date = $yesterday_daily;
293         AddIssue( $borrower, $barcode2, $date_due, undef, $issue_date );
294
295         $expected_slip = <<EOS;
296 Checked out today:
297
298 Title: $title1
299 Barcode: $barcode1
300 Date due: $today_daily_as_formatted
301
302 EOS
303         $slip = IssueSlip( $branchcode, $borrowernumber, 'quick slip' );
304         is( $slip->{content}, $expected_slip, 'IssueSlip should return 2 checkouts for today');
305
306         AddReturn( $barcode1, $branchcode );
307         AddReturn( $barcode2, $branchcode );
308
309         # Test 2: 1 Overdue
310         $date_due = $today_daily;
311         $issue_date = $today_daily->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
312         AddIssue( $borrower, $barcode1, $date_due, undef, $issue_date );
313         $date_due = $yesterday_daily;
314         $issue_date = $yesterday_daily;
315         AddIssue( $borrower, $barcode2, $date_due, undef, $issue_date );
316
317         $expected_slip = <<EOS;
318 Checked out today:
319
320 Title: $title1
321 Barcode: $barcode1
322 Date due: $today_daily_as_formatted
323
324 EOS
325         $slip = IssueSlip( $branchcode, $borrowernumber, 'quickslip' );
326         is( $slip->{content}, $expected_slip );
327     };
328
329     subtest 'Hourly loans' => sub {
330         plan tests => 2;
331         # Test 1: No overdue
332         my ( $date_due_in_time, $date_due_in_time_as_formatted, $date_due_in_late, $date_due_in_late_as_formatted, $issue_date, $slip, $expected_slip );
333         # Assuming today is not hour = 23 and minute = 59
334         $date_due_in_time = $today->clone->set(hour => ($today->hour < 23 ? $today->hour + 1 : 23), minute => 59);
335         $date_due_in_time_as_formatted = output_pref( $date_due_in_time );
336         $issue_date = $date_due_in_time->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
337         AddIssue( $borrower, $barcode1, $date_due_in_time, undef, $issue_date );
338         $issue_date = $yesterday->clone;
339         AddIssue( $borrower, $barcode2, $date_due_in_time, undef, $issue_date );
340
341         $expected_slip = <<EOS;
342 Checked out today:
343
344 Title: $title1
345 Barcode: $barcode1
346 Date due: $date_due_in_time_as_formatted
347
348 EOS
349         $slip = IssueSlip( $branchcode, $borrowernumber, 'quickslip' );
350         is( $slip->{content}, $expected_slip );
351
352         AddReturn( $barcode1, $branchcode );
353         AddReturn( $barcode2, $branchcode );
354
355         # Test 2: 1 Overdue
356         $date_due_in_time = $today->clone->set(hour => ($today->hour < 23 ? $today->hour + 1 : 23), minute => 59);
357         $date_due_in_time_as_formatted = output_pref( $date_due_in_time );
358         $issue_date = $date_due_in_time->clone->subtract_duration( DateTime::Duration->new( minutes => 1 ) );
359         AddIssue( $borrower, $barcode1, $date_due_in_time, undef, $issue_date );
360         $date_due_in_late = $today->clone->set(hour => $today->hour - 1);
361         $date_due_in_late_as_formatted = output_pref( $date_due_in_late );
362         $issue_date = $yesterday->clone;
363         AddIssue( $borrower, $barcode2, $date_due_in_late, undef, $issue_date );
364
365         $expected_slip = <<EOS;
366 Checked out today:
367
368 Title: $title1
369 Barcode: $barcode1
370 Date due: $date_due_in_time_as_formatted
371
372 EOS
373         $slip = IssueSlip( $branchcode, $borrowernumber, 'quickslip' );
374         is( $slip->{content}, $expected_slip );
375
376         AddReturn( $barcode1, $branchcode );
377         AddReturn( $barcode2, $branchcode );
378     };
379
380 };
381
382 subtest 'bad calls' => sub {
383     plan tests => 2;
384     AddIssue( $borrower, $barcode1, $today, undef, $yesterday );
385     my $slip = IssueSlip();
386     isnt( $slip, undef, 'IssueSlip should return if no param passed FIXME, should return undef' );
387     my $empty_slip = <<EOS;
388 Checked out:
389
390
391 Overdues:
392
393 EOS
394
395     $slip = IssueSlip(undef, $borrowernumber+1);
396     is( $slip->{content}, $empty_slip, 'IssueSlip should not return an empty slip if the borrowernumber passed in param does not exist. But it is what it does for now (FIXME)' );
397 };