Bug 26922: Regression tests
[koha.git] / t / db_dependent / Circulation / TooMany.t
blobd1663d98a3b0466e7d258e6c55b79bade601eb73
1 #!/usr/bin/perl
3 # This file is part of Koha.
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.
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.
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>.
17 use Modern::Perl;
18 use Test::More tests => 10;
19 use C4::Context;
21 use C4::Members;
22 use C4::Items;
23 use C4::Biblio;
24 use C4::Circulation;
25 use C4::Context;
27 use Koha::DateUtils qw( dt_from_string );
28 use Koha::Database;
29 use Koha::CirculationRules;
31 use t::lib::TestBuilder;
32 use t::lib::Mocks;
34 my $schema = Koha::Database->new->schema;
35 $schema->storage->txn_begin;
37 our $dbh = C4::Context->dbh;
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 Koha::CirculationRules->search()->delete();
48 my $builder = t::lib::TestBuilder->new();
49 t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
51 my $branch = $builder->build({
52 source => 'Branch',
53 });
55 my $category = $builder->build({
56 source => 'Category',
57 });
59 my $patron = $builder->build({
60 source => 'Borrower',
61 value => {
62 categorycode => $category->{categorycode},
63 branchcode => $branch->{branchcode},
65 });
67 my $biblio = $builder->build_sample_biblio({ branchcode => $branch->{branchcode} });
68 my $item = $builder->build_sample_item({
69 biblionumber => $biblio->biblionumber,
70 homebranch => $branch->{branchcode},
71 holdingbranch => $branch->{branchcode},
72 });
74 my $patron_object = Koha::Patrons->find( $patron->{borrowernumber} );
75 t::lib::Mocks::mock_userenv( { patron => $patron_object });
77 # TooMany return ($current_loan_count, $max_loans_allowed) or undef
78 # CO = Checkout
79 # OSCO: On-site checkout
81 subtest 'no rules exist' => sub {
82 plan tests => 2;
83 is_deeply(
84 C4::Circulation::TooMany( $patron, $item ),
85 { reason => 'NO_RULE_DEFINED', max_allowed => 0 },
86 'CO should not be allowed, in any cases'
88 is_deeply(
89 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
90 { reason => 'NO_RULE_DEFINED', max_allowed => 0 },
91 'OSCO should not be allowed, in any cases'
95 subtest '1 Issuingrule exist 0 0: no issue allowed' => sub {
96 plan tests => 4;
97 Koha::CirculationRules->set_rules(
99 branchcode => $branch->{branchcode},
100 categorycode => $category->{categorycode},
101 itemtype => undef,
102 rules => {
103 maxissueqty => 0,
104 maxonsiteissueqty => 0,
108 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
109 is_deeply(
110 C4::Circulation::TooMany( $patron, $item ),
112 reason => 'TOO_MANY_CHECKOUTS',
113 count => 0,
114 max_allowed => 0,
116 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
118 is_deeply(
119 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
121 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
122 count => 0,
123 max_allowed => 0,
125 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
128 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
129 is_deeply(
130 C4::Circulation::TooMany( $patron, $item ),
132 reason => 'TOO_MANY_CHECKOUTS',
133 count => 0,
134 max_allowed => 0,
136 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
138 is_deeply(
139 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
141 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
142 count => 0,
143 max_allowed => 0,
145 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
148 teardown();
151 subtest '1 Issuingrule exist with onsiteissueqty=unlimited' => sub {
152 plan tests => 4;
154 Koha::CirculationRules->set_rules(
156 branchcode => $branch->{branchcode},
157 categorycode => $category->{categorycode},
158 itemtype => undef,
159 rules => {
160 maxissueqty => 1,
161 maxonsiteissueqty => undef,
166 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
167 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
168 is_deeply(
169 C4::Circulation::TooMany( $patron, $item ),
171 reason => 'TOO_MANY_CHECKOUTS',
172 count => 1,
173 max_allowed => 1,
175 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
178 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
179 undef,
180 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
183 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
184 is_deeply(
185 C4::Circulation::TooMany( $patron, $item ),
187 reason => 'TOO_MANY_CHECKOUTS',
188 count => 1,
189 max_allowed => 1,
191 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
193 is_deeply(
194 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
196 reason => 'TOO_MANY_CHECKOUTS',
197 count => 1,
198 max_allowed => 1,
200 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
203 teardown();
207 subtest '1 Issuingrule exist 1 1: issue is allowed' => sub {
208 plan tests => 4;
209 Koha::CirculationRules->set_rules(
211 branchcode => $branch->{branchcode},
212 categorycode => $category->{categorycode},
213 itemtype => undef,
214 rules => {
215 maxissueqty => 1,
216 maxonsiteissueqty => 1,
220 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
222 C4::Circulation::TooMany( $patron, $item ),
223 undef,
224 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
227 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
228 undef,
229 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
232 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
234 C4::Circulation::TooMany( $patron, $item ),
235 undef,
236 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
239 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
240 undef,
241 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
244 teardown();
247 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed. Do a CO' => sub {
248 plan tests => 5;
249 Koha::CirculationRules->set_rules(
251 branchcode => $branch->{branchcode},
252 categorycode => $category->{categorycode},
253 itemtype => undef,
254 rules => {
255 maxissueqty => 1,
256 maxonsiteissueqty => 1,
261 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
262 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
264 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
265 is_deeply(
266 C4::Circulation::TooMany( $patron, $item ),
268 reason => 'TOO_MANY_CHECKOUTS',
269 count => 1,
270 max_allowed => 1,
272 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
275 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
276 undef,
277 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
280 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
281 is_deeply(
282 C4::Circulation::TooMany( $patron, $item ),
284 reason => 'TOO_MANY_CHECKOUTS',
285 count => 1,
286 max_allowed => 1,
288 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
290 is_deeply(
291 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
293 reason => 'TOO_MANY_CHECKOUTS',
294 count => 1,
295 max_allowed => 1,
297 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
300 teardown();
303 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed, Do a OSCO' => sub {
304 plan tests => 5;
305 Koha::CirculationRules->set_rules(
307 branchcode => $branch->{branchcode},
308 categorycode => $category->{categorycode},
309 itemtype => undef,
310 rules => {
311 maxissueqty => 1,
312 maxonsiteissueqty => 1,
317 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
318 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
320 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
322 C4::Circulation::TooMany( $patron, $item ),
323 undef,
324 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
326 is_deeply(
327 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
329 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
330 count => 1,
331 max_allowed => 1,
333 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
336 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
337 is_deeply(
338 C4::Circulation::TooMany( $patron, $item ),
340 reason => 'TOO_MANY_CHECKOUTS',
341 count => 1,
342 max_allowed => 1,
344 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
346 is_deeply(
347 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
349 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
350 count => 1,
351 max_allowed => 1,
353 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
356 teardown();
359 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub {
360 # Note: the same test coul be done for
361 # DefaultBorrowerCircRule, DefaultBranchCircRule, DefaultBranchItemRule ans DefaultCircRule.pm
363 plan tests => 10;
364 Koha::CirculationRules->set_rules(
366 branchcode => $branch->{branchcode},
367 categorycode => $category->{categorycode},
368 itemtype => undef,
369 rules => {
370 maxissueqty => 1,
371 maxonsiteissueqty => 1,
376 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef );
377 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
379 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
380 is_deeply(
381 C4::Circulation::TooMany( $patron, $item ),
383 reason => 'TOO_MANY_CHECKOUTS',
384 count => 1,
385 max_allowed => 1,
387 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
390 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
391 undef,
392 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
395 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
396 is_deeply(
397 C4::Circulation::TooMany( $patron, $item ),
399 reason => 'TOO_MANY_CHECKOUTS',
400 count => 1,
401 max_allowed => 1,
403 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
405 is_deeply(
406 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
408 reason => 'TOO_MANY_CHECKOUTS',
409 count => 1,
410 max_allowed => 1,
412 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
415 teardown();
416 Koha::CirculationRules->set_rules(
418 branchcode => $branch->{branchcode},
419 categorycode => $category->{categorycode},
420 itemtype => undef,
421 rules => {
422 maxissueqty => 1,
423 maxonsiteissueqty => 1,
428 $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
429 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
431 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
433 C4::Circulation::TooMany( $patron, $item ),
434 undef,
435 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
437 is_deeply(
438 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
440 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
441 count => 1,
442 max_allowed => 1,
444 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
447 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
448 is_deeply(
449 C4::Circulation::TooMany( $patron, $item ),
451 reason => 'TOO_MANY_CHECKOUTS',
452 count => 1,
453 max_allowed => 1,
455 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
457 is_deeply(
458 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
460 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
461 count => 1,
462 max_allowed => 1,
464 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
467 teardown();
470 subtest 'General vs specific rules limit quantity correctly' => sub {
471 plan tests => 10;
473 t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary');
474 my $branch = $builder->build({source => 'Branch',});
475 my $category = $builder->build({source => 'Category',});
476 my $itemtype = $builder->build({
477 source => 'Itemtype',
478 value => {
479 rentalcharge => 0,
480 rentalcharge_daily => 0,
481 rentalcharge_hourly => 0,
482 notforloan => 0,
485 my $patron = $builder->build({
486 source => 'Borrower',
487 value => {
488 categorycode => $category->{categorycode},
489 branchcode => $branch->{branchcode},
493 # Set up an issuing rule
494 Koha::CirculationRules->set_rules(
496 categorycode => '*',
497 itemtype => $itemtype->{itemtype},
498 branchcode => '*',
499 rules => {
500 issuelength => 1,
501 firstremind => 1, # 1 day of grace
502 finedays => 2, # 2 days of fine per day of overdue
503 lengthunit => 'days',
508 # Set default maximum issue quantity limits for branch
509 Koha::CirculationRules->set_rules(
511 branchcode => $branch->{branchcode},
512 categorycode => '*',
513 rules => {
514 patron_maxissueqty => 1,
515 patron_maxonsiteissueqty => 1,
520 # Set an All->All for an itemtype
521 Koha::CirculationRules->set_rules(
523 branchcode => '*',
524 categorycode => '*',
525 itemtype => $itemtype->{itemtype},
526 rules => {
527 maxissueqty => 1,
528 maxonsiteissueqty => 1,
533 # Create an item
534 my $issue_item = $builder->build_sample_item({
535 itype => $itemtype->{itemtype}
537 my $branch_item = $builder->build_sample_item({
538 itype => $itemtype->{itemtype},
539 homebranch => $branch->{branchcode},
540 holdingbranch => $branch->{branchcode}
544 t::lib::Mocks::mock_userenv({ branchcode => $branch->{branchcode} });
545 my $issue = C4::Circulation::AddIssue( $patron, $issue_item->barcode, dt_from_string() );
546 # We checkout one item
547 is_deeply(
548 C4::Circulation::TooMany( $patron, $branch_item ),
550 reason => 'TOO_MANY_CHECKOUTS',
551 count => 1,
552 max_allowed => 1,
554 'We are only allowed one, and we have one (itemtype on item)'
557 # Check itemtype on biblio level
558 t::lib::Mocks::mock_preference('item-level_itypes', 0);
559 $issue_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
560 $branch_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
561 # We checkout one item
562 is_deeply(
563 C4::Circulation::TooMany( $patron, $branch_item ),
565 reason => 'TOO_MANY_CHECKOUTS',
566 count => 1,
567 max_allowed => 1,
569 'We are only allowed one, and we have one (itemtype on biblioitem)'
571 t::lib::Mocks::mock_preference('item-level_itypes', 1);
573 # Set a branch specific rule
574 Koha::CirculationRules->set_rules(
576 branchcode => $branch->{branchcode},
577 categorycode => $category->{categorycode},
578 itemtype => $itemtype->{itemtype},
579 rules => {
580 maxissueqty => 1,
581 maxonsiteissueqty => 1,
587 C4::Circulation::TooMany( $patron, $branch_item ),
588 undef,
589 'We are allowed one from the branch specifically now'
592 # If circcontrol is PatronLibrary we count all the patron's loan, regardless of branch
593 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
594 is_deeply(
595 C4::Circulation::TooMany( $patron, $branch_item ),
597 reason => 'TOO_MANY_CHECKOUTS',
598 count => 1,
599 max_allowed => 1,
601 'We are allowed one from the branch specifically, but have one'
603 t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary');
605 $issue = C4::Circulation::AddIssue( $patron, $branch_item->barcode, dt_from_string() );
606 # We issue that one
607 # And make another
608 my $branch_item_2 = $builder->build_sample_item({
609 itype => $itemtype->{itemtype},
610 homebranch => $branch->{branchcode},
611 holdingbranch => $branch->{branchcode}
613 is_deeply(
614 C4::Circulation::TooMany( $patron, $branch_item_2 ),
616 reason => 'TOO_MANY_CHECKOUTS',
617 count => 1,
618 max_allowed => 1,
620 'We are only allowed one from that branch, and have one'
623 # Now we make anothe from a different branch
624 my $item_2 = $builder->build_sample_item({
625 itype => $itemtype->{itemtype},
627 is_deeply(
628 C4::Circulation::TooMany( $patron, $item_2 ),
630 reason => 'TOO_MANY_CHECKOUTS',
631 count => 2,
632 max_allowed => 1,
634 'We are only allowed one for general rule, and have two'
636 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
637 is_deeply(
638 C4::Circulation::TooMany( $patron, $item_2 ),
640 reason => 'TOO_MANY_CHECKOUTS',
641 count => 2,
642 max_allowed => 1,
644 'We are only allowed one for general rule, and have two'
647 t::lib::Mocks::mock_preference('CircControl', 'PickupLibrary');
648 is_deeply(
649 C4::Circulation::TooMany( $patron, $item_2 ),
651 reason => 'TOO_MANY_CHECKOUTS',
652 count => 2,
653 max_allowed => 1,
655 'We are only allowed one for general rule, and have checked out two at this branch'
658 my $branch2 = $builder->build({source => 'Branch',});
659 t::lib::Mocks::mock_userenv({ branchcode => $branch2->{branchcode} });
660 is_deeply(
661 C4::Circulation::TooMany( $patron, $item_2 ),
663 reason => 'TOO_MANY_CHECKOUTS',
664 count => 2,
665 max_allowed => 1,
667 'We are only allowed one for general rule, and have two total (no rule for specific branch)'
669 # Set a branch specific rule for new branch
670 Koha::CirculationRules->set_rules(
672 branchcode => $branch2->{branchcode},
673 categorycode => $category->{categorycode},
674 itemtype => $itemtype->{itemtype},
675 rules => {
676 maxissueqty => 1,
677 maxonsiteissueqty => 1,
683 C4::Circulation::TooMany( $patron, $branch_item ),
684 undef,
685 'We are allowed one from the branch specifically now'
689 subtest 'empty string means unlimited' => sub {
690 plan tests => 2;
692 Koha::CirculationRules->set_rules(
694 branchcode => '*',
695 categorycode => '*',
696 itemtype => '*',
697 rules => {
698 maxissueqty => '',
699 maxonsiteissueqty => '',
704 C4::Circulation::TooMany( $patron, $item ),
705 undef,
706 'maxissueqty="" should mean unlimited'
710 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
711 undef,
712 'maxonsiteissueqty="" should mean unlimited'
716 subtest 'itemtype group tests' => sub {
717 plan tests => 13;
719 t::lib::Mocks::mock_preference( 'CircControl', 'ItemHomeLibrary' );
720 Koha::CirculationRules->set_rules(
722 branchcode => '*',
723 categorycode => '*',
724 itemtype => '*',
725 rules => {
726 maxissueqty => '',
727 maxonsiteissueqty => '',
728 issuelength => 1,
729 firstremind => 1, # 1 day of grace
730 finedays => 2, # 2 days of fine per day of overdue
731 lengthunit => 'days',
736 my $parent_itype = $builder->build(
738 source => 'Itemtype',
739 value => {
740 parent_type => undef,
741 rentalcharge => undef,
742 rentalcharge_daily => undef,
743 rentalcharge_hourly => undef,
744 notforloan => 0,
748 my $child_itype_1 = $builder->build(
750 source => 'Itemtype',
751 value => {
752 parent_type => $parent_itype->{itemtype},
753 rentalcharge => 0,
754 rentalcharge_daily => 0,
755 rentalcharge_hourly => 0,
756 notforloan => 0,
760 my $child_itype_2 = $builder->build(
762 source => 'Itemtype',
763 value => {
764 parent_type => $parent_itype->{itemtype},
765 rentalcharge => 0,
766 rentalcharge_daily => 0,
767 rentalcharge_hourly => 0,
768 notforloan => 0,
773 my $branch = $builder->build( { source => 'Branch', } );
774 my $category = $builder->build( { source => 'Category', } );
775 my $patron = $builder->build(
777 source => 'Borrower',
778 value => {
779 categorycode => $category->{categorycode},
780 branchcode => $branch->{branchcode},
784 my $item = $builder->build_sample_item(
786 homebranch => $branch->{branchcode},
787 holdingbranch => $branch->{branchcode},
788 itype => $child_itype_1->{itemtype}
792 my $all_iq_rule = $builder->build(
794 source => 'CirculationRule',
795 value => {
796 branchcode => $branch->{branchcode},
797 categorycode => $category->{categorycode},
798 itemtype => undef,
799 rule_name => 'maxissueqty',
800 rule_value => 1
804 is( C4::Circulation::TooMany( $patron, $item ),
805 undef, 'Checkout allowed, using all rule of 1' );
807 #Checkout an item
808 my $issue =
809 C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
810 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
812 #Patron has 1 checkout of child itype1
814 my $parent_iq_rule = $builder->build(
816 source => 'CirculationRule',
817 value => {
818 branchcode => $branch->{branchcode},
819 categorycode => $category->{categorycode},
820 itemtype => $parent_itype->{itemtype},
821 rule_name => 'maxissueqty',
822 rule_value => 2
827 is( C4::Circulation::TooMany( $patron, $item ),
828 undef, 'Checkout allowed, using parent type rule of 2' );
830 my $child1_iq_rule = $builder->build_object(
832 class => 'Koha::CirculationRules',
833 value => {
834 branchcode => $branch->{branchcode},
835 categorycode => $category->{categorycode},
836 itemtype => $child_itype_1->{itemtype},
837 rule_name => 'maxissueqty',
838 rule_value => 1
843 is_deeply(
844 C4::Circulation::TooMany( $patron, $item ),
846 reason => 'TOO_MANY_CHECKOUTS',
847 count => 1,
848 max_allowed => 1,
850 'Checkout not allowed, using specific type rule of 1'
853 my $item_1 = $builder->build_sample_item(
855 homebranch => $branch->{branchcode},
856 holdingbranch => $branch->{branchcode},
857 itype => $child_itype_2->{itemtype}
861 my $child2_iq_rule = $builder->build(
863 source => 'CirculationRule',
864 value => {
865 branchcode => $branch->{branchcode},
866 categorycode => $category->{categorycode},
867 itemtype => $child_itype_2->{itemtype},
868 rule_name => 'maxissueqty',
869 rule_value => 3
874 is( C4::Circulation::TooMany( $patron, $item_1 ),
875 undef, 'Checkout allowed' );
877 #checkout an item
878 $issue =
879 C4::Circulation::AddIssue( $patron, $item_1->barcode, dt_from_string() );
880 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
882 #patron has 1 checkout of childitype1 and 1 checkout of childitype2
884 is_deeply(
885 C4::Circulation::TooMany( $patron, $item ),
887 reason => 'TOO_MANY_CHECKOUTS',
888 count => 2,
889 max_allowed => 2,
891 'Checkout not allowed, using parent type rule of 2, checkout of sibling itemtype counted'
894 my $parent_item = $builder->build_sample_item(
896 homebranch => $branch->{branchcode},
897 holdingbranch => $branch->{branchcode},
898 itype => $parent_itype->{itemtype}
902 is_deeply(
903 C4::Circulation::TooMany( $patron, $parent_item ),
905 reason => 'TOO_MANY_CHECKOUTS',
906 count => 2,
907 max_allowed => 2,
909 'Checkout not allowed, using parent type rule of 2, checkout of child itemtypes counted'
912 #increase parent type to greater than specific
913 my $circ_rule_object =
914 Koha::CirculationRules->find( $parent_iq_rule->{id} );
915 $circ_rule_object->rule_value(4)->store();
917 is( C4::Circulation::TooMany( $patron, $item_1 ),
918 undef, 'Checkout allowed, using specific type rule of 3' );
920 my $item_2 = $builder->build_sample_item(
922 homebranch => $branch->{branchcode},
923 holdingbranch => $branch->{branchcode},
924 itype => $child_itype_2->{itemtype}
928 #checkout an item
929 $issue =
930 C4::Circulation::AddIssue( $patron, $item_2->barcode, dt_from_string(),
931 undef, undef, undef );
932 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
934 #patron has 1 checkout of childitype1 and 2 of childitype2
937 C4::Circulation::TooMany( $patron, $item_2 ),
938 undef,
939 'Checkout allowed, using specific type rule of 3, checkout of sibling itemtype not counted'
942 $child1_iq_rule->rule_value(2)->store(); #Allow 2 checkouts for child type 1
944 my $item_3 = $builder->build_sample_item(
946 homebranch => $branch->{branchcode},
947 holdingbranch => $branch->{branchcode},
948 itype => $child_itype_1->{itemtype}
951 my $item_4 = $builder->build_sample_item(
953 homebranch => $branch->{branchcode},
954 holdingbranch => $branch->{branchcode},
955 itype => $child_itype_2->{itemtype}
959 #checkout an item
960 $issue =
961 C4::Circulation::AddIssue( $patron, $item_4->barcode, dt_from_string(),
962 undef, undef, undef );
963 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
965 #patron has 1 checkout of childitype 1 and 3 of childitype2
967 is_deeply(
968 C4::Circulation::TooMany( $patron, $item_3 ),
970 reason => 'TOO_MANY_CHECKOUTS',
971 max_allowed => 4,
972 count => 4,
974 'Checkout not allowed, using specific type rule of 2, checkout of sibling itemtype not counted, but parent rule (4) prevents another'
977 teardown();
980 $schema->storage->txn_rollback;
982 sub teardown {
983 $dbh->do(q|DELETE FROM issues|);
984 $dbh->do(q|DELETE FROM circulation_rules|);