Bug 18936: Convert issuingrules fields to circulation_rules
authorKyle M Hall <kyle@bywatersolutions.com>
Thu, 13 Jul 2017 14:03:54 +0000 (10:03 -0400)
committerMartin Renvoize <martin.renvoize@ptfs-europe.com>
Tue, 4 Feb 2020 09:23:55 +0000 (09:23 +0000)
Signed-off-by: Minna Kivinen <minna.kivinen@hamk.fi>
Signed-off-by: Joonas Kylmälä <joonas.kylmala@helsinki.fi>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

31 files changed:
C4/Circulation.pm
C4/Overdues.pm
C4/Reserves.pm
Koha/Biblio.pm
Koha/CirculationRules.pm
Koha/IssuingRule.pm [deleted file]
Koha/Item.pm
Koha/Schema/Result/Issuingrule.pm [deleted file]
admin/smart-rules.pl
installer/data/mysql/atomicupdate/bug_18936.perl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt
t/db_dependent/ArticleRequests.t
t/db_dependent/Circulation.t
t/db_dependent/Circulation/CalcDateDue.t
t/db_dependent/Circulation/CalcFine.t
t/db_dependent/Circulation/GetHardDueDate.t
t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t
t/db_dependent/Circulation/Returns.t
t/db_dependent/Circulation/SwitchOnSiteCheckouts.t
t/db_dependent/Circulation/TooMany.t
t/db_dependent/Circulation/issue.t
t/db_dependent/DecreaseLoanHighHolds.t
t/db_dependent/Fines.t
t/db_dependent/Holds.t
t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t
t/db_dependent/Koha/IssuingRules.t
t/db_dependent/Koha/Objects.t
t/db_dependent/Reserves.t
t/db_dependent/Reserves/MultiplePerRecord.t
t/db_dependent/TestBuilder.t
t/db_dependent/api/v1/holds.t

index 9fe6625..d9fad94 100644 (file)
@@ -44,7 +44,6 @@ use Koha::Biblioitems;
 use Koha::DateUtils;
 use Koha::Calendar;
 use Koha::Checkouts;
-use Koha::IssuingRules;
 use Koha::Items;
 use Koha::Patrons;
 use Koha::Patron::Debarments;
@@ -423,18 +422,20 @@ sub TooMany {
             # specific rule
             if (C4::Context->preference('item-level_itypes')) {
                 $count_query .= " WHERE items.itype NOT IN (
-                                    SELECT itemtype FROM issuingrules
+                                    SELECT itemtype FROM circulation_rules
                                     WHERE branchcode = ?
                                     AND   (categorycode = ? OR categorycode = ?)
                                     AND   itemtype <> '*'
+                                    AND   rule_name = 'maxissueqty'
                                   ) ";
-            } else { 
-                $count_query .= " JOIN  biblioitems USING (biblionumber) 
+            } else {
+                $count_query .= " JOIN  biblioitems USING (biblionumber)
                                   WHERE biblioitems.itemtype NOT IN (
-                                    SELECT itemtype FROM issuingrules
+                                    SELECT itemtype FROM circulation_rules
                                     WHERE branchcode = ?
                                     AND   (categorycode = ? OR categorycode = ?)
                                     AND   itemtype <> '*'
+                                    AND   rule_name = 'maxissueqty'
                                   ) ";
             }
             push @bind_params, $maxissueqty_rule->branchcode;
