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 => 10;
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 $category = $builder->build({
59 my $patron = $builder->build({
62 categorycode => $category->{categorycode},
63 branchcode => $branch->{branchcode},
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},
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
79 # OSCO: On-site checkout
81 subtest 'no rules exist' => sub {
84 C4::Circulation::TooMany( $patron, $item ),
85 { reason => 'NO_RULE_DEFINED', max_allowed => 0 },
86 'CO should not be allowed, in any cases'
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 {
97 Koha::CirculationRules->set_rules(
99 branchcode => $branch->{branchcode},
100 categorycode => $category->{categorycode},
104 maxonsiteissueqty => 0,
108 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
110 C4::Circulation::TooMany( $patron, $item ),
112 reason => 'TOO_MANY_CHECKOUTS',
116 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
119 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
121 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
125 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
128 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
130 C4::Circulation::TooMany( $patron, $item ),
132 reason => 'TOO_MANY_CHECKOUTS',
136 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
139 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
141 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
145 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
151 subtest '1 Issuingrule exist with onsiteissueqty=unlimited' => sub {
154 Koha::CirculationRules->set_rules(
156 branchcode => $branch->{branchcode},
157 categorycode => $category->{categorycode},
161 maxonsiteissueqty => undef,
166 my $issue = C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
167 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
169 C4::Circulation::TooMany( $patron, $item ),
171 reason => 'TOO_MANY_CHECKOUTS',
175 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
178 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
180 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
183 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
185 C4::Circulation::TooMany( $patron, $item ),
187 reason => 'TOO_MANY_CHECKOUTS',
191 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
194 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
196 reason => 'TOO_MANY_CHECKOUTS',
200 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
207 subtest '1 Issuingrule exist 1 1: issue is allowed' => sub {
209 Koha::CirculationRules->set_rules(
211 branchcode => $branch->{branchcode},
212 categorycode => $category->{categorycode},
216 maxonsiteissueqty => 1,
220 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 0);
222 C4::Circulation::TooMany( $patron, $item ),
224 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
227 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
229 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
232 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
234 C4::Circulation::TooMany( $patron, $item ),
236 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
239 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
241 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
247 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed. Do a CO' => sub {
249 Koha::CirculationRules->set_rules(
251 branchcode => $branch->{branchcode},
252 categorycode => $category->{categorycode},
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);
266 C4::Circulation::TooMany( $patron, $item ),
268 reason => 'TOO_MANY_CHECKOUTS',
272 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
275 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
277 'OSCO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
280 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
282 C4::Circulation::TooMany( $patron, $item ),
284 reason => 'TOO_MANY_CHECKOUTS',
288 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
291 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
293 reason => 'TOO_MANY_CHECKOUTS',
297 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
303 subtest '1 Issuingrule exist: 1 CO allowed, 1 OSCO allowed, Do a OSCO' => sub {
305 Koha::CirculationRules->set_rules(
307 branchcode => $branch->{branchcode},
308 categorycode => $category->{categorycode},
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 ),
324 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
327 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
329 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
333 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
336 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
338 C4::Circulation::TooMany( $patron, $item ),
340 reason => 'TOO_MANY_CHECKOUTS',
344 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
347 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
349 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
353 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
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
364 Koha::CirculationRules->set_rules(
366 branchcode => $branch->{branchcode},
367 categorycode => $category->{categorycode},
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);
381 C4::Circulation::TooMany( $patron, $item ),
383 reason => 'TOO_MANY_CHECKOUTS',
387 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
390 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
392 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
395 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
397 C4::Circulation::TooMany( $patron, $item ),
399 reason => 'TOO_MANY_CHECKOUTS',
403 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
406 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
408 reason => 'TOO_MANY_CHECKOUTS',
412 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
416 Koha::CirculationRules->set_rules(
418 branchcode => $branch->{branchcode},
419 categorycode => $category->{categorycode},
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 ),
435 'CO should be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
438 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
440 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
444 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 0'
447 t::lib::Mocks::mock_preference('ConsiderOnSiteCheckoutsAsNormalCheckouts', 1);
449 C4::Circulation::TooMany( $patron, $item ),
451 reason => 'TOO_MANY_CHECKOUTS',
455 'CO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
458 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
460 reason => 'TOO_MANY_ONSITE_CHECKOUTS',
464 'OSCO should not be allowed if ConsiderOnSiteCheckoutsAsNormalCheckouts == 1'
470 subtest 'General vs specific rules limit quantity correctly' => sub {
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',
480 rentalcharge_daily => 0,
481 rentalcharge_hourly => 0,
485 my $patron = $builder->build({
486 source => 'Borrower',
488 categorycode => $category->{categorycode},
489 branchcode => $branch->{branchcode},
493 # Set up an issuing rule
494 Koha::CirculationRules->set_rules(
497 itemtype => $itemtype->{itemtype},
501 firstremind => 1, # 1 day of grace
502 finedays => 2, # 2 days of fine per day of overdue
503 lengthunit => 'days',
508 # Set an All->All for an itemtype
509 Koha::CirculationRules->set_rules(
513 itemtype => $itemtype->{itemtype},
516 maxonsiteissueqty => 1,
522 my $issue_item = $builder->build_sample_item({
523 itype => $itemtype->{itemtype}
525 my $branch_item = $builder->build_sample_item({
526 itype => $itemtype->{itemtype},
527 homebranch => $branch->{branchcode},
528 holdingbranch => $branch->{branchcode}
532 t::lib::Mocks::mock_userenv({ branchcode => $branch->{branchcode} });
533 my $issue = C4::Circulation::AddIssue( $patron, $issue_item->barcode, dt_from_string() );
534 # We checkout one item
536 C4::Circulation::TooMany( $patron, $branch_item ),
538 reason => 'TOO_MANY_CHECKOUTS',
542 'We are only allowed one, and we have one (itemtype on item)'
545 # Check itemtype on biblio level
546 t::lib::Mocks::mock_preference('item-level_itypes', 0);
547 $issue_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
548 $branch_item->biblio->biblioitem->itemtype($itemtype->{itemtype})->store;
549 # We checkout one item
551 C4::Circulation::TooMany( $patron, $branch_item ),
553 reason => 'TOO_MANY_CHECKOUTS',
557 'We are only allowed one, and we have one (itemtype on biblioitem)'
559 t::lib::Mocks::mock_preference('item-level_itypes', 1);
561 # Set a branch specific rule
562 Koha::CirculationRules->set_rules(
564 branchcode => $branch->{branchcode},
565 categorycode => $category->{categorycode},
566 itemtype => $itemtype->{itemtype},
569 maxonsiteissueqty => 1,
575 C4::Circulation::TooMany( $patron, $branch_item ),
577 'We are allowed one from the branch specifically now'
580 # If circcontrol is PatronLibrary we count all the patron's loan, regardless of branch
581 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
583 C4::Circulation::TooMany( $patron, $branch_item ),
585 reason => 'TOO_MANY_CHECKOUTS',
589 'We are allowed one from the branch specifically, but have one'
591 t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary');
593 $issue = C4::Circulation::AddIssue( $patron, $branch_item->barcode, dt_from_string() );
596 my $branch_item_2 = $builder->build_sample_item({
597 itype => $itemtype->{itemtype},
598 homebranch => $branch->{branchcode},
599 holdingbranch => $branch->{branchcode}
602 C4::Circulation::TooMany( $patron, $branch_item_2 ),
604 reason => 'TOO_MANY_CHECKOUTS',
608 'We are only allowed one from that branch, and have one'
611 # Now we make anothe from a different branch
612 my $item_2 = $builder->build_sample_item({
613 itype => $itemtype->{itemtype},
616 C4::Circulation::TooMany( $patron, $item_2 ),
618 reason => 'TOO_MANY_CHECKOUTS',
622 'We are only allowed one for general rule, and have two'
624 t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
626 C4::Circulation::TooMany( $patron, $item_2 ),
628 reason => 'TOO_MANY_CHECKOUTS',
632 'We are only allowed one for general rule, and have two'
635 t::lib::Mocks::mock_preference('CircControl', 'PickupLibrary');
637 C4::Circulation::TooMany( $patron, $item_2 ),
639 reason => 'TOO_MANY_CHECKOUTS',
643 'We are only allowed one for general rule, and have checked out two at this branch'
646 my $branch2 = $builder->build({source => 'Branch',});
647 t::lib::Mocks::mock_userenv({ branchcode => $branch2->{branchcode} });
649 C4::Circulation::TooMany( $patron, $item_2 ),
651 reason => 'TOO_MANY_CHECKOUTS',
655 'We are only allowed one for general rule, and have two total (no rule for specific branch)'
657 # Set a branch specific rule for new branch
658 Koha::CirculationRules->set_rules(
660 branchcode => $branch2->{branchcode},
661 categorycode => $category->{categorycode},
662 itemtype => $itemtype->{itemtype},
665 maxonsiteissueqty => 1,
671 C4::Circulation::TooMany( $patron, $branch_item ),
673 'We are allowed one from the branch specifically now'
677 subtest 'empty string means unlimited' => sub {
680 Koha::CirculationRules->set_rules(
687 maxonsiteissueqty => '',
692 C4::Circulation::TooMany( $patron, $item ),
694 'maxissueqty="" should mean unlimited'
698 C4::Circulation::TooMany( $patron, $item, { onsite_checkout => 1 } ),
700 'maxonsiteissueqty="" should mean unlimited'
704 subtest 'itemtype group tests' => sub {
707 t::lib::Mocks::mock_preference( 'CircControl', 'ItemHomeLibrary' );
708 Koha::CirculationRules->set_rules(
715 maxonsiteissueqty => '',
717 firstremind => 1, # 1 day of grace
718 finedays => 2, # 2 days of fine per day of overdue
719 lengthunit => 'days',
724 my $parent_itype = $builder->build(
726 source => 'Itemtype',
728 parent_type => undef,
729 rentalcharge => undef,
730 rentalcharge_daily => undef,
731 rentalcharge_hourly => undef,
736 my $child_itype_1 = $builder->build(
738 source => 'Itemtype',
740 parent_type => $parent_itype->{itemtype},
742 rentalcharge_daily => 0,
743 rentalcharge_hourly => 0,
748 my $child_itype_2 = $builder->build(
750 source => 'Itemtype',
752 parent_type => $parent_itype->{itemtype},
754 rentalcharge_daily => 0,
755 rentalcharge_hourly => 0,
761 my $branch = $builder->build( { source => 'Branch', } );
762 my $category = $builder->build( { source => 'Category', } );
763 my $patron = $builder->build(
765 source => 'Borrower',
767 categorycode => $category->{categorycode},
768 branchcode => $branch->{branchcode},
772 my $item = $builder->build_sample_item(
774 homebranch => $branch->{branchcode},
775 holdingbranch => $branch->{branchcode},
776 itype => $child_itype_1->{itemtype}
780 my $all_iq_rule = $builder->build(
782 source => 'CirculationRule',
784 branchcode => $branch->{branchcode},
785 categorycode => $category->{categorycode},
787 rule_name => 'maxissueqty',
792 is( C4::Circulation::TooMany( $patron, $item ),
793 undef, 'Checkout allowed, using all rule of 1' );
797 C4::Circulation::AddIssue( $patron, $item->barcode, dt_from_string() );
798 like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
800 #Patron has 1 checkout of child itype1
802 my $parent_iq_rule = $builder->build(
804 source => 'CirculationRule',
806 branchcode => $branch->{branchcode},
807 categorycode => $category->{categorycode},
808 itemtype => $parent_itype->{itemtype},
809 rule_name => 'maxissueqty',
815 is( C4::Circulation::TooMany( $patron, $item ),
816 undef, 'Checkout allowed, using parent type rule of 2' );
818 my $child1_iq_rule = $builder->build_object(
820 class => 'Koha::CirculationRules',
822 branchcode => $branch->{branchcode},
823 categorycode => $category->{categorycode},
824 itemtype => $child_itype_1->{itemtype},
825 rule_name => 'maxissueqty',
832 C4::Circulation::TooMany( $patron, $item ),
834 reason => 'TOO_MANY_CHECKOUTS',
838 'Checkout not allowed, using specific type rule of 1'
841 my $item_1 = $builder->build_sample_item(
843 homebranch => $branch->{branchcode},
844 holdingbranch => $branch->{branchcode},
845 itype => $child_itype_2->{itemtype}
849 my $child2_iq_rule = $builder->build(
851 source => 'CirculationRule',
853 branchcode => $branch->{branchcode},
854 categorycode => $category->{categorycode},
855 itemtype => $child_itype_2->{itemtype},
856 rule_name => 'maxissueqty',
862 is( C4::Circulation::TooMany( $patron, $item_1 ),
863 undef, 'Checkout allowed' );
867 C4::Circulation::AddIssue( $patron, $item_1->barcode, dt_from_string() );
868 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
870 #patron has 1 checkout of childitype1 and 1 checkout of childitype2
873 C4::Circulation::TooMany( $patron, $item ),
875 reason => 'TOO_MANY_CHECKOUTS',
879 'Checkout not allowed, using parent type rule of 2, checkout of sibling itemtype counted'
882 my $parent_item = $builder->build_sample_item(
884 homebranch => $branch->{branchcode},
885 holdingbranch => $branch->{branchcode},
886 itype => $parent_itype->{itemtype}
891 C4::Circulation::TooMany( $patron, $parent_item ),
893 reason => 'TOO_MANY_CHECKOUTS',
897 'Checkout not allowed, using parent type rule of 2, checkout of child itemtypes counted'
900 #increase parent type to greater than specific
901 my $circ_rule_object =
902 Koha::CirculationRules->find( $parent_iq_rule->{id} );
903 $circ_rule_object->rule_value(4)->store();
905 is( C4::Circulation::TooMany( $patron, $item_1 ),
906 undef, 'Checkout allowed, using specific type rule of 3' );
908 my $item_2 = $builder->build_sample_item(
910 homebranch => $branch->{branchcode},
911 holdingbranch => $branch->{branchcode},
912 itype => $child_itype_2->{itemtype}
918 C4::Circulation::AddIssue( $patron, $item_2->barcode, dt_from_string(),
919 undef, undef, undef );
920 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
922 #patron has 1 checkout of childitype1 and 2 of childitype2
925 C4::Circulation::TooMany( $patron, $item_2 ),
927 'Checkout allowed, using specific type rule of 3, checkout of sibling itemtype not counted'
930 $child1_iq_rule->rule_value(2)->store(); #Allow 2 checkouts for child type 1
932 my $item_3 = $builder->build_sample_item(
934 homebranch => $branch->{branchcode},
935 holdingbranch => $branch->{branchcode},
936 itype => $child_itype_1->{itemtype}
939 my $item_4 = $builder->build_sample_item(
941 homebranch => $branch->{branchcode},
942 holdingbranch => $branch->{branchcode},
943 itype => $child_itype_2->{itemtype}
949 C4::Circulation::AddIssue( $patron, $item_4->barcode, dt_from_string(),
950 undef, undef, undef );
951 like( $issue->issue_id, qr|^\d+$|, 'the issue should have been inserted' );
953 #patron has 1 checkout of childitype 1 and 3 of childitype2
956 C4::Circulation::TooMany( $patron, $item_3 ),
958 reason => 'TOO_MANY_CHECKOUTS',
962 'Checkout not allowed, using specific type rule of 2, checkout of sibling itemtype not counted, but parent rule (4) prevents another'
968 $schema->storage->txn_rollback;
971 $dbh->do(q|DELETE FROM issues|);
972 $dbh->do(q|DELETE FROM circulation_rules|);