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