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