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
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>.
18 use Test::More tests => 11;
24 use C4::Circulation qw( TooMany AddIssue );
27 use Koha::DateUtils qw( dt_from_string );
29 use Koha::CirculationRules;
31 use t::lib::TestBuilder;
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({
55 my $branch2 = $builder->build({
59 my $category = $builder->build({
63 my $patron = $builder->build({
66 categorycode => $category->{categorycode},
67 branchcode => $branch->{branchcode},
71 my $biblio = $builder->build_sample_biblio({ branchcode => $branch->{branchcode} });
72 my $item = $builder->build_sample_item({
73 biblionumber => $biblio->biblionumber,
74 homebranch => $branch->{branchcode},
75 holdingbranch => $branch->{branchcode},
78 my $patron_object = Koha::Patrons->find( $patron->{borrowernumber} );
79 t::lib::Mocks::mock_userenv( { patron => $patron_object });
81 # TooMany return ($current_loan_count, $max_loans_allowed) or undef
83 # OSCO: On-site checkout
85 subtest 'no rules exist' => sub {
88 C4::Circulation::TooMany( $patron, $item ),
89 { reason => 'NO_RULE_DEFINED', max_allowed => 0 },
90 'CO should not be allowed, in any cases'
93 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
94 { reason => 'NO_RULE_DEFINED', max_allowed => 0 },
95 'OSCO should not be allowed, in any cases'
99 subtest '1 Issuingrule exist 0 0: no issue allowed' => sub {
101 Koha::CirculationRules->set_rules(
103 branchcode => $branch->{branchcode},
104 categorycode => $category->{categorycode},
108 maxonsiteissueqty => 0,
112 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
114 C4::Circulation::TooMany( $patron, $item ),
116 reason => 'TOO_MANY_CHECKOUTS',
120 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
123 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
125 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
129 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
132 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
134 C4::Circulation::TooMany( $patron, $item ),
136 reason => 'TOO_MANY_CHECKOUTS',
140 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
143 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
145 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
149 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
155 subtest '1 Issuingrule exist with onsiteissueqty=unlimited' => sub {
158 Koha::CirculationRules->set_rules(
160 branchcode => $branch->{branchcode},
161 categorycode => $category->{categorycode},
165 maxonsiteissueqty => undef,
170 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
171 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
173 C4::Circulation::TooMany( $patron, $item ),
175 reason => 'TOO_MANY_CHECKOUTS',
179 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
182 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
184 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
187 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
189 C4::Circulation::TooMany( $patron, $item ),
191 reason => 'TOO_MANY_CHECKOUTS',
195 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
198 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
200 reason => 'TOO_MANY_CHECKOUTS',
204 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
211 subtest '1 Issuingrule exist 1 1: issue is allowed' => sub {
213 Koha::CirculationRules->set_rules(
215 branchcode => $branch->{branchcode},
216 categorycode => $category->{categorycode},
220 maxonsiteissueqty => 1,
224 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
226 C4::Circulation::TooMany( $patron, $item ),
228 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
231 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
233 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
236 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
238 C4::Circulation::TooMany( $patron, $item ),
240 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
243 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
245 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
251 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed. Do a CO' => sub {
253 Koha::CirculationRules->set_rules(
255 branchcode => $branch->{branchcode},
256 categorycode => $category->{categorycode},
260 maxonsiteissueqty => 1,
265 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
266 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
268 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
270 C4::Circulation::TooMany( $patron, $item ),
272 reason => 'TOO_MANY_CHECKOUTS',
276 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
279 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
281 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
284 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
286 C4::Circulation::TooMany( $patron, $item ),
288 reason => 'TOO_MANY_CHECKOUTS',
292 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
295 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
297 reason => 'TOO_MANY_CHECKOUTS',
301 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
307 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed, Do a OSCO' => sub {
309 Koha::CirculationRules->set_rules(
311 branchcode => $branch->{branchcode},
312 categorycode => $category->{categorycode},
316 maxonsiteissueqty => 1,
321 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
322 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
324 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
326 C4::Circulation::TooMany( $patron, $item ),
328 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
331 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
333 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
337 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
340 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
342 C4::Circulation::TooMany( $patron, $item ),
344 reason => 'TOO_MANY_CHECKOUTS',
348 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
351 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
353 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
357 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
363 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub {
364 # Note: the same test coul be done for
365 # DefaultBorrowerCircRule, DefaultBranchCircRule, DefaultBranchItemRule ans DefaultCircRule.pm
368 Koha::CirculationRules->set_rules(
370 branchcode => $branch->{branchcode},
371 categorycode => $category->{categorycode},
375 maxonsiteissueqty => 1,
380 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef );
381 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
383 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
385 C4::Circulation::TooMany( $patron, $item ),
387 reason => 'TOO_MANY_CHECKOUTS',
391 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
394 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
396 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
399 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
401 C4::Circulation::TooMany( $patron, $item ),
403 reason => 'TOO_MANY_CHECKOUTS',
407 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
410 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
412 reason => 'TOO_MANY_CHECKOUTS',
416 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
420 Koha::CirculationRules->set_rules(
422 branchcode => $branch->{branchcode},
423 categorycode => $category->{categorycode},
427 maxonsiteissueqty => 1,
432 $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
433 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
435 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
437 C4::Circulation::TooMany( $patron, $item ),
439 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
442 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
444 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
448 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
451 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
453 C4::Circulation::TooMany( $patron, $item ),
455 reason => 'TOO_MANY_CHECKOUTS',
459 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
462 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
464 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
468 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
474 subtest 'General vs specific rules limit quantity correctly' => sub {
477 t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary');
478 my $branch = $builder->build({source => 'Branch',});
479 my $category = $builder->build({source => 'Category',});
480 my $itemtype = $builder->build({
481 source => 'Itemtype',
484 rentalcharge_daily => 0,
485 rentalcharge_hourly => 0,
489 my $patron = $builder->build({
490 source => 'Borrower',
492 categorycode => $category->{categorycode},
493 branchcode => $branch->{branchcode},
497 # Set up an issuing rule
498 Koha::CirculationRules->set_rules(
501 itemtype => $itemtype->{itemtype},
505 firstremind => 1, # 1 day of grace
506 finedays => 2, # 2 days of fine per day of overdue
507 lengthunit => 'days',
512 # Set default maximum issue quantity limits for branch
513 Koha::CirculationRules->set_rules(
515 branchcode => $branch->{branchcode},
518 patron_maxissueqty => 1,
519 patron_maxonsiteissueqty => 1,
524 # Set an All->All for an itemtype
525 Koha::CirculationRules->set_rules(
529 itemtype => $itemtype->{itemtype},
532 maxonsiteissueqty => 1,
538 my $issue_item = $builder->build_sample_item({
539 itype => $itemtype->{itemtype}
541 my $branch_item = $builder->build_sample_item({
542 itype => $itemtype->{itemtype},
543 homebranch => $branch->{branchcode},
544 holdingbranch => $branch->{branchcode}
548 t::lib::Mocks::mock_userenv({ branchcode => $branch->{branchcode} });
549 my $issue = C4::Circulation::AddIssue( $patron, $issue_item->barcode, dt_from_string() );
550 # We checkout one item
552 C4::Circulation::TooMany( $patron, $branch_item ),
554 reason => 'TOO_MANY_CHECKOUTS',
558 'We are only allowed one, and we have one (itemtype on item)'
561 # Check itemtype on biblio level
562 t::lib::Mocks::mock_preference('item-level_itypes', 0);
563 $issue_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
564 $branch_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
565 # We checkout one item
567 C4::Circulation::TooMany( $patron, $branch_item ),
569 reason => 'TOO_MANY_CHECKOUTS',
573 'We are only allowed one, and we have one (itemtype on biblioitem)'
575 t::lib::Mocks::mock_preference('item-level_itypes', 1);
577 # Set a branch specific rule
578 Koha::CirculationRules->set_rules(
580 branchcode => $branch->{branchcode},
581 categorycode => $category->{categorycode},
582 itemtype => $itemtype->{itemtype},
585 maxonsiteissueqty => 1,
590 t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'homebranch');
593 C4::Circulation::TooMany( $patron, $branch_item ),
595 'We are allowed one from the branch specifically now'
598 # If circcontrol is PatronLibrary we count all the patron's loan, regardless of branch
599 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
601 C4::Circulation::TooMany( $patron, $branch_item ),
603 reason => 'TOO_MANY_CHECKOUTS',
607 'We are allowed one from the branch specifically, but have one'
609 t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary');
611 $issue = C4::Circulation::AddIssue( $patron, $branch_item->barcode, dt_from_string() );
614 my $branch_item_2 = $builder->build_sample_item({
615 itype => $itemtype->{itemtype},
616 homebranch => $branch->{branchcode},
617 holdingbranch => $branch->{branchcode}
620 C4::Circulation::TooMany( $patron, $branch_item_2 ),
622 reason => 'TOO_MANY_CHECKOUTS',
626 'We are only allowed one from that branch, and have one'
629 # Now we make anothe from a different branch
630 my $item_2 = $builder->build_sample_item({
631 itype => $itemtype->{itemtype},
634 C4::Circulation::TooMany( $patron, $item_2 ),
636 reason => 'TOO_MANY_CHECKOUTS',
640 'We are only allowed one for general rule, and have two'
642 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
644 C4::Circulation::TooMany( $patron, $item_2 ),
646 reason => 'TOO_MANY_CHECKOUTS',
650 'We are only allowed one for general rule, and have two'
653 t::lib::Mocks::mock_preference('CircControl', 'PickupLibrary');
655 C4::Circulation::TooMany( $patron, $item_2 ),
657 reason => 'TOO_MANY_CHECKOUTS',
661 'We are only allowed one for general rule, and have checked out two at this branch'
664 t::lib::Mocks::mock_userenv({ branchcode => $branch2->{branchcode} });
666 C4::Circulation::TooMany( $patron, $item_2 ),
668 reason => 'TOO_MANY_CHECKOUTS',
672 'We are only allowed one for general rule, and have two total (no rule for specific branch)'
674 # Set a branch specific rule for new branch
675 Koha::CirculationRules->set_rules(
677 branchcode => $branch2->{branchcode},
678 categorycode => $category->{categorycode},
679 itemtype => $itemtype->{itemtype},
682 maxonsiteissueqty => 1,
688 C4::Circulation::TooMany( $patron, $branch_item ),
690 'We are allowed one from the branch specifically now'
694 subtest 'empty string means unlimited' => sub {
697 Koha::CirculationRules->set_rules(
704 maxonsiteissueqty => '',
709 C4::Circulation::TooMany( $patron, $item ),
711 'maxissueqty="" should mean unlimited'
715 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
717 'maxonsiteissueqty="" should mean unlimited'
721 subtest 'itemtype group tests' => sub {
724 t::lib::Mocks::mock_preference( 'CircControl', 'ItemHomeLibrary' );
725 Koha::CirculationRules->set_rules(
732 maxonsiteissueqty => '',
734 firstremind => 1, # 1 day of grace
735 finedays => 2, # 2 days of fine per day of overdue
736 lengthunit => 'days',
741 my $parent_itype = $builder->build(
743 source => 'Itemtype',
745 parent_type => undef,
746 rentalcharge => undef,
747 rentalcharge_daily => undef,
748 rentalcharge_hourly => undef,
753 my $child_itype_1 = $builder->build(
755 source => 'Itemtype',
757 parent_type => $parent_itype->{itemtype},
759 rentalcharge_daily => 0,
760 rentalcharge_hourly => 0,
765 my $child_itype_2 = $builder->build(
767 source => 'Itemtype',
769 parent_type => $parent_itype->{itemtype},
771 rentalcharge_daily => 0,
772 rentalcharge_hourly => 0,
778 my $branch = $builder->build( { source => 'Branch', } );
779 my $category = $builder->build( { source => 'Category', } );
780 my $patron = $builder->build(
782 source => 'Borrower',
784 categorycode => $category->{categorycode},
785 branchcode => $branch->{branchcode},
789 my $item = $builder->build_sample_item(
791 homebranch => $branch->{branchcode},
792 holdingbranch => $branch->{branchcode},
793 itype => $child_itype_1->{itemtype}
797 my $all_iq_rule = $builder->build(
799 source => 'CirculationRule',
801 branchcode => $branch->{branchcode},
802 categorycode => $category->{categorycode},
804 rule_name => 'maxissueqty',
809 is( C4::Circulation::TooMany( $patron, $item ),
810 undef, 'Checkout allowed, using all rule of 1' );
814 C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
815 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
817 #Patron has 1 checkout of child itype1
819 my $parent_iq_rule = $builder->build(
821 source => 'CirculationRule',
823 branchcode => $branch->{branchcode},
824 categorycode => $category->{categorycode},
825 itemtype => $parent_itype->{itemtype},
826 rule_name => 'maxissueqty',
832 is( C4::Circulation::TooMany( $patron, $item ),
833 undef, 'Checkout allowed, using parent type rule of 2' );
835 my $child1_iq_rule = $builder->build_object(
837 class => 'Koha::CirculationRules',
839 branchcode => $branch->{branchcode},
840 categorycode => $category->{categorycode},
841 itemtype => $child_itype_1->{itemtype},
842 rule_name => 'maxissueqty',
849 C4::Circulation::TooMany( $patron, $item ),
851 reason => 'TOO_MANY_CHECKOUTS',
855 'Checkout not allowed, using specific type rule of 1'
858 my $item_1 = $builder->build_sample_item(
860 homebranch => $branch->{branchcode},
861 holdingbranch => $branch->{branchcode},
862 itype => $child_itype_2->{itemtype}
866 my $child2_iq_rule = $builder->build(
868 source => 'CirculationRule',
870 branchcode => $branch->{branchcode},
871 categorycode => $category->{categorycode},
872 itemtype => $child_itype_2->{itemtype},
873 rule_name => 'maxissueqty',
879 is( C4::Circulation::TooMany( $patron, $item_1 ),
880 undef, 'Checkout allowed' );
884 C4::Circulation::AddIssue( $patron, $item_1->barcode, dt_from_string() );
885 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
887 #patron has 1 checkout of childitype1 and 1 checkout of childitype2
890 C4::Circulation::TooMany( $patron, $item ),
892 reason => 'TOO_MANY_CHECKOUTS',
896 'Checkout not allowed, using parent type rule of 2, checkout of sibling itemtype counted'
899 my $parent_item = $builder->build_sample_item(
901 homebranch => $branch->{branchcode},
902 holdingbranch => $branch->{branchcode},
903 itype => $parent_itype->{itemtype}
908 C4::Circulation::TooMany( $patron, $parent_item ),
910 reason => 'TOO_MANY_CHECKOUTS',
914 'Checkout not allowed, using parent type rule of 2, checkout of child itemtypes counted'
917 #increase parent type to greater than specific
918 my $circ_rule_object =
919 Koha::CirculationRules->find( $parent_iq_rule->{id} );
920 $circ_rule_object->rule_value(4)->store();
922 is( C4::Circulation::TooMany( $patron, $item_1 ),
923 undef, 'Checkout allowed, using specific type rule of 3' );
925 my $item_2 = $builder->build_sample_item(
927 homebranch => $branch->{branchcode},
928 holdingbranch => $branch->{branchcode},
929 itype => $child_itype_2->{itemtype}
935 C4::Circulation::AddIssue( $patron, $item_2->barcode, dt_from_string(),
936 undef, undef, undef );
937 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
939 #patron has 1 checkout of childitype1 and 2 of childitype2
942 C4::Circulation::TooMany( $patron, $item_2 ),
944 'Checkout allowed, using specific type rule of 3, checkout of sibling itemtype not counted'
947 $child1_iq_rule->rule_value(2)->store(); #Allow 2 checkouts for child type 1
949 my $item_3 = $builder->build_sample_item(
951 homebranch => $branch->{branchcode},
952 holdingbranch => $branch->{branchcode},
953 itype => $child_itype_1->{itemtype}
956 my $item_4 = $builder->build_sample_item(
958 homebranch => $branch->{branchcode},
959 holdingbranch => $branch->{branchcode},
960 itype => $child_itype_2->{itemtype}
966 C4::Circulation::AddIssue( $patron, $item_4->barcode, dt_from_string(),
967 undef, undef, undef );
968 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
970 #patron has 1 checkout of childitype 1 and 3 of childitype2
973 C4::Circulation::TooMany( $patron, $item_3 ),
975 reason => 'TOO_MANY_CHECKOUTS',
979 'Checkout not allowed, using specific type rule of 2, checkout of sibling itemtype not counted, but parent rule (4) prevents another'
985 subtest 'HomeOrHoldingBranch is used' => sub {
988 t::lib::Mocks::mock_preference( 'CircControl', 'ItemHomeLibrary' );
990 my $item_1 = $builder->build_sample_item(
992 homebranch => $branch->{branchcode},
993 holdingbranch => $branch2->{branchcode},
997 Koha::CirculationRules->set_rules(
999 branchcode => $branch->{branchcode},
1000 categorycode => undef,
1008 Koha::CirculationRules->set_rules(
1010 branchcode => $branch2->{branchcode},
1011 categorycode => undef,
1019 t::lib::Mocks::mock_userenv({ branchcode => $branch2->{branchcode} });
1020 my $issue = C4::Circulation::AddIssue( $patron, $item_1->barcode, dt_from_string() );
1022 t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'homebranch');
1025 C4::Circulation::TooMany( $patron, $item_1 ),
1027 reason => 'TOO_MANY_CHECKOUTS',
1031 'We are allowed zero issues from the homebranch specifically'
1034 t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'holdingbranch');
1037 C4::Circulation::TooMany( $patron, $item_1 ),
1039 reason => 'TOO_MANY_CHECKOUTS',
1043 'We are allowed one issue from the holdingbranch specifically'
1049 $schema->storage->txn_rollback;
1052 $dbh->do(q|DELETE FROM issues|);
1053 $dbh->do(q|DELETE FROM circulation_rules|);