Bug 15081: (followup) Make test files using TestBuilder handle their transactions
[koha.git] / t / db_dependent / Circulation / TooMany.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 under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, see <http://www.gnu.org/licenses>.
16
17 use Modern::Perl;
18 use Test::More tests => 6;
19 use C4::Context;
20
21 use C4::Biblio;
22 use C4::Members;
23 use C4::Branch;
24 use C4::Circulation;
25 use C4::Items;
26 use C4::Context;
27
28 use Koha::DateUtils qw( dt_from_string );
29 use Koha::Database;
30
31 use t::lib::TestBuilder;
32 use t::lib::Mocks;
33
34 my $schema = Koha::Database->new->schema;
35 $schema->storage->txn_begin;
36
37 our $dbh = C4::Context->dbh;
38
39 $dbh->do(q|DELETE FROM issues|);
40 $dbh->do(q|DELETE FROM items|);
41 $dbh->do(q|DELETE FROM borrowers|);
42 $dbh->do(q|DELETE FROM branches|);
43 $dbh->do(q|DELETE FROM categories|);
44 $dbh->do(q|DELETE FROM accountlines|);
45 $dbh->do(q|DELETE FROM itemtypes|);
46 $dbh->do(q|DELETE FROM branch_item_rules|);
47 $dbh->do(q|DELETE FROM branch_borrower_circ_rules|);
48 $dbh->do(q|DELETE FROM default_branch_circ_rules|);
49 $dbh->do(q|DELETE FROM default_circ_rules|);
50 $dbh->do(q|DELETE FROM default_branch_item_rules|);
51
52 my $builder = t::lib::TestBuilder->new();
53
54 my $branch = $builder->build({
55     source => 'Branch',
56 });
57
58 my $category = $builder->build({
59     source => 'Category',
60 });
61
62 my $patron = $builder->build({
63     source => 'Borrower',
64     value => {
65         categorycode => $category->{categorycode},
66         branchcode => $branch->{branchcode},
67     },
68 });
69
70 my $biblio = $builder->build({
71     source => 'Biblio',
72     value => {
73         branchcode => $branch->{branchcode},
74     },
75 });
76 my $item = $builder->build({
77     source => 'Item',
78     value => {
79         biblionumber => $biblio->{biblionumber},
80         homebranch => $branch->{branchcode},
81         holdingbranch => $branch->{branchcode},
82     },
83 });
84
85 C4::Context->_new_userenv ('DUMMY_SESSION_ID');
86 C4::Context->set_userenv($patron->{borrowernumber}, $patron->{userid}, 'usercnum', 'First name', 'Surname', $branch->{branchcode}, 'My Library', 0);
87
88 # TooMany return ($current_loan_count, $max_loans_allowed) or undef
89 # CO = Checkout
90 # OSCO: On-site checkout
91
92 subtest 'no rules exist' => sub {
93     plan tests => 2;
94     is(
95         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
96         undef,
97         'CO should be allowed, in any cases'
98     );
99     is(
100         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
101         undef,
102         'OSCO should be allowed, in any cases'
103     );
104 };
105
106 subtest '1 Issuingrule exist 0 0: no issue allowed' => sub {
107     plan tests => 4;
108     my $issuingrule = $builder->build({
109         source => 'Issuingrule',
110         value => {
111             branchcode         => $branch->{branchcode},
112             categorycode       => $category->{categorycode},
113             itemtype           => '*',
114             maxissueqty        => 0,
115             maxonsiteissueqty  => 0,
116         },
117     });
118     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
119     is_deeply(
120         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
121         {
122             reason => 'TOO_MANY_CHECKOUTS',
123             count => 0,
124             max_allowed => 0,
125         },
126         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
127     );
128     is_deeply(
129         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
130         {
131             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
132             count => 0,
133             max_allowed => 0,
134         },
135         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
136     );
137
138     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
139     is_deeply(
140         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
141         {
142             reason => 'TOO_MANY_CHECKOUTS',
143             count => 0,
144             max_allowed => 0,
145         },
146         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
147     );
148     is_deeply(
149         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
150         {
151             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
152             count => 0,
153             max_allowed => 0,
154         },
155         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
156     );
157
158     teardown();
159 };
160
161 subtest '1 Issuingrule exist 1 1: issue is allowed' => sub {
162     plan tests => 4;
163     my $issuingrule = $builder->build({
164         source => 'Issuingrule',
165         value => {
166             branchcode         => $branch->{branchcode},
167             categorycode       => $category->{categorycode},
168             itemtype           => '*',
169             maxissueqty        => 1,
170             maxonsiteissueqty  => 1,
171         },
172     });
173     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
174     is(
175         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
176         undef,
177         'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
178     );
179     is(
180         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
181         undef,
182         'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
183     );
184
185     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
186     is(
187         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
188         undef,
189         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
190     );
191     is(
192         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
193         undef,
194         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
195     );
196
197     teardown();
198 };
199
200 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed. Do a CO' => sub {
201     plan tests => 5;
202     my $issuingrule = $builder->build({
203         source => 'Issuingrule',
204         value => {
205             branchcode         => $branch->{branchcode},
206             categorycode       => $category->{categorycode},
207             itemtype           => '*',
208             maxissueqty        => 1,
209             maxonsiteissueqty  => 1,
210         },
211     });
212
213     my $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string() );
214     like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
215
216     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
217     is_deeply(
218         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
219         {
220             reason => 'TOO_MANY_CHECKOUTS',
221             count => 1,
222             max_allowed => 1,
223         },
224         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
225     );
226     is(
227         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
228         undef,
229         'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
230     );
231
232     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
233     is_deeply(
234         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
235         {
236             reason => 'TOO_MANY_CHECKOUTS',
237             count => 1,
238             max_allowed => 1,
239         },
240         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
241     );
242     is_deeply(
243         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
244         {
245             reason => 'TOO_MANY_CHECKOUTS',
246             count => 1,
247             max_allowed => 1,
248         },
249         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
250     );
251
252     teardown();
253 };
254
255 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed, Do a OSCO' => sub {
256     plan tests => 5;
257     my $issuingrule = $builder->build({
258         source => 'Issuingrule',
259         value => {
260             branchcode         => $branch->{branchcode},
261             categorycode       => $category->{categorycode},
262             itemtype           => '*',
263             maxissueqty        => 1,
264             maxonsiteissueqty  => 1,
265         },
266     });
267
268     my $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
269     like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
270
271     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
272     is(
273         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
274         undef,
275         'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
276     );
277     is_deeply(
278         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
279         {
280             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
281             count => 1,
282             max_allowed => 1,
283         },
284         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
285     );
286
287     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
288     is_deeply(
289         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
290         {
291             reason => 'TOO_MANY_CHECKOUTS',
292             count => 1,
293             max_allowed => 1,
294         },
295         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
296     );
297     is_deeply(
298         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
299         {
300             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
301             count => 1,
302             max_allowed => 1,
303         },
304         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
305     );
306
307     teardown();
308 };
309
310 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub {
311     # Note: the same test coul be done for
312     # DefaultBorrowerCircRule, DefaultBranchCircRule, DefaultBranchItemRule ans DefaultCircRule.pm
313
314     plan tests => 10;
315     my $issuingrule = $builder->build({
316         source => 'BranchBorrowerCircRule',
317         value => {
318             branchcode         => $branch->{branchcode},
319             categorycode       => $category->{categorycode},
320             maxissueqty        => 1,
321             maxonsiteissueqty  => 1,
322         },
323     });
324
325     my $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef );
326     like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
327
328     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
329     is_deeply(
330         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
331         {
332             reason => 'TOO_MANY_CHECKOUTS',
333             count => 1,
334             max_allowed => 1,
335         },
336         'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
337     );
338     is(
339         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
340         undef,
341         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
342     );
343
344     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
345     is_deeply(
346         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
347         {
348             reason => 'TOO_MANY_CHECKOUTS',
349             count => 1,
350             max_allowed => 1,
351         },
352         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
353     );
354     is_deeply(
355         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
356         {
357             reason => 'TOO_MANY_CHECKOUTS',
358             count => 1,
359             max_allowed => 1,
360         },
361         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
362     );
363
364     teardown();
365
366     $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
367     like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
368
369     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
370     is(
371         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
372         undef,
373         'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
374     );
375     is_deeply(
376         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
377         {
378             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
379             count => 1,
380             max_allowed => 1,
381         },
382         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
383     );
384
385     t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
386     is_deeply(
387         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item ),
388         {
389             reason => 'TOO_MANY_CHECKOUTS',
390             count => 1,
391             max_allowed => 1,
392         },
393         'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
394     );
395     is_deeply(
396         C4::Circulation::TooMany( $patron, $biblio->{biblionumber}, $item, { onsite_checkout => 1 } ),
397         {
398             reason => 'TOO_MANY_ONSITE_CHECKOUTS',
399             count => 1,
400             max_allowed => 1,
401         },
402         'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
403     );
404
405     teardown();
406 };
407
408 $schema->storage->txn_rollback;
409
410 sub teardown {
411     $dbh->do(q|DELETE FROM issues|);
412     $dbh->do(q|DELETE FROM issuingrules|);
413 }
414
415 1;