@@ -1391,14 +1392,16 @@ sub AddIssue {
 
             # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
             unless ($auto_renew) {
-                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
-                    {   categorycode => $borrower->{categorycode},
+                my $rule = Koha::CirculationRules->get_effective_rule(
+                    {
+                        categorycode => $borrower->{categorycode},
                         itemtype     => $item_object->effective_itemtype,
-                        branchcode   => $branchcode
+                        branchcode   => $branchcode,
+                        rule_name    => 'auto_renew'
                     }
                 );
 
-                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
+                $auto_renew = $rule->rule_value if $rule;
             }
 
             # Record in the database the fact that the book was issued.
@@ -1539,67 +1542,77 @@ Get loan length for an itemtype, a borrower type and a branch
 =cut
 
 sub GetLoanLength {
-    my ( $borrowertype, $itemtype, $branchcode ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare(qq{
-        SELECT issuelength, lengthunit, renewalperiod
-        FROM issuingrules
-        WHERE   categorycode=?
-            AND itemtype=?
-            AND branchcode=?
-            AND issuelength IS NOT NULL
-    });
+    my ( $categorycode, $itemtype, $branchcode ) = @_;
+
+    # Set search precedences
+    my @params = (
+        {
+            categorycode => $categorycode,
+            itemtype     => $itemtype,
+            branchcode   => $branchcode,
+        },
+        {
+            categorycode => $categorycode,
+            itemtype     => '*',
+            branchcode   => $branchcode,
+        },
+        {
+            categorycode => '*',
+            itemtype     => $itemtype,
+            branchcode   => $branchcode,
+        },
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => $branchcode,
+        },
+        {
+            categorycode => $categorycode,
+            itemtype     => $itemtype,
+            branchcode   => '*',
+        },
+        {
+            categorycode => $categorycode,
+            itemtype     => '*',
+            branchcode   => '*',
+        },
+        {
+            categorycode => '*',
+            itemtype     => $itemtype,
+            branchcode   => '*',
+        },
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+        },
+    );
 
-    # try to find issuelength & return the 1st available.
-    # check with borrowertype, itemtype and branchcode, then without one of those parameters
-    $sth->execute( $borrowertype, $itemtype, $branchcode );
-    my $loanlength = $sth->fetchrow_hashref;
-
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( $borrowertype, '*', $branchcode );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( '*', $itemtype, $branchcode );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( '*', '*', $branchcode );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( $borrowertype, $itemtype, '*' );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( $borrowertype, '*', '*' );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( '*', $itemtype, '*' );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    $sth->execute( '*', '*', '*' );
-    $loanlength = $sth->fetchrow_hashref;
-    return $loanlength
-      if defined($loanlength) && defined $loanlength->{issuelength};
-
-    # if no rule is set => 0 day (hardcoded)
-    return {
-        issuelength => 0,
+    # Initialize default values
+    my $rules = {
+        issuelength   => 0,
         renewalperiod => 0,
-        lengthunit => 'days',
+        lengthunit    => 'days',
     };
 
+    # Search for rules!
+    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
+        foreach my $params (@params) {
+            my $rule = Koha::CirculationRules->search(
+                {
+                    rule_name => $rule_name,
+                    %$params,
+                }
+            )->next();
+
+            if ($rule) {
+                $rules->{$rule_name} = $rule->rule_value;
+                last;
+            }
+        }
+    }
+
+    return $rules;
 }
 
 
@@ -1614,19 +1627,21 @@ Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a
 sub GetHardDueDate {
     my ( $borrowertype, $itemtype, $branchcode ) = @_;
 
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
-        {   categorycode => $borrowertype,
+    my $rules = Koha::CirculationRules->get_effective_rules(
+        {
+            categorycode => $borrowertype,
             itemtype     => $itemtype,
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rules        => [ 'hardduedate', 'hardduedatecompare' ],
         }
     );
 
-
-    if ( defined( $issuing_rule ) ) {
-        if ( $issuing_rule->hardduedate ) {
-            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
-        } else {
-            return (undef, undef);
+    if ( defined( $rules->{hardduedate} ) ) {
+        if ( $rules->{hardduedate} ) {
+            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
+        }
+        else {
+            return ( undef, undef );
         }
     }
 }
@@ -2245,14 +2260,20 @@ sub _calculate_new_debar_dt {
 
     my $branchcode = _GetCircControlBranch( $item, $borrower );
     my $circcontrol = C4::Context->preference('CircControl');
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
         {   categorycode => $borrower->{categorycode},
             itemtype     => $item->{itype},
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rules => [
+                'finedays',
+                'lengthunit',
+                'firstremind',
+                'maxsuspensiondays',
+            ]
         }
     );
-    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
-    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
+    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
+    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
     my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
 
     return unless $finedays;
@@ -2263,7 +2284,7 @@ sub _calculate_new_debar_dt {
 
     # grace period is measured in the same units as the loan
     my $grace =
-      DateTime::Duration->new( $unit => $issuing_rule->firstremind );
+      DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
 
     my $deltadays = DateTime::Duration->new(
         days => $chargeable_units
@@ -2272,16 +2293,16 @@ sub _calculate_new_debar_dt {
     if ( $deltadays->subtract($grace)->is_positive() ) {
         my $suspension_days = $deltadays * $finedays;
 
-        if ( $issuing_rule->suspension_chargeperiod > 1 ) {
+        if ( $issuing_rule->{suspension_chargeperiod} > 1 ) {
             # No need to / 1 and do not consider / 0
             $suspension_days = DateTime::Duration->new(
-                days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod )
+                days => floor( $suspension_days->in_units('days') / $issuing_rule->{suspension_chargeperiod} )
             );
         }
 
         # If the max suspension days is < than the suspension days
         # the suspension days is limited to this maximum period.
-        my $max_sd = $issuing_rule->maxsuspensiondays;
+        my $max_sd = $issuing_rule->{maxsuspensiondays};
         if ( defined $max_sd ) {
             $max_sd = DateTime::Duration->new( days => $max_sd );
             $suspension_days = $max_sd
@@ -2749,15 +2770,23 @@ sub CanBookBeRenewed {
     return ( 1, undef ) if $override_limit;
 
     my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
-        {   categorycode => $patron->categorycode,
+    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
+        {
+            categorycode => $patron->categorycode,
             itemtype     => $item->effective_itemtype,
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rules => [
+                'renewalsallowed',
+                'no_auto_renewal_after',
+                'no_auto_renewal_after_hard_limit',
+                'lengthunit',
+                'norenewalbefore',
+            ]
         }
     );
 
     return ( 0, "too_many" )
-      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
+      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
 
     my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
     my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
@@ -2777,23 +2806,23 @@ sub CanBookBeRenewed {
             return ( 0, 'auto_account_expired' );
         }
 
-        if ( defined $issuing_rule->no_auto_renewal_after
-                and $issuing_rule->no_auto_renewal_after ne "" ) {
+        if ( defined $issuing_rule->{no_auto_renewal_after}
+                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
             # Get issue_date and add no_auto_renewal_after
             # If this is greater than today, it's too late for renewal.
             my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
             $maximum_renewal_date->add(
-                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
+                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
             );
             my $now = dt_from_string;
             if ( $now >= $maximum_renewal_date ) {
                 return ( 0, "auto_too_late" );
             }
         }
-        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
-                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
+        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
+                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
             # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
-            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
+            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
                 return ( 0, "auto_too_late" );
             }
         }
@@ -2810,17 +2839,17 @@ sub CanBookBeRenewed {
         }
     }
 
-    if ( defined $issuing_rule->norenewalbefore
-        and $issuing_rule->norenewalbefore ne "" )
+    if ( defined $issuing_rule->{norenewalbefore}
+        and $issuing_rule->{norenewalbefore} ne "" )
     {
 
         # Calculate soonest renewal by subtracting 'No renewal before' from due date
         my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
-            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
+            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
 
         # Depending on syspref reset the exact time, only check the date
         if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
-            and $issuing_rule->lengthunit eq 'days' )
+            and $issuing_rule->{lengthunit} eq 'days' )
         {
             $soonestrenewal->truncate( to => 'day' );
         }
@@ -3042,14 +3071,16 @@ sub GetRenewCount {
     # $item and $borrower should be calculated
     my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
 
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
-        {   categorycode => $patron->categorycode,
+    my $rule = Koha::CirculationRules->get_effective_rule(
+        {
+            categorycode => $patron->categorycode,
             itemtype     => $item->effective_itemtype,
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rule_name    => 'renewalsallowed',
         }
     );
 
-    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
+    $renewsallowed = $rule ? $rule->rule_value : 0;
     $renewsleft    = $renewsallowed - $renewcount;
     if($renewsleft < 0){ $renewsleft = 0; }
     return ( $renewcount, $renewsallowed, $renewsleft );
@@ -3087,25 +3118,29 @@ sub GetSoonestRenewDate {
       or return;
 
     my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
         {   categorycode => $patron->categorycode,
             itemtype     => $item->effective_itemtype,
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rules => [
+                'norenewalbefore',
+                'lengthunit',
+            ]
         }
     );
 
     my $now = dt_from_string;
     return $now unless $issuing_rule;
 
-    if ( defined $issuing_rule->norenewalbefore
-        and $issuing_rule->norenewalbefore ne "" )
+    if ( defined $issuing_rule->{norenewalbefore}
+        and $issuing_rule->{norenewalbefore} ne "" )
     {
         my $soonestrenewal =
           dt_from_string( $itemissue->date_due )->subtract(
-            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
+            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
 
         if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
-            and $issuing_rule->lengthunit eq 'days' )
+            and $issuing_rule->{lengthunit} eq 'days' )
         {
             $soonestrenewal->truncate( to => 'day' );
         }
@@ -3146,30 +3181,36 @@ sub GetLatestAutoRenewDate {
       or return;
 
     my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
-        {   categorycode => $patron->categorycode,
+    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
+        {
+            categorycode => $patron->categorycode,
             itemtype     => $item->effective_itemtype,
-            branchcode   => $branchcode
+            branchcode   => $branchcode,
+            rules => [
+                'no_auto_renewal_after',
+                'no_auto_renewal_after_hard_limit',
+                'lengthunit',
+            ]
         }
     );
 
-    return unless $issuing_rule;
+    return unless $circulation_rules;
     return
-      if ( not $issuing_rule->no_auto_renewal_after
-            or $issuing_rule->no_auto_renewal_after eq '' )
-      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
-             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
+      if ( not $circulation_rules->{no_auto_renewal_after}
+            or $circulation_rules->{no_auto_renewal_after} eq '' )
+      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
+             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
 
     my $maximum_renewal_date;
-    if ( $issuing_rule->no_auto_renewal_after ) {
+    if ( $circulation_rules->{no_auto_renewal_after} ) {
         $maximum_renewal_date = dt_from_string($itemissue->issuedate);
         $maximum_renewal_date->add(
-            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
+            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
         );
     }
 
-    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
-        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
+    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
+        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
         $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
     }
     return $maximum_renewal_date;
@@ -3216,19 +3257,10 @@ sub GetIssuingCharges {
         $item_type = $item_data->{itemtype};
         $charge    = $item_data->{rentalcharge};
         my $branch = C4::Context::mybranch();
-        my $discount_query = q|SELECT rentaldiscount,
-            issuingrules.itemtype, issuingrules.branchcode
-            FROM borrowers
-            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
-            WHERE borrowers.borrowernumber = ?
-            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
-            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
-        my $discount_sth = $dbh->prepare($discount_query);
-        $discount_sth->execute( $borrowernumber, $item_type, $branch );
-        my $discount_rules = $discount_sth->fetchall_arrayref({});
-        if (@{$discount_rules}) {
+        my $patron = Koha::Patrons->find( $borrowernumber );
+        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
+        if ($discount) {
             # We may have multiple rules so get the most specific
-            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
             $charge = ( $charge * ( 100 - $discount ) ) / 100;
         }
         if ($charge) {
@@ -3241,37 +3273,43 @@ sub GetIssuingCharges {
 
 # Select most appropriate discount rule from those returned
 sub _get_discount_from_rule {
-    my ($rules_ref, $branch, $itemtype) = @_;
-    my $discount;
+    my ($categorycode, $branchcode, $itemtype) = @_;
 
-    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
-        $discount = $rules_ref->[0]->{rentaldiscount};
-        return (defined $discount) ? $discount : 0;
-    }
-    # could have up to 4 does one match $branch and $itemtype
-    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
-    if (@d) {
-        $discount = $d[0]->{rentaldiscount};
-        return (defined $discount) ? $discount : 0;
-    }
-    # do we have item type + all branches
-    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
-    if (@d) {
-        $discount = $d[0]->{rentaldiscount};
-        return (defined $discount) ? $discount : 0;
-    }
-    # do we all item types + this branch
-    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
-    if (@d) {
-        $discount = $d[0]->{rentaldiscount};
-        return (defined $discount) ? $discount : 0;
-    }
-    # so all and all (surely we wont get here)
-    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
-    if (@d) {
-        $discount = $d[0]->{rentaldiscount};
-        return (defined $discount) ? $discount : 0;
+    # Set search precedences
+    my @params = (
+        {
+            branchcode   => $branchcode,
+            itemtype     => $itemtype,
+            categorycode => $categorycode,
+        },
+        {
+            branchcode   => '*',
+            categorycode => $categorycode,
+            itemtype     => $itemtype,
+        },
+        {
+            branchcode   => $branchcode,
+            categorycode => $categorycode,
+            itemtype     => '*',
+        },
+        {
+            branchcode   => '*',
+            categorycode => $categorycode,
+            itemtype     => '*',
+        },
+    );
+
+    foreach my $params (@params) {
+        my $rule = Koha::CirculationRules->search(
+            {
+                rule_name => 'rentaldiscount',
+                %$params,
+            }
+        )->next();
+
+        return $rule->rule_value if $rule;
     }
+
     # none of the above
     return 0;
 }
index cd4f838..160bdb1 100644 (file)
@@ -35,7 +35,6 @@ use C4::Debug;
 use Koha::DateUtils;
 use Koha::Account::Lines;
 use Koha::Account::Offsets;
-use Koha::IssuingRules;
 use Koha::Libraries;
 
 use vars qw(@ISA @EXPORT);
@@ -238,27 +237,43 @@ sub CalcFine {
     my $start_date = $due_dt->clone();
     # get issuingrules (fines part will be used)
     my $itemtype = $item->{itemtype} || $item->{itype};
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
+    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
+        {
+            categorycode => $bortype,
+            itemtype     => $itemtype,
+            branchcode   => $branchcode,
+            rules => [
+                'lengthunit',
+                'firstremind',
+                'chargeperiod',
+                'chargeperiod_charge_at',
+                'fine',
+                'overduefinescap',
+                'cap_fine_to_replacement_price',
+                'chargename',
+            ]
+        }
+    );
 
     $itemtype = Koha::ItemTypes->find($itemtype);
 
     return unless $issuing_rule; # If not rule exist, there is no fine
 
-    my $fine_unit = $issuing_rule->lengthunit || 'days';
+    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
 
     my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
-    my $units_minus_grace = $chargeable_units - ($issuing_rule->firstremind || 0);
+    my $units_minus_grace = $chargeable_units - ($issuing_rule->{firstremind} || 0);
     my $amount = 0;
-    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
+    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
         my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
-        my $charge_periods = $units / $issuing_rule->chargeperiod;
+        my $charge_periods = $units / $issuing_rule->{chargeperiod};
         # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
         # if chargeperiod_charge_at = 0, we charge at the end of each charge period
-        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
-        $amount = $charge_periods * $issuing_rule->fine;
+        $charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
+        $amount = $charge_periods * $issuing_rule->{fine};
     } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
 
-    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
+    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
 
     # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
     $item->{replacementprice} ||= $itemtype->defaultreplacecost
@@ -266,7 +281,7 @@ sub CalcFine {
       && ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
       && C4::Context->preference("useDefaultReplacementCost");
 
-    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
+    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
 
     $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
     return ($amount, $units_minus_grace, $chargeable_units);
index f2bf8bd..39e61a9 100644 (file)
@@ -40,7 +40,6 @@ use Koha::Database;
 use Koha::DateUtils;
 use Koha::Hold;
 use Koha::Holds;
-use Koha::IssuingRules;
 use Koha::ItemTypes;
 use Koha::Items;
 use Koha::Libraries;
@@ -2206,24 +2205,40 @@ patron category, itemtype, and library.
 sub GetHoldRule {
     my ( $categorycode, $itemtype, $branchcode ) = @_;
 
-    my $dbh = C4::Context->dbh;
-
-    my $sth = $dbh->prepare(
-        q{
-         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record, holds_per_day
-           FROM issuingrules
-          WHERE (categorycode in (?,'*') )
-            AND (itemtype IN (?,'*'))
-            AND (branchcode IN (?,'*'))
-       ORDER BY categorycode DESC,
-                itemtype     DESC,
-                branchcode   DESC
+    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
+        {
+            itemtype     => $itemtype,
+            categorycode => $categorycode,
+            branchcode   => $branchcode,
+            rule_name    => 'reservesallowed',
+            order_by     => {
+                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
+            }
         }
     );
+    return unless $reservesallowed;;
 
-    $sth->execute( $categorycode, $itemtype, $branchcode );
+    my $rules;
+    $rules->{reservesallowed} = $reservesallowed->rule_value;
+    $rules->{itemtype}        = $reservesallowed->itemtype;
+    $rules->{categorycode}    = $reservesallowed->categorycode;
+    $rules->{branchcode}      = $reservesallowed->branchcode;
+
+    my $holds_per_x_rules = Koha::CirculationRules->get_effective_rules(
+        {
+            itemtype     => $itemtype,
+            categorycode => $categorycode,
+            branchcode   => $branchcode,
+            rules        => ['holds_per_record', 'holds_per_day'],
+            order_by     => {
+                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
+            }
+        }
+    );
+    $rules->{holds_per_record} = $holds_per_x_rules->{holds_per_record};
+    $rules->{holds_per_day} = $holds_per_x_rules->{holds_per_day};
 
-    return $sth->fetchrow_hashref();
+    return $rules;
 }
 
 =head1 AUTHOR
index d5fe1f9..a95822c 100644 (file)
@@ -37,7 +37,7 @@ use Koha::ArticleRequest::Status;
 use Koha::ArticleRequests;
 use Koha::Biblio::Metadatas;
 use Koha::Biblioitems;
-use Koha::IssuingRules;
+use Koha::CirculationRules;
 use Koha::Item::Transfer::Limits;
 use Koha::Items;
 use Koha::Libraries;
@@ -299,10 +299,16 @@ sub article_request_type_for_bib {
     my $borrowertype = $borrower->categorycode;
     my $itemtype     = $self->itemtype();
 
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
+    my $rule = Koha::CirculationRules->get_effective_rule(
+        {
+            rule_name    => 'article_requests',
+            categorycode => $borrowertype,
+            itemtype     => $itemtype,
+        }
+    );
 
-    return q{} unless $issuing_rule;
-    return $issuing_rule->article_requests || q{}
+    return q{} unless $rule;
+    return $rule->rule_value || q{}
 }
 
 =head3 article_request_type_for_items
index 1294eeb..82ac198 100644 (file)
@@ -1,7 +1,6 @@
 package Koha::CirculationRules;
 
-# Copyright Vaara-kirjastot 2015
-# Copyright Koha Development Team 2016
+# Copyright ByWater Solutions 2017
 #
 # This file is part of Koha.
 #
@@ -42,6 +41,10 @@ Koha::CirculationRules - Koha CirculationRule Object set class
 sub get_effective_rule {
     my ( $self, $params ) = @_;
 
+    $params->{categorycode} = '*' if exists($params->{categorycode}) && !defined($params->{categorycode});
+    $params->{branchcode}   = '*' if exists($params->{branchcode})   && !defined($params->{branchcode});
+    $params->{itemtype}     = '*' if exists($params->{itemtype})     && !defined($params->{itemtype});
+
     my $rule_name    = $params->{rule_name};
     my $categorycode = $params->{categorycode};
     my $itemtype     = $params->{itemtype};
@@ -55,6 +58,9 @@ sub get_effective_rule {
         $v = undef if $v and $v eq '*';
     }
 
+    my $order_by = $params->{order_by}
+      // { -desc => [ 'branchcode', 'categorycode', 'itemtype' ] };
+
     my $search_params;
     $search_params->{rule_name} = $rule_name;
 
@@ -65,9 +71,7 @@ sub get_effective_rule {
     my $rule = $self->search(
         $search_params,
         {
-            order_by => {
-                -desc => [ 'branchcode', 'categorycode', 'itemtype' ]
-            },
+            order_by => $order_by,
             rows => 1,
         }
     )->single;
@@ -75,6 +79,35 @@ sub get_effective_rule {
     return $rule;
 }
 
+=head3 get_effective_rule
+
+=cut
+
+sub get_effective_rules {
+    my ( $self, $params ) = @_;
+
+    my $rules        = $params->{rules};
+    my $categorycode = $params->{categorycode};
+    my $itemtype     = $params->{itemtype};
+    my $branchcode   = $params->{branchcode};
+
+    my $r;
+    foreach my $rule (@$rules) {
+        my $effective_rule = $self->get_effective_rule(
+            {
+                rule_name    => $rule,
+                categorycode => $categorycode,
+                itemtype     => $itemtype,
+                branchcode   => $branchcode,
+            }
+        );
+
+        $r->{$rule} = $effective_rule->rule_value if $effective_rule;
+    }
+
+    return $r;
+}
+
 =head3 set_rule
 
 =cut
diff --git a/Koha/IssuingRule.pm b/Koha/IssuingRule.pm
deleted file mode 100644 (file)
index cb9ac70..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package Koha::IssuingRule;
-
-# Copyright Vaara-kirjastot 2015
-#
-# This file is part of Koha.
-#
-# Koha is free software; you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 3 of the License, or (at your option) any later
-# version.
-#
-# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with Koha; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-use Modern::Perl;
-use Koha::Database;
-use base qw(Koha::Object);
-
-=head1 NAME
-
-Koha::Hold - Koha Hold object class
-
-=head1 API
-
-=head2 Class Methods
-
-=cut
-
-=head3 delete
-
-=cut
-
-sub delete {
-    my ($self) = @_;
-
-    my $branchcode = $self->branchcode eq '*' ? undef : $self->branchcode;
-    my $categorycode = $self->categorycode eq '*' ? undef : $self->categorycode;
-    my $itemtype = $self->itemtype eq '*' ? undef : $self->itemtype;
-
-    Koha::CirculationRules->search({
-        branchcode   => $branchcode,
-        itemtype     => $itemtype,
-        categorycode => $categorycode,
-        rule_name => [qw(
-            maxissueqty
-            maxonsiteissueqty
-            max_holds
-        )],
-    })->delete;
-
-    $self->SUPER::delete;
-
-}
-
-=head3 type
-
-=cut
-
-sub _type {
-    return 'Issuingrule';
-}
-
-1;
index e77f819..e8e5e21 100644 (file)
@@ -29,7 +29,7 @@ use C4::Context;
 use C4::Circulation;
 use C4::Reserves;
 use Koha::Checkouts;
-use Koha::IssuingRules;
+use Koha::CirculationRules;
 use Koha::Item::Transfer::Limits;
 use Koha::Item::Transfers;
 use Koha::Patrons;
@@ -369,10 +369,17 @@ sub article_request_type {
       :                                      undef;
     my $borrowertype = $borrower->categorycode;
     my $itemtype = $self->effective_itemtype();
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
+    my $rule = Koha::CirculationRules->get_effective_rule(
+        {
+            rule_name    => 'article_requests',
+            categorycode => $borrowertype,
+            itemtype     => $itemtype,
+            branchcode   => $branchcode
+        }
+    );
 
-    return q{} unless $issuing_rule;
-    return $issuing_rule->article_requests || q{}
+    return q{} unless $rule;
+    return $rule->rule_value || q{}
 }
 
 =head3 current_holds
diff --git a/Koha/Schema/Result/Issuingrule.pm b/Koha/Schema/Result/Issuingrule.pm
deleted file mode 100644 (file)
index ecc549e..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-use utf8;
-package Koha::Schema::Result::Issuingrule;
-
-# Created by DBIx::Class::Schema::Loader
-# DO NOT MODIFY THE FIRST PART OF THIS FILE
-
-=head1 NAME
-
-Koha::Schema::Result::Issuingrule
-
-=cut
-
-use strict;
-use warnings;
-
-use base 'DBIx::Class::Core';
-
-=head1 TABLE: C<issuingrules>
-
-=cut
-
-__PACKAGE__->table("issuingrules");
-
-=head1 ACCESSORS
-
-=head2 categorycode
-
-  data_type: 'varchar'
-  default_value: (empty string)
-  is_nullable: 0
-  size: 10
-
-=head2 itemtype
-
-  data_type: 'varchar'
-  default_value: (empty string)
-  is_nullable: 0
-  size: 10
-
-=head2 restrictedtype
-
-  data_type: 'tinyint'
-  is_nullable: 1
-
-=head2 rentaldiscount
-
-  data_type: 'decimal'
-  is_nullable: 1
-  size: [28,6]
-
-=head2 reservecharge
-
-  data_type: 'decimal'
-  is_nullable: 1
-  size: [28,6]
-
-=head2 fine
-
-  data_type: 'decimal'
-  is_nullable: 1
-  size: [28,6]
-
-=head2 finedays
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 maxsuspensiondays
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 suspension_chargeperiod
-
-  data_type: 'integer'
-  default_value: 1
-  is_nullable: 1
-
-=head2 firstremind
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 chargeperiod
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 chargeperiod_charge_at
-
-  data_type: 'tinyint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 accountsent
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 issuelength
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 lengthunit
-
-  data_type: 'varchar'
-  default_value: 'days'
-  is_nullable: 1
-  size: 10
-
-=head2 hardduedate
-
-  data_type: 'date'
-  datetime_undef_if_invalid: 1
-  is_nullable: 1
-
-=head2 hardduedatecompare
-
-  data_type: 'tinyint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 renewalsallowed
-
-  data_type: 'smallint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 renewalperiod
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 norenewalbefore
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 auto_renew
-
-  data_type: 'tinyint'
-  default_value: 0
-  is_nullable: 1
-
-=head2 no_auto_renewal_after
-
-  data_type: 'integer'
-  is_nullable: 1
-
-=head2 no_auto_renewal_after_hard_limit
-
-  data_type: 'date'
-  datetime_undef_if_invalid: 1
-  is_nullable: 1
-
-=head2 reservesallowed
-
-  data_type: 'smallint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 holds_per_record
-
-  data_type: 'smallint'
-  default_value: 1
-  is_nullable: 0
-
-=head2 holds_per_day
-
-  data_type: 'smallint'
-  is_nullable: 1
-
-=head2 branchcode
-
-  data_type: 'varchar'
-  default_value: (empty string)
-  is_nullable: 0
-  size: 10
-
-=head2 overduefinescap
-
-  data_type: 'decimal'
-  is_nullable: 1
-  size: [28,6]
-
-=head2 cap_fine_to_replacement_price
-
-  data_type: 'tinyint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 onshelfholds
-
-  data_type: 'tinyint'
-  default_value: 0
-  is_nullable: 0
-
-=head2 opacitemholds
-
-  data_type: 'char'
-  default_value: 'N'
-  is_nullable: 0
-  size: 1
-
-=head2 article_requests
-
-  data_type: 'enum'
-  default_value: 'no'
-  extra: {list => ["no","yes","bib_only","item_only"]}
-  is_nullable: 0
-
-=head2 note
-
-  data_type: 'varchar'
-  is_nullable: 1
-  size: 100
-
-=cut
-
-__PACKAGE__->add_columns(
-  "categorycode",
-  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
-  "itemtype",
-  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
-  "restrictedtype",
-  { data_type => "tinyint", is_nullable => 1 },
-  "rentaldiscount",
-  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
-  "reservecharge",
-  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
-  "fine",
-  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
-  "finedays",
-  { data_type => "integer", is_nullable => 1 },
-  "maxsuspensiondays",
-  { data_type => "integer", is_nullable => 1 },
-  "suspension_chargeperiod",
-  { data_type => "integer", default_value => 1, is_nullable => 1 },
-  "firstremind",
-  { data_type => "integer", is_nullable => 1 },
-  "chargeperiod",
-  { data_type => "integer", is_nullable => 1 },
-  "chargeperiod_charge_at",
-  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
-  "accountsent",
-  { data_type => "integer", is_nullable => 1 },
-  "issuelength",
-  { data_type => "integer", is_nullable => 1 },
-  "lengthunit",
-  {
-    data_type => "varchar",
-    default_value => "days",
-    is_nullable => 1,
-    size => 10,
-  },
-  "hardduedate",
-  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
-  "hardduedatecompare",
-  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
-  "renewalsallowed",
-  { data_type => "smallint", default_value => 0, is_nullable => 0 },
-  "renewalperiod",
-  { data_type => "integer", is_nullable => 1 },
-  "norenewalbefore",
-  { data_type => "integer", is_nullable => 1 },
-  "auto_renew",
-  { data_type => "tinyint", default_value => 0, is_nullable => 1 },
-  "no_auto_renewal_after",
-  { data_type => "integer", is_nullable => 1 },
-  "no_auto_renewal_after_hard_limit",
-  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
-  "reservesallowed",
-  { data_type => "smallint", default_value => 0, is_nullable => 0 },
-  "holds_per_record",
-  { data_type => "smallint", default_value => 1, is_nullable => 0 },
-  "holds_per_day",
-  { data_type => "smallint", is_nullable => 1 },
-  "branchcode",
-  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
-  "overduefinescap",
-  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
-  "cap_fine_to_replacement_price",
-  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
-  "onshelfholds",
-  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
-  "opacitemholds",
-  { data_type => "char", default_value => "N", is_nullable => 0, size => 1 },
-  "article_requests",
-  {
-    data_type => "enum",
-    default_value => "no",
-    extra => { list => ["no", "yes", "bib_only", "item_only"] },
-    is_nullable => 0,
-  },
-  "note",
-  { data_type => "varchar", is_nullable => 1, size => 100 },
-);
-
-=head1 PRIMARY KEY
-
-=over 4
-
-=item * L</branchcode>
-
-=item * L</categorycode>
-
-=item * L</itemtype>
-
-=back
-
-=cut
-
-__PACKAGE__->set_primary_key("branchcode", "categorycode", "itemtype");
-
-
-# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-03-05 20:49:11
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6bPX0BRWWQZrWFun3GP86Q
-
-sub koha_object_class {
-    'Koha::IssuingRule';
-}
-sub koha_objects_class {
-    'Koha::IssuingRules';
-}
-
-1;
index 403f425..a8dc91e 100755 (executable)
@@ -26,8 +26,6 @@ use C4::Koha;
 use C4::Debug;
 use Koha::DateUtils;
 use Koha::Database;
-use Koha::IssuingRule;
-use Koha::IssuingRules;
 use Koha::Logger;
 use Koha::RefundLostItemFeeRules;
 use Koha::Libraries;
@@ -81,12 +79,41 @@ if ($op eq 'delete') {
     my $categorycode = $input->param('categorycode');
     $debug and warn "deleting $1 $2 $branch";
 
-    Koha::IssuingRules->find({
-        branchcode   => $branch,
-        categorycode => $categorycode,
-        itemtype     => $itemtype
-    })->delete;
-
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => $categorycode,
+            branchcode   => $branch,
+            itemtype     => $itemtype,
+            rules        => {
+                restrictedtype                   => undef,
+                rentaldiscount                   => undef,
+                fine                             => undef,
+                finedays                         => undef,
+                maxsuspensiondays                => undef,
+                firstremind                      => undef,
+                chargeperiod                     => undef,
+                chargeperiod_charge_at           => undef,
+                accountsent                      => undef,
+                issuelength                      => undef,
+                lengthunit                       => undef,
+                hardduedate                      => undef,
+                hardduedatecompare               => undef,
+                renewalsallowed                  => undef,
+                renewalperiod                    => undef,
+                norenewalbefore                  => undef,
+                auto_renew                       => undef,
+                no_auto_renewal_after            => undef,
+                no_auto_renewal_after_hard_limit => undef,
+                reservesallowed                  => undef,
+                holds_per_record                 => undef,
+                overduefinescap                  => undef,
+                cap_fine_to_replacement_price    => undef,
+                onshelfholds                     => undef,
+                opacitemholds                    => undef,
+                article_requests                 => undef,
+            }
+        }
+    );
 }
 elsif ($op eq 'delete-branch-cat') {
     my $categorycode  = $input->param('categorycode');
@@ -264,10 +291,9 @@ elsif ($op eq 'add') {
     my $note = $input->param('note');
     $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
 
-    my $params = {
-        branchcode                    => $br,
-        categorycode                  => $bor,
-        itemtype                      => $itemtype,
+    my $rules = {
+        maxissueqty                   => $maxissueqty,
+        maxonsiteissueqty             => $maxonsiteissueqty,
         fine                          => $fine,
         finedays                      => $finedays,
         maxsuspensiondays             => $maxsuspensiondays,
@@ -297,21 +323,12 @@ elsif ($op eq 'add') {
         note                          => $note,
     };
 
-    my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
-    if ($issuingrule) {
-        $issuingrule->set($params)->store();
-    } else {
-        Koha::IssuingRule->new()->set($params)->store();
-    }
     Koha::CirculationRules->set_rules(
         {
             categorycode => $bor,
             itemtype     => $itemtype,
             branchcode   => $br,
-            rules        => {
-                maxissueqty       => $maxissueqty,
-                maxonsiteissueqty => $maxonsiteissueqty,
-            }
+            rules        => $rules,
         }
     );
 
@@ -548,62 +565,16 @@ $template->param(
 
 my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
 
-my @row_loop;
 my $itemtypes = Koha::ItemTypes->search_with_localization;
 
-my $sth2 = $dbh->prepare("
-    SELECT  issuingrules.*,
-            itemtypes.description AS humanitemtype,
-            categories.description AS humancategorycode,
-            COALESCE( localization.translation, itemtypes.description ) AS translated_description
-    FROM issuingrules
-    LEFT JOIN itemtypes
-        ON (itemtypes.itemtype = issuingrules.itemtype)
-    LEFT JOIN categories
-        ON (categories.categorycode = issuingrules.categorycode)
-    LEFT JOIN localization ON issuingrules.itemtype = localization.code
-        AND localization.entity = 'itemtypes'
-        AND localization.lang = ?
-    WHERE issuingrules.branchcode = ?
-");
-$sth2->execute($language, $branch);
-
-while (my $row = $sth2->fetchrow_hashref) {
-    $row->{'current_branch'} ||= $row->{'branchcode'};
-    $row->{humanitemtype} ||= $row->{itemtype};
-    $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
-    $row->{'humancategorycode'} ||= $row->{'categorycode'};
-    $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
-    $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
-    if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
-       my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
-       $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
-       $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
-       $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
-       $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
-    } else {
-       $row->{'hardduedate'} = 0;
-    }
-    if ($row->{no_auto_renewal_after_hard_limit}) {
-       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
-       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
-    }
-
-    push @row_loop, $row;
-}
-
-my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
-
 $template->param(show_branch_cat_rule_form => 1);
 
 $template->param(
     patron_categories => $patron_categories,
-                        itemtypeloop => $itemtypes,
-                        rules => \@sorted_row_loop,
-                        humanbranch => ($branch ne '*' ? $branch : ''),
-                        current_branch => $branch,
-                        definedbranch => scalar(@sorted_row_loop)>0
-                        );
+    itemtypeloop      => $itemtypes,
+    humanbranch       => ( $branch ne '*' ? $branch : '' ),
+    current_branch    => $branch,
+);
 output_html_with_http_headers $input, $cookie, $template->output;
 
 exit 0;
diff --git a/installer/data/mysql/atomicupdate/bug_18936.perl b/installer/data/mysql/atomicupdate/bug_18936.perl
new file mode 100644 (file)
index 0000000..61b5fb9
--- /dev/null
@@ -0,0 +1,45 @@
+$DBversion = 'XXX';  # will be replaced by the RM
+if( CheckVersion( $DBversion ) ) {
+       my @columns = qw(
+               restrictedtype
+               rentaldiscount
+               fine
+               finedays
+               maxsuspensiondays
+               firstremind
+               chargeperiod
+               chargeperiod_charge_at
+               accountsent
+               issuelength
+               lengthunit
+               hardduedate
+               hardduedatecompare
+               renewalsallowed
+               renewalperiod
+               norenewalbefore
+               auto_renew
+               no_auto_renewal_after
+               no_auto_renewal_after_hard_limit
+               reservesallowed
+               holds_per_record
+               overduefinescap
+               cap_fine_to_replacement_price
+               onshelfholds
+               opacitemholds
+               article_requests
+       );
+
+    if ( column_exists( 'issuingrules', 'categorycode' ) ) {
+               foreach my $column ( @columns ) {
+                       $dbh->do("
+                               INSERT INTO circulation_rules ( categorycode, branchcode, itemtype, rule_name, rule_value )
+                               SELECT categorycode, branchcode, itemtype, 'column', $column
+                               FROM issuingrules
+                       ");
+               }
+        $dbh->do("DROP TABLE issuingrules");
+    }
+
+    SetVersion( $DBversion );
+    print "Upgrade to $DBversion done (Bug 18930 - Move lost item refund rules to circulation_rules table)\n";
+}
index b2d4d40..738c2ad 100644 (file)
@@ -1,17 +1,26 @@
 [% USE raw %]
 [% USE Asset %]
 [% USE Koha %]
+[% USE KohaDates %]
 [% USE Branches %]
 [% USE Categories %]
+[% USE ItemTypes %]
 [% USE CirculationRules %]
 [% SET footerjs = 1 %]
 
-[% SET branchcode = humanbranch %]
+[% SET branchcode = humanbranch || '*' %]
 
-[% SET categorycodes = ['*'] %]
+[% SET categorycodes = [] %]
 [% FOREACH pc IN patron_categories %]
     [% categorycodes.push( pc.id ) %]
 [% END %]
+[% categorycodes.push('*') %]
+
+[% SET itemtypes = [] %]
+[% FOREACH i IN itemtypeloop %]
+    [% itemtypes.push( i.itemtype ) %]
+[% END %]
+[% itemtypes.push('*') %]
 
 [% INCLUDE 'doc-head-open.inc' %]
 <title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
             </tr>
             </thead>
             <tbody>
-                               [% FOREACH rule IN rules %]
-                                       <tr id="row_[% loop.count | html %]">
-                                                       <td>[% IF ( rule.default_humancategorycode ) %]
-                                                                       <em>All</em>
-                                                               [% ELSE %]
-                                                                       [% rule.humancategorycode | html %]
-                                                               [% END %]
-                                                       </td>
-                            <td>[% IF rule.default_translated_description %]
-                                                                       <em>All</em>
-                                                               [% ELSE %]
-                                                                       [% rule.translated_description | html %]
-                                                               [% END %]
-                                                       </td>
-                                                        <td class="actions">
-                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
-                                                          <a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype | html %]&amp;categorycode=[% rule.categorycode | html %]&amp;branch=[% rule.current_branch | html %]"><i class="fa fa-trash"></i> Delete</a>
-                                                        </td>
-
-                                                        <td>
-                                                            [% IF rule.note %]
-                                                                <a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
-                                                            [% ELSE %]&nbsp;[% END %]
-                                                        </td>
-                            <td>
-                                [% SET rule_value = CirculationRules.Search( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
-                                [% IF rule_value || rule_value == "0"  %]
-                                    [% rule_value | html %]
-                                [% ELSE %]
-                                    <span>Unlimited</span>
-                                [% END %]
-                            </td>
-                            <td>
-                                [% SET rule_value = CirculationRules.Search( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
-                                [% IF rule_value || rule_value == "0" %]
-                                    [% rule_value | html %]
-                                [% ELSE %]
-                                    <span>Unlimited</span>
-                                [% END %]
-                            </td>
-                            <td>[% rule.issuelength | html %]</td>
-                            <td>
-                                [% IF ( rule.lengthunit == 'days' ) %]
-                                    Days
-                                [% ELSIF ( rule.lengthunit == 'hours') %]
-                                    Hours
-                                [% ELSE %]
-                                    Undefined
-                                [% END %]
-                            </td>
-                            <td>
-                              [% IF ( rule.hardduedate ) %]
-                                [% IF ( rule.hardduedatebefore ) %]
-                                  before [% rule.hardduedate | html %]
-                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
-                                [% ELSIF ( rule.hardduedateexact ) %]
-                                  on [% rule.hardduedate | html %]
-                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
-                                [% ELSIF ( rule.hardduedateafter ) %]
-                                  after [% rule.hardduedate | html %]
-                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
-                                [% END %]
-                              [% ELSE %]
-                                <span>None defined</span>
-                              [% END %]
-                            </td>
-                                                       <td>[% rule.fine | html %]</td>
-                                                       <td>[% rule.chargeperiod | html %]</td>
-                            <td>
-                                [% IF rule.chargeperiod_charge_at %]
-                                    <span>Start of interval</span>
-                                [% ELSE %]
-                                    <span>End of interval</span>
-                                [% END %]
-                            </td>
-                                                       <td>[% rule.firstremind | html %]</td>
-                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
-                            <td>
-                                [% IF rule.cap_fine_to_replacement_price %]
-                                    <input type="checkbox" checked="checked" disabled="disabled" />
-                                [% ELSE %]
-                                    <input type="checkbox" disabled="disabled" />
-                                [% END %]
-                            </td>
-                                                       <td>[% rule.finedays | html %]</td>
-                            <td>[% rule.maxsuspensiondays | html %]</td>
-                            <td>[% rule.suspension_chargeperiod | html %]</td>
-                                                       <td>[% rule.renewalsallowed | html %]</td>
-                            <td>[% rule.renewalperiod | html %]</td>
-                            <td>[% rule.norenewalbefore | html %]</td>
-                            <td>
-                                [% IF ( rule.auto_renew ) %]
-                                    <span>Yes</span>
-                                [% ELSE %]
-                                    <span>No</span>
-                                [% END %]
-                            </td>
-                            <td>[% rule.no_auto_renewal_after | html %]</td>
-                            <td>[% rule.no_auto_renewal_after_hard_limit | html %]</td>
-                                                       <td>[% rule.reservesallowed | html %]</td>
-                            <td>[% IF rule.unlimited_holds_per_day %]
-                                    <span>Unlimited</span>
-                                [% ELSE %]
-                                    [% rule.holds_per_day | html %]
-                                [% END %]
-                            </td>
-                            <td>[% rule.holds_per_record | html %]</td>
-                                                        <td>
-                                                            [% IF rule.onshelfholds == 1 %]
-                                                                <span>Yes</span>
-                                                            [% ELSIF rule.onshelfholds == 2 %]
-                                                                <span>If all unavailable</span>
-                                                            [% ELSE %]
-                                                                <span>If any unavailable</span>
-                                                            [% END %]
-                                                        </td>
-                                                        <td>
-                                                            [% IF rule.opacitemholds == 'F'%]
-                                                                <span>Force</span>
-                                                            [% ELSIF rule.opacitemholds == 'Y'%]
-                                                                <span>Allow</span>
-                                                            [% ELSE %]
-                                                                <span>Don't allow</span>
-                                                            [% END %]
-                                                        </td>
-                                                        <td>
-                                                            [% IF rule.article_requests == 'no' %]
-                                                                <span>No</span>
-                                                            [% ELSIF rule.article_requests == 'yes' %]
-                                                                <span>Yes</span>
-                                                            [% ELSIF rule.article_requests == 'bib_only' %]
-                                                                <span>Record only</span>
-                                                            [% ELSIF rule.article_requests == 'item_only' %]
-                                                                <span>Item only</span>
-                                                            [% END %]
-                                                        </td>
-                                                        <td>[% rule.rentaldiscount | html %]</td>
-                                                        <td class="actions">
-                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
-                                                          <a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype | html %]&amp;categorycode=[% rule.categorycode | html %]&amp;branch=[% rule.current_branch | html %]"><i class="fa fa-trash"></i> Delete</a>
-                                                        </td>
-
-                       </tr>
-               [% END %]
+                [% SET row_count = 0 %]
+                [% FOREACH c IN categorycodes %]
+                    [% FOREACH i IN itemtypes %]
+                        [% SET note = CirculationRules.Get( branchcode, c, i, 'note' ) %]
+                        [% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
+                        [% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
+                        [% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
+                        [% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
+                        [% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
+                        [% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
+                        [% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
+                        [% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
+                        [% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
+                        [% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
+                        [% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
+                        [% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
+                        [% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
+                        [% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
+                        [% SET suspension_chargeperiod = CirculationRules.Get( branchcode, c, i, 'suspension_chargeperiod' ) %]
+                        [% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
+                        [% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
+                        [% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
+                        [% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
+                        [% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
+                        [% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
+                        [% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
+                        [% SET holds_per_day = CirculationRules.Get( branchcode, c, i, 'holds_per_day' ) %]
+                        [% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
+                        [% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
+                        [% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
+                        [% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
+                        [% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
+
+                        [% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
+                                        || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed
+                                        || renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
+                                        || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
+                        [% IF show_rule %]
+                            [% SET row_count = row_count + 1 %]
+                            <tr row_countd="row_[% row_count %]">
+                                    <td>
+                                        [% IF c == '*' %]
+                                            <em>All</em>
+                                        [% ELSE %]
+                                            [% Categories.GetName(c) %]
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                        [% IF i == '*' %]
+                                            <em>All</em>
+                                        [% ELSE %]
+                                            [% ItemTypes.GetDescription(i) %]
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                        [% IF rule.note %]
+                                            <a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
+                                        [% ELSE %]<span>&nbsp;</span>[% END %]
+                                    </td>
+                                    <td>
+                                        [% IF maxissueqty  %]
+                                            [% maxissueqty %]
+                                        [% ELSE %]
+                                            <span>Unlimited</span>
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                        [% IF maxonsiteissueqty  %]
+                                            [% maxonsiteissueqty %]
+                                        [% ELSE %]
+                                            <span>Unlimited</span>
+                                        [% END %]
+                                    </td>
+                                    <td>[% issuelength %]</td>
+                                    <td>
+                                        [% IF ( lengthunit == 'days' ) %]
+                                            Days
+                                        [% ELSIF ( lengthunit == 'hours') %]
+                                            Hours
+                                        [% ELSE %]
+                                            Undefined
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                      [% IF ( hardduedate ) %]
+                                        [% IF ( hardduedatecompare == '-1' ) %]
+                                          before [% hardduedate | $KohaDates %]
+                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
+                                        [% ELSIF ( hardduedatecompare == '0' ) %]
+                                          on [% hardduedate | $KohaDates %]
+                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
+                                        [% ELSIF ( hardduedatecompare == '1' ) %]
+                                          after [% hardduedate | $KohaDates %]
+                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
+                                        [% END %]
+                                      [% ELSE %]
+                                        <span>None defined</span>
+                                      [% END %]
+                                    </td>
+                                    <td>[% fine %]</td>
+                                    <td>[% chargeperiod %]</td>
+                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
+                                    <td>[% firstremind %]</td>
+                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
+                                    <td>
+                                        [% IF cap_fine_to_replacement_price %]
+                                            <input type="checkbox" checked="checked" disabled="disabled" />
+                                        [% ELSE %]
+                                            <input type="checkbox" disabled="disabled" />
+                                        [% END %]
+                                    </td>
+                                    <td>[% finedays %]</td>
+                                    <td>[% maxsuspensiondays %]</td>
+                                    <td>[% suspension_chargeperiod %]</td>
+                                    <td>[% renewalsallowed %]</td>
+                                    <td>[% renewalperiod %]</td>
+                                    <td>[% norenewalbefore %]</td>
+                                    <td>
+                                        [% IF auto_renew %]
+                                            <span>Yes</span>
+                                        [% ELSE %]
+                                            <span>No</span>
+                                        [% END %]
+                                    </td>
+                                    <td>[% no_auto_renewal_after %]</td>
+                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
+                                    <td>[% reservesallowed %]</td>
+                                    <td>
+                                        [% IF holds_per_day.defined && holds != '' %]
+                                            [% holds_per_day %]
+                                        [% ELSE %]
+                                            <span>Unlimited</span>
+                                        [% END %]
+                                    </td>
+                                    <td>[% holds_per_record %]</td>
+                                    <td>
+                                        [% IF onshelfholds == 1 %]
+                                            <span>Yes</span>
+                                        [% ELSIF onshelfholds == 2 %]
+                                            <span>If all unavailable</span>
+                                        [% ELSE %]
+                                            <span>If any unavailable</span>
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                        [% IF opacitemholds == 'F'%]
+                                            <span>Force</span>
+                                        [% ELSIF opacitemholds == 'Y'%]
+                                            <span>Allow</span>
+                                        [% ELSE %]
+                                            <span>Don't allow</span>
+                                        [% END %]
+                                    </td>
+                                    <td>
+                                        [% IF article_requests == 'no' %]
+                                            <span>No</span>
+                                        [% ELSIF article_requests == 'yes' %]
+                                            <span>Yes</span>
+                                        [% ELSIF article_requests == 'bib_only' %]
+                                            <span>Record only</span>
+                                        [% ELSIF article_requests == 'item_only' %]
+                                            <span>Item only</span>
+                                        [% END %]
+                                    </td>
+                                    <td>[% rentaldiscount %]</td>
+                                    <td class="actions">
+                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
+                                      <a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype | uri %]&amp;categorycode=[% rule.categorycode | uri %]&amp;branch=[% rule.current_branch | uri %]"><i class="fa fa-trash"></i> Delete</a>
+                                    </td>
+                            </tr>
+                        [% END %]
+                    [% END %]
+                [% END %]
                 <tr id="edit_row">
                     <td>
                         <select name="categorycode" id="categorycode">
index 84ddbde..0acc9eb 100755 (executable)
@@ -29,7 +29,7 @@ use Koha::Biblio;
 use Koha::Notice::Messages;
 use Koha::Patron;
 use Koha::Library::Group;
-use Koha::IssuingRules;
+use Koha::CirculationRules;
 use Koha::Caches;
 
 BEGIN {
@@ -46,7 +46,7 @@ our $cache = Koha::Caches->get_instance;
 my $dbh = C4::Context->dbh;
 $dbh->{RaiseError} = 1;
 
-$dbh->do("DELETE FROM issuingrules");
+$dbh->do("DELETE FROM circulation_rules");
 
 my $biblio = Koha::Biblio->new()->store();
 ok( $biblio->id, 'Koha::Biblio created' );
@@ -172,33 +172,60 @@ $article_request->complete();
 $article_request->cancel();
 is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
 
-my $rule;
-$rule = $schema->resultset('Issuingrule')
-  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
+my $rule = Koha::CirculationRules->set_rule(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rule_name    => 'article_requests',
+        rule_value   => 'yes',
+    }
+);
 ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
 is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
 ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
 is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
 $rule->delete();
 
-$rule = $schema->resultset('Issuingrule')
-  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
+$rule = Koha::CirculationRules->set_rule(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rule_name    => 'article_requests',
+        rule_value   => 'bib_only',
+    }
+);
 ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
 is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
 ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
 is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
 $rule->delete();
 
-$rule = $schema->resultset('Issuingrule')
-  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
+$rule = Koha::CirculationRules->set_rule(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rule_name    => 'article_requests',
+        rule_value   => 'item_only',
+    }
+);
 ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
 is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
 ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
 is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
 $rule->delete();
 
-$rule = $schema->resultset('Issuingrule')
-  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
+$rule = Koha::CirculationRules->set_rule(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rule_name    => 'article_requests',
+        rule_value   => 'no',
+    }
+);
 ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
 is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
 ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
index 8bf9e56..a71bb1b 100755 (executable)
@@ -38,7 +38,6 @@ use C4::Reserves;
 use C4::Overdues qw(UpdateFine CalcFine);
 use Koha::DateUtils;
 use Koha::Database;
-use Koha::IssuingRules;
 use Koha::Items;
 use Koha::Checkouts;
 use Koha::Patrons;
@@ -252,27 +251,24 @@ is(
 );
 
 # Set a simple circ policy
-$dbh->do('DELETE FROM issuingrules');
-Koha::CirculationRules->search()->delete();
-$dbh->do(
-    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed,
-                                issuelength, lengthunit,
-                                renewalsallowed, renewalperiod,
-                                norenewalbefore, auto_renew,
-                                fine, chargeperiod)
-      VALUES (?, ?, ?, ?,
-              ?, ?,
-              ?, ?,
-              ?, ?,
-              ?, ?
-             )
-    },
-    {},
-    '*', '*', '*', 25,
-    14, 'days',
-    1, 7,
-    undef, 0,
-    .10, 1
+$dbh->do('DELETE FROM circulation_rules');
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => '*',
+        rules        => {
+            reservesallowed => 25,
+            issuelength     => 14,
+            lengthunit      => 'days',
+            renewalsallowed => 1,
+            renewalperiod   => 7,
+            norenewalbefore => undef,
+            auto_renew      => 0,
+            fine            => .10,
+            chargeperiod    => 1,
+        }
+    }
 );
 
 my ( $reused_itemnumber_1, $reused_itemnumber_2 );
@@ -394,7 +390,15 @@ subtest "CanBookBeRenewed tests" => sub {
     );
 
     # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
-    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
+    Koha::CirculationRules->set_rule(
+        {
+            categorycode => '*',
+            branchcode   => '*',
+            itemtype     => '*',
+            rule_name    => 'onshelfholds',
+            rule_value   => '1',
+        }
+    );
     t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
     ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
     is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
@@ -609,7 +613,15 @@ subtest "CanBookBeRenewed tests" => sub {
 
     # Bug 7413
     # Test premature manual renewal
-    $dbh->do('UPDATE issuingrules SET norenewalbefore = 7');
+    Koha::CirculationRules->set_rule(
+        {
+            categorycode => '*',
+            branchcode   => '*',
+            itemtype     => '*',
+            rule_name    => 'norenewalbefore',
+            rule_value   => '7',
+        }
+    );
 
     ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
     is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
@@ -644,7 +656,7 @@ subtest "CanBookBeRenewed tests" => sub {
 
     # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
     # and test automatic renewal again
-    $dbh->do('UPDATE issuingrules SET norenewalbefore = 0');
+    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
     ( $renewokay, $error ) =
       CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
     is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
@@ -654,7 +666,7 @@ subtest "CanBookBeRenewed tests" => sub {
 
     # Change policy so that loans can be renewed 99 days prior to the due date
     # and test automatic renewal again
-    $dbh->do('UPDATE issuingrules SET norenewalbefore = 99');
+    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
     ( $renewokay, $error ) =
       CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
     is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
@@ -678,43 +690,116 @@ subtest "CanBookBeRenewed tests" => sub {
         my $ten_days_ahead  = dt_from_string->add( days => 10 );
         AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '7',
+                    no_auto_renewal_after => '9',
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
         is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '7',
+                    no_auto_renewal_after => '10',
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
         is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '7',
+                    no_auto_renewal_after => '11',
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
         is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '11',
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0,            'Do not renew, renewal is automatic' );
         is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => -1 ) );
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => undef,
+                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
         is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => -1 ) );
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '7',
+                    no_auto_renewal_after => '15',
+                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
         is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 1 ) );
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => undef,
+                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 1 ),
+                }
+            }
+        );
         ( $renewokay, $error ) =
           CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $renewokay, 0, 'Do not renew, renewal is automatic' );
@@ -736,7 +821,17 @@ subtest "CanBookBeRenewed tests" => sub {
         my $ten_days_ahead = dt_from_string->add( days => 10 );
         AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
 
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '11',
+                }
+            }
+        );
         C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
         C4::Context->set_preference('OPACFineNoRenewals','10');
         C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','1');
@@ -874,31 +969,89 @@ subtest "CanBookBeRenewed tests" => sub {
         my $ten_days_before = dt_from_string->add( days => -10 );
         my $ten_days_ahead  = dt_from_string->add( days => 10 );
         AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = NULL');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '7',
+                    no_auto_renewal_after => '',
+                    no_auto_renewal_after_hard_limit => undef,
+                }
+            }
+        );
         my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $latest_auto_renew_date, undef, 'GetLatestAutoRenewDate should return undef if no_auto_renewal_after or no_auto_renewal_after_hard_limit are not defined' );
         my $five_days_before = dt_from_string->add( days => -5 );
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '5',
+                    no_auto_renewal_after_hard_limit => undef,
+                }
+            }
+        );
         $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $latest_auto_renew_date->truncate( to => 'minute' ),
             $five_days_before->truncate( to => 'minute' ),
             'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
         );
         my $five_days_ahead = dt_from_string->add( days => 5 );
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
+        $dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
+        $dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
+        $dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '15',
+                    no_auto_renewal_after_hard_limit => undef,
+                }
+            }
+        );
         $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $latest_auto_renew_date->truncate( to => 'minute' ),
             $five_days_ahead->truncate( to => 'minute' ),
             'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
         );
         my $two_days_ahead = dt_from_string->add( days => 2 );
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '',
+                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
+                }
+            }
+        );
         $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $latest_auto_renew_date->truncate( to => 'day' ),
             $two_days_ahead->truncate( to => 'day' ),
             'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
         );
-        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
+        Koha::CirculationRules->set_rules(
+            {
+                categorycode => '*',
+                branchcode   => '*',
+                itemtype     => '*',
+                rules        => {
+                    norenewalbefore       => '10',
+                    no_auto_renewal_after => '15',
+                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
+                }
+            }
+        );
         $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
         is( $latest_auto_renew_date->truncate( to => 'day' ),
             $two_days_ahead->truncate( to => 'day' ),
@@ -906,11 +1059,20 @@ subtest "CanBookBeRenewed tests" => sub {
         );
 
     };
-
     # Too many renewals
 
     # set policy to forbid renewals
-    $dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            branchcode   => '*',
+            itemtype     => '*',
+            rules        => {
+                norenewalbefore => undef,
+                renewalsallowed => 0,
+            }
+        }
+    );
 
     ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
     is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
@@ -1145,27 +1307,23 @@ subtest "Bug 13841 - Do not create new 0 amount fines" => sub {
 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
     $dbh->do('DELETE FROM issues');
     $dbh->do('DELETE FROM items');
-    $dbh->do('DELETE FROM issuingrules');
-    Koha::CirculationRules->search()->delete();
-    $dbh->do(
-        q{
-        INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
-                    norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
-        },
-        {},
-        '*', '*', '*', 25,
-        14,  'days',
-        1,   7,
-        undef,  0,
-        .10, 1
-    );
+    $dbh->do('DELETE FROM circulation_rules');
     Koha::CirculationRules->set_rules(
         {
             categorycode => '*',
             itemtype     => '*',
             branchcode   => '*',
             rules        => {
-                maxissueqty => 20
+                reservesallowed => 25,
+                issuelength     => 14,
+                lengthunit      => 'days',
+                renewalsallowed => 1,
+                renewalperiod   => 7,
+                norenewalbefore => undef,
+                auto_renew      => 0,
+                fine            => .10,
+                chargeperiod    => 1,
+                maxissueqty     => 20
             }
         }
     );
@@ -1214,22 +1372,58 @@ subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
         undef, undef, undef
     );
 
-    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+            rules        => {
+                onshelfholds => 0,
+            }
+        }
+    );
     t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
     ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
     is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
 
-    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+            rules        => {
+                onshelfholds => 0,
+            }
+        }
+    );
     t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
     ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
     is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
 
-    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+            rules        => {
+                onshelfholds => 1,
+            }
+        }
+    );
     t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
     ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
     is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
 
-    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+            rules        => {
+                onshelfholds => 1,
+            }
+        }
+    );
     t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
     ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
     is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
@@ -1706,20 +1900,21 @@ subtest 'AddReturn + CumulativeRestrictionPeriods' => sub {
         }
     )->unblessed;
 
-    # And the issuing rule
-    Koha::IssuingRules->search->delete;
-    my $rule = Koha::IssuingRule->new(
+    # And the circulation rule
+    Koha::CirculationRules->search->delete;
+    Koha::CirculationRules->set_rules(
         {
             categorycode => '*',
             itemtype     => '*',
             branchcode   => '*',
-            issuelength  => 1,
-            firstremind  => 1,        # 1 day of grace
-            finedays     => 2,        # 2 days of fine per day of overdue
-            lengthunit   => 'days',
+            rules        => {
+                issuelength => 1,
+                firstremind => 1,        # 1 day of grace
+                finedays    => 2,        # 2 days of fine per day of overdue
+                lengthunit  => 'days',
+            }
         }
     );
-    $rule->store();
 
     # Patron cannot issue item_1, they have overdues
     my $five_days_ago = dt_from_string->subtract( days => 5 );
@@ -2017,19 +2212,20 @@ subtest 'AddReturn | is_overdue' => sub {
         }
     )->unblessed;
 
-    Koha::IssuingRules->search->delete;
-    my $rule = Koha::IssuingRule->new(
+    Koha::CirculationRules->search->delete;
+    my $rule = Koha::CirculationRules->set_rules(
         {
             categorycode => '*',
             itemtype     => '*',
             branchcode   => '*',
-            issuelength  => 6,
-            lengthunit   => 'days',
-            fine         => 1, # Charge 1 every day of overdue
-            chargeperiod => 1,
+            rules        => {
+                issuelength  => 6,
+                lengthunit   => 'days',
+                fine         => 1,        # Charge 1 every day of overdue
+                chargeperiod => 1,
+            }
         }
     );
-    $rule->store();
 
     my $now   = dt_from_string;
     my $one_day_ago   = dt_from_string->subtract( days => 1 );
index 35829ea..b154c1f 100644 (file)
@@ -10,6 +10,8 @@ use t::lib::Mocks;
 use t::lib::TestBuilder;
 use C4::Calendar;
 
+use Koha::CirculationRules;
+
 use_ok('C4::Circulation');
 
 my $schema = Koha::Database->new->schema;
@@ -23,14 +25,19 @@ my $issuelength = 10;
 my $renewalperiod = 5;
 my $lengthunit = 'days';
 
-Koha::Database->schema->resultset('Issuingrule')->create({
-  categorycode => $categorycode,
-  itemtype => $itemtype,
-  branchcode => $branchcode,
-  issuelength => $issuelength,
-  renewalperiod => $renewalperiod,
-  lengthunit => $lengthunit,
-});
+Koha::CirculationRules->search()->delete();
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => $categorycode,
+        itemtype     => $itemtype,
+        branchcode   => $branchcode,
+        rules        => {
+            issuelength   => $issuelength,
+            renewalperiod => $renewalperiod,
+            lengthunit    => $lengthunit,
+        }
+    }
+);
 
 #Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
 t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
index f9104fe..daff962 100644 (file)
@@ -78,19 +78,12 @@ my $item = $builder->build(
 subtest 'Test basic functionality' => sub {
     plan tests => 1;
 
-    my $rule = $builder->schema->resultset('Issuingrule')->find({
-        branchcode                    => '*',
-        categorycode                  => '*',
-        itemtype                      => '*',
-    });
-    $rule->delete if $rule;
-    my $issuingrule = $builder->build(
+    Koha::CirculationRules->set_rules(
         {
-            source => 'Issuingrule',
-            value  => {
-                branchcode                    => '*',
-                categorycode                  => '*',
-                itemtype                      => '*',
+            branchcode   => '*',
+            categorycode => '*',
+            itemtype     => '*',
+            rules        => {
                 fine                          => '1.00',
                 lengthunit                    => 'days',
                 finedays                      => 0,
@@ -98,8 +91,8 @@ subtest 'Test basic functionality' => sub {
                 chargeperiod                  => 1,
                 overduefinescap               => undef,
                 cap_fine_to_replacement_price => 0,
-            },
-        }
+            }
+        },
     );
 
     my $start_dt = DateTime->new(
@@ -125,13 +118,12 @@ subtest 'Test cap_fine_to_replacement_price' => sub {
     plan tests => 2;
 
     t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
-    my $issuingrule = $builder->build(
+    Koha::CirculationRules->set_rules(
         {
-            source => 'Issuingrule',
-            value  => {
-                branchcode                    => '*',
-                categorycode                  => '*',
-                itemtype                      => '*',
+            branchcode   => '*',
+            categorycode => '*',
+            itemtype     => '*',
+            rules        => {
                 fine                          => '1.00',
                 lengthunit                    => 'days',
                 finedays                      => 0,
@@ -214,5 +206,5 @@ subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub {
 };
 
 sub teardown {
-    $dbh->do(q|DELETE FROM issuingrules|);
+    $dbh->do(q|DELETE FROM circulation_rules|);
 }
index c70c727..0968213 100644 (file)
@@ -5,10 +5,10 @@ use C4::Context;
 use DateTime;
 use Koha::Database;
 use Koha::DateUtils;
-use Koha::IssuingRules;
+use Koha::CirculationRules;
 use Koha::Library;
 
-use Test::More tests => 9;
+use Test::More tests => 8;
 
 BEGIN {
     use_ok('C4::Circulation');
@@ -31,7 +31,7 @@ $dbh->do(q|DELETE FROM borrowers|);
 $dbh->do(q|DELETE FROM edifact_ean|);
 $dbh->do(q|DELETE FROM branches|);
 $dbh->do(q|DELETE FROM categories|);
-$dbh->do(q|DELETE FROM issuingrules|);
+$dbh->do(q|DELETE FROM circulation_rules|);
 
 #Add sample datas
 
@@ -111,219 +111,111 @@ my $default = {
     lengthunit => 'days'
 };
 
-#Test GetIssuingRule
+#Test get_effective_rules
 my $sampleissuingrule1 = {
-    reservecharge      => 0,
-    restrictedtype     => 0,
-    accountsent        => 0,
-    finedays           => 0,
-    lengthunit         => 'days',
-    renewalperiod      => 5,
-    norenewalbefore    => 6,
-    auto_renew         => 0,
-    issuelength        => 5,
-    chargeperiod       => 0,
-    chargeperiod_charge_at => 0,
-    rentaldiscount     => 2,
-    reservesallowed    => 0,
-    hardduedate        => '2013-01-01',
-    branchcode         => $samplebranch1->{branchcode},
-    fine               => 0,
-    hardduedatecompare => 0,
-    overduefinescap    => 0,
-    renewalsallowed    => 0,
-    firstremind        => 0,
-    itemtype           => 'BOOK',
-    categorycode       => $samplecat->{categorycode},
-    maxsuspensiondays  => 0,
-    onshelfholds       => 0,
-    opacitemholds      => 'N',
-    cap_fine_to_replacement_price => 0,
-    holds_per_record   => 1,
-    article_requests   => 'yes',
-    no_auto_renewal_after => undef,
-    no_auto_renewal_after_hard_limit => undef,
-    suspension_chargeperiod => 1,
-    holds_per_day => undef,
+    branchcode   => $samplebranch1->{branchcode},
+    categorycode => $samplecat->{categorycode},
+    itemtype     => 'BOOK',
+    rules        => {
+        reservecharge                    => 0,
+        restrictedtype                   => 0,
+        accountsent                      => 0,
+        finedays                         => 0,
+        lengthunit                       => 'days',
+        renewalperiod                    => 5,
+        norenewalbefore                  => 6,
+        auto_renew                       => 0,
+        issuelength                      => 5,
+        chargeperiod                     => 0,
+        chargeperiod_charge_at           => 0,
+        rentaldiscount                   => 2,
+        reservesallowed                  => 0,
+        hardduedate                      => '2013-01-01',
+        fine                             => 0,
+        hardduedatecompare               => 5,
+        overduefinescap                  => 0,
+        renewalsallowed                  => 0,
+        firstremind                      => 0,
+        maxsuspensiondays                => 0,
+        onshelfholds                     => 0,
+        opacitemholds                    => 'N',
+        cap_fine_to_replacement_price    => 0,
+        holds_per_record                 => 1,
+        article_requests                 => 'yes',
+        no_auto_renewal_after            => undef,
+        no_auto_renewal_after_hard_limit => undef,
+        suspension_chargeperiod          => 1,
+        holds_per_day                    => undef,
+    }
 };
 my $sampleissuingrule2 = {
-    branchcode         => $samplebranch2->{branchcode},
-    categorycode       => $samplecat->{categorycode},
-    itemtype           => 'BOOK',
-    renewalsallowed    => 0,
-    renewalperiod      => 2,
-    norenewalbefore    => 7,
-    auto_renew         => 0,
-    reservesallowed    => 0,
-    issuelength        => 2,
-    lengthunit         => 'days',
-    hardduedate        => undef,
-    hardduedatecompare => 0,
-    fine               => undef,
-    finedays           => undef,
-    firstremind        => undef,
-    chargeperiod       => undef,
-    chargeperiod_charge_at => 0,
-    rentaldiscount     => 2.00,
-    overduefinescap    => undef,
-    accountsent        => undef,
-    reservecharge      => undef,
-    restrictedtype     => undef,
-    maxsuspensiondays  => 0,
-    onshelfholds       => 1,
-    opacitemholds      => 'Y',
-    cap_fine_to_replacement_price => 0,
-    holds_per_record   => 1,
-    article_requests   => 'yes',
+    branchcode   => $samplebranch2->{branchcode},
+    categorycode => $samplecat->{categorycode},
+    itemtype     => 'BOOK',
+    rules        => {
+        renewalsallowed               => 0,
+        renewalperiod                 => 2,
+        norenewalbefore               => 7,
+        auto_renew                    => 0,
+        reservesallowed               => 0,
+        issuelength                   => 2,
+        lengthunit                    => 'days',
+        hardduedate                   => 2,
+        hardduedatecompare            => undef,
+        fine                          => undef,
+        finedays                      => undef,
+        firstremind                   => undef,
+        chargeperiod                  => undef,
+        chargeperiod_charge_at        => 0,
+        rentaldiscount                => 2.00,
+        overduefinescap               => undef,
+        accountsent                   => undef,
+        reservecharge                 => undef,
+        restrictedtype                => undef,
+        maxsuspensiondays             => 0,
+        onshelfholds                  => 1,
+        opacitemholds                 => 'Y',
+        cap_fine_to_replacement_price => 0,
+        holds_per_record              => 1,
+        article_requests              => 'yes',
+    }
 };
 my $sampleissuingrule3 = {
-    branchcode         => $samplebranch1->{branchcode},
-    categorycode       => $samplecat->{categorycode},
-    itemtype           => 'DVD',
-    renewalsallowed    => 0,
-    renewalperiod      => 3,
-    norenewalbefore    => 8,
-    auto_renew         => 0,
-    reservesallowed    => 0,
-    issuelength        => 3,
-    lengthunit         => 'days',
-    hardduedate        => undef,
-    hardduedatecompare => 0,
-    fine               => undef,
-    finedays           => undef,
-    firstremind        => undef,
-    chargeperiod       => undef,
-    chargeperiod_charge_at => 0,
-    rentaldiscount     => 3.00,
-    overduefinescap    => undef,
-    accountsent        => undef,
-    reservecharge      => undef,
-    restrictedtype     => undef,
-    maxsuspensiondays  => 0,
-    onshelfholds       => 1,
-    opacitemholds      => 'F',
-    cap_fine_to_replacement_price => 0,
-    holds_per_record   => 1,
-    article_requests   => 'yes',
+    branchcode   => $samplebranch1->{branchcode},
+    categorycode => $samplecat->{categorycode},
+    itemtype     => 'DVD',
+    rules        => {
+        renewalsallowed               => 0,
+        renewalperiod                 => 3,
+        norenewalbefore               => 8,
+        auto_renew                    => 0,
+        reservesallowed               => 0,
+        issuelength                   => 3,
+        lengthunit                    => 'days',
+        hardduedate                   => 3,
+        hardduedatecompare            => undef,
+        fine                          => undef,
+        finedays                      => undef,
+        firstremind                   => undef,
+        chargeperiod                  => undef,
+        chargeperiod_charge_at        => 0,
+        rentaldiscount                => 3.00,
+        overduefinescap               => undef,
+        accountsent                   => undef,
+        reservecharge                 => undef,
+        restrictedtype                => undef,
+        maxsuspensiondays             => 0,
+        onshelfholds                  => 1,
+        opacitemholds                 => 'F',
+        cap_fine_to_replacement_price => 0,
+        holds_per_record              => 1,
+        article_requests              => 'yes',
+    }
 };
 
-$query = 'INSERT INTO issuingrules (
-                branchcode,
-                categorycode,
-                itemtype,
-                renewalsallowed,
-                renewalperiod,
-                norenewalbefore,
-                auto_renew,
-                reservesallowed,
-                issuelength,
-                lengthunit,
-                hardduedate,
-                hardduedatecompare,
-                fine,
-                finedays,
-                firstremind,
-                chargeperiod,
-                chargeperiod_charge_at,
-                rentaldiscount,
-                overduefinescap,
-                accountsent,
-                reservecharge,
-                restrictedtype,
-                maxsuspensiondays,
-                onshelfholds,
-                opacitemholds,
-                cap_fine_to_replacement_price,
-                article_requests
-                ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
-my $sth = $dbh->prepare($query);
-$sth->execute(
-    $sampleissuingrule1->{branchcode},
-    $sampleissuingrule1->{categorycode},
-    $sampleissuingrule1->{itemtype},
-    $sampleissuingrule1->{renewalsallowed},
-    $sampleissuingrule1->{renewalperiod},
-    $sampleissuingrule1->{norenewalbefore},
-    $sampleissuingrule1->{auto_renew},
-    $sampleissuingrule1->{reservesallowed},
-    $sampleissuingrule1->{issuelength},
-    $sampleissuingrule1->{lengthunit},
-    $sampleissuingrule1->{hardduedate},
-    $sampleissuingrule1->{hardduedatecompare},
-    $sampleissuingrule1->{fine},
-    $sampleissuingrule1->{finedays},
-    $sampleissuingrule1->{firstremind},
-    $sampleissuingrule1->{chargeperiod},
-    $sampleissuingrule1->{chargeperiod_charge_at},
-    $sampleissuingrule1->{rentaldiscount},
-    $sampleissuingrule1->{overduefinescap},
-    $sampleissuingrule1->{accountsent},
-    $sampleissuingrule1->{reservecharge},
-    $sampleissuingrule1->{restrictedtype},
-    $sampleissuingrule1->{maxsuspensiondays},
-    $sampleissuingrule1->{onshelfholds},
-    $sampleissuingrule1->{opacitemholds},
-    $sampleissuingrule1->{cap_fine_to_replacement_price},
-    $sampleissuingrule1->{article_requests},
-);
-$sth->execute(
-    $sampleissuingrule2->{branchcode},
-    $sampleissuingrule2->{categorycode},
-    $sampleissuingrule2->{itemtype},
-    $sampleissuingrule2->{renewalsallowed},
-    $sampleissuingrule2->{renewalperiod},
-    $sampleissuingrule2->{norenewalbefore},
-    $sampleissuingrule2->{auto_renew},
-    $sampleissuingrule2->{reservesallowed},
-    $sampleissuingrule2->{issuelength},
-    $sampleissuingrule2->{lengthunit},
-    $sampleissuingrule2->{hardduedate},
-    $sampleissuingrule2->{hardduedatecompare},
-    $sampleissuingrule2->{fine},
-    $sampleissuingrule2->{finedays},
-    $sampleissuingrule2->{firstremind},
-    $sampleissuingrule2->{chargeperiod},
-    $sampleissuingrule2->{chargeperiod_charge_at},
-    $sampleissuingrule2->{rentaldiscount},
-    $sampleissuingrule2->{overduefinescap},
-    $sampleissuingrule2->{accountsent},
-    $sampleissuingrule2->{reservecharge},
-    $sampleissuingrule2->{restrictedtype},
-    $sampleissuingrule2->{maxsuspensiondays},
-    $sampleissuingrule2->{onshelfholds},
-    $sampleissuingrule2->{opacitemholds},
-    $sampleissuingrule2->{cap_fine_to_replacement_price},
-    $sampleissuingrule2->{article_requests},
-);
-$sth->execute(
-    $sampleissuingrule3->{branchcode},
-    $sampleissuingrule3->{categorycode},
-    $sampleissuingrule3->{itemtype},
-    $sampleissuingrule3->{renewalsallowed},
-    $sampleissuingrule3->{renewalperiod},
-    $sampleissuingrule3->{norenewalbefore},
-    $sampleissuingrule3->{auto_renew},
-    $sampleissuingrule3->{reservesallowed},
-    $sampleissuingrule3->{issuelength},
-    $sampleissuingrule3->{lengthunit},
-    $sampleissuingrule3->{hardduedate},
-    $sampleissuingrule3->{hardduedatecompare},
-    $sampleissuingrule3->{fine},
-    $sampleissuingrule3->{finedays},
-    $sampleissuingrule3->{firstremind},
-    $sampleissuingrule3->{chargeperiod},
-    $sampleissuingrule3->{chargeperiod_charge_at},
-    $sampleissuingrule3->{rentaldiscount},
-    $sampleissuingrule3->{overduefinescap},
-    $sampleissuingrule3->{accountsent},
-    $sampleissuingrule3->{reservecharge},
-    $sampleissuingrule3->{restrictedtype},
-    $sampleissuingrule3->{maxsuspensiondays},
-    $sampleissuingrule3->{onshelfholds},
-    $sampleissuingrule3->{opacitemholds},
-    $sampleissuingrule3->{cap_fine_to_replacement_price},
-    $sampleissuingrule3->{article_requests},
-);
+Koha::CirculationRules->set_rules( $sampleissuingrule1 );
+Koha::CirculationRules->set_rules( $sampleissuingrule2 );
+Koha::CirculationRules->set_rules( $sampleissuingrule3 );
 
 #Test GetLoanLength
 is_deeply(
@@ -371,8 +263,8 @@ my @hardduedate = C4::Circulation::GetHardDueDate( $samplecat->{categorycode},
 is_deeply(
     \@hardduedate,
     [
-        dt_from_string( $sampleissuingrule1->{hardduedate}, 'iso' ),
-        $sampleissuingrule1->{hardduedatecompare}
+        dt_from_string( $sampleissuingrule1->{rules}->{hardduedate}, 'iso' ),
+        $sampleissuingrule1->{rules}->{hardduedatecompare}
     ],
     "GetHardDueDate returns the duedate and the duedatecompare"
 );
index a587398..1662d30 100644 (file)
@@ -29,17 +29,16 @@ my $patron_category = $builder->build({ source => 'Category' });
 t::lib::Mocks::mock_userenv({ branchcode => $branchcode });
 
 # Test without maxsuspensiondays set
-Koha::IssuingRules->search->delete;
-$builder->build(
+Koha::CirculationRules->search->delete;
+Koha::CirculationRules->set_rules(
     {
-        source => 'Issuingrule',
-        value  => {
-            categorycode => '*',
-            itemtype     => '*',
-            branchcode   => '*',
-            firstremind  => 0,
-            finedays     => 2,
-            lengthunit   => 'days',
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            firstremind => 0,
+            finedays    => 2,
+            lengthunit  => 'days',
             suspension_chargeperiod => 1,
         }
     }
@@ -87,8 +86,16 @@ is(
 DelDebarment( $debarments->[0]->{borrower_debarment_id} );
 
 # Test with maxsuspensiondays = 10 days
-my $issuing_rule = Koha::IssuingRules->search->next;
-$issuing_rule->maxsuspensiondays( 10 )->store;
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            maxsuspensiondays => 10,
+        }
+    }
+);
 
 my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
 AddIssue( $borrower, $barcode, $daysago20 );
index 5def587..c931d36 100644 (file)
@@ -57,16 +57,16 @@ my $schema = Koha::Database->schema;
 $schema->storage->txn_begin;
 
 my $builder = t::lib::TestBuilder->new();
-Koha::IssuingRules->search->delete;
-my $rule = Koha::IssuingRule->new(
+Koha::CirculationRules->search->delete;
+Koha::CirculationRules->set_rule(
     {
         categorycode => '*',
         itemtype     => '*',
         branchcode   => '*',
-        issuelength  => 1,
+        rule_name    => 'issuelength',
+        rule_value   => 1,
     }
 );
-$rule->store();
 
 subtest "AddReturn logging on statistics table (item-level_itypes=1)" => sub {
 
@@ -254,7 +254,18 @@ subtest 'Handle ids duplication' => sub {
     t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
     t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
     t::lib::Mocks::mock_preference( 'finesMode', 'production' );
-    Koha::IssuingRules->search->update({ chargeperiod => 1, fine => 1, firstremind => 1, });
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            itemtype     => '*',
+            branchcode   => '*',
+            rules        => {
+                chargeperiod => 1,
+                fine         => 1,
+                firstremind  => 1,
+            }
+        }
+    );
 
     my $biblio = $builder->build( { source => 'Biblio' } );
     my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
index fed7bc2..0a654a8 100644 (file)
@@ -38,7 +38,7 @@ $schema->storage->txn_begin;
 our $dbh = C4::Context->dbh;
 
 $dbh->do(q|DELETE FROM issues|);
-$dbh->do(q|DELETE FROM issuingrules|);
+$dbh->do(q|DELETE FROM circulation_rules|);
 
 my $builder = t::lib::TestBuilder->new();
 
@@ -81,18 +81,6 @@ my $item = $builder->build({
     },
 });
 
-my $issuingrule = $builder->build({
-    source => 'Issuingrule',
-    value => {
-        branchcode         => $branch->{branchcode},
-        categorycode       => '*',
-        itemtype           => '*',
-        lengthunit         => 'days',
-        issuelength        => 5,
-        hardduedate        => undef,
-        hardduedatecompare => 0,
-    },
-});
 Koha::CirculationRules->search()->delete();
 Koha::CirculationRules->set_rules(
     {
@@ -102,6 +90,13 @@ Koha::CirculationRules->set_rules(
         rules        => {
             maxissueqty       => 2,
             maxonsiteissueqty => 1,
+            branchcode        => $branch->{branchcode},
+            categorycode      => '*',
+            itemtype          => '*',
+            lengthunit        => 'days',
+            issuelength       => 5,
+            hardduedate        => undef,
+            hardduedatecompare => 0,
         }
     }
 );
index 8c86cbc..f813ed0 100644 (file)
@@ -43,7 +43,6 @@ $dbh->do(q|DELETE FROM branches|);
 $dbh->do(q|DELETE FROM categories|);
 $dbh->do(q|DELETE FROM accountlines|);
 $dbh->do(q|DELETE FROM itemtypes|);
-$dbh->do(q|DELETE FROM issuingrules|);
 Koha::CirculationRules->search()->delete();
 
 my $builder = t::lib::TestBuilder->new();
@@ -423,6 +422,17 @@ subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub {
     );
 
     teardown();
+    Koha::CirculationRules->set_rules(
+        {
+            branchcode   => $branch->{branchcode},
+            categorycode => $category->{categorycode},
+            itemtype     => undef,
+            rules        => {
+                maxissueqty       => 1,
+                maxonsiteissueqty => 1,
+            }
+        }
+    );
 
     $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
     like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
@@ -705,6 +715,6 @@ $schema->storage->txn_rollback;
 
 sub teardown {
     $dbh->do(q|DELETE FROM issues|);
-    $dbh->do(q|DELETE FROM issuingrules|);
+    $dbh->do(q|DELETE FROM circulation_rules|);
 }
 
index 81d98bd..7d391a4 100644 (file)
@@ -35,6 +35,7 @@ use Koha::Holds;
 use Koha::Items;
 use Koha::Library;
 use Koha::Patrons;
+use Koha::CirculationRules;
 
 BEGIN {
     require_ok('C4::Circulation');
@@ -66,7 +67,7 @@ $dbh->do(q|DELETE FROM items|);
 $dbh->do(q|DELETE FROM borrowers|);
 $dbh->do(q|DELETE FROM categories|);
 $dbh->do(q|DELETE FROM accountlines|);
-$dbh->do(q|DELETE FROM issuingrules|);
+$dbh->do(q|DELETE FROM circulation_rules|);
 $dbh->do(q|DELETE FROM reserves|);
 $dbh->do(q|DELETE FROM old_reserves|);
 $dbh->do(q|DELETE FROM statistics|);
@@ -316,9 +317,16 @@ is_deeply(
 );
 
 # Add a default rule: renewal is allowed
-$dbh->do(q|
-    UPDATE issuingrules SET renewalsallowed = 3
-|);
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            renewalsallowed => 3,
+        }
+    }
+);
 @renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
 is_deeply(
     \@renewcount,
index daa975b..a72754f 100755 (executable)
@@ -25,6 +25,7 @@ use Koha::Biblio;
 use Koha::Item;
 use Koha::Holds;
 use Koha::Hold;
+use Koha::CirculationRules;
 use t::lib::TestBuilder;
 use t::lib::Mocks;
 
@@ -96,15 +97,14 @@ for my $i ( 0 .. 5 ) {
 my $item   = pop(@items);
 my $patron = pop(@patrons);
 
-$builder->build(
+Koha::CirculationRules->set_rules(
     {
-        source => 'Issuingrule',
-        value => {
-            branchcode => '*',
-            categorycode => '*',
-            itemtype => $item->itype,
-            issuelength => '14',
-            lengthunit => 'days',
+        branchcode   => '*',
+        categorycode => '*',
+        itemtype     => $item->itype,
+        rules        => {
+            issuelength     => '14',
+            lengthunit      => 'days',
             reservesallowed => '99',
         }
     }
index 7a0ede4..1960a1f 100644 (file)
@@ -13,19 +13,21 @@ my $schema = Koha::Database->new->schema;
 $schema->storage->txn_begin;
 my $dbh = C4::Context->dbh;
 
-$dbh->do(q|DELETE FROM issuingrules|);
+$dbh->do(q|DELETE FROM circulation_rules|);
 
-my $issuingrule = $schema->resultset('Issuingrule')->create(
+my $issuingrule = Koha::CirculationRules->set_rules(
     {
-        categorycode           => '*',
-        itemtype               => '*',
-        branchcode             => '*',
-        fine                   => 1,
-        finedays               => 0,
-        chargeperiod           => 7,
-        chargeperiod_charge_at => 0,
-        lengthunit             => 'days',
-        issuelength            => 1,
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            fine                   => 1,
+            finedays               => 0,
+            chargeperiod           => 7,
+            chargeperiod_charge_at => 0,
+            lengthunit             => 'days',
+            issuelength            => 1,
+        }
     }
 );
 
@@ -42,7 +44,16 @@ $period_end = dt_from_string('2000-01-10');
 is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
 
 # Test charging fine at the *beginning* of each charge period
-$issuingrule->update( { chargeperiod_charge_at => 1 } );
+my $issuingrule = Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            chargeperiod_charge_at => 1,
+        }
+    }
+);
 
 $period_end = dt_from_string('2000-01-05');
 ( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
index 2ecbdb4..fde87fe 100755 (executable)
@@ -244,19 +244,27 @@ is( $hold->priority, '6', "Test AlterPriority(), move to bottom" );
 my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
 my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
   = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
-# Cleanup circulation rules
-$dbh->do('DELETE FROM circulation_rules');
-# $dbh->do(
-#     q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
-#       VALUES (?, ?, ?, ?, ?)},
-#     {},
-#     '*', '*', '*', 25, 99
-# );
-$dbh->do(
-    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
-      VALUES (?, ?, ?, ?, ?)},
-    {},
-    '*', '*', 'CANNOT', 0, 99
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => '*',
+        rules        => {
+            reservesallowed  => 25,
+            holds_per_record => 99,
+        }
+    }
+);
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => 'CANNOT',
+        rules        => {
+            reservesallowed  => 0,
+            holds_per_record => 99,
+        }
+    }
 );
 
 # make sure some basic sysprefs are set
@@ -266,8 +274,8 @@ t::lib::Mocks::mock_preference('item-level_itypes', 1);
 # if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
 t::lib::Mocks::mock_preference('IndependentBranches', 0);
 
-ok(
-    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'OK',
+is(
+    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status}, 'OK',
     '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
 );
 
@@ -354,13 +362,17 @@ ok(
 
 # Test branch item rules
 
-$dbh->do('DELETE FROM issuingrules');
 $dbh->do('DELETE FROM circulation_rules');
-$dbh->do(
-    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
-      VALUES (?, ?, ?, ?)},
-    {},
-    '*', '*', '*', 25
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => '*',
+        rules        => {
+            reservesallowed  => 25,
+            holds_per_record => 99,
+        }
+    }
 );
 Koha::CirculationRules->set_rules(
     {
@@ -419,11 +431,16 @@ $biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' });
 ( $item_bibnum, $item_bibitemnum, $itemnumber )
     = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
 
-$dbh->do(
-    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
-      VALUES (?, ?, ?, ?, ?)},
-    {},
-    '*', '*', 'ONLY1', 1, 99
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => 'ONLY1',
+        rules        => {
+            reservesallowed  => 1,
+            holds_per_record => 99,
+        }
+    }
 );
 is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
     'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
@@ -444,20 +461,22 @@ subtest 'Test max_holds per library/patron category' => sub {
     plan tests => 6;
 
     $dbh->do('DELETE FROM reserves');
-    $dbh->do('DELETE FROM issuingrules');
     $dbh->do('DELETE FROM circulation_rules');
 
     $biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
     ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
       AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
         $biblio->biblionumber );
-    $dbh->do(
-        q{
-            INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
-            VALUES (?, ?, ?, ?, ?)
-        },
-        {},
-        '*', '*', 'TEST', 99, 99
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => '*',
+            branchcode   => '*',
+            itemtype     => 'TEST',
+            rules        => {
+                reservesallowed  => 99,
+                holds_per_record => 99,
+            }
+        }
     );
     AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
     AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
index 755721d..72012ca 100755 (executable)
@@ -5,8 +5,9 @@ use Modern::Perl;
 use C4::Context;
 use C4::Circulation;
 use C4::Items;
-use Koha::IssuingRule;
 use Koha::Items;
+use Koha::CirculationRules;
+
 use Test::More tests => 6;
 
 use t::lib::TestBuilder;
@@ -80,18 +81,20 @@ my $item2  = $builder->build_sample_item({
 });
 
 # Test hold_fulfillment_policy
-my $rule = Koha::IssuingRule->new(
+$dbh->do("DELETE FROM circulation_rules");
+Koha::CirculationRules->set_rules(
     {
         categorycode => '*',
         itemtype     => $itemtype,
         branchcode   => '*',
-        issuelength  => 7,
-        lengthunit   => 8,
-        reservesallowed => 99,
-        onshelfholds => 2,
+        rules        => {
+            issuelength     => 7,
+            lengthunit      => 8,
+            reservesallowed => 99,
+            onshelfholds    => 2,
+        }
     }
 );
-$rule->store();
 
 my $is = IsAvailableForItemLevelRequest( $item1, $patron1);
 is( $is, 0, "Item cannot be held, 2 items available" );
@@ -213,7 +216,7 @@ my $hold = $builder->build({
     }
 });
 
-$rule = Koha::IssuingRule->new(
+Koha::IssuingRule->new(
     {
         categorycode => '*',
         itemtype     => $itemtype2,
@@ -223,8 +226,7 @@ $rule = Koha::IssuingRule->new(
         reservesallowed => 99,
         onshelfholds => 0,
     }
-);
-$rule->store();
+)->store();
 
 $is = IsAvailableForItemLevelRequest( $item3, $patron1);
 is( $is, 1, "Item can be held, items in transit are not available" );
index 90dd0a8..6c6d4ad 100644 (file)
@@ -23,7 +23,6 @@ use Test::More tests => 4;
 
 use Benchmark;
 
-use Koha::IssuingRules;
 use Koha::CirculationRules;
 
 use t::lib::TestBuilder;
@@ -48,26 +47,29 @@ subtest 'get_effective_issuing_rule' => sub {
         plan tests => 4;
 
         my $rule;
-        Koha::IssuingRules->delete;
+        Koha::CirculationRules->delete;
 
-        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => undef,
             categorycode => undef,
             itemtype     => undef,
+            rule_name    => 'fine',
         });
         is($rule, undef, 'When I attempt to get effective issuing rule by'
            .' providing undefined values, then undef is returned.');
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => '*',
             categorycode => '*',
             itemtype => '*',
+            rule_name => 'fine',
         })->store, 'Given I added an issuing rule branchcode => *,'
            .' categorycode => *, itemtype => *,');
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
-            branchcode   => undef,
-            categorycode => undef,
-            itemtype     => undef,
+        $rule = Koha::CirculationRules->get_effective_rule({
+            branchcode   => '*',
+            categorycode => '*',
+            itemtype     => '*',
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
            .' issuing rule by providing undefined values, then the above one is'
@@ -78,116 +80,133 @@ subtest 'get_effective_issuing_rule' => sub {
         plan tests => 18;
 
         my $rule;
-        Koha::IssuingRules->delete;
-        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        Koha::CirculationRules->delete;
+        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
                         .' is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => '*',
             categorycode => '*',
             itemtype => '*',
+            rule_name => 'fine',
         })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => '*',
             categorycode => '*',
             itemtype => $itemtype,
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => '*',
             categorycode => $categorycode,
             itemtype => '*',
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => '*',
             categorycode => $categorycode,
             itemtype => $itemtype,
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => $branchcode,
             categorycode => '*',
             itemtype => '*',
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => $branchcode,
             categorycode => '*',
             itemtype => $itemtype,
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => $branchcode,
             categorycode => $categorycode,
             itemtype => '*',
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
 
-        ok(Koha::IssuingRule->new({
+        ok(Koha::CirculationRule->new({
             branchcode => $branchcode,
             categorycode => $categorycode,
             itemtype => $itemtype,
+            rule_name => 'fine',
         })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
-        $rule = Koha::IssuingRules->get_effective_issuing_rule({
+        $rule = Koha::CirculationRules->get_effective_rule({
             branchcode   => $branchcode,
             categorycode => $categorycode,
             itemtype     => $itemtype,
+            rule_name    => 'fine',
         });
         ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
            .' then the above one is returned.');
@@ -197,34 +216,38 @@ subtest 'get_effective_issuing_rule' => sub {
         plan tests => 4;
 
         my $worst_case = timethis(500,
-                    sub { Koha::IssuingRules->get_effective_issuing_rule({
+                    sub { Koha::CirculationRules->get_effective_rule({
                             branchcode   => 'nonexistent',
                             categorycode => 'nonexistent',
                             itemtype     => 'nonexistent',
+                            rule_name    => 'nonexistent',
                         });
                     }
                 );
         my $mid_case = timethis(500,
-                    sub { Koha::IssuingRules->get_effective_issuing_rule({
+                    sub { Koha::CirculationRules->get_effective_rule({
                             branchcode   => $branchcode,
                             categorycode => 'nonexistent',
                             itemtype     => 'nonexistent',
+                            rule_name    => 'nonexistent',
                         });
                     }
                 );
         my $sec_best_case = timethis(500,
-                    sub { Koha::IssuingRules->get_effective_issuing_rule({
+                    sub { Koha::CirculationRules->get_effective_rule({
                             branchcode   => $branchcode,
                             categorycode => $categorycode,
                             itemtype     => 'nonexistent',
+                            rule_name    => 'nonexistent',
                         });
                     }
                 );
         my $best_case = timethis(500,
-                    sub { Koha::IssuingRules->get_effective_issuing_rule({
+                    sub { Koha::CirculationRules->get_effective_rule({
                             branchcode   => $branchcode,
                             categorycode => $categorycode,
                             itemtype     => $itemtype,
+                            rule_name    => 'nonexistent',
                         });
                     }
                 );
index 27dd449..56cf4af 100644 (file)
@@ -25,7 +25,6 @@ use Test::Warn;
 
 use Koha::Authority::Types;
 use Koha::Cities;
-use Koha::IssuingRules;
 use Koha::Patron::Category;
 use Koha::Patron::Categories;
 use Koha::Patrons;
@@ -114,7 +113,7 @@ subtest 'new' => sub {
 };
 
 subtest 'find' => sub {
-    plan tests => 5;
+    plan tests => 4;
 
     # check find on a single PK
     my $patron = $builder->build({ source => 'Borrower' });
@@ -132,12 +131,6 @@ subtest 'find' => sub {
         { where => { surname => { '!=', $patron->{surname} }}},
     ), undef, 'Additional where clause in find call' );
 
-    # check find with a composite FK
-    my $rule = $builder->build({ source => 'Issuingrule' });
-    my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
-    is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
-        'Find returned a Koha object for composite primary key' );
-
     is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
 };
 
index 618f059..5c2f570 100755 (executable)
@@ -190,12 +190,17 @@ $requesters{$branch_3} = Koha::Patron->new({
 # to request its items, while $branch_2 will allow its items
 # to fill holds from anywhere.
 
-$dbh->do('DELETE FROM issuingrules');
-$dbh->do(
-    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
-      VALUES (?, ?, ?, ?)},
-    {},
-    '*', '*', '*', 25
+$dbh->do('DELETE FROM circulation_rules');
+Koha::CirculationRules->set_rules(
+    {
+        branchcode   => '*',
+        categorycode => '*',
+        itemtype     => '*',
+        rules        => {
+            reservesallowed => 25,
+            holds_per_record => 1,
+        }
+    }
 );
 
 # CPL allows only its own patrons to request its items
@@ -546,6 +551,33 @@ my $limit = Koha::Item::Transfer::Limit->new(
 is( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron, $pickup_branch), 0, "Item level request not available due to transfer limit" );
 t::lib::Mocks::mock_preference( 'UseBranchTransferLimits',  '0' );
 
+my $itype = C4::Reserves::_get_itype($item);
+my $categorycode = $borrower->{categorycode};
+my $holdingbranch = $item->{holdingbranch};
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => $categorycode,
+        itemtype     => $itype,
+        branchcode   => $holdingbranch,
+        rules => {
+            onshelfholds => 1,
+        }
+    }
+);
+
+ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => $categorycode,
+        itemtype     => $itype,
+        branchcode   => $holdingbranch,
+        rules => {
+            onshelfholds => 0,
+        }
+    }
+);
+ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
+
 # tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
 #   hold from A pos 1, today, no fut holds: MoveReserve should fill it
 $dbh->do('DELETE FROM reserves', undef, ($bibnum));
index 80c1c3e..b64fd44 100755 (executable)
@@ -115,19 +115,20 @@ my $item3 = $builder->build(
     }
 );
 
-my $rules_rs = Koha::Database->new()->schema()->resultset('Issuingrule');
-$rules_rs->delete();
+Koha::CirculationRules->delete();
 
 # Test GetMaxPatronHoldsForRecord and GetHoldRule
-my $rule1 = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => '*',
-        itemtype         => '*',
-        branchcode       => '*',
-        reservesallowed  => 1,
-        holds_per_record => 1,
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            reservesallowed  => 1,
+            holds_per_record => 1,
+        }
     }
-)->insert();
+);
 
 t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
 
@@ -144,15 +145,17 @@ is( $rule->{branchcode},       '*', 'Got rule with universal branchcode' );
 is( $rule->{reservesallowed},  1,   'Got reservesallowed of 1' );
 is( $rule->{holds_per_record}, 1,   'Got holds_per_record of 1' );
 
-my $rule2 = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => $category->{categorycode},
-        itemtype         => '*',
-        branchcode       => '*',
-        reservesallowed  => 2,
-        holds_per_record => 2,
+        categorycode => $category->{categorycode},
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            reservesallowed  => 2,
+            holds_per_record => 2,
+        }
     }
-)->insert();
+);
 
 $max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
 is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
@@ -167,15 +170,17 @@ is( $rule->{branchcode},       '*',                       'Got rule with univers
 is( $rule->{reservesallowed},  2,                         'Got reservesallowed of 2' );
 is( $rule->{holds_per_record}, 2,                         'Got holds_per_record of 2' );
 
-my $rule3 = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => $category->{categorycode},
-        itemtype         => $itemtype1->{itemtype},
-        branchcode       => '*',
-        reservesallowed  => 3,
-        holds_per_record => 3,
+        categorycode => $category->{categorycode},
+        itemtype     => $itemtype1->{itemtype},
+        branchcode   => '*',
+        rules        => {
+            reservesallowed  => 3,
+            holds_per_record => 3,
+        }
     }
-)->insert();
+);
 
 $max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
 is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
@@ -190,15 +195,17 @@ is( $rule->{branchcode},       '*',                       'Got rule with univers
 is( $rule->{reservesallowed},  3,                         'Got reservesallowed of 3' );
 is( $rule->{holds_per_record}, 3,                         'Got holds_per_record of 3' );
 
-my $rule4 = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => $category->{categorycode},
-        itemtype         => $itemtype2->{itemtype},
-        branchcode       => '*',
-        reservesallowed  => 4,
-        holds_per_record => 4,
+        categorycode => $category->{categorycode},
+        itemtype     => $itemtype2->{itemtype},
+        branchcode   => '*',
+        rules        => {
+            reservesallowed  => 4,
+            holds_per_record => 4,
+        }
     }
-)->insert();
+);
 
 $max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
 is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
@@ -213,15 +220,17 @@ is( $rule->{branchcode},       '*',                       'Got rule with univers
 is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
 is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
 
-my $rule5 = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => $category->{categorycode},
-        itemtype         => $itemtype2->{itemtype},
-        branchcode       => $library->{branchcode},
-        reservesallowed  => 5,
-        holds_per_record => 5,
+        categorycode => $category->{categorycode},
+        itemtype     => $itemtype2->{itemtype},
+        branchcode   => $library->{branchcode},
+        rules        => {
+            reservesallowed  => 5,
+            holds_per_record => 5,
+        }
     }
-)->insert();
+);
 
 $max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
 is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
@@ -236,11 +245,7 @@ is( $rule->{branchcode},       $library->{branchcode},    'Got rule with specifi
 is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
 is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
 
-$rule1->delete();
-$rule2->delete();
-$rule3->delete();
-$rule4->delete();
-$rule5->delete();
+Koha::CirculationRules->delete();
 
 my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
 is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
@@ -266,15 +271,17 @@ is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds"
 $hold->delete();
 
 # Test multi-hold via AddReserve
-$rule = $rules_rs->new(
+Koha::CirculationRules->set_rules(
     {
-        categorycode     => '*',
-        itemtype         => '*',
-        branchcode       => '*',
-        reservesallowed  => 2,
-        holds_per_record => 2,
+        categorycode => '*',
+        itemtype     => '*',
+        branchcode   => '*',
+        rules        => {
+            reservesallowed  => 2,
+            holds_per_record => 2,
+        }
     }
-)->insert();
+);
 
 my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
 is( $can->{status}, 'OK', 'Hold can be placed with 0 holds' );
index 0050463..97ff96c 100644 (file)
@@ -368,7 +368,7 @@ subtest 'build_object() tests' => sub {
     my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
 
     my $issuing_rule = $builder->build_object(
-        {   class => 'Koha::IssuingRules',
+        {   class => 'Koha::CirculationRules',
             value => {
                 categorycode => $categorycode,
                 itemtype     => $itemtype
@@ -376,7 +376,7 @@ subtest 'build_object() tests' => sub {
         }
     );
 
-    is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
+    is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
     is( $issuing_rule->categorycode,
         $categorycode, 'Category code correctly set' );
     is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
index a1234da..11fa62d 100644 (file)
@@ -114,11 +114,17 @@ my $item_2   = $builder->build_sample_item({ biblionumber => $biblio_2->biblionu
 
 my $dbh = C4::Context->dbh;
 $dbh->do('DELETE FROM reserves');
-$dbh->do('DELETE FROM issuingrules');
-    $dbh->do(q{
-        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
-        VALUES (?, ?, ?, ?)
-    }, {}, '*', '*', '*', 1);
+$dbh->do('DELETE FROM circulation_rules');
+Koha::CirculationRules->set_rules(
+    {
+        categorycode => '*',
+        branchcode   => '*',
+        itemtype     => '*',
+        rules        => {
+            reservesallowed => 1
+        }
+    }
+);
 
 my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
     $biblio_1->biblionumber, undef, 1, undef, undef, undef, '', $item_1->itemnumber);