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