View | Details | Raw Unified | Return to bug 18936
Collapse All | Expand All

(-)a/C4/Circulation.pm (-158 / +196 lines)
Lines 46-52 use Koha::Biblioitems; Link Here
46
use Koha::DateUtils;
46
use Koha::DateUtils;
47
use Koha::Calendar;
47
use Koha::Calendar;
48
use Koha::Checkouts;
48
use Koha::Checkouts;
49
use Koha::IssuingRules;
50
use Koha::Items;
49
use Koha::Items;
51
use Koha::Patrons;
50
use Koha::Patrons;
52
use Koha::Patron::Debarments;
51
use Koha::Patron::Debarments;
Lines 426-443 sub TooMany { Link Here
426
            # specific rule
425
            # specific rule
427
            if (C4::Context->preference('item-level_itypes')) {
426
            if (C4::Context->preference('item-level_itypes')) {
428
                $count_query .= " WHERE items.itype NOT IN (
427
                $count_query .= " WHERE items.itype NOT IN (
429
                                    SELECT itemtype FROM issuingrules
428
                                    SELECT itemtype FROM circulation_rules
430
                                    WHERE branchcode = ?
429
                                    WHERE branchcode = ?
431
                                    AND   (categorycode = ? OR categorycode = ?)
430
                                    AND   (categorycode = ? OR categorycode = ?)
432
                                    AND   itemtype <> '*'
431
                                    AND   itemtype <> '*'
432
                                    AND   rule_name = 'maxissueqty'
433
                                  ) ";
433
                                  ) ";
434
            } else { 
434
            } else {
435
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
435
                $count_query .= " JOIN  biblioitems USING (biblionumber)
436
                                  WHERE biblioitems.itemtype NOT IN (
436
                                  WHERE biblioitems.itemtype NOT IN (
437
                                    SELECT itemtype FROM issuingrules
437
                                    SELECT itemtype FROM circulation_rules
438
                                    WHERE branchcode = ?
438
                                    WHERE branchcode = ?
439
                                    AND   (categorycode = ? OR categorycode = ?)
439
                                    AND   (categorycode = ? OR categorycode = ?)
440
                                    AND   itemtype <> '*'
440
                                    AND   itemtype <> '*'
441
                                    AND   rule_name = 'maxissueqty'
441
                                  ) ";
442
                                  ) ";
442
            }
443
            }
443
            push @bind_params, $maxissueqty_rule->branchcode;
444
            push @bind_params, $maxissueqty_rule->branchcode;
Lines 1388-1401 sub AddIssue { Link Here
1388
1389
1389
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1390
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1390
            unless ($auto_renew) {
1391
            unless ($auto_renew) {
1391
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1392
                my $rule = Koha::CirculationRules->get_effective_rule(
1392
                    {   categorycode => $borrower->{categorycode},
1393
                    {
1394
                        categorycode => $borrower->{categorycode},
1393
                        itemtype     => $item_object->effective_itemtype,
1395
                        itemtype     => $item_object->effective_itemtype,
1394
                        branchcode   => $branch
1396
                        branchcode   => $branch,
1397
                        rule_name    => 'auto_renew'
1395
                    }
1398
                    }
1396
                );
1399
                );
1397
1400
1398
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1401
                $auto_renew = $rule->rule_value if $rule;
1399
            }
1402
            }
1400
1403
1401
            # Record in the database the fact that the book was issued.
1404
            # Record in the database the fact that the book was issued.
Lines 1535-1601 Get loan length for an itemtype, a borrower type and a branch Link Here
1535
=cut
1538
=cut
1536
1539
1537
sub GetLoanLength {
1540
sub GetLoanLength {
1538
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1541
    my ( $categorycode, $itemtype, $branchcode ) = @_;
1539
    my $dbh = C4::Context->dbh;
1542
1540
    my $sth = $dbh->prepare(qq{
1543
    # Set search precedences
1541
        SELECT issuelength, lengthunit, renewalperiod
1544
    my @params = (
1542
        FROM issuingrules
1545
        {
1543
        WHERE   categorycode=?
1546
            categorycode => $categorycode,
1544
            AND itemtype=?
1547
            itemtype     => $itemtype,
1545
            AND branchcode=?
1548
            branchcode   => $branchcode,
1546
            AND issuelength IS NOT NULL
1549
        },
1547
    });
1550
        {
1551
            categorycode => $categorycode,
1552
            itemtype     => '*',
1553
            branchcode   => $branchcode,
1554
        },
1555
        {
1556
            categorycode => '*',
1557
            itemtype     => $itemtype,
1558
            branchcode   => $branchcode,
1559
        },
1560
        {
1561
            categorycode => '*',
1562
            itemtype     => '*',
1563
            branchcode   => $branchcode,
1564
        },
1565
        {
1566
            categorycode => $categorycode,
1567
            itemtype     => $itemtype,
1568
            branchcode   => '*',
1569
        },
1570
        {
1571
            categorycode => $categorycode,
1572
            itemtype     => '*',
1573
            branchcode   => '*',
1574
        },
1575
        {
1576
            categorycode => '*',
1577
            itemtype     => $itemtype,
1578
            branchcode   => '*',
1579
        },
1580
        {
1581
            categorycode => '*',
1582
            itemtype     => '*',
1583
            branchcode   => '*',
1584
        },
1585
    );
1548
1586
1549
    # try to find issuelength & return the 1st available.
1587
    # Initialize default values
1550
    # check with borrowertype, itemtype and branchcode, then without one of those parameters
1588
    my $rules = {
1551
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1589
        issuelength   => 0,
1552
    my $loanlength = $sth->fetchrow_hashref;
1553
1554
    return $loanlength
1555
      if defined($loanlength) && defined $loanlength->{issuelength};
1556
1557
    $sth->execute( $borrowertype, '*', $branchcode );
1558
    $loanlength = $sth->fetchrow_hashref;
1559
    return $loanlength
1560
      if defined($loanlength) && defined $loanlength->{issuelength};
1561
1562
    $sth->execute( '*', $itemtype, $branchcode );
1563
    $loanlength = $sth->fetchrow_hashref;
1564
    return $loanlength
1565
      if defined($loanlength) && defined $loanlength->{issuelength};
1566
1567
    $sth->execute( '*', '*', $branchcode );
1568
    $loanlength = $sth->fetchrow_hashref;
1569
    return $loanlength
1570
      if defined($loanlength) && defined $loanlength->{issuelength};
1571
1572
    $sth->execute( $borrowertype, $itemtype, '*' );
1573
    $loanlength = $sth->fetchrow_hashref;
1574
    return $loanlength
1575
      if defined($loanlength) && defined $loanlength->{issuelength};
1576
1577
    $sth->execute( $borrowertype, '*', '*' );
1578
    $loanlength = $sth->fetchrow_hashref;
1579
    return $loanlength
1580
      if defined($loanlength) && defined $loanlength->{issuelength};
1581
1582
    $sth->execute( '*', $itemtype, '*' );
1583
    $loanlength = $sth->fetchrow_hashref;
1584
    return $loanlength
1585
      if defined($loanlength) && defined $loanlength->{issuelength};
1586
1587
    $sth->execute( '*', '*', '*' );
1588
    $loanlength = $sth->fetchrow_hashref;
1589
    return $loanlength
1590
      if defined($loanlength) && defined $loanlength->{issuelength};
1591
1592
    # if no rule is set => 0 day (hardcoded)
1593
    return {
1594
        issuelength => 0,
1595
        renewalperiod => 0,
1590
        renewalperiod => 0,
1596
        lengthunit => 'days',
1591
        lengthunit    => 'days',
1597
    };
1592
    };
1598
1593
1594
    # Search for rules!
1595
    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
1596
        foreach my $params (@params) {
1597
            my $rule = Koha::CirculationRules->search(
1598
                {
1599
                    rule_name => $rule_name,
1600
                    %$params,
1601
                }
1602
            )->next();
1603
1604
            if ($rule) {
1605
                $rules->{$rule_name} = $rule->rule_value;
1606
                last;
1607
            }
1608
        }
1609
    }
1610
1611
    return $rules;
1599
}
1612
}
1600
1613
1601
1614
Lines 1610-1628 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1610
sub GetHardDueDate {
1623
sub GetHardDueDate {
1611
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1624
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1612
1625
1613
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1626
    my $rules = Koha::CirculationRules->get_effective_rules(
1614
        {   categorycode => $borrowertype,
1627
        {
1628
            categorycode => $borrowertype,
1615
            itemtype     => $itemtype,
1629
            itemtype     => $itemtype,
1616
            branchcode   => $branchcode
1630
            branchcode   => $branchcode,
1631
            rules        => [ 'hardduedate', 'hardduedatecompare' ],
1617
        }
1632
        }
1618
    );
1633
    );
1619
1634
1620
1635
    if ( defined( $rules->{hardduedate} ) ) {
1621
    if ( defined( $issuing_rule ) ) {
1636
        if ( $rules->{hardduedate} ) {
1622
        if ( $issuing_rule->hardduedate ) {
1637
            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
1623
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1638
        }
1624
        } else {
1639
        else {
1625
            return (undef, undef);
1640
            return ( undef, undef );
1626
        }
1641
        }
1627
    }
1642
    }
1628
}
1643
}
Lines 2226-2239 sub _debar_user_on_return { Link Here
2226
    $return_date //= dt_from_string();
2241
    $return_date //= dt_from_string();
2227
2242
2228
    my $circcontrol = C4::Context->preference('CircControl');
2243
    my $circcontrol = C4::Context->preference('CircControl');
2229
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2244
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2230
        {   categorycode => $borrower->{categorycode},
2245
        {   categorycode => $borrower->{categorycode},
2231
            itemtype     => $item->{itype},
2246
            itemtype     => $item->{itype},
2232
            branchcode   => $branchcode
2247
            branchcode   => $branchcode,
2248
            rules => [
2249
                'finedays',
2250
                'lengthunit',
2251
                'firstremind',
2252
                'maxsuspensiondays',
2253
            ]
2233
        }
2254
        }
2234
    );
2255
    );
2235
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2256
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2236
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2257
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2237
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2258
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2238
2259
2239
    if ($finedays) {
2260
    if ($finedays) {
Lines 2244-2250 sub _debar_user_on_return { Link Here
2244
2265
2245
        # grace period is measured in the same units as the loan
2266
        # grace period is measured in the same units as the loan
2246
        my $grace =
2267
        my $grace =
2247
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2268
          DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
2248
2269
2249
        my $deltadays = DateTime::Duration->new(
2270
        my $deltadays = DateTime::Duration->new(
2250
            days => $chargeable_units
2271
            days => $chargeable_units
Lines 2254-2260 sub _debar_user_on_return { Link Here
2254
2275
2255
            # If the max suspension days is < than the suspension days
2276
            # If the max suspension days is < than the suspension days
2256
            # the suspension days is limited to this maximum period.
2277
            # the suspension days is limited to this maximum period.
2257
            my $max_sd = $issuing_rule->maxsuspensiondays;
2278
            my $max_sd = $issuing_rule->{maxsuspensiondays};
2258
            if ( defined $max_sd ) {
2279
            if ( defined $max_sd ) {
2259
                $max_sd = DateTime::Duration->new( days => $max_sd );
2280
                $max_sd = DateTime::Duration->new( days => $max_sd );
2260
                $suspension_days = $max_sd
2281
                $suspension_days = $max_sd
Lines 2720-2734 sub CanBookBeRenewed { Link Here
2720
    return ( 1, undef ) if $override_limit;
2741
    return ( 1, undef ) if $override_limit;
2721
2742
2722
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2743
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2723
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2744
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2724
        {   categorycode => $patron->categorycode,
2745
        {
2746
            categorycode => $patron->categorycode,
2725
            itemtype     => $item->effective_itemtype,
2747
            itemtype     => $item->effective_itemtype,
2726
            branchcode   => $branchcode
2748
            branchcode   => $branchcode,
2749
            rules => [
2750
                'renewalsallowed',
2751
                'no_auto_renewal_after',
2752
                'no_auto_renewal_after_hard_limit',
2753
                'lengthunit',
2754
                'norenewalbefore',
2755
            ]
2727
        }
2756
        }
2728
    );
2757
    );
2729
2758
2730
    return ( 0, "too_many" )
2759
    return ( 0, "too_many" )
2731
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2760
      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
2732
2761
2733
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2762
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2734
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2763
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2748-2770 sub CanBookBeRenewed { Link Here
2748
            return ( 0, 'auto_account_expired' );
2777
            return ( 0, 'auto_account_expired' );
2749
        }
2778
        }
2750
2779
2751
        if ( defined $issuing_rule->no_auto_renewal_after
2780
        if ( defined $issuing_rule->{no_auto_renewal_after}
2752
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2781
                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
2753
            # Get issue_date and add no_auto_renewal_after
2782
            # Get issue_date and add no_auto_renewal_after
2754
            # If this is greater than today, it's too late for renewal.
2783
            # If this is greater than today, it's too late for renewal.
2755
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2784
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2756
            $maximum_renewal_date->add(
2785
            $maximum_renewal_date->add(
2757
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2786
                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
2758
            );
2787
            );
2759
            my $now = dt_from_string;
2788
            my $now = dt_from_string;
2760
            if ( $now >= $maximum_renewal_date ) {
2789
            if ( $now >= $maximum_renewal_date ) {
2761
                return ( 0, "auto_too_late" );
2790
                return ( 0, "auto_too_late" );
2762
            }
2791
            }
2763
        }
2792
        }
2764
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2793
        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
2765
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2794
                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
2766
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2795
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2767
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2796
            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
2768
                return ( 0, "auto_too_late" );
2797
                return ( 0, "auto_too_late" );
2769
            }
2798
            }
2770
        }
2799
        }
Lines 2778-2794 sub CanBookBeRenewed { Link Here
2778
        }
2807
        }
2779
    }
2808
    }
2780
2809
2781
    if ( defined $issuing_rule->norenewalbefore
2810
    if ( defined $issuing_rule->{norenewalbefore}
2782
        and $issuing_rule->norenewalbefore ne "" )
2811
        and $issuing_rule->{norenewalbefore} ne "" )
2783
    {
2812
    {
2784
2813
2785
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2814
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2786
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2815
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2787
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2816
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
2788
2817
2789
        # Depending on syspref reset the exact time, only check the date
2818
        # Depending on syspref reset the exact time, only check the date
2790
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2819
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2791
            and $issuing_rule->lengthunit eq 'days' )
2820
            and $issuing_rule->{lengthunit} eq 'days' )
2792
        {
2821
        {
2793
            $soonestrenewal->truncate( to => 'day' );
2822
            $soonestrenewal->truncate( to => 'day' );
2794
        }
2823
        }
Lines 3005-3018 sub GetRenewCount { Link Here
3005
    # $item and $borrower should be calculated
3034
    # $item and $borrower should be calculated
3006
    my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
3035
    my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
3007
3036
3008
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3037
    my $rule = Koha::CirculationRules->get_effective_rule(
3009
        {   categorycode => $patron->categorycode,
3038
        {
3039
            categorycode => $patron->categorycode,
3010
            itemtype     => $item->effective_itemtype,
3040
            itemtype     => $item->effective_itemtype,
3011
            branchcode   => $branchcode
3041
            branchcode   => $branchcode,
3042
            rule_name    => 'renewalsallowed',
3012
        }
3043
        }
3013
    );
3044
    );
3014
3045
3015
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
3046
    $renewsallowed = $rule ? $rule->rule_value : 0;
3016
    $renewsleft    = $renewsallowed - $renewcount;
3047
    $renewsleft    = $renewsallowed - $renewcount;
3017
    if($renewsleft < 0){ $renewsleft = 0; }
3048
    if($renewsleft < 0){ $renewsleft = 0; }
3018
    return ( $renewcount, $renewsallowed, $renewsleft );
3049
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3050-3074 sub GetSoonestRenewDate { Link Here
3050
      or return;
3081
      or return;
3051
3082
3052
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3083
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3053
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3084
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3054
        {   categorycode => $patron->categorycode,
3085
        {   categorycode => $patron->categorycode,
3055
            itemtype     => $item->effective_itemtype,
3086
            itemtype     => $item->effective_itemtype,
3056
            branchcode   => $branchcode
3087
            branchcode   => $branchcode,
3088
            rules => [
3089
                'norenewalbefore',
3090
                'lengthunit',
3091
            ]
3057
        }
3092
        }
3058
    );
3093
    );
3059
3094
3060
    my $now = dt_from_string;
3095
    my $now = dt_from_string;
3061
    return $now unless $issuing_rule;
3096
    return $now unless $issuing_rule;
3062
3097
3063
    if ( defined $issuing_rule->norenewalbefore
3098
    if ( defined $issuing_rule->{norenewalbefore}
3064
        and $issuing_rule->norenewalbefore ne "" )
3099
        and $issuing_rule->{norenewalbefore} ne "" )
3065
    {
3100
    {
3066
        my $soonestrenewal =
3101
        my $soonestrenewal =
3067
          dt_from_string( $itemissue->date_due )->subtract(
3102
          dt_from_string( $itemissue->date_due )->subtract(
3068
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3103
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3069
3104
3070
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3105
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3071
            and $issuing_rule->lengthunit eq 'days' )
3106
            and $issuing_rule->{lengthunit} eq 'days' )
3072
        {
3107
        {
3073
            $soonestrenewal->truncate( to => 'day' );
3108
            $soonestrenewal->truncate( to => 'day' );
3074
        }
3109
        }
Lines 3109-3138 sub GetLatestAutoRenewDate { Link Here
3109
      or return;
3144
      or return;
3110
3145
3111
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3146
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3112
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3147
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3113
        {   categorycode => $patron->categorycode,
3148
        {
3149
            categorycode => $patron->categorycode,
3114
            itemtype     => $item->effective_itemtype,
3150
            itemtype     => $item->effective_itemtype,
3115
            branchcode   => $branchcode
3151
            branchcode   => $branchcode,
3152
            rules => [
3153
                'no_auto_renewal_after',
3154
                'no_auto_renewal_after_hard_limit',
3155
                'lengthunit',
3156
            ]
3116
        }
3157
        }
3117
    );
3158
    );
3118
3159
3119
    return unless $issuing_rule;
3160
    return unless $circulation_rules;
3120
    return
3161
    return
3121
      if ( not $issuing_rule->no_auto_renewal_after
3162
      if ( not $circulation_rules->{no_auto_renewal_after}
3122
            or $issuing_rule->no_auto_renewal_after eq '' )
3163
            or $circulation_rules->{no_auto_renewal_after} eq '' )
3123
      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
3164
      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
3124
             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
3165
             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
3125
3166
3126
    my $maximum_renewal_date;
3167
    my $maximum_renewal_date;
3127
    if ( $issuing_rule->no_auto_renewal_after ) {
3168
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3128
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3169
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3129
        $maximum_renewal_date->add(
3170
        $maximum_renewal_date->add(
3130
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3171
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3131
        );
3172
        );
3132
    }
3173
    }
3133
3174
3134
    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
3175
    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
3135
        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
3176
        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
3136
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3177
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3137
    }
3178
    }
3138
    return $maximum_renewal_date;
3179
    return $maximum_renewal_date;
Lines 3179-3197 sub GetIssuingCharges { Link Here
3179
        $item_type = $item_data->{itemtype};
3220
        $item_type = $item_data->{itemtype};
3180
        $charge    = $item_data->{rentalcharge};
3221
        $charge    = $item_data->{rentalcharge};
3181
        my $branch = C4::Context::mybranch();
3222
        my $branch = C4::Context::mybranch();
3182
        my $discount_query = q|SELECT rentaldiscount,
3223
        my $patron = Koha::Patrons->find( $borrowernumber );
3183
            issuingrules.itemtype, issuingrules.branchcode
3224
        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
3184
            FROM borrowers
3225
        if ($discount) {
3185
            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
3186
            WHERE borrowers.borrowernumber = ?
3187
            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
3188
            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
3189
        my $discount_sth = $dbh->prepare($discount_query);
3190
        $discount_sth->execute( $borrowernumber, $item_type, $branch );
3191
        my $discount_rules = $discount_sth->fetchall_arrayref({});
3192
        if (@{$discount_rules}) {
3193
            # We may have multiple rules so get the most specific
3226
            # We may have multiple rules so get the most specific
3194
            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
3195
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3227
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3196
        }
3228
        }
3197
        if ($charge) {
3229
        if ($charge) {
Lines 3204-3240 sub GetIssuingCharges { Link Here
3204
3236
3205
# Select most appropriate discount rule from those returned
3237
# Select most appropriate discount rule from those returned
3206
sub _get_discount_from_rule {
3238
sub _get_discount_from_rule {
3207
    my ($rules_ref, $branch, $itemtype) = @_;
3239
    my ($categorycode, $branchcode, $itemtype) = @_;
3208
    my $discount;
3209
3240
3210
    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
3241
    # Set search precedences
3211
        $discount = $rules_ref->[0]->{rentaldiscount};
3242
    my @params = (
3212
        return (defined $discount) ? $discount : 0;
3243
        {
3213
    }
3244
            branchcode   => $branchcode,
3214
    # could have up to 4 does one match $branch and $itemtype
3245
            itemtype     => $itemtype,
3215
    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
3246
            categorycode => $categorycode,
3216
    if (@d) {
3247
        },
3217
        $discount = $d[0]->{rentaldiscount};
3248
        {
3218
        return (defined $discount) ? $discount : 0;
3249
            branchcode   => '*',
3219
    }
3250
            categorycode => $categorycode,
3220
    # do we have item type + all branches
3251
            itemtype     => $itemtype,
3221
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
3252
        },
3222
    if (@d) {
3253
        {
3223
        $discount = $d[0]->{rentaldiscount};
3254
            branchcode   => $branchcode,
3224
        return (defined $discount) ? $discount : 0;
3255
            categorycode => $categorycode,
3225
    }
3256
            itemtype     => '*',
3226
    # do we all item types + this branch
3257
        },
3227
    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
3258
        {
3228
    if (@d) {
3259
            branchcode   => '*',
3229
        $discount = $d[0]->{rentaldiscount};
3260
            categorycode => $categorycode,
3230
        return (defined $discount) ? $discount : 0;
3261
            itemtype     => '*',
3231
    }
3262
        },
3232
    # so all and all (surely we wont get here)
3263
    );
3233
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
3264
3234
    if (@d) {
3265
    foreach my $params (@params) {
3235
        $discount = $d[0]->{rentaldiscount};
3266
        my $rule = Koha::CirculationRules->search(
3236
        return (defined $discount) ? $discount : 0;
3267
            {
3268
                rule_name => 'rentaldiscount',
3269
                %$params,
3270
            }
3271
        )->next();
3272
3273
        return $rule->rule_value if $rule;
3237
    }
3274
    }
3275
3238
    # none of the above
3276
    # none of the above
3239
    return 0;
3277
    return 0;
3240
}
3278
}
(-)a/C4/Overdues.pm (-10 / +25 lines)
Lines 36-42 use C4::Debug; Link Here
36
use Koha::DateUtils;
36
use Koha::DateUtils;
37
use Koha::Account::Lines;
37
use Koha::Account::Lines;
38
use Koha::Account::Offsets;
38
use Koha::Account::Offsets;
39
use Koha::IssuingRules;
40
use Koha::Libraries;
39
use Koha::Libraries;
41
40
42
use vars qw(@ISA @EXPORT);
41
use vars qw(@ISA @EXPORT);
Lines 235-261 sub CalcFine { Link Here
235
    my $start_date = $due_dt->clone();
234
    my $start_date = $due_dt->clone();
236
    # get issuingrules (fines part will be used)
235
    # get issuingrules (fines part will be used)
237
    my $itemtype = $item->{itemtype} || $item->{itype};
236
    my $itemtype = $item->{itemtype} || $item->{itype};
238
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
237
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
238
        {
239
            categorycode => $bortype,
240
            itemtype     => $itemtype,
241
            branchcode   => $branchcode,
242
            rules => [
243
                'lengthunit',
244
                'firstremind',
245
                'chargeperiod',
246
                'chargeperiod_charge_at',
247
                'fine',
248
                'overduefinescap',
249
                'cap_fine_to_replacement_price',
250
                'chargename',
251
            ]
252
        }
253
    );
239
254
240
    $itemtype = Koha::ItemTypes->find($itemtype);
255
    $itemtype = Koha::ItemTypes->find($itemtype);
241
256
242
    return unless $issuing_rule; # If not rule exist, there is no fine
257
    return unless $issuing_rule; # If not rule exist, there is no fine
243
258
244
    my $fine_unit = $issuing_rule->lengthunit || 'days';
259
    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
245
260
246
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
261
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
247
    my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
262
    my $units_minus_grace = $chargeable_units - $issuing_rule->{firstremind};
248
    my $amount = 0;
263
    my $amount = 0;
249
    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
264
    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
250
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
265
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
251
        my $charge_periods = $units / $issuing_rule->chargeperiod;
266
        my $charge_periods = $units / $issuing_rule->{chargeperiod};
252
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
267
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
253
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
268
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
254
        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
269
        $charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
255
        $amount = $charge_periods * $issuing_rule->fine;
270
        $amount = $charge_periods * $issuing_rule->{fine};
256
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
271
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
257
272
258
    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
273
    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
259
274
260
    # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
275
    # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
261
    $item->{replacementprice} ||= $itemtype->defaultreplacecost
276
    $item->{replacementprice} ||= $itemtype->defaultreplacecost
Lines 263-269 sub CalcFine { Link Here
263
      && $item->{replacementprice} == 0
278
      && $item->{replacementprice} == 0
264
      && C4::Context->preference("useDefaultReplacementCost");
279
      && C4::Context->preference("useDefaultReplacementCost");
265
280
266
    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
281
    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
267
282
268
    $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
283
    $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
269
    return ($amount, $units_minus_grace, $chargeable_units);
284
    return ($amount, $units_minus_grace, $chargeable_units);
(-)a/C4/Reserves.pm (-15 / +30 lines)
Lines 41-47 use Koha::Database; Link Here
41
use Koha::DateUtils;
41
use Koha::DateUtils;
42
use Koha::Hold;
42
use Koha::Hold;
43
use Koha::Holds;
43
use Koha::Holds;
44
use Koha::IssuingRules;
45
use Koha::ItemTypes;
44
use Koha::ItemTypes;
46
use Koha::Items;
45
use Koha::Items;
47
use Koha::Libraries;
46
use Koha::Libraries;
Lines 2153-2176 patron category, itemtype, and library. Link Here
2153
sub GetHoldRule {
2152
sub GetHoldRule {
2154
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2153
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2155
2154
2156
    my $dbh = C4::Context->dbh;
2155
    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
2157
2156
        {
2158
    my $sth = $dbh->prepare(
2157
            itemtype     => $itemtype,
2159
        q{
2158
            categorycode => $categorycode,
2160
         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record, holds_per_day
2159
            branchcode   => $branchcode,
2161
           FROM issuingrules
2160
            rule_name    => 'reservesallowed',
2162
          WHERE (categorycode in (?,'*') )
2161
            order_by     => {
2163
            AND (itemtype IN (?,'*'))
2162
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2164
            AND (branchcode IN (?,'*'))
2163
            }
2165
       ORDER BY categorycode DESC,
2166
                itemtype     DESC,
2167
                branchcode   DESC
2168
        }
2164
        }
2169
    );
2165
    );
2166
    return unless $reservesallowed;;
2170
2167
2171
    $sth->execute( $categorycode, $itemtype, $branchcode );
2168
    my $rules;
2169
    $rules->{reservesallowed} = $reservesallowed->rule_value;
2170
    $rules->{itemtype}        = $reservesallowed->itemtype;
2171
    $rules->{categorycode}    = $reservesallowed->categorycode;
2172
    $rules->{branchcode}      = $reservesallowed->branchcode;
2173
2174
    my $holds_per_x_rules = Koha::CirculationRules->get_effective_rules(
2175
        {
2176
            itemtype     => $itemtype,
2177
            categorycode => $categorycode,
2178
            branchcode   => $branchcode,
2179
            rules        => ['holds_per_record', 'holds_per_day'],
2180
            order_by     => {
2181
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2182
            }
2183
        }
2184
    );
2185
    $rules->{holds_per_record} = $holds_per_x_rules->{holds_per_record};
2186
    $rules->{holds_per_day} = $holds_per_x_rules->{holds_per_day};
2172
2187
2173
    return $sth->fetchrow_hashref();
2188
    return $rules;
2174
}
2189
}
2175
2190
2176
=head1 AUTHOR
2191
=head1 AUTHOR
(-)a/Koha/Biblio.pm (-4 / +10 lines)
Lines 35-41 use Koha::ArticleRequest::Status; Link Here
35
use Koha::ArticleRequests;
35
use Koha::ArticleRequests;
36
use Koha::Biblio::Metadatas;
36
use Koha::Biblio::Metadatas;
37
use Koha::Biblioitems;
37
use Koha::Biblioitems;
38
use Koha::IssuingRules;
38
use Koha::CirculationRules;
39
use Koha::Item::Transfer::Limits;
39
use Koha::Item::Transfer::Limits;
40
use Koha::Items;
40
use Koha::Items;
41
use Koha::Libraries;
41
use Koha::Libraries;
Lines 258-267 sub article_request_type_for_bib { Link Here
258
    my $borrowertype = $borrower->categorycode;
258
    my $borrowertype = $borrower->categorycode;
259
    my $itemtype     = $self->itemtype();
259
    my $itemtype     = $self->itemtype();
260
260
261
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
261
    my $rule = Koha::CirculationRules->get_effective_rule(
262
        {
263
            rule_name    => 'article_requests',
264
            categorycode => $borrowertype,
265
            itemtype     => $itemtype,
266
        }
267
    );
262
268
263
    return q{} unless $issuing_rule;
269
    return q{} unless $rule;
264
    return $issuing_rule->article_requests || q{}
270
    return $rule->rule_value || q{}
265
}
271
}
266
272
267
=head3 article_request_type_for_items
273
=head3 article_request_type_for_items
(-)a/Koha/CirculationRules.pm (-5 / +38 lines)
Lines 1-7 Link Here
1
package Koha::CirculationRules;
1
package Koha::CirculationRules;
2
2
3
# Copyright Vaara-kirjastot 2015
3
# Copyright ByWater Solutions 2017
4
# Copyright Koha Development Team 2016
5
#
4
#
6
# This file is part of Koha.
5
# This file is part of Koha.
7
#
6
#
Lines 42-47 Koha::CirculationRules - Koha CirculationRule Object set class Link Here
42
sub get_effective_rule {
41
sub get_effective_rule {
43
    my ( $self, $params ) = @_;
42
    my ( $self, $params ) = @_;
44
43
44
    $params->{categorycode} = '*' if exists($params->{categorycode}) && !defined($params->{categorycode});
45
    $params->{branchcode}   = '*' if exists($params->{branchcode})   && !defined($params->{branchcode});
46
    $params->{itemtype}     = '*' if exists($params->{itemtype})     && !defined($params->{itemtype});
47
45
    my $rule_name    = $params->{rule_name};
48
    my $rule_name    = $params->{rule_name};
46
    my $categorycode = $params->{categorycode};
49
    my $categorycode = $params->{categorycode};
47
    my $itemtype     = $params->{itemtype};
50
    my $itemtype     = $params->{itemtype};
Lines 55-60 sub get_effective_rule { Link Here
55
        $v = undef if $v and $v eq '*';
58
        $v = undef if $v and $v eq '*';
56
    }
59
    }
57
60
61
    my $order_by = $params->{order_by}
62
      // { -desc => [ 'branchcode', 'categorycode', 'itemtype' ] };
63
58
    my $search_params;
64
    my $search_params;
59
    $search_params->{rule_name} = $rule_name;
65
    $search_params->{rule_name} = $rule_name;
60
66
Lines 65-73 sub get_effective_rule { Link Here
65
    my $rule = $self->search(
71
    my $rule = $self->search(
66
        $search_params,
72
        $search_params,
67
        {
73
        {
68
            order_by => {
74
            order_by => $order_by,
69
                -desc => [ 'branchcode', 'categorycode', 'itemtype' ]
70
            },
71
            rows => 1,
75
            rows => 1,
72
        }
76
        }
73
    )->single;
77
    )->single;
Lines 75-80 sub get_effective_rule { Link Here
75
    return $rule;
79
    return $rule;
76
}
80
}
77
81
82
=head3 get_effective_rule
83
84
=cut
85
86
sub get_effective_rules {
87
    my ( $self, $params ) = @_;
88
89
    my $rules        = $params->{rules};
90
    my $categorycode = $params->{categorycode};
91
    my $itemtype     = $params->{itemtype};
92
    my $branchcode   = $params->{branchcode};
93
94
    my $r;
95
    foreach my $rule (@$rules) {
96
        my $effective_rule = $self->get_effective_rule(
97
            {
98
                rule_name    => $rule,
99
                categorycode => $categorycode,
100
                itemtype     => $itemtype,
101
                branchcode   => $branchcode,
102
            }
103
        );
104
105
        $r->{$rule} = $effective_rule->rule_value if $effective_rule;
106
    }
107
108
    return $r;
109
}
110
78
=head3 set_rule
111
=head3 set_rule
79
112
80
=cut
113
=cut
(-)a/Koha/IssuingRule.pm (-68 lines)
Lines 1-68 Link Here
1
package Koha::IssuingRule;
2
3
# Copyright Vaara-kirjastot 2015
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
use Koha::Database;
22
use base qw(Koha::Object);
23
24
=head1 NAME
25
26
Koha::Hold - Koha Hold object class
27
28
=head1 API
29
30
=head2 Class Methods
31
32
=cut
33
34
=head3 delete
35
36
=cut
37
38
sub delete {
39
    my ($self) = @_;
40
41
    my $branchcode = $self->branchcode eq '*' ? undef : $self->branchcode;
42
    my $categorycode = $self->categorycode eq '*' ? undef : $self->categorycode;
43
    my $itemtype = $self->itemtype eq '*' ? undef : $self->itemtype;
44
45
    Koha::CirculationRules->search({
46
        branchcode   => $branchcode,
47
        itemtype     => $itemtype,
48
        categorycode => $categorycode,
49
        rule_name => [qw(
50
            maxissueqty
51
            maxonsiteissueqty
52
            max_holds
53
        )],
54
    })->delete;
55
56
    $self->SUPER::delete;
57
58
}
59
60
=head3 type
61
62
=cut
63
64
sub _type {
65
    return 'Issuingrule';
66
}
67
68
1;
(-)a/Koha/Item.pm (-4 / +11 lines)
Lines 27-33 use Koha::DateUtils qw( dt_from_string ); Link Here
27
27
28
use C4::Context;
28
use C4::Context;
29
use Koha::Checkouts;
29
use Koha::Checkouts;
30
use Koha::IssuingRules;
30
use Koha::CirculationRules;
31
use Koha::Item::Transfer::Limits;
31
use Koha::Item::Transfer::Limits;
32
use Koha::Item::Transfers;
32
use Koha::Item::Transfers;
33
use Koha::Patrons;
33
use Koha::Patrons;
Lines 297-306 sub article_request_type { Link Here
297
      :                                      undef;
297
      :                                      undef;
298
    my $borrowertype = $borrower->categorycode;
298
    my $borrowertype = $borrower->categorycode;
299
    my $itemtype = $self->effective_itemtype();
299
    my $itemtype = $self->effective_itemtype();
300
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
300
    my $rule = Koha::CirculationRules->get_effective_rule(
301
        {
302
            rule_name    => 'article_requests',
303
            categorycode => $borrowertype,
304
            itemtype     => $itemtype,
305
            branchcode   => $branchcode
306
        }
307
    );
301
308
302
    return q{} unless $issuing_rule;
309
    return q{} unless $rule;
303
    return $issuing_rule->article_requests || q{}
310
    return $rule->rule_value || q{}
304
}
311
}
305
312
306
=head3 current_holds
313
=head3 current_holds
(-)a/Koha/Schema/Result/Issuingrule.pm (-327 lines)
Lines 1-327 Link Here
1
use utf8;
2
package Koha::Schema::Result::Issuingrule;
3
4
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
7
=head1 NAME
8
9
Koha::Schema::Result::Issuingrule
10
11
=cut
12
13
use strict;
14
use warnings;
15
16
use base 'DBIx::Class::Core';
17
18
=head1 TABLE: C<issuingrules>
19
20
=cut
21
22
__PACKAGE__->table("issuingrules");
23
24
=head1 ACCESSORS
25
26
=head2 categorycode
27
28
  data_type: 'varchar'
29
  default_value: (empty string)
30
  is_nullable: 0
31
  size: 10
32
33
=head2 itemtype
34
35
  data_type: 'varchar'
36
  default_value: (empty string)
37
  is_nullable: 0
38
  size: 10
39
40
=head2 restrictedtype
41
42
  data_type: 'tinyint'
43
  is_nullable: 1
44
45
=head2 rentaldiscount
46
47
  data_type: 'decimal'
48
  is_nullable: 1
49
  size: [28,6]
50
51
=head2 reservecharge
52
53
  data_type: 'decimal'
54
  is_nullable: 1
55
  size: [28,6]
56
57
=head2 fine
58
59
  data_type: 'decimal'
60
  is_nullable: 1
61
  size: [28,6]
62
63
=head2 finedays
64
65
  data_type: 'integer'
66
  is_nullable: 1
67
68
=head2 maxsuspensiondays
69
70
  data_type: 'integer'
71
  is_nullable: 1
72
73
=head2 suspension_chargeperiod
74
75
  data_type: 'integer'
76
  default_value: 1
77
  is_nullable: 1
78
79
=head2 firstremind
80
81
  data_type: 'integer'
82
  is_nullable: 1
83
84
=head2 chargeperiod
85
86
  data_type: 'integer'
87
  is_nullable: 1
88
89
=head2 chargeperiod_charge_at
90
91
  data_type: 'tinyint'
92
  default_value: 0
93
  is_nullable: 0
94
95
=head2 accountsent
96
97
  data_type: 'integer'
98
  is_nullable: 1
99
100
=head2 issuelength
101
102
  data_type: 'integer'
103
  is_nullable: 1
104
105
=head2 lengthunit
106
107
  data_type: 'varchar'
108
  default_value: 'days'
109
  is_nullable: 1
110
  size: 10
111
112
=head2 hardduedate
113
114
  data_type: 'date'
115
  datetime_undef_if_invalid: 1
116
  is_nullable: 1
117
118
=head2 hardduedatecompare
119
120
  data_type: 'tinyint'
121
  default_value: 0
122
  is_nullable: 0
123
124
=head2 renewalsallowed
125
126
  data_type: 'smallint'
127
  default_value: 0
128
  is_nullable: 0
129
130
=head2 renewalperiod
131
132
  data_type: 'integer'
133
  is_nullable: 1
134
135
=head2 norenewalbefore
136
137
  data_type: 'integer'
138
  is_nullable: 1
139
140
=head2 auto_renew
141
142
  data_type: 'tinyint'
143
  default_value: 0
144
  is_nullable: 1
145
146
=head2 no_auto_renewal_after
147
148
  data_type: 'integer'
149
  is_nullable: 1
150
151
=head2 no_auto_renewal_after_hard_limit
152
153
  data_type: 'date'
154
  datetime_undef_if_invalid: 1
155
  is_nullable: 1
156
157
=head2 reservesallowed
158
159
  data_type: 'smallint'
160
  default_value: 0
161
  is_nullable: 0
162
163
=head2 holds_per_record
164
165
  data_type: 'smallint'
166
  default_value: 1
167
  is_nullable: 0
168
169
=head2 holds_per_day
170
171
  data_type: 'smallint'
172
  is_nullable: 1
173
174
=head2 branchcode
175
176
  data_type: 'varchar'
177
  default_value: (empty string)
178
  is_nullable: 0
179
  size: 10
180
181
=head2 overduefinescap
182
183
  data_type: 'decimal'
184
  is_nullable: 1
185
  size: [28,6]
186
187
=head2 cap_fine_to_replacement_price
188
189
  data_type: 'tinyint'
190
  default_value: 0
191
  is_nullable: 0
192
193
=head2 onshelfholds
194
195
  data_type: 'tinyint'
196
  default_value: 0
197
  is_nullable: 0
198
199
=head2 opacitemholds
200
201
  data_type: 'char'
202
  default_value: 'N'
203
  is_nullable: 0
204
  size: 1
205
206
=head2 article_requests
207
208
  data_type: 'enum'
209
  default_value: 'no'
210
  extra: {list => ["no","yes","bib_only","item_only"]}
211
  is_nullable: 0
212
213
=head2 note
214
215
  data_type: 'varchar'
216
  is_nullable: 1
217
  size: 100
218
219
=cut
220
221
__PACKAGE__->add_columns(
222
  "categorycode",
223
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
224
  "itemtype",
225
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
226
  "restrictedtype",
227
  { data_type => "tinyint", is_nullable => 1 },
228
  "rentaldiscount",
229
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
230
  "reservecharge",
231
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
232
  "fine",
233
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
234
  "finedays",
235
  { data_type => "integer", is_nullable => 1 },
236
  "maxsuspensiondays",
237
  { data_type => "integer", is_nullable => 1 },
238
  "suspension_chargeperiod",
239
  { data_type => "integer", default_value => 1, is_nullable => 1 },
240
  "firstremind",
241
  { data_type => "integer", is_nullable => 1 },
242
  "chargeperiod",
243
  { data_type => "integer", is_nullable => 1 },
244
  "chargeperiod_charge_at",
245
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
246
  "accountsent",
247
  { data_type => "integer", is_nullable => 1 },
248
  "issuelength",
249
  { data_type => "integer", is_nullable => 1 },
250
  "lengthunit",
251
  {
252
    data_type => "varchar",
253
    default_value => "days",
254
    is_nullable => 1,
255
    size => 10,
256
  },
257
  "hardduedate",
258
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
259
  "hardduedatecompare",
260
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
261
  "renewalsallowed",
262
  { data_type => "smallint", default_value => 0, is_nullable => 0 },
263
  "renewalperiod",
264
  { data_type => "integer", is_nullable => 1 },
265
  "norenewalbefore",
266
  { data_type => "integer", is_nullable => 1 },
267
  "auto_renew",
268
  { data_type => "tinyint", default_value => 0, is_nullable => 1 },
269
  "no_auto_renewal_after",
270
  { data_type => "integer", is_nullable => 1 },
271
  "no_auto_renewal_after_hard_limit",
272
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
273
  "reservesallowed",
274
  { data_type => "smallint", default_value => 0, is_nullable => 0 },
275
  "holds_per_record",
276
  { data_type => "smallint", default_value => 1, is_nullable => 0 },
277
  "holds_per_day",
278
  { data_type => "smallint", is_nullable => 1 },
279
  "branchcode",
280
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
281
  "overduefinescap",
282
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
283
  "cap_fine_to_replacement_price",
284
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
285
  "onshelfholds",
286
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
287
  "opacitemholds",
288
  { data_type => "char", default_value => "N", is_nullable => 0, size => 1 },
289
  "article_requests",
290
  {
291
    data_type => "enum",
292
    default_value => "no",
293
    extra => { list => ["no", "yes", "bib_only", "item_only"] },
294
    is_nullable => 0,
295
  },
296
  "note",
297
  { data_type => "varchar", is_nullable => 1, size => 100 },
298
);
299
300
=head1 PRIMARY KEY
301
302
=over 4
303
304
=item * L</branchcode>
305
306
=item * L</categorycode>
307
308
=item * L</itemtype>
309
310
=back
311
312
=cut
313
314
__PACKAGE__->set_primary_key("branchcode", "categorycode", "itemtype");
315
316
317
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-03-05 20:49:11
318
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6bPX0BRWWQZrWFun3GP86Q
319
320
sub koha_object_class {
321
    'Koha::IssuingRule';
322
}
323
sub koha_objects_class {
324
    'Koha::IssuingRules';
325
}
326
327
1;
(-)a/admin/smart-rules.pl (-72 / +43 lines)
Lines 26-33 use C4::Koha; Link Here
26
use C4::Debug;
26
use C4::Debug;
27
use Koha::DateUtils;
27
use Koha::DateUtils;
28
use Koha::Database;
28
use Koha::Database;
29
use Koha::IssuingRule;
30
use Koha::IssuingRules;
31
use Koha::Logger;
29
use Koha::Logger;
32
use Koha::RefundLostItemFeeRules;
30
use Koha::RefundLostItemFeeRules;
33
use Koha::Libraries;
31
use Koha::Libraries;
Lines 81-92 if ($op eq 'delete') { Link Here
81
    my $categorycode = $input->param('categorycode');
79
    my $categorycode = $input->param('categorycode');
82
    $debug and warn "deleting $1 $2 $branch";
80
    $debug and warn "deleting $1 $2 $branch";
83
81
84
    Koha::IssuingRules->find({
82
    Koha::CirculationRules->set_rules(
85
        branchcode   => $branch,
83
        {
86
        categorycode => $categorycode,
84
            categorycode => $categorycode,
87
        itemtype     => $itemtype
85
            branchcode   => $branch,
88
    })->delete;
86
            itemtype     => $itemtype,
89
87
            rules        => {
88
                restrictedtype                   => undef,
89
                rentaldiscount                   => undef,
90
                fine                             => undef,
91
                finedays                         => undef,
92
                maxsuspensiondays                => undef,
93
                firstremind                      => undef,
94
                chargeperiod                     => undef,
95
                chargeperiod_charge_at           => undef,
96
                accountsent                      => undef,
97
                issuelength                      => undef,
98
                lengthunit                       => undef,
99
                hardduedate                      => undef,
100
                hardduedatecompare               => undef,
101
                renewalsallowed                  => undef,
102
                renewalperiod                    => undef,
103
                norenewalbefore                  => undef,
104
                auto_renew                       => undef,
105
                no_auto_renewal_after            => undef,
106
                no_auto_renewal_after_hard_limit => undef,
107
                reservesallowed                  => undef,
108
                holds_per_record                 => undef,
109
                overduefinescap                  => undef,
110
                cap_fine_to_replacement_price    => undef,
111
                onshelfholds                     => undef,
112
                opacitemholds                    => undef,
113
                article_requests                 => undef,
114
            }
115
        }
116
    );
90
}
117
}
91
elsif ($op eq 'delete-branch-cat') {
118
elsif ($op eq 'delete-branch-cat') {
92
    my $categorycode  = $input->param('categorycode');
119
    my $categorycode  = $input->param('categorycode');
Lines 264-273 elsif ($op eq 'add') { Link Here
264
    my $note = $input->param('note');
291
    my $note = $input->param('note');
265
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
292
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
266
293
267
    my $params = {
294
    my $rules = {
268
        branchcode                    => $br,
295
        maxissueqty                   => $maxissueqty,
269
        categorycode                  => $bor,
296
        maxonsiteissueqty             => $maxonsiteissueqty,
270
        itemtype                      => $itemtype,
271
        fine                          => $fine,
297
        fine                          => $fine,
272
        finedays                      => $finedays,
298
        finedays                      => $finedays,
273
        maxsuspensiondays             => $maxsuspensiondays,
299
        maxsuspensiondays             => $maxsuspensiondays,
Lines 297-317 elsif ($op eq 'add') { Link Here
297
        note                          => $note,
323
        note                          => $note,
298
    };
324
    };
299
325
300
    my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
301
    if ($issuingrule) {
302
        $issuingrule->set($params)->store();
303
    } else {
304
        Koha::IssuingRule->new()->set($params)->store();
305
    }
306
    Koha::CirculationRules->set_rules(
326
    Koha::CirculationRules->set_rules(
307
        {
327
        {
308
            categorycode => $bor,
328
            categorycode => $bor,
309
            itemtype     => $itemtype,
329
            itemtype     => $itemtype,
310
            branchcode   => $br,
330
            branchcode   => $br,
311
            rules        => {
331
            rules        => $rules,
312
                maxissueqty       => $maxissueqty,
313
                maxonsiteissueqty => $maxonsiteissueqty,
314
            }
315
        }
332
        }
316
    );
333
    );
317
334
Lines 548-609 $template->param( Link Here
548
565
549
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
566
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
550
567
551
my @row_loop;
552
my $itemtypes = Koha::ItemTypes->search_with_localization;
568
my $itemtypes = Koha::ItemTypes->search_with_localization;
553
569
554
my $sth2 = $dbh->prepare("
555
    SELECT  issuingrules.*,
556
            itemtypes.description AS humanitemtype,
557
            categories.description AS humancategorycode,
558
            COALESCE( localization.translation, itemtypes.description ) AS translated_description
559
    FROM issuingrules
560
    LEFT JOIN itemtypes
561
        ON (itemtypes.itemtype = issuingrules.itemtype)
562
    LEFT JOIN categories
563
        ON (categories.categorycode = issuingrules.categorycode)
564
    LEFT JOIN localization ON issuingrules.itemtype = localization.code
565
        AND localization.entity = 'itemtypes'
566
        AND localization.lang = ?
567
    WHERE issuingrules.branchcode = ?
568
");
569
$sth2->execute($language, $branch);
570
571
while (my $row = $sth2->fetchrow_hashref) {
572
    $row->{'current_branch'} ||= $row->{'branchcode'};
573
    $row->{humanitemtype} ||= $row->{itemtype};
574
    $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
575
    $row->{'humancategorycode'} ||= $row->{'categorycode'};
576
    $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
577
    $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
578
    if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
579
       my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
580
       $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
581
       $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
582
       $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
583
       $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
584
    } else {
585
       $row->{'hardduedate'} = 0;
586
    }
587
    if ($row->{no_auto_renewal_after_hard_limit}) {
588
       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
589
       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
590
    }
591
592
    push @row_loop, $row;
593
}
594
595
my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
596
597
$template->param(show_branch_cat_rule_form => 1);
570
$template->param(show_branch_cat_rule_form => 1);
598
571
599
$template->param(
572
$template->param(
600
    patron_categories => $patron_categories,
573
    patron_categories => $patron_categories,
601
                        itemtypeloop => $itemtypes,
574
    itemtypeloop      => $itemtypes,
602
                        rules => \@sorted_row_loop,
575
    humanbranch       => ( $branch ne '*' ? $branch : '' ),
603
                        humanbranch => ($branch ne '*' ? $branch : ''),
576
    current_branch    => $branch,
604
                        current_branch => $branch,
577
);
605
                        definedbranch => scalar(@sorted_row_loop)>0
606
                        );
607
output_html_with_http_headers $input, $cookie, $template->output;
578
output_html_with_http_headers $input, $cookie, $template->output;
608
579
609
exit 0;
580
exit 0;
(-)a/installer/data/mysql/atomicupdate/bug_18936.perl (+45 lines)
Line 0 Link Here
1
$DBversion = 'XXX';  # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
	my @columns = qw(
4
		restrictedtype
5
		rentaldiscount
6
		fine
7
		finedays
8
		maxsuspensiondays
9
		firstremind
10
		chargeperiod
11
		chargeperiod_charge_at
12
		accountsent
13
		issuelength
14
		lengthunit
15
		hardduedate
16
		hardduedatecompare
17
		renewalsallowed
18
		renewalperiod
19
		norenewalbefore
20
		auto_renew
21
		no_auto_renewal_after
22
		no_auto_renewal_after_hard_limit
23
		reservesallowed
24
		holds_per_record
25
		overduefinescap
26
		cap_fine_to_replacement_price
27
		onshelfholds
28
		opacitemholds
29
		article_requests
30
	);
31
32
    if ( column_exists( 'issuingrules', 'categorycode' ) ) {
33
		foreach my $column ( @columns ) {
34
			$dbh->do("
35
				INSERT INTO circulation_rules ( categorycode, branchcode, itemtype, rule_name, rule_value )
36
				SELECT categorycode, branchcode, itemtype, 'column', $column
37
				FROM issuingrules
38
			");
39
		}
40
        $dbh->do("DROP TABLE issuingrules");
41
    }
42
43
    SetVersion( $DBversion );
44
    print "Upgrade to $DBversion done (Bug 18930 - Move lost item refund rules to circulation_rules table)\n";
45
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (-140 / +178 lines)
Lines 1-17 Link Here
1
[% USE raw %]
1
[% USE raw %]
2
[% USE Asset %]
2
[% USE Asset %]
3
[% USE Koha %]
3
[% USE Koha %]
4
[% USE KohaDates %]
4
[% USE Branches %]
5
[% USE Branches %]
5
[% USE Categories %]
6
[% USE Categories %]
7
[% USE ItemTypes %]
6
[% USE CirculationRules %]
8
[% USE CirculationRules %]
7
[% SET footerjs = 1 %]
9
[% SET footerjs = 1 %]
8
10
9
[% SET branchcode = humanbranch %]
11
[% SET branchcode = humanbranch || '*' %]
10
12
11
[% SET categorycodes = ['*'] %]
13
[% SET categorycodes = [] %]
12
[% FOREACH pc IN patron_categories %]
14
[% FOREACH pc IN patron_categories %]
13
    [% categorycodes.push( pc.id ) %]
15
    [% categorycodes.push( pc.id ) %]
14
[% END %]
16
[% END %]
17
[% categorycodes.push('*') %]
18
19
[% SET itemtypes = [] %]
20
[% FOREACH i IN itemtypeloop %]
21
    [% itemtypes.push( i.itemtype ) %]
22
[% END %]
23
[% itemtypes.push('*') %]
15
24
16
[% INCLUDE 'doc-head-open.inc' %]
25
[% INCLUDE 'doc-head-open.inc' %]
17
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
26
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
Lines 112-255 Link Here
112
            </tr>
121
            </tr>
113
            </thead>
122
            </thead>
114
            <tbody>
123
            <tbody>
115
				[% FOREACH rule IN rules %]
124
                [% SET row_count = 0 %]
116
					<tr id="row_[% loop.count | html %]">
125
                [% FOREACH c IN categorycodes %]
117
							<td>[% IF ( rule.default_humancategorycode ) %]
126
                    [% FOREACH i IN itemtypes %]
118
									<em>All</em>
127
                        [% SET note = CirculationRules.Get( branchcode, c, i, 'note' ) %]
119
								[% ELSE %]
128
                        [% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
120
									[% rule.humancategorycode | html %]
129
                        [% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
121
								[% END %]
130
                        [% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
122
							</td>
131
                        [% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
123
                            <td>[% IF rule.default_translated_description %]
132
                        [% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
124
									<em>All</em>
133
                        [% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
125
								[% ELSE %]
134
                        [% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
126
									[% rule.translated_description | html %]
135
                        [% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
127
								[% END %]
136
                        [% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
128
							</td>
137
                        [% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
129
                                                        <td class="actions">
138
                        [% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
130
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
139
                        [% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
131
                                                          <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>
140
                        [% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
132
                                                        </td>
141
                        [% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
133
142
                        [% SET suspension_chargeperiod = CirculationRules.Get( branchcode, c, i, 'suspension_chargeperiod' ) %]
134
                                                        <td>
143
                        [% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
135
                                                            [% IF rule.note %]
144
                        [% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
136
                                                                <a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
145
                        [% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
137
                                                            [% ELSE %]&nbsp;[% END %]
146
                        [% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
138
                                                        </td>
147
                        [% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
139
                            <td>
148
                        [% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
140
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
149
                        [% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
141
                                [% IF rule_value || rule_value == "0"  %]
150
                        [% SET holds_per_day = CirculationRules.Get( branchcode, c, i, 'holds_per_day' ) %]
142
                                    [% rule_value | html %]
151
                        [% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
143
                                [% ELSE %]
152
                        [% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
144
                                    <span>Unlimited</span>
153
                        [% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
145
                                [% END %]
154
                        [% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
146
                            </td>
155
                        [% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
147
                            <td>
156
148
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
157
                        [% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
149
                                [% IF rule_value || rule_value == "0" %]
158
                                        || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed
150
                                    [% rule_value | html %]
159
                                        || renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
151
                                [% ELSE %]
160
                                        || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
152
                                    <span>Unlimited</span>
161
                        [% IF show_rule %]
153
                                [% END %]
162
                            [% SET row_count = row_count + 1 %]
154
                            </td>
163
                            <tr row_countd="row_[% row_count %]">
155
                            <td>[% rule.issuelength | html %]</td>
164
                                    <td>
156
                            <td>
165
                                        [% IF c == '*' %]
157
                                [% rule.lengthunit | html %]
166
                                            <em>All</em>
158
                            </td>
167
                                        [% ELSE %]
159
                            <td>
168
                                            [% Categories.GetName(c) %]
160
                              [% IF ( rule.hardduedate ) %]
169
                                        [% END %]
161
                                [% IF ( rule.hardduedatebefore ) %]
170
                                    </td>
162
                                  before [% rule.hardduedate | html %]
171
                                    <td>
163
                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
172
                                        [% IF i == '*' %]
164
                                [% ELSIF ( rule.hardduedateexact ) %]
173
                                            <em>All</em>
165
                                  on [% rule.hardduedate | html %]
174
                                        [% ELSE %]
166
                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
175
                                            [% ItemTypes.GetDescription(i) %]
167
                                [% ELSIF ( rule.hardduedateafter ) %]
176
                                        [% END %]
168
                                  after [% rule.hardduedate | html %]
177
                                    </td>
169
                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
178
                                    <td>
170
                                [% END %]
179
                                        [% IF rule.note %]
171
                              [% ELSE %]
180
                                            <a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
172
                                <span>None defined</span>
181
                                        [% ELSE %]<span>&nbsp;</span>[% END %]
173
                              [% END %]
182
                                    </td>
174
                            </td>
183
                                    <td>
175
							<td>[% rule.fine | html %]</td>
184
                                        [% IF maxissueqty  %]
176
							<td>[% rule.chargeperiod | html %]</td>
185
                                            [% maxissueqty %]
177
                            <td>
186
                                        [% ELSE %]
178
                                [% IF rule.chargeperiod_charge_at %]
187
                                            <span>Unlimited</span>
179
                                    <span>Start of interval</span>
188
                                        [% END %]
180
                                [% ELSE %]
189
                                    </td>
181
                                    <span>End of interval</span>
190
                                    <td>
182
                                [% END %]
191
                                        [% IF maxonsiteissueqty  %]
183
                            </td>
192
                                            [% maxonsiteissueqty %]
184
							<td>[% rule.firstremind | html %]</td>
193
                                        [% ELSE %]
185
                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
194
                                            <span>Unlimited</span>
186
                            <td>
195
                                        [% END %]
187
                                [% IF rule.cap_fine_to_replacement_price %]
196
                                    </td>
188
                                    <input type="checkbox" checked="checked" disabled="disabled" />
197
                                    <td>[% issuelength %]</td>
189
                                [% ELSE %]
198
                                    <td>
190
                                    <input type="checkbox" disabled="disabled" />
199
                                        [% lengthunit %]
191
                                [% END %]
200
                                    </td>
192
                            </td>
201
                                    <td>
193
							<td>[% rule.finedays | html %]</td>
202
                                      [% IF ( hardduedate ) %]
194
                            <td>[% rule.maxsuspensiondays | html %]</td>
203
                                        [% IF ( hardduedatecompare == '-1' ) %]
195
                            <td>[% rule.suspension_chargeperiod | html %]</td>
204
                                          before [% hardduedate | $KohaDates %]
196
							<td>[% rule.renewalsallowed | html %]</td>
205
                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
197
                            <td>[% rule.renewalperiod | html %]</td>
206
                                        [% ELSIF ( hardduedatecompare == '0' ) %]
198
                            <td>[% rule.norenewalbefore | html %]</td>
207
                                          on [% hardduedate | $KohaDates %]
199
                            <td>
208
                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
200
                                [% IF ( rule.auto_renew ) %]
209
                                        [% ELSIF ( hardduedatecompare == '1' ) %]
201
                                    <span>Yes</span>
210
                                          after [% hardduedate | $KohaDates %]
202
                                [% ELSE %]
211
                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
203
                                    <span>No</span>
212
                                        [% END %]
204
                                [% END %]
213
                                      [% ELSE %]
205
                            </td>
214
                                        <span>None defined</span>
206
                            <td>[% rule.no_auto_renewal_after | html %]</td>
215
                                      [% END %]
207
                            <td>[% rule.no_auto_renewal_after_hard_limit | html %]</td>
216
                                    </td>
208
							<td>[% rule.reservesallowed | html %]</td>
217
                                    <td>[% fine %]</td>
209
                            <td>[% IF rule.unlimited_holds_per_day %]
218
                                    <td>[% chargeperiod %]</td>
210
                                    <span>Unlimited</span>
219
                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
211
                                [% ELSE %]
220
                                    <td>[% firstremind %]</td>
212
                                    [% rule.holds_per_day | html %]
221
                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
213
                                [% END %]
222
                                    <td>
214
                            </td>
223
                                        [% IF cap_fine_to_replacement_price %]
215
                            <td>[% rule.holds_per_record | html %]</td>
224
                                            <input type="checkbox" checked="checked" disabled="disabled" />
216
                                                        <td>
225
                                        [% ELSE %]
217
                                                            [% IF rule.onshelfholds == 1 %]
226
                                            <input type="checkbox" disabled="disabled" />
218
                                                                <span>Yes</span>
227
                                        [% END %]
219
                                                            [% ELSIF rule.onshelfholds == 2 %]
228
                                    </td>
220
                                                                <span>If all unavailable</span>
229
                                    <td>[% finedays %]</td>
221
                                                            [% ELSE %]
230
                                    <td>[% maxsuspensiondays %]</td>
222
                                                                <span>If any unavailable</span>
231
                                    <td>[% suspension_chargeperiod %]</td>
223
                                                            [% END %]
232
                                    <td>[% renewalsallowed %]</td>
224
                                                        </td>
233
                                    <td>[% renewalperiod %]</td>
225
                                                        <td>
234
                                    <td>[% norenewalbefore %]</td>
226
                                                            [% IF rule.opacitemholds == 'F'%]
235
                                    <td>
227
                                                                <span>Force</span>
236
                                        [% IF auto_renew %]
228
                                                            [% ELSIF rule.opacitemholds == 'Y'%]
237
                                            <span>Yes</span>
229
                                                                <span>Allow</span>
238
                                        [% ELSE %]
230
                                                            [% ELSE %]
239
                                            <span>No</span>
231
                                                                <span>Don't allow</span>
240
                                        [% END %]
232
                                                            [% END %]
241
                                    </td>
233
                                                        </td>
242
                                    <td>[% no_auto_renewal_after %]</td>
234
                                                        <td>
243
                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
235
                                                            [% IF rule.article_requests == 'no' %]
244
                                    <td>[% reservesallowed %]</td>
236
                                                                <span>No</span>
245
                                    <td>
237
                                                            [% ELSIF rule.article_requests == 'yes' %]
246
                                        [% IF holds_per_day.defined && holds != '' %]
238
                                                                <span>Yes</span>
247
                                            [% holds_per_day %]
239
                                                            [% ELSIF rule.article_requests == 'bib_only' %]
248
                                        [% ELSE %]
240
                                                                <span>Record only</span>
249
                                            <span>Unlimited</span>
241
                                                            [% ELSIF rule.article_requests == 'item_only' %]
250
                                        [% END %]
242
                                                                <span>Item only</span>
251
                                    </td>
243
                                                            [% END %]
252
                                    <td>[% holds_per_record %]</td>
244
                                                        </td>
253
                                    <td>
245
                                                        <td>[% rule.rentaldiscount | html %]</td>
254
                                        [% IF onshelfholds == 1 %]
246
                                                        <td class="actions">
255
                                            <span>Yes</span>
247
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
256
                                        [% ELSIF onshelfholds == 2 %]
248
                                                          <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>
257
                                            <span>If all unavailable</span>
249
                                                        </td>
258
                                        [% ELSE %]
250
259
                                            <span>If any unavailable</span>
251
                	</tr>
260
                                        [% END %]
252
            	[% END %]
261
                                    </td>
262
                                    <td>
263
                                        [% IF opacitemholds == 'F'%]
264
                                            <span>Force</span>
265
                                        [% ELSIF opacitemholds == 'Y'%]
266
                                            <span>Allow</span>
267
                                        [% ELSE %]
268
                                            <span>Don't allow</span>
269
                                        [% END %]
270
                                    </td>
271
                                    <td>
272
                                        [% IF article_requests == 'no' %]
273
                                            <span>No</span>
274
                                        [% ELSIF article_requests == 'yes' %]
275
                                            <span>Yes</span>
276
                                        [% ELSIF article_requests == 'bib_only' %]
277
                                            <span>Record only</span>
278
                                        [% ELSIF article_requests == 'item_only' %]
279
                                            <span>Item only</span>
280
                                        [% END %]
281
                                    </td>
282
                                    <td>[% rentaldiscount %]</td>
283
                                    <td class="actions">
284
                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
285
                                      <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>
286
                                    </td>
287
                            </tr>
288
                        [% END %]
289
                    [% END %]
290
                [% END %]
253
                <tr id="edit_row">
291
                <tr id="edit_row">
254
                    <td>
292
                    <td>
255
                        <select name="categorycode" id="categorycode">
293
                        <select name="categorycode" id="categorycode">
(-)a/t/db_dependent/ArticleRequests.t (-11 / +38 lines)
Lines 29-35 use Koha::Biblio; Link Here
29
use Koha::Notice::Messages;
29
use Koha::Notice::Messages;
30
use Koha::Patron;
30
use Koha::Patron;
31
use Koha::Library::Group;
31
use Koha::Library::Group;
32
use Koha::IssuingRules;
32
use Koha::CirculationRules;
33
use Koha::Caches;
33
use Koha::Caches;
34
34
35
BEGIN {
35
BEGIN {
Lines 46-52 our $cache = Koha::Caches->get_instance; Link Here
46
my $dbh = C4::Context->dbh;
46
my $dbh = C4::Context->dbh;
47
$dbh->{RaiseError} = 1;
47
$dbh->{RaiseError} = 1;
48
48
49
$dbh->do("DELETE FROM issuingrules");
49
$dbh->do("DELETE FROM circulation_rules");
50
50
51
my $biblio = Koha::Biblio->new()->store();
51
my $biblio = Koha::Biblio->new()->store();
52
ok( $biblio->id, 'Koha::Biblio created' );
52
ok( $biblio->id, 'Koha::Biblio created' );
Lines 172-204 $article_request->complete(); Link Here
172
$article_request->cancel();
172
$article_request->cancel();
173
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
173
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
174
174
175
my $rule;
175
my $rule = Koha::CirculationRules->set_rule(
176
$rule = $schema->resultset('Issuingrule')
176
    {
177
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
177
        categorycode => '*',
178
        itemtype     => '*',
179
        branchcode   => '*',
180
        rule_name    => 'article_requests',
181
        rule_value   => 'yes',
182
    }
183
);
178
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
184
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
179
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
185
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
180
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
186
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
181
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
187
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
182
$rule->delete();
188
$rule->delete();
183
189
184
$rule = $schema->resultset('Issuingrule')
190
$rule = Koha::CirculationRules->set_rule(
185
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
191
    {
192
        categorycode => '*',
193
        itemtype     => '*',
194
        branchcode   => '*',
195
        rule_name    => 'article_requests',
196
        rule_value   => 'bib_only',
197
    }
198
);
186
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
199
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
187
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
200
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
188
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
201
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
189
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
202
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
190
$rule->delete();
203
$rule->delete();
191
204
192
$rule = $schema->resultset('Issuingrule')
205
$rule = Koha::CirculationRules->set_rule(
193
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
206
    {
207
        categorycode => '*',
208
        itemtype     => '*',
209
        branchcode   => '*',
210
        rule_name    => 'article_requests',
211
        rule_value   => 'item_only',
212
    }
213
);
194
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
214
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
195
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
215
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
196
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
216
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
197
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
217
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
198
$rule->delete();
218
$rule->delete();
199
219
200
$rule = $schema->resultset('Issuingrule')
220
$rule = Koha::CirculationRules->set_rule(
201
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
221
    {
222
        categorycode => '*',
223
        itemtype     => '*',
224
        branchcode   => '*',
225
        rule_name    => 'article_requests',
226
        rule_value   => 'no',
227
    }
228
);
202
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
229
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
203
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
230
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
204
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
231
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
(-)a/t/db_dependent/Circulation.t (-75 / +271 lines)
Lines 38-44 use C4::Reserves; Link Here
38
use C4::Overdues qw(UpdateFine CalcFine);
38
use C4::Overdues qw(UpdateFine CalcFine);
39
use Koha::DateUtils;
39
use Koha::DateUtils;
40
use Koha::Database;
40
use Koha::Database;
41
use Koha::IssuingRules;
42
use Koha::Items;
41
use Koha::Items;
43
use Koha::Checkouts;
42
use Koha::Checkouts;
44
use Koha::Patrons;
43
use Koha::Patrons;
Lines 252-278 is( Link Here
252
);
251
);
253
252
254
# Set a simple circ policy
253
# Set a simple circ policy
255
$dbh->do('DELETE FROM issuingrules');
254
$dbh->do('DELETE FROM circulation_rules');
256
Koha::CirculationRules->search()->delete();
255
Koha::CirculationRules->set_rules(
257
$dbh->do(
256
    {
258
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed,
257
        categorycode => '*',
259
                                issuelength, lengthunit,
258
        branchcode   => '*',
260
                                renewalsallowed, renewalperiod,
259
        itemtype     => '*',
261
                                norenewalbefore, auto_renew,
260
        rules        => {
262
                                fine, chargeperiod)
261
            reservesallowed => 25,
263
      VALUES (?, ?, ?, ?,
262
            issuelength     => 14,
264
              ?, ?,
263
            lengthunit      => 'days',
265
              ?, ?,
264
            renewalsallowed => 1,
266
              ?, ?,
265
            renewalperiod   => 7,
267
              ?, ?
266
            norenewalbefore => undef,
268
             )
267
            auto_renew      => 0,
269
    },
268
            fine            => .10,
270
    {},
269
            chargeperiod    => 1,
271
    '*', '*', '*', 25,
270
        }
272
    14, 'days',
271
    }
273
    1, 7,
274
    undef, 0,
275
    .10, 1
276
);
272
);
277
273
278
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
274
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
Lines 394-400 subtest "CanBookBeRenewed tests" => sub { Link Here
394
    );
390
    );
395
391
396
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
392
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
397
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
393
    Koha::CirculationRules->set_rule(
394
        {
395
            categorycode => '*',
396
            branchcode   => '*',
397
            itemtype     => '*',
398
            rule_name    => 'onshelfholds',
399
            rule_value   => '1',
400
        }
401
    );
398
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
402
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
399
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
403
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
400
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
404
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
Lines 609-615 subtest "CanBookBeRenewed tests" => sub { Link Here
609
613
610
    # Bug 7413
614
    # Bug 7413
611
    # Test premature manual renewal
615
    # Test premature manual renewal
612
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 7');
616
    Koha::CirculationRules->set_rule(
617
        {
618
            categorycode => '*',
619
            branchcode   => '*',
620
            itemtype     => '*',
621
            rule_name    => 'norenewalbefore',
622
            rule_value   => '7',
623
        }
624
    );
613
625
614
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
626
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
615
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
627
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
Lines 644-650 subtest "CanBookBeRenewed tests" => sub { Link Here
644
656
645
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
657
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
646
    # and test automatic renewal again
658
    # and test automatic renewal again
647
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 0');
659
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
648
    ( $renewokay, $error ) =
660
    ( $renewokay, $error ) =
649
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
661
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
650
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
662
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
Lines 654-660 subtest "CanBookBeRenewed tests" => sub { Link Here
654
666
655
    # Change policy so that loans can be renewed 99 days prior to the due date
667
    # Change policy so that loans can be renewed 99 days prior to the due date
656
    # and test automatic renewal again
668
    # and test automatic renewal again
657
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 99');
669
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
658
    ( $renewokay, $error ) =
670
    ( $renewokay, $error ) =
659
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
671
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
660
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
672
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
Lines 678-720 subtest "CanBookBeRenewed tests" => sub { Link Here
678
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
690
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
679
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
691
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
680
692
681
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9');
693
        Koha::CirculationRules->set_rules(
694
            {
695
                categorycode => '*',
696
                branchcode   => '*',
697
                itemtype     => '*',
698
                rules        => {
699
                    norenewalbefore       => '7',
700
                    no_auto_renewal_after => '9',
701
                }
702
            }
703
        );
682
        ( $renewokay, $error ) =
704
        ( $renewokay, $error ) =
683
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
705
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
684
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
706
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
685
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
707
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
686
708
687
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10');
709
        Koha::CirculationRules->set_rules(
710
            {
711
                categorycode => '*',
712
                branchcode   => '*',
713
                itemtype     => '*',
714
                rules        => {
715
                    norenewalbefore       => '7',
716
                    no_auto_renewal_after => '10',
717
                }
718
            }
719
        );
688
        ( $renewokay, $error ) =
720
        ( $renewokay, $error ) =
689
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
721
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
690
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
722
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
691
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
723
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
692
724
693
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11');
725
        Koha::CirculationRules->set_rules(
726
            {
727
                categorycode => '*',
728
                branchcode   => '*',
729
                itemtype     => '*',
730
                rules        => {
731
                    norenewalbefore       => '7',
732
                    no_auto_renewal_after => '11',
733
                }
734
            }
735
        );
694
        ( $renewokay, $error ) =
736
        ( $renewokay, $error ) =
695
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
737
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
696
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
738
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
697
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
739
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
698
740
699
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
741
        Koha::CirculationRules->set_rules(
742
            {
743
                categorycode => '*',
744
                branchcode   => '*',
745
                itemtype     => '*',
746
                rules        => {
747
                    norenewalbefore       => '10',
748
                    no_auto_renewal_after => '11',
749
                }
750
            }
751
        );
700
        ( $renewokay, $error ) =
752
        ( $renewokay, $error ) =
701
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
753
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
702
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
754
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
703
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
755
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
704
756
705
        $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 ) );
757
        Koha::CirculationRules->set_rules(
758
            {
759
                categorycode => '*',
760
                branchcode   => '*',
761
                itemtype     => '*',
762
                rules        => {
763
                    norenewalbefore       => '10',
764
                    no_auto_renewal_after => undef,
765
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
766
                }
767
            }
768
        );
706
        ( $renewokay, $error ) =
769
        ( $renewokay, $error ) =
707
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
770
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
708
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
771
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
709
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
772
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
710
773
711
        $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 ) );
774
        Koha::CirculationRules->set_rules(
775
            {
776
                categorycode => '*',
777
                branchcode   => '*',
778
                itemtype     => '*',
779
                rules        => {
780
                    norenewalbefore       => '7',
781
                    no_auto_renewal_after => '15',
782
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
783
                }
784
            }
785
        );
712
        ( $renewokay, $error ) =
786
        ( $renewokay, $error ) =
713
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
787
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
714
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
788
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
715
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
789
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
716
790
717
        $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 ) );
791
        Koha::CirculationRules->set_rules(
792
            {
793
                categorycode => '*',
794
                branchcode   => '*',
795
                itemtype     => '*',
796
                rules        => {
797
                    norenewalbefore       => '10',
798
                    no_auto_renewal_after => undef,
799
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 1 ),
800
                }
801
            }
802
        );
718
        ( $renewokay, $error ) =
803
        ( $renewokay, $error ) =
719
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
804
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
720
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
805
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
Lines 736-742 subtest "CanBookBeRenewed tests" => sub { Link Here
736
        my $ten_days_ahead = dt_from_string->add( days => 10 );
821
        my $ten_days_ahead = dt_from_string->add( days => 10 );
737
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
822
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
738
823
739
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
824
        Koha::CirculationRules->set_rules(
825
            {
826
                categorycode => '*',
827
                branchcode   => '*',
828
                itemtype     => '*',
829
                rules        => {
830
                    norenewalbefore       => '10',
831
                    no_auto_renewal_after => '11',
832
                }
833
            }
834
        );
740
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
835
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
741
        C4::Context->set_preference('OPACFineNoRenewals','10');
836
        C4::Context->set_preference('OPACFineNoRenewals','10');
742
        my $fines_amount = 5;
837
        my $fines_amount = 5;
Lines 853-883 subtest "CanBookBeRenewed tests" => sub { Link Here
853
        my $ten_days_before = dt_from_string->add( days => -10 );
948
        my $ten_days_before = dt_from_string->add( days => -10 );
854
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
949
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
855
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
950
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
856
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = NULL');
951
        Koha::CirculationRules->set_rules(
952
            {
953
                categorycode => '*',
954
                branchcode   => '*',
955
                itemtype     => '*',
956
                rules        => {
957
                    norenewalbefore       => '7',
958
                    no_auto_renewal_after => '',
959
                    no_auto_renewal_after_hard_limit => undef,
960
                }
961
            }
962
        );
857
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
963
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
858
        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' );
964
        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' );
859
        my $five_days_before = dt_from_string->add( days => -5 );
965
        my $five_days_before = dt_from_string->add( days => -5 );
860
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
966
        Koha::CirculationRules->set_rules(
967
            {
968
                categorycode => '*',
969
                branchcode   => '*',
970
                itemtype     => '*',
971
                rules        => {
972
                    norenewalbefore       => '10',
973
                    no_auto_renewal_after => '5',
974
                    no_auto_renewal_after_hard_limit => undef,
975
                }
976
            }
977
        );
861
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
978
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
862
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
979
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
863
            $five_days_before->truncate( to => 'minute' ),
980
            $five_days_before->truncate( to => 'minute' ),
864
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
981
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
865
        );
982
        );
866
        my $five_days_ahead = dt_from_string->add( days => 5 );
983
        my $five_days_ahead = dt_from_string->add( days => 5 );
867
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
984
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
985
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
986
        $dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
987
        Koha::CirculationRules->set_rules(
988
            {
989
                categorycode => '*',
990
                branchcode   => '*',
991
                itemtype     => '*',
992
                rules        => {
993
                    norenewalbefore       => '10',
994
                    no_auto_renewal_after => '15',
995
                    no_auto_renewal_after_hard_limit => undef,
996
                }
997
            }
998
        );
868
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
999
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
869
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1000
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
870
            $five_days_ahead->truncate( to => 'minute' ),
1001
            $five_days_ahead->truncate( to => 'minute' ),
871
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
1002
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
872
        );
1003
        );
873
        my $two_days_ahead = dt_from_string->add( days => 2 );
1004
        my $two_days_ahead = dt_from_string->add( days => 2 );
874
        $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 ) );
1005
        Koha::CirculationRules->set_rules(
1006
            {
1007
                categorycode => '*',
1008
                branchcode   => '*',
1009
                itemtype     => '*',
1010
                rules        => {
1011
                    norenewalbefore       => '10',
1012
                    no_auto_renewal_after => '',
1013
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
1014
                }
1015
            }
1016
        );
875
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
1017
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
876
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1018
        is( $latest_auto_renew_date->truncate( to => 'day' ),
877
            $two_days_ahead->truncate( to => 'day' ),
1019
            $two_days_ahead->truncate( to => 'day' ),
878
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
1020
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
879
        );
1021
        );
880
        $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 ) );
1022
        Koha::CirculationRules->set_rules(
1023
            {
1024
                categorycode => '*',
1025
                branchcode   => '*',
1026
                itemtype     => '*',
1027
                rules        => {
1028
                    norenewalbefore       => '10',
1029
                    no_auto_renewal_after => '15',
1030
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
1031
                }
1032
            }
1033
        );
881
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
1034
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
882
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1035
        is( $latest_auto_renew_date->truncate( to => 'day' ),
883
            $two_days_ahead->truncate( to => 'day' ),
1036
            $two_days_ahead->truncate( to => 'day' ),
Lines 885-895 subtest "CanBookBeRenewed tests" => sub { Link Here
885
        );
1038
        );
886
1039
887
    };
1040
    };
888
889
    # Too many renewals
1041
    # Too many renewals
890
1042
891
    # set policy to forbid renewals
1043
    # set policy to forbid renewals
892
    $dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
1044
    Koha::CirculationRules->set_rules(
1045
        {
1046
            categorycode => '*',
1047
            branchcode   => '*',
1048
            itemtype     => '*',
1049
            rules        => {
1050
                norenewalbefore => undef,
1051
                renewalsallowed => 0,
1052
            }
1053
        }
1054
    );
893
1055
894
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
1056
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
895
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
1057
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
Lines 1124-1150 subtest "Bug 13841 - Do not create new 0 amount fines" => sub { Link Here
1124
subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
1286
subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
1125
    $dbh->do('DELETE FROM issues');
1287
    $dbh->do('DELETE FROM issues');
1126
    $dbh->do('DELETE FROM items');
1288
    $dbh->do('DELETE FROM items');
1127
    $dbh->do('DELETE FROM issuingrules');
1289
    $dbh->do('DELETE FROM circulation_rules');
1128
    Koha::CirculationRules->search()->delete();
1129
    $dbh->do(
1130
        q{
1131
        INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
1132
                    norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
1133
        },
1134
        {},
1135
        '*', '*', '*', 25,
1136
        14,  'days',
1137
        1,   7,
1138
        undef,  0,
1139
        .10, 1
1140
    );
1141
    Koha::CirculationRules->set_rules(
1290
    Koha::CirculationRules->set_rules(
1142
        {
1291
        {
1143
            categorycode => '*',
1292
            categorycode => '*',
1144
            itemtype     => '*',
1293
            itemtype     => '*',
1145
            branchcode   => '*',
1294
            branchcode   => '*',
1146
            rules        => {
1295
            rules        => {
1147
                maxissueqty => 20
1296
                reservesallowed => 25,
1297
                issuelength     => 14,
1298
                lengthunit      => 'days',
1299
                renewalsallowed => 1,
1300
                renewalperiod   => 7,
1301
                norenewalbefore => undef,
1302
                auto_renew      => 0,
1303
                fine            => .10,
1304
                chargeperiod    => 1,
1305
                maxissueqty     => 20
1148
            }
1306
            }
1149
        }
1307
        }
1150
    );
1308
    );
Lines 1193-1214 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1193
        undef, undef, undef
1351
        undef, undef, undef
1194
    );
1352
    );
1195
1353
1196
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1354
    Koha::CirculationRules->set_rules(
1355
        {
1356
            categorycode => '*',
1357
            itemtype     => '*',
1358
            branchcode   => '*',
1359
            rules        => {
1360
                onshelfholds => 0,
1361
            }
1362
        }
1363
    );
1197
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1364
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1198
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1365
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1199
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1366
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1200
1367
1201
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1368
    Koha::CirculationRules->set_rules(
1369
        {
1370
            categorycode => '*',
1371
            itemtype     => '*',
1372
            branchcode   => '*',
1373
            rules        => {
1374
                onshelfholds => 0,
1375
            }
1376
        }
1377
    );
1202
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1378
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1203
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1379
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1204
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1380
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1205
1381
1206
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1382
    Koha::CirculationRules->set_rules(
1383
        {
1384
            categorycode => '*',
1385
            itemtype     => '*',
1386
            branchcode   => '*',
1387
            rules        => {
1388
                onshelfholds => 1,
1389
            }
1390
        }
1391
    );
1207
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1392
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1208
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1393
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1209
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1394
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1210
1395
1211
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1396
    Koha::CirculationRules->set_rules(
1397
        {
1398
            categorycode => '*',
1399
            itemtype     => '*',
1400
            branchcode   => '*',
1401
            rules        => {
1402
                onshelfholds => 1,
1403
            }
1404
        }
1405
    );
1212
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1406
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1213
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1407
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1214
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1408
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
Lines 1726-1745 subtest 'AddReturn + CumulativeRestrictionPeriods' => sub { Link Here
1726
        }
1920
        }
1727
    );
1921
    );
1728
1922
1729
    # And the issuing rule
1923
    # And the circulation rule
1730
    Koha::IssuingRules->search->delete;
1924
    Koha::CirculationRules->search->delete;
1731
    my $rule = Koha::IssuingRule->new(
1925
    Koha::CirculationRules->set_rules(
1732
        {
1926
        {
1733
            categorycode => '*',
1927
            categorycode => '*',
1734
            itemtype     => '*',
1928
            itemtype     => '*',
1735
            branchcode   => '*',
1929
            branchcode   => '*',
1736
            issuelength  => 1,
1930
            rules        => {
1737
            firstremind  => 1,        # 1 day of grace
1931
                issuelength => 1,
1738
            finedays     => 2,        # 2 days of fine per day of overdue
1932
                firstremind => 1,        # 1 day of grace
1739
            lengthunit   => 'days',
1933
                finedays    => 2,        # 2 days of fine per day of overdue
1934
                lengthunit  => 'days',
1935
            }
1740
        }
1936
        }
1741
    );
1937
    );
1742
    $rule->store();
1743
1938
1744
    # Patron cannot issue item_1, they have overdues
1939
    # Patron cannot issue item_1, they have overdues
1745
    my $five_days_ago = dt_from_string->subtract( days => 5 );
1940
    my $five_days_ago = dt_from_string->subtract( days => 5 );
Lines 2073-2091 subtest 'AddReturn | is_overdue' => sub { Link Here
2073
        }
2268
        }
2074
    );
2269
    );
2075
2270
2076
    Koha::IssuingRules->search->delete;
2271
    Koha::CirculationRules->search->delete;
2077
    my $rule = Koha::IssuingRule->new(
2272
    my $rule = Koha::CirculationRules->set_rules(
2078
        {
2273
        {
2079
            categorycode => '*',
2274
            categorycode => '*',
2080
            itemtype     => '*',
2275
            itemtype     => '*',
2081
            branchcode   => '*',
2276
            branchcode   => '*',
2082
            issuelength  => 6,
2277
            rules        => {
2083
            lengthunit   => 'days',
2278
                issuelength  => 6,
2084
            fine         => 1, # Charge 1 every day of overdue
2279
                lengthunit   => 'days',
2085
            chargeperiod => 1,
2280
                fine         => 1,        # Charge 1 every day of overdue
2281
                chargeperiod => 1,
2282
            }
2086
        }
2283
        }
2087
    );
2284
    );
2088
    $rule->store();
2089
2285
2090
    my $now   = dt_from_string;
2286
    my $now   = dt_from_string;
2091
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
2287
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
(-)a/t/db_dependent/Circulation/CalcDateDue.t (-8 / +15 lines)
Lines 10-15 use t::lib::Mocks; Link Here
10
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
11
use C4::Calendar;
11
use C4::Calendar;
12
12
13
use Koha::CirculationRules;
14
13
use_ok('C4::Circulation');
15
use_ok('C4::Circulation');
14
16
15
my $schema = Koha::Database->new->schema;
17
my $schema = Koha::Database->new->schema;
Lines 23-36 my $issuelength = 10; Link Here
23
my $renewalperiod = 5;
25
my $renewalperiod = 5;
24
my $lengthunit = 'days';
26
my $lengthunit = 'days';
25
27
26
Koha::Database->schema->resultset('Issuingrule')->create({
28
Koha::CirculationRules->search()->delete();
27
  categorycode => $categorycode,
29
Koha::CirculationRules->set_rules(
28
  itemtype => $itemtype,
30
    {
29
  branchcode => $branchcode,
31
        categorycode => $categorycode,
30
  issuelength => $issuelength,
32
        itemtype     => $itemtype,
31
  renewalperiod => $renewalperiod,
33
        branchcode   => $branchcode,
32
  lengthunit => $lengthunit,
34
        rules        => {
33
});
35
            issuelength   => $issuelength,
36
            renewalperiod => $renewalperiod,
37
            lengthunit    => $lengthunit,
38
        }
39
    }
40
);
34
41
35
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
42
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
36
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
43
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
(-)a/t/db_dependent/Circulation/CalcFine.t (-21 / +13 lines)
Lines 78-96 my $item = $builder->build( Link Here
78
subtest 'Test basic functionality' => sub {
78
subtest 'Test basic functionality' => sub {
79
    plan tests => 1;
79
    plan tests => 1;
80
80
81
    my $rule = $builder->schema->resultset('Issuingrule')->find({
81
    Koha::CirculationRules->set_rules(
82
        branchcode                    => '*',
83
        categorycode                  => '*',
84
        itemtype                      => '*',
85
    });
86
    $rule->delete if $rule;
87
    my $issuingrule = $builder->build(
88
        {
82
        {
89
            source => 'Issuingrule',
83
            branchcode   => '*',
90
            value  => {
84
            categorycode => '*',
91
                branchcode                    => '*',
85
            itemtype     => '*',
92
                categorycode                  => '*',
86
            rules        => {
93
                itemtype                      => '*',
94
                fine                          => '1.00',
87
                fine                          => '1.00',
95
                lengthunit                    => 'days',
88
                lengthunit                    => 'days',
96
                finedays                      => 0,
89
                finedays                      => 0,
Lines 98-105 subtest 'Test basic functionality' => sub { Link Here
98
                chargeperiod                  => 1,
91
                chargeperiod                  => 1,
99
                overduefinescap               => undef,
92
                overduefinescap               => undef,
100
                cap_fine_to_replacement_price => 0,
93
                cap_fine_to_replacement_price => 0,
101
            },
94
            }
102
        }
95
        },
103
    );
96
    );
104
97
105
    my $start_dt = DateTime->new(
98
    my $start_dt = DateTime->new(
Lines 125-137 subtest 'Test cap_fine_to_replacement_price' => sub { Link Here
125
    plan tests => 2;
118
    plan tests => 2;
126
119
127
    t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
120
    t::lib::Mocks::mock_preference('useDefaultReplacementCost', '1');
128
    my $issuingrule = $builder->build(
121
    Koha::CirculationRules->set_rules(
129
        {
122
        {
130
            source => 'Issuingrule',
123
            branchcode   => '*',
131
            value  => {
124
            categorycode => '*',
132
                branchcode                    => '*',
125
            itemtype     => '*',
133
                categorycode                  => '*',
126
            rules        => {
134
                itemtype                      => '*',
135
                fine                          => '1.00',
127
                fine                          => '1.00',
136
                lengthunit                    => 'days',
128
                lengthunit                    => 'days',
137
                finedays                      => 0,
129
                finedays                      => 0,
Lines 214-218 subtest 'Test cap_fine_to_replacement_pricew with overduefinescap' => sub { Link Here
214
};
206
};
215
207
216
sub teardown {
208
sub teardown {
217
    $dbh->do(q|DELETE FROM issuingrules|);
209
    $dbh->do(q|DELETE FROM circulation_rules|);
218
}
210
}
(-)a/t/db_dependent/Circulation/GetHardDueDate.t (-211 / +103 lines)
Lines 5-14 use C4::Context; Link Here
5
use DateTime;
5
use DateTime;
6
use Koha::Database;
6
use Koha::Database;
7
use Koha::DateUtils;
7
use Koha::DateUtils;
8
use Koha::IssuingRules;
8
use Koha::CirculationRules;
9
use Koha::Library;
9
use Koha::Library;
10
10
11
use Test::More tests => 9;
11
use Test::More tests => 8;
12
12
13
BEGIN {
13
BEGIN {
14
    use_ok('C4::Circulation');
14
    use_ok('C4::Circulation');
Lines 31-37 $dbh->do(q|DELETE FROM borrowers|); Link Here
31
$dbh->do(q|DELETE FROM edifact_ean|);
31
$dbh->do(q|DELETE FROM edifact_ean|);
32
$dbh->do(q|DELETE FROM branches|);
32
$dbh->do(q|DELETE FROM branches|);
33
$dbh->do(q|DELETE FROM categories|);
33
$dbh->do(q|DELETE FROM categories|);
34
$dbh->do(q|DELETE FROM issuingrules|);
34
$dbh->do(q|DELETE FROM circulation_rules|);
35
35
36
#Add sample datas
36
#Add sample datas
37
37
Lines 111-329 my $default = { Link Here
111
    lengthunit => 'days'
111
    lengthunit => 'days'
112
};
112
};
113
113
114
#Test GetIssuingRule
114
#Test get_effective_rules
115
my $sampleissuingrule1 = {
115
my $sampleissuingrule1 = {
116
    reservecharge      => '0.000000',
116
    branchcode   => $samplebranch1->{branchcode},
117
    restrictedtype     => 0,
117
    categorycode => $samplecat->{categorycode},
118
    accountsent        => 0,
118
    itemtype     => 'BOOK',
119
    finedays           => 0,
119
    rules        => {
120
    lengthunit         => 'days',
120
        reservecharge                    => '0.000000',
121
    renewalperiod      => 5,
121
        restrictedtype                   => 0,
122
    norenewalbefore    => 6,
122
        accountsent                      => 0,
123
    auto_renew         => 0,
123
        finedays                         => 0,
124
    issuelength        => 5,
124
        lengthunit                       => 'days',
125
    chargeperiod       => 0,
125
        renewalperiod                    => 5,
126
    chargeperiod_charge_at => 0,
126
        norenewalbefore                  => 6,
127
    rentaldiscount     => '2.000000',
127
        auto_renew                       => 0,
128
    reservesallowed    => 0,
128
        issuelength                      => 5,
129
    hardduedate        => '2013-01-01',
129
        chargeperiod                     => 0,
130
    branchcode         => $samplebranch1->{branchcode},
130
        chargeperiod_charge_at           => 0,
131
    fine               => '0.000000',
131
        rentaldiscount                   => '2.000000',
132
    hardduedatecompare => 0,
132
        reservesallowed                  => 0,
133
    overduefinescap    => '0.000000',
133
        hardduedate                      => '2013-01-01',
134
    renewalsallowed    => 0,
134
        fine                             => '0.000000',
135
    firstremind        => 0,
135
        hardduedatecompare               => 5,
136
    itemtype           => 'BOOK',
136
        overduefinescap                  => '0.000000',
137
    categorycode       => $samplecat->{categorycode},
137
        renewalsallowed                  => 0,
138
    maxsuspensiondays  => 0,
138
        firstremind                      => 0,
139
    onshelfholds       => 0,
139
        maxsuspensiondays                => 0,
140
    opacitemholds      => 'N',
140
        onshelfholds                     => 0,
141
    cap_fine_to_replacement_price => 0,
141
        opacitemholds                    => 'N',
142
    holds_per_record   => 1,
142
        cap_fine_to_replacement_price    => 0,
143
    article_requests   => 'yes',
143
        holds_per_record                 => 1,
144
    no_auto_renewal_after => undef,
144
        article_requests                 => 'yes',
145
    no_auto_renewal_after_hard_limit => undef,
145
        no_auto_renewal_after            => undef,
146
    suspension_chargeperiod => 1,
146
        no_auto_renewal_after_hard_limit => undef,
147
    holds_per_day => undef,
147
        suspension_chargeperiod          => 1,
148
        holds_per_day                    => undef,
149
    }
148
};
150
};
149
my $sampleissuingrule2 = {
151
my $sampleissuingrule2 = {
150
    branchcode         => $samplebranch2->{branchcode},
152
    branchcode   => $samplebranch2->{branchcode},
151
    categorycode       => $samplecat->{categorycode},
153
    categorycode => $samplecat->{categorycode},
152
    itemtype           => 'BOOK',
154
    itemtype     => 'BOOK',
153
    renewalsallowed    => 0,
155
    rules        => {
154
    renewalperiod      => 2,
156
        renewalsallowed               => 0,
155
    norenewalbefore    => 7,
157
        renewalperiod                 => 2,
156
    auto_renew         => 0,
158
        norenewalbefore               => 7,
157
    reservesallowed    => 0,
159
        auto_renew                    => 0,
158
    issuelength        => 2,
160
        reservesallowed               => 0,
159
    lengthunit         => 'days',
161
        issuelength                   => 2,
160
    hardduedate        => undef,
162
        lengthunit                    => 'days',
161
    hardduedatecompare => 0,
163
        hardduedate                   => 2,
162
    fine               => undef,
164
        hardduedatecompare            => undef,
163
    finedays           => undef,
165
        fine                          => undef,
164
    firstremind        => undef,
166
        finedays                      => undef,
165
    chargeperiod       => undef,
167
        firstremind                   => undef,
166
    chargeperiod_charge_at => 0,
168
        chargeperiod                  => undef,
167
    rentaldiscount     => 2.00,
169
        chargeperiod_charge_at        => 0,
168
    overduefinescap    => undef,
170
        rentaldiscount                => 2.00,
169
    accountsent        => undef,
171
        overduefinescap               => undef,
170
    reservecharge      => undef,
172
        accountsent                   => undef,
171
    restrictedtype     => undef,
173
        reservecharge                 => undef,
172
    maxsuspensiondays  => 0,
174
        restrictedtype                => undef,
173
    onshelfholds       => 1,
175
        maxsuspensiondays             => 0,
174
    opacitemholds      => 'Y',
176
        onshelfholds                  => 1,
175
    cap_fine_to_replacement_price => 0,
177
        opacitemholds                 => 'Y',
176
    holds_per_record   => 1,
178
        cap_fine_to_replacement_price => 0,
177
    article_requests   => 'yes',
179
        holds_per_record              => 1,
180
        article_requests              => 'yes',
181
    }
178
};
182
};
179
my $sampleissuingrule3 = {
183
my $sampleissuingrule3 = {
180
    branchcode         => $samplebranch1->{branchcode},
184
    branchcode   => $samplebranch1->{branchcode},
181
    categorycode       => $samplecat->{categorycode},
185
    categorycode => $samplecat->{categorycode},
182
    itemtype           => 'DVD',
186
    itemtype     => 'DVD',
183
    renewalsallowed    => 0,
187
    rules        => {
184
    renewalperiod      => 3,
188
        renewalsallowed               => 0,
185
    norenewalbefore    => 8,
189
        renewalperiod                 => 3,
186
    auto_renew         => 0,
190
        norenewalbefore               => 8,
187
    reservesallowed    => 0,
191
        auto_renew                    => 0,
188
    issuelength        => 3,
192
        reservesallowed               => 0,
189
    lengthunit         => 'days',
193
        issuelength                   => 3,
190
    hardduedate        => undef,
194
        lengthunit                    => 'days',
191
    hardduedatecompare => 0,
195
        hardduedate                   => 3,
192
    fine               => undef,
196
        hardduedatecompare            => undef,
193
    finedays           => undef,
197
        fine                          => undef,
194
    firstremind        => undef,
198
        finedays                      => undef,
195
    chargeperiod       => undef,
199
        firstremind                   => undef,
196
    chargeperiod_charge_at => 0,
200
        chargeperiod                  => undef,
197
    rentaldiscount     => 3.00,
201
        chargeperiod_charge_at        => 0,
198
    overduefinescap    => undef,
202
        rentaldiscount                => 3.00,
199
    accountsent        => undef,
203
        overduefinescap               => undef,
200
    reservecharge      => undef,
204
        accountsent                   => undef,
201
    restrictedtype     => undef,
205
        reservecharge                 => undef,
202
    maxsuspensiondays  => 0,
206
        restrictedtype                => undef,
203
    onshelfholds       => 1,
207
        maxsuspensiondays             => 0,
204
    opacitemholds      => 'F',
208
        onshelfholds                  => 1,
205
    cap_fine_to_replacement_price => 0,
209
        opacitemholds                 => 'F',
206
    holds_per_record   => 1,
210
        cap_fine_to_replacement_price => 0,
207
    article_requests   => 'yes',
211
        holds_per_record              => 1,
212
        article_requests              => 'yes',
213
    }
208
};
214
};
209
215
210
$query = 'INSERT INTO issuingrules (
216
Koha::CirculationRules->set_rules( $sampleissuingrule1 );
211
                branchcode,
217
Koha::CirculationRules->set_rules( $sampleissuingrule2 );
212
                categorycode,
218
Koha::CirculationRules->set_rules( $sampleissuingrule3 );
213
                itemtype,
214
                renewalsallowed,
215
                renewalperiod,
216
                norenewalbefore,
217
                auto_renew,
218
                reservesallowed,
219
                issuelength,
220
                lengthunit,
221
                hardduedate,
222
                hardduedatecompare,
223
                fine,
224
                finedays,
225
                firstremind,
226
                chargeperiod,
227
                chargeperiod_charge_at,
228
                rentaldiscount,
229
                overduefinescap,
230
                accountsent,
231
                reservecharge,
232
                restrictedtype,
233
                maxsuspensiondays,
234
                onshelfholds,
235
                opacitemholds,
236
                cap_fine_to_replacement_price,
237
                article_requests
238
                ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
239
my $sth = $dbh->prepare($query);
240
$sth->execute(
241
    $sampleissuingrule1->{branchcode},
242
    $sampleissuingrule1->{categorycode},
243
    $sampleissuingrule1->{itemtype},
244
    $sampleissuingrule1->{renewalsallowed},
245
    $sampleissuingrule1->{renewalperiod},
246
    $sampleissuingrule1->{norenewalbefore},
247
    $sampleissuingrule1->{auto_renew},
248
    $sampleissuingrule1->{reservesallowed},
249
    $sampleissuingrule1->{issuelength},
250
    $sampleissuingrule1->{lengthunit},
251
    $sampleissuingrule1->{hardduedate},
252
    $sampleissuingrule1->{hardduedatecompare},
253
    $sampleissuingrule1->{fine},
254
    $sampleissuingrule1->{finedays},
255
    $sampleissuingrule1->{firstremind},
256
    $sampleissuingrule1->{chargeperiod},
257
    $sampleissuingrule1->{chargeperiod_charge_at},
258
    $sampleissuingrule1->{rentaldiscount},
259
    $sampleissuingrule1->{overduefinescap},
260
    $sampleissuingrule1->{accountsent},
261
    $sampleissuingrule1->{reservecharge},
262
    $sampleissuingrule1->{restrictedtype},
263
    $sampleissuingrule1->{maxsuspensiondays},
264
    $sampleissuingrule1->{onshelfholds},
265
    $sampleissuingrule1->{opacitemholds},
266
    $sampleissuingrule1->{cap_fine_to_replacement_price},
267
    $sampleissuingrule1->{article_requests},
268
);
269
$sth->execute(
270
    $sampleissuingrule2->{branchcode},
271
    $sampleissuingrule2->{categorycode},
272
    $sampleissuingrule2->{itemtype},
273
    $sampleissuingrule2->{renewalsallowed},
274
    $sampleissuingrule2->{renewalperiod},
275
    $sampleissuingrule2->{norenewalbefore},
276
    $sampleissuingrule2->{auto_renew},
277
    $sampleissuingrule2->{reservesallowed},
278
    $sampleissuingrule2->{issuelength},
279
    $sampleissuingrule2->{lengthunit},
280
    $sampleissuingrule2->{hardduedate},
281
    $sampleissuingrule2->{hardduedatecompare},
282
    $sampleissuingrule2->{fine},
283
    $sampleissuingrule2->{finedays},
284
    $sampleissuingrule2->{firstremind},
285
    $sampleissuingrule2->{chargeperiod},
286
    $sampleissuingrule2->{chargeperiod_charge_at},
287
    $sampleissuingrule2->{rentaldiscount},
288
    $sampleissuingrule2->{overduefinescap},
289
    $sampleissuingrule2->{accountsent},
290
    $sampleissuingrule2->{reservecharge},
291
    $sampleissuingrule2->{restrictedtype},
292
    $sampleissuingrule2->{maxsuspensiondays},
293
    $sampleissuingrule2->{onshelfholds},
294
    $sampleissuingrule2->{opacitemholds},
295
    $sampleissuingrule2->{cap_fine_to_replacement_price},
296
    $sampleissuingrule2->{article_requests},
297
);
298
$sth->execute(
299
    $sampleissuingrule3->{branchcode},
300
    $sampleissuingrule3->{categorycode},
301
    $sampleissuingrule3->{itemtype},
302
    $sampleissuingrule3->{renewalsallowed},
303
    $sampleissuingrule3->{renewalperiod},
304
    $sampleissuingrule3->{norenewalbefore},
305
    $sampleissuingrule3->{auto_renew},
306
    $sampleissuingrule3->{reservesallowed},
307
    $sampleissuingrule3->{issuelength},
308
    $sampleissuingrule3->{lengthunit},
309
    $sampleissuingrule3->{hardduedate},
310
    $sampleissuingrule3->{hardduedatecompare},
311
    $sampleissuingrule3->{fine},
312
    $sampleissuingrule3->{finedays},
313
    $sampleissuingrule3->{firstremind},
314
    $sampleissuingrule3->{chargeperiod},
315
    $sampleissuingrule3->{chargeperiod_charge_at},
316
    $sampleissuingrule3->{rentaldiscount},
317
    $sampleissuingrule3->{overduefinescap},
318
    $sampleissuingrule3->{accountsent},
319
    $sampleissuingrule3->{reservecharge},
320
    $sampleissuingrule3->{restrictedtype},
321
    $sampleissuingrule3->{maxsuspensiondays},
322
    $sampleissuingrule3->{onshelfholds},
323
    $sampleissuingrule3->{opacitemholds},
324
    $sampleissuingrule3->{cap_fine_to_replacement_price},
325
    $sampleissuingrule3->{article_requests},
326
);
327
219
328
#Test GetLoanLength
220
#Test GetLoanLength
329
is_deeply(
221
is_deeply(
Lines 371-378 my @hardduedate = C4::Circulation::GetHardDueDate( $samplecat->{categorycode}, Link Here
371
is_deeply(
263
is_deeply(
372
    \@hardduedate,
264
    \@hardduedate,
373
    [
265
    [
374
        dt_from_string( $sampleissuingrule1->{hardduedate}, 'iso' ),
266
        dt_from_string( $sampleissuingrule1->{rules}->{hardduedate}, 'iso' ),
375
        $sampleissuingrule1->{hardduedatecompare}
267
        $sampleissuingrule1->{rules}->{hardduedatecompare}
376
    ],
268
    ],
377
    "GetHardDueDate returns the duedate and the duedatecompare"
269
    "GetHardDueDate returns the duedate and the duedatecompare"
378
);
270
);
(-)a/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t (-12 / +19 lines)
Lines 29-45 my $patron_category = $builder->build({ source => 'Category' }); Link Here
29
t::lib::Mocks::mock_userenv({ branchcode => $branchcode });
29
t::lib::Mocks::mock_userenv({ branchcode => $branchcode });
30
30
31
# Test without maxsuspensiondays set
31
# Test without maxsuspensiondays set
32
Koha::IssuingRules->search->delete;
32
Koha::CirculationRules->search->delete;
33
$builder->build(
33
Koha::CirculationRules->set_rules(
34
    {
34
    {
35
        source => 'Issuingrule',
35
        categorycode => '*',
36
        value  => {
36
        itemtype     => '*',
37
            categorycode => '*',
37
        branchcode   => '*',
38
            itemtype     => '*',
38
        rules        => {
39
            branchcode   => '*',
39
            firstremind => 0,
40
            firstremind  => 0,
40
            finedays    => 2,
41
            finedays     => 2,
41
            lengthunit  => 'days',
42
            lengthunit   => 'days',
43
            suspension_chargeperiod => 1,
42
            suspension_chargeperiod => 1,
44
        }
43
        }
45
    }
44
    }
Lines 87-94 is( Link Here
87
DelDebarment( $debarments->[0]->{borrower_debarment_id} );
86
DelDebarment( $debarments->[0]->{borrower_debarment_id} );
88
87
89
# Test with maxsuspensiondays = 10 days
88
# Test with maxsuspensiondays = 10 days
90
my $issuing_rule = Koha::IssuingRules->search->next;
89
Koha::CirculationRules->set_rules(
91
$issuing_rule->maxsuspensiondays( 10 )->store;
90
    {
91
        categorycode => '*',
92
        itemtype     => '*',
93
        branchcode   => '*',
94
        rules        => {
95
            maxsuspensiondays => 10,
96
        }
97
    }
98
);
92
99
93
my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
100
my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
94
AddIssue( $borrower, $barcode, $daysago20 );
101
AddIssue( $borrower, $barcode, $daysago20 );
(-)a/t/db_dependent/Circulation/Returns.t (-5 / +16 lines)
Lines 57-72 my $schema = Koha::Database->schema; Link Here
57
$schema->storage->txn_begin;
57
$schema->storage->txn_begin;
58
58
59
my $builder = t::lib::TestBuilder->new();
59
my $builder = t::lib::TestBuilder->new();
60
Koha::IssuingRules->search->delete;
60
Koha::CirculationRules->search->delete;
61
my $rule = Koha::IssuingRule->new(
61
Koha::CirculationRules->set_rule(
62
    {
62
    {
63
        categorycode => '*',
63
        categorycode => '*',
64
        itemtype     => '*',
64
        itemtype     => '*',
65
        branchcode   => '*',
65
        branchcode   => '*',
66
        issuelength  => 1,
66
        rule_name    => 'issuelength',
67
        rule_value   => 1,
67
    }
68
    }
68
);
69
);
69
$rule->store();
70
70
71
subtest "AddReturn logging on statistics table (item-level_itypes=1)" => sub {
71
subtest "AddReturn logging on statistics table (item-level_itypes=1)" => sub {
72
72
Lines 254-260 subtest 'Handle ids duplication' => sub { Link Here
254
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
254
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
255
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
255
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
256
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
256
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
257
    Koha::IssuingRules->search->update({ chargeperiod => 1, fine => 1, firstremind => 1, });
257
    Koha::CirculationRules->set_rules(
258
        {
259
            categorycode => '*',
260
            itemtype     => '*',
261
            branchcode   => '*',
262
            rules        => {
263
                chargeperiod => 1,
264
                fine         => 1,
265
                firstremind  => 1,
266
            }
267
        }
268
    );
258
269
259
    my $biblio = $builder->build( { source => 'Biblio' } );
270
    my $biblio = $builder->build( { source => 'Biblio' } );
260
    my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
271
    my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
(-)a/t/db_dependent/Circulation/SwitchOnSiteCheckouts.t (-13 / +8 lines)
Lines 38-44 $schema->storage->txn_begin; Link Here
38
our $dbh = C4::Context->dbh;
38
our $dbh = C4::Context->dbh;
39
39
40
$dbh->do(q|DELETE FROM issues|);
40
$dbh->do(q|DELETE FROM issues|);
41
$dbh->do(q|DELETE FROM issuingrules|);
41
$dbh->do(q|DELETE FROM circulation_rules|);
42
42
43
my $builder = t::lib::TestBuilder->new();
43
my $builder = t::lib::TestBuilder->new();
44
44
Lines 81-98 my $item = $builder->build({ Link Here
81
    },
81
    },
82
});
82
});
83
83
84
my $issuingrule = $builder->build({
85
    source => 'Issuingrule',
86
    value => {
87
        branchcode         => $branch->{branchcode},
88
        categorycode       => '*',
89
        itemtype           => '*',
90
        lengthunit         => 'days',
91
        issuelength        => 5,
92
        hardduedate        => undef,
93
        hardduedatecompare => 0,
94
    },
95
});
96
Koha::CirculationRules->search()->delete();
84
Koha::CirculationRules->search()->delete();
97
Koha::CirculationRules->set_rules(
85
Koha::CirculationRules->set_rules(
98
    {
86
    {
Lines 102-107 Koha::CirculationRules->set_rules( Link Here
102
        rules        => {
90
        rules        => {
103
            maxissueqty       => 2,
91
            maxissueqty       => 2,
104
            maxonsiteissueqty => 1,
92
            maxonsiteissueqty => 1,
93
            branchcode        => $branch->{branchcode},
94
            categorycode      => '*',
95
            itemtype          => '*',
96
            lengthunit        => 'days',
97
            issuelength       => 5,
98
            hardduedate        => undef,
99
            hardduedatecompare => 0,
105
        }
100
        }
106
    }
101
    }
107
);
102
);
(-)a/t/db_dependent/Circulation/TooMany.t (-2 / +12 lines)
Lines 43-49 $dbh->do(q|DELETE FROM branches|); Link Here
43
$dbh->do(q|DELETE FROM categories|);
43
$dbh->do(q|DELETE FROM categories|);
44
$dbh->do(q|DELETE FROM accountlines|);
44
$dbh->do(q|DELETE FROM accountlines|);
45
$dbh->do(q|DELETE FROM itemtypes|);
45
$dbh->do(q|DELETE FROM itemtypes|);
46
$dbh->do(q|DELETE FROM issuingrules|);
47
Koha::CirculationRules->search()->delete();
46
Koha::CirculationRules->search()->delete();
48
47
49
my $builder = t::lib::TestBuilder->new();
48
my $builder = t::lib::TestBuilder->new();
Lines 422-427 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub { Link Here
422
    );
421
    );
423
422
424
    teardown();
423
    teardown();
424
    Koha::CirculationRules->set_rules(
425
        {
426
            branchcode   => $branch->{branchcode},
427
            categorycode => $category->{categorycode},
428
            itemtype     => undef,
429
            rules        => {
430
                maxissueqty       => 1,
431
                maxonsiteissueqty => 1,
432
            }
433
        }
434
    );
425
435
426
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
436
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
427
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
437
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
Lines 689-694 $schema->storage->txn_rollback; Link Here
689
699
690
sub teardown {
700
sub teardown {
691
    $dbh->do(q|DELETE FROM issues|);
701
    $dbh->do(q|DELETE FROM issues|);
692
    $dbh->do(q|DELETE FROM issuingrules|);
702
    $dbh->do(q|DELETE FROM circulation_rules|);
693
}
703
}
694
704
(-)a/t/db_dependent/Circulation/issue.t (-4 / +12 lines)
Lines 35-40 use Koha::Holds; Link Here
35
use Koha::Items;
35
use Koha::Items;
36
use Koha::Library;
36
use Koha::Library;
37
use Koha::Patrons;
37
use Koha::Patrons;
38
use Koha::CirculationRules;
38
39
39
BEGIN {
40
BEGIN {
40
    require_ok('C4::Circulation');
41
    require_ok('C4::Circulation');
Lines 66-72 $dbh->do(q|DELETE FROM items|); Link Here
66
$dbh->do(q|DELETE FROM borrowers|);
67
$dbh->do(q|DELETE FROM borrowers|);
67
$dbh->do(q|DELETE FROM categories|);
68
$dbh->do(q|DELETE FROM categories|);
68
$dbh->do(q|DELETE FROM accountlines|);
69
$dbh->do(q|DELETE FROM accountlines|);
69
$dbh->do(q|DELETE FROM issuingrules|);
70
$dbh->do(q|DELETE FROM circulation_rules|);
70
$dbh->do(q|DELETE FROM reserves|);
71
$dbh->do(q|DELETE FROM reserves|);
71
$dbh->do(q|DELETE FROM old_reserves|);
72
$dbh->do(q|DELETE FROM old_reserves|);
72
$dbh->do(q|DELETE FROM statistics|);
73
$dbh->do(q|DELETE FROM statistics|);
Lines 316-324 is_deeply( Link Here
316
);
317
);
317
318
318
# Add a default rule: renewal is allowed
319
# Add a default rule: renewal is allowed
319
$dbh->do(q|
320
Koha::CirculationRules->set_rules(
320
    UPDATE issuingrules SET renewalsallowed = 3
321
    {
321
|);
322
        categorycode => '*',
323
        itemtype     => '*',
324
        branchcode   => '*',
325
        rules        => {
326
            renewalsallowed => 3,
327
        }
328
    }
329
);
322
@renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
330
@renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
323
is_deeply(
331
is_deeply(
324
    \@renewcount,
332
    \@renewcount,
(-)a/t/db_dependent/DecreaseLoanHighHolds.t (-8 / +8 lines)
Lines 25-30 use Koha::Biblio; Link Here
25
use Koha::Item;
25
use Koha::Item;
26
use Koha::Holds;
26
use Koha::Holds;
27
use Koha::Hold;
27
use Koha::Hold;
28
use Koha::CirculationRules;
28
use t::lib::TestBuilder;
29
use t::lib::TestBuilder;
29
use t::lib::Mocks;
30
use t::lib::Mocks;
30
31
Lines 96-110 for my $i ( 0 .. 5 ) { Link Here
96
my $item   = pop(@items);
97
my $item   = pop(@items);
97
my $patron = pop(@patrons);
98
my $patron = pop(@patrons);
98
99
99
$builder->build(
100
Koha::CirculationRules->set_rules(
100
    {
101
    {
101
        source => 'Issuingrule',
102
        branchcode   => '*',
102
        value => {
103
        categorycode => '*',
103
            branchcode => '*',
104
        itemtype     => $item->itype,
104
            categorycode => '*',
105
        rules        => {
105
            itemtype => $item->itype,
106
            issuelength     => '14',
106
            issuelength => '14',
107
            lengthunit      => 'days',
107
            lengthunit => 'days',
108
            reservesallowed => '99',
108
            reservesallowed => '99',
109
        }
109
        }
110
    }
110
    }
(-)a/t/db_dependent/Fines.t (-12 / +23 lines)
Lines 13-31 my $schema = Koha::Database->new->schema; Link Here
13
$schema->storage->txn_begin;
13
$schema->storage->txn_begin;
14
my $dbh = C4::Context->dbh;
14
my $dbh = C4::Context->dbh;
15
15
16
$dbh->do(q|DELETE FROM issuingrules|);
16
$dbh->do(q|DELETE FROM circulation_rules|);
17
17
18
my $issuingrule = $schema->resultset('Issuingrule')->create(
18
my $issuingrule = Koha::CirculationRules->set_rules(
19
    {
19
    {
20
        categorycode           => '*',
20
        categorycode => '*',
21
        itemtype               => '*',
21
        itemtype     => '*',
22
        branchcode             => '*',
22
        branchcode   => '*',
23
        fine                   => 1,
23
        rules        => {
24
        finedays               => 0,
24
            fine                   => 1,
25
        chargeperiod           => 7,
25
            finedays               => 0,
26
        chargeperiod_charge_at => 0,
26
            chargeperiod           => 7,
27
        lengthunit             => 'days',
27
            chargeperiod_charge_at => 0,
28
        issuelength            => 1,
28
            lengthunit             => 'days',
29
            issuelength            => 1,
30
        }
29
    }
31
    }
30
);
32
);
31
33
Lines 42-48 $period_end = dt_from_string('2000-01-10'); Link Here
42
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
44
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
43
45
44
# Test charging fine at the *beginning* of each charge period
46
# Test charging fine at the *beginning* of each charge period
45
$issuingrule->update( { chargeperiod_charge_at => 1 } );
47
my $issuingrule = Koha::CirculationRules->set_rules(
48
    {
49
        categorycode => '*',
50
        itemtype     => '*',
51
        branchcode   => '*',
52
        rules        => {
53
            chargeperiod_charge_at => 1,
54
        }
55
    }
56
);
46
57
47
$period_end = dt_from_string('2000-01-05');
58
$period_end = dt_from_string('2000-01-05');
48
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
59
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
(-)a/t/db_dependent/Holds.t (-32 / +52 lines)
Lines 243-260 is( $hold->priority, '6', "Test AlterPriority(), move to bottom" ); Link Here
243
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
243
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
244
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
244
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
245
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
245
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
246
$dbh->do('DELETE FROM issuingrules');
246
Koha::CirculationRules->set_rules(
247
$dbh->do(
247
    {
248
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
248
        categorycode => '*',
249
      VALUES (?, ?, ?, ?, ?)},
249
        branchcode   => '*',
250
    {},
250
        itemtype     => '*',
251
    '*', '*', '*', 25, 99
251
        rules        => {
252
            reservesallowed  => 25,
253
            holds_per_record => 99,
254
        }
255
    }
252
);
256
);
253
$dbh->do(
257
Koha::CirculationRules->set_rules(
254
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
258
    {
255
      VALUES (?, ?, ?, ?, ?)},
259
        categorycode => '*',
256
    {},
260
        branchcode   => '*',
257
    '*', '*', 'CANNOT', 0, 99
261
        itemtype     => 'CANNOT',
262
        rules        => {
263
            reservesallowed  => 0,
264
            holds_per_record => 99,
265
        }
266
    }
258
);
267
);
259
268
260
# make sure some basic sysprefs are set
269
# make sure some basic sysprefs are set
Lines 263-270 t::lib::Mocks::mock_preference('item-level_itypes', 1); Link Here
263
272
264
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
273
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
265
t::lib::Mocks::mock_preference('IndependentBranches', 0);
274
t::lib::Mocks::mock_preference('IndependentBranches', 0);
266
ok(
275
is(
267
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'OK',
276
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status}, 'OK',
268
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
277
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
269
);
278
);
270
279
Lines 351-363 ok( Link Here
351
360
352
# Test branch item rules
361
# Test branch item rules
353
362
354
$dbh->do('DELETE FROM issuingrules');
355
$dbh->do('DELETE FROM circulation_rules');
363
$dbh->do('DELETE FROM circulation_rules');
356
$dbh->do(
364
Koha::CirculationRules->set_rules(
357
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
365
    {
358
      VALUES (?, ?, ?, ?)},
366
        categorycode => '*',
359
    {},
367
        branchcode   => '*',
360
    '*', '*', '*', 25
368
        itemtype     => '*',
369
        rules        => {
370
            reservesallowed  => 25,
371
            holds_per_record => 99,
372
        }
373
    }
361
);
374
);
362
Koha::CirculationRules->set_rules(
375
Koha::CirculationRules->set_rules(
363
    {
376
    {
Lines 416-426 $biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); Link Here
416
( $item_bibnum, $item_bibitemnum, $itemnumber )
429
( $item_bibnum, $item_bibitemnum, $itemnumber )
417
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
430
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
418
431
419
$dbh->do(
432
Koha::CirculationRules->set_rules(
420
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
433
    {
421
      VALUES (?, ?, ?, ?, ?)},
434
        categorycode => '*',
422
    {},
435
        branchcode   => '*',
423
    '*', '*', 'ONLY1', 1, 99
436
        itemtype     => 'ONLY1',
437
        rules        => {
438
            reservesallowed  => 1,
439
            holds_per_record => 99,
440
        }
441
    }
424
);
442
);
425
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
443
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
426
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
444
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
Lines 441-460 subtest 'Test max_holds per library/patron category' => sub { Link Here
441
    plan tests => 6;
459
    plan tests => 6;
442
460
443
    $dbh->do('DELETE FROM reserves');
461
    $dbh->do('DELETE FROM reserves');
444
    $dbh->do('DELETE FROM issuingrules');
445
    $dbh->do('DELETE FROM circulation_rules');
462
    $dbh->do('DELETE FROM circulation_rules');
446
463
447
    $biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
464
    $biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
448
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
465
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
449
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
466
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
450
        $biblio->biblionumber );
467
        $biblio->biblionumber );
451
    $dbh->do(
468
    Koha::CirculationRules->set_rules(
452
        q{
469
        {
453
            INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
470
            categorycode => '*',
454
            VALUES (?, ?, ?, ?, ?)
471
            branchcode   => '*',
455
        },
472
            itemtype     => 'TEST',
456
        {},
473
            rules        => {
457
        '*', '*', 'TEST', 99, 99
474
                reservesallowed  => 99,
475
                holds_per_record => 99,
476
            }
477
        }
458
    );
478
    );
459
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
479
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
460
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
480
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
(-)a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t (-10 / +12 lines)
Lines 5-12 use Modern::Perl; Link Here
5
use C4::Context;
5
use C4::Context;
6
use C4::Circulation;
6
use C4::Circulation;
7
use C4::Items;
7
use C4::Items;
8
use Koha::IssuingRule;
9
use Koha::Items;
8
use Koha::Items;
9
use Koha::CirculationRules;
10
10
use Test::More tests => 6;
11
use Test::More tests => 6;
11
12
12
use t::lib::TestBuilder;
13
use t::lib::TestBuilder;
Lines 80-97 my $item2 = $builder->build_sample_item({ Link Here
80
});
81
});
81
82
82
# Test hold_fulfillment_policy
83
# Test hold_fulfillment_policy
83
my $rule = Koha::IssuingRule->new(
84
$dbh->do("DELETE FROM circulation_rules");
85
Koha::CirculationRules->set_rules(
84
    {
86
    {
85
        categorycode => '*',
87
        categorycode => '*',
86
        itemtype     => $itemtype,
88
        itemtype     => $itemtype,
87
        branchcode   => '*',
89
        branchcode   => '*',
88
        issuelength  => 7,
90
        rules        => {
89
        lengthunit   => 8,
91
            issuelength     => 7,
90
        reservesallowed => 99,
92
            lengthunit      => 8,
91
        onshelfholds => 2,
93
            reservesallowed => 99,
94
            onshelfholds    => 2,
95
        }
92
    }
96
    }
93
);
97
);
94
$rule->store();
95
98
96
my $is = IsAvailableForItemLevelRequest( $item1, $patron1);
99
my $is = IsAvailableForItemLevelRequest( $item1, $patron1);
97
is( $is, 0, "Item cannot be held, 2 items available" );
100
is( $is, 0, "Item cannot be held, 2 items available" );
Lines 213-219 my $hold = $builder->build({ Link Here
213
    }
216
    }
214
});
217
});
215
218
216
$rule = Koha::IssuingRule->new(
219
Koha::IssuingRule->new(
217
    {
220
    {
218
        categorycode => '*',
221
        categorycode => '*',
219
        itemtype     => $itemtype2,
222
        itemtype     => $itemtype2,
Lines 223-230 $rule = Koha::IssuingRule->new( Link Here
223
        reservesallowed => 99,
226
        reservesallowed => 99,
224
        onshelfholds => 0,
227
        onshelfholds => 0,
225
    }
228
    }
226
);
229
)->store();
227
$rule->store();
228
230
229
$is = IsAvailableForItemLevelRequest( $item3, $patron1);
231
$is = IsAvailableForItemLevelRequest( $item3, $patron1);
230
is( $is, 1, "Item can be held, items in transit are not available" );
232
is( $is, 1, "Item can be held, items in transit are not available" );
(-)a/t/db_dependent/Koha/IssuingRules.t (-32 / +55 lines)
Lines 23-29 use Test::More tests => 4; Link Here
23
23
24
use Benchmark;
24
use Benchmark;
25
25
26
use Koha::IssuingRules;
27
use Koha::CirculationRules;
26
use Koha::CirculationRules;
28
27
29
use t::lib::TestBuilder;
28
use t::lib::TestBuilder;
Lines 48-73 subtest 'get_effective_issuing_rule' => sub { Link Here
48
        plan tests => 4;
47
        plan tests => 4;
49
48
50
        my $rule;
49
        my $rule;
51
        Koha::IssuingRules->delete;
50
        Koha::CirculationRules->delete;
52
51
53
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
52
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
54
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
53
        $rule = Koha::CirculationRules->get_effective_rule({
55
            branchcode   => undef,
54
            branchcode   => undef,
56
            categorycode => undef,
55
            categorycode => undef,
57
            itemtype     => undef,
56
            itemtype     => undef,
57
            rule_name    => 'fine',
58
        });
58
        });
59
        is($rule, undef, 'When I attempt to get effective issuing rule by'
59
        is($rule, undef, 'When I attempt to get effective issuing rule by'
60
           .' providing undefined values, then undef is returned.');
60
           .' providing undefined values, then undef is returned.');
61
        ok(Koha::IssuingRule->new({
61
        ok(Koha::CirculationRule->new({
62
            branchcode => '*',
62
            branchcode => '*',
63
            categorycode => '*',
63
            categorycode => '*',
64
            itemtype => '*',
64
            itemtype => '*',
65
            rule_name => 'fine',
65
        })->store, 'Given I added an issuing rule branchcode => *,'
66
        })->store, 'Given I added an issuing rule branchcode => *,'
66
           .' categorycode => *, itemtype => *,');
67
           .' categorycode => *, itemtype => *,');
67
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
68
        $rule = Koha::CirculationRules->get_effective_rule({
68
            branchcode   => undef,
69
            branchcode   => '*',
69
            categorycode => undef,
70
            categorycode => '*',
70
            itemtype     => undef,
71
            itemtype     => '*',
72
            rule_name    => 'fine',
71
        });
73
        });
72
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
74
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
73
           .' issuing rule by providing undefined values, then the above one is'
75
           .' issuing rule by providing undefined values, then the above one is'
Lines 78-193 subtest 'get_effective_issuing_rule' => sub { Link Here
78
        plan tests => 18;
80
        plan tests => 18;
79
81
80
        my $rule;
82
        my $rule;
81
        Koha::IssuingRules->delete;
83
        Koha::CirculationRules->delete;
82
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
84
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
83
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
85
        $rule = Koha::CirculationRules->get_effective_rule({
84
            branchcode   => $branchcode,
86
            branchcode   => $branchcode,
85
            categorycode => $categorycode,
87
            categorycode => $categorycode,
86
            itemtype     => $itemtype,
88
            itemtype     => $itemtype,
89
            rule_name    => 'fine',
87
        });
90
        });
88
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
91
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
89
                        .' is returned.');
92
                        .' is returned.');
90
93
91
        ok(Koha::IssuingRule->new({
94
        ok(Koha::CirculationRule->new({
92
            branchcode => '*',
95
            branchcode => '*',
93
            categorycode => '*',
96
            categorycode => '*',
94
            itemtype => '*',
97
            itemtype => '*',
98
            rule_name => 'fine',
95
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
99
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
96
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
100
        $rule = Koha::CirculationRules->get_effective_rule({
97
            branchcode   => $branchcode,
101
            branchcode   => $branchcode,
98
            categorycode => $categorycode,
102
            categorycode => $categorycode,
99
            itemtype     => $itemtype,
103
            itemtype     => $itemtype,
104
            rule_name    => 'fine',
100
        });
105
        });
101
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
106
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
102
           .' then the above one is returned.');
107
           .' then the above one is returned.');
103
108
104
        ok(Koha::IssuingRule->new({
109
        ok(Koha::CirculationRule->new({
105
            branchcode => '*',
110
            branchcode => '*',
106
            categorycode => '*',
111
            categorycode => '*',
107
            itemtype => $itemtype,
112
            itemtype => $itemtype,
113
            rule_name => 'fine',
108
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
114
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
109
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
115
        $rule = Koha::CirculationRules->get_effective_rule({
110
            branchcode   => $branchcode,
116
            branchcode   => $branchcode,
111
            categorycode => $categorycode,
117
            categorycode => $categorycode,
112
            itemtype     => $itemtype,
118
            itemtype     => $itemtype,
119
            rule_name    => 'fine',
113
        });
120
        });
114
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
121
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
115
           .' then the above one is returned.');
122
           .' then the above one is returned.');
116
123
117
        ok(Koha::IssuingRule->new({
124
        ok(Koha::CirculationRule->new({
118
            branchcode => '*',
125
            branchcode => '*',
119
            categorycode => $categorycode,
126
            categorycode => $categorycode,
120
            itemtype => '*',
127
            itemtype => '*',
128
            rule_name => 'fine',
121
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
129
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
122
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
130
        $rule = Koha::CirculationRules->get_effective_rule({
123
            branchcode   => $branchcode,
131
            branchcode   => $branchcode,
124
            categorycode => $categorycode,
132
            categorycode => $categorycode,
125
            itemtype     => $itemtype,
133
            itemtype     => $itemtype,
134
            rule_name    => 'fine',
126
        });
135
        });
127
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
136
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
128
           .' then the above one is returned.');
137
           .' then the above one is returned.');
129
138
130
        ok(Koha::IssuingRule->new({
139
        ok(Koha::CirculationRule->new({
131
            branchcode => '*',
140
            branchcode => '*',
132
            categorycode => $categorycode,
141
            categorycode => $categorycode,
133
            itemtype => $itemtype,
142
            itemtype => $itemtype,
143
            rule_name => 'fine',
134
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
144
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
135
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
145
        $rule = Koha::CirculationRules->get_effective_rule({
136
            branchcode   => $branchcode,
146
            branchcode   => $branchcode,
137
            categorycode => $categorycode,
147
            categorycode => $categorycode,
138
            itemtype     => $itemtype,
148
            itemtype     => $itemtype,
149
            rule_name    => 'fine',
139
        });
150
        });
140
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
151
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
141
           .' then the above one is returned.');
152
           .' then the above one is returned.');
142
153
143
        ok(Koha::IssuingRule->new({
154
        ok(Koha::CirculationRule->new({
144
            branchcode => $branchcode,
155
            branchcode => $branchcode,
145
            categorycode => '*',
156
            categorycode => '*',
146
            itemtype => '*',
157
            itemtype => '*',
158
            rule_name => 'fine',
147
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
159
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
148
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
160
        $rule = Koha::CirculationRules->get_effective_rule({
149
            branchcode   => $branchcode,
161
            branchcode   => $branchcode,
150
            categorycode => $categorycode,
162
            categorycode => $categorycode,
151
            itemtype     => $itemtype,
163
            itemtype     => $itemtype,
164
            rule_name    => 'fine',
152
        });
165
        });
153
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
166
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
154
           .' then the above one is returned.');
167
           .' then the above one is returned.');
155
168
156
        ok(Koha::IssuingRule->new({
169
        ok(Koha::CirculationRule->new({
157
            branchcode => $branchcode,
170
            branchcode => $branchcode,
158
            categorycode => '*',
171
            categorycode => '*',
159
            itemtype => $itemtype,
172
            itemtype => $itemtype,
173
            rule_name => 'fine',
160
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
174
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
161
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
175
        $rule = Koha::CirculationRules->get_effective_rule({
162
            branchcode   => $branchcode,
176
            branchcode   => $branchcode,
163
            categorycode => $categorycode,
177
            categorycode => $categorycode,
164
            itemtype     => $itemtype,
178
            itemtype     => $itemtype,
179
            rule_name    => 'fine',
165
        });
180
        });
166
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
181
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
167
           .' then the above one is returned.');
182
           .' then the above one is returned.');
168
183
169
        ok(Koha::IssuingRule->new({
184
        ok(Koha::CirculationRule->new({
170
            branchcode => $branchcode,
185
            branchcode => $branchcode,
171
            categorycode => $categorycode,
186
            categorycode => $categorycode,
172
            itemtype => '*',
187
            itemtype => '*',
188
            rule_name => 'fine',
173
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
189
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
174
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
190
        $rule = Koha::CirculationRules->get_effective_rule({
175
            branchcode   => $branchcode,
191
            branchcode   => $branchcode,
176
            categorycode => $categorycode,
192
            categorycode => $categorycode,
177
            itemtype     => $itemtype,
193
            itemtype     => $itemtype,
194
            rule_name    => 'fine',
178
        });
195
        });
179
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
196
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
180
           .' then the above one is returned.');
197
           .' then the above one is returned.');
181
198
182
        ok(Koha::IssuingRule->new({
199
        ok(Koha::CirculationRule->new({
183
            branchcode => $branchcode,
200
            branchcode => $branchcode,
184
            categorycode => $categorycode,
201
            categorycode => $categorycode,
185
            itemtype => $itemtype,
202
            itemtype => $itemtype,
203
            rule_name => 'fine',
186
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
204
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
187
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
205
        $rule = Koha::CirculationRules->get_effective_rule({
188
            branchcode   => $branchcode,
206
            branchcode   => $branchcode,
189
            categorycode => $categorycode,
207
            categorycode => $categorycode,
190
            itemtype     => $itemtype,
208
            itemtype     => $itemtype,
209
            rule_name    => 'fine',
191
        });
210
        });
192
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
211
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
193
           .' then the above one is returned.');
212
           .' then the above one is returned.');
Lines 197-230 subtest 'get_effective_issuing_rule' => sub { Link Here
197
        plan tests => 4;
216
        plan tests => 4;
198
217
199
        my $worst_case = timethis(500,
218
        my $worst_case = timethis(500,
200
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
219
                    sub { Koha::CirculationRules->get_effective_rule({
201
                            branchcode   => 'nonexistent',
220
                            branchcode   => 'nonexistent',
202
                            categorycode => 'nonexistent',
221
                            categorycode => 'nonexistent',
203
                            itemtype     => 'nonexistent',
222
                            itemtype     => 'nonexistent',
223
                            rule_name    => 'nonexistent',
204
                        });
224
                        });
205
                    }
225
                    }
206
                );
226
                );
207
        my $mid_case = timethis(500,
227
        my $mid_case = timethis(500,
208
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
228
                    sub { Koha::CirculationRules->get_effective_rule({
209
                            branchcode   => $branchcode,
229
                            branchcode   => $branchcode,
210
                            categorycode => 'nonexistent',
230
                            categorycode => 'nonexistent',
211
                            itemtype     => 'nonexistent',
231
                            itemtype     => 'nonexistent',
232
                            rule_name    => 'nonexistent',
212
                        });
233
                        });
213
                    }
234
                    }
214
                );
235
                );
215
        my $sec_best_case = timethis(500,
236
        my $sec_best_case = timethis(500,
216
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
237
                    sub { Koha::CirculationRules->get_effective_rule({
217
                            branchcode   => $branchcode,
238
                            branchcode   => $branchcode,
218
                            categorycode => $categorycode,
239
                            categorycode => $categorycode,
219
                            itemtype     => 'nonexistent',
240
                            itemtype     => 'nonexistent',
241
                            rule_name    => 'nonexistent',
220
                        });
242
                        });
221
                    }
243
                    }
222
                );
244
                );
223
        my $best_case = timethis(500,
245
        my $best_case = timethis(500,
224
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
246
                    sub { Koha::CirculationRules->get_effective_rule({
225
                            branchcode   => $branchcode,
247
                            branchcode   => $branchcode,
226
                            categorycode => $categorycode,
248
                            categorycode => $categorycode,
227
                            itemtype     => $itemtype,
249
                            itemtype     => $itemtype,
250
                            rule_name    => 'nonexistent',
228
                        });
251
                        });
229
                    }
252
                    }
230
                );
253
                );
(-)a/t/db_dependent/Koha/Objects.t (-8 / +1 lines)
Lines 25-31 use Test::Warn; Link Here
25
25
26
use Koha::Authority::Types;
26
use Koha::Authority::Types;
27
use Koha::Cities;
27
use Koha::Cities;
28
use Koha::IssuingRules;
29
use Koha::Patron::Category;
28
use Koha::Patron::Category;
30
use Koha::Patron::Categories;
29
use Koha::Patron::Categories;
31
use Koha::Patrons;
30
use Koha::Patrons;
Lines 107-113 subtest 'new' => sub { Link Here
107
};
106
};
108
107
109
subtest 'find' => sub {
108
subtest 'find' => sub {
110
    plan tests => 5;
109
    plan tests => 4;
111
110
112
    # check find on a single PK
111
    # check find on a single PK
113
    my $patron = $builder->build({ source => 'Borrower' });
112
    my $patron = $builder->build({ source => 'Borrower' });
Lines 125-136 subtest 'find' => sub { Link Here
125
        { where => { surname => { '!=', $patron->{surname} }}},
124
        { where => { surname => { '!=', $patron->{surname} }}},
126
    ), undef, 'Additional where clause in find call' );
125
    ), undef, 'Additional where clause in find call' );
127
126
128
    # check find with a composite FK
129
    my $rule = $builder->build({ source => 'Issuingrule' });
130
    my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
131
    is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
132
        'Find returned a Koha object for composite primary key' );
133
134
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
127
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
135
};
128
};
136
129
(-)a/t/db_dependent/Reserves.t (-6 / +38 lines)
Lines 190-201 $requesters{$branch_3} = Koha::Patron->new({ Link Here
190
# to request its items, while $branch_2 will allow its items
190
# to request its items, while $branch_2 will allow its items
191
# to fill holds from anywhere.
191
# to fill holds from anywhere.
192
192
193
$dbh->do('DELETE FROM issuingrules');
193
$dbh->do('DELETE FROM circulation_rules');
194
$dbh->do(
194
Koha::CirculationRules->set_rules(
195
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
195
    {
196
      VALUES (?, ?, ?, ?)},
196
        branchcode   => '*',
197
    {},
197
        categorycode => '*',
198
    '*', '*', '*', 25
198
        itemtype     => '*',
199
        rules        => {
200
            reservesallowed => 25,
201
            holds_per_record => 1,
202
        }
203
    }
199
);
204
);
200
205
201
# CPL allows only its own patrons to request its items
206
# CPL allows only its own patrons to request its items
Lines 546-551 my $limit = Koha::Item::Transfer::Limit->new( Link Here
546
is( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron, $pickup_branch), 0, "Item level request not available due to transfer limit" );
551
is( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron, $pickup_branch), 0, "Item level request not available due to transfer limit" );
547
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits',  '0' );
552
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits',  '0' );
548
553
554
my $itype = C4::Reserves::_get_itype($item);
555
my $categorycode = $borrower->{categorycode};
556
my $holdingbranch = $item->{holdingbranch};
557
Koha::CirculationRules->set_rules(
558
    {
559
        categorycode => $categorycode,
560
        itemtype     => $itype,
561
        branchcode   => $holdingbranch,
562
        rules => {
563
            onshelfholds => 1,
564
        }
565
    }
566
);
567
568
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
569
Koha::CirculationRules->set_rules(
570
    {
571
        categorycode => $categorycode,
572
        itemtype     => $itype,
573
        branchcode   => $holdingbranch,
574
        rules => {
575
            onshelfholds => 0,
576
        }
577
    }
578
);
579
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
580
549
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
581
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
550
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
582
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
551
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
583
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
(-)a/t/db_dependent/Reserves/MultiplePerRecord.t (-49 / +56 lines)
Lines 115-133 my $item3 = $builder->build( Link Here
115
    }
115
    }
116
);
116
);
117
117
118
my $rules_rs = Koha::Database->new()->schema()->resultset('Issuingrule');
118
Koha::CirculationRules->delete();
119
$rules_rs->delete();
120
119
121
# Test GetMaxPatronHoldsForRecord and GetHoldRule
120
# Test GetMaxPatronHoldsForRecord and GetHoldRule
122
my $rule1 = $rules_rs->new(
121
Koha::CirculationRules->set_rules(
123
    {
122
    {
124
        categorycode     => '*',
123
        categorycode => '*',
125
        itemtype         => '*',
124
        itemtype     => '*',
126
        branchcode       => '*',
125
        branchcode   => '*',
127
        reservesallowed  => 1,
126
        rules        => {
128
        holds_per_record => 1,
127
            reservesallowed  => 1,
128
            holds_per_record => 1,
129
        }
129
    }
130
    }
130
)->insert();
131
);
131
132
132
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
133
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
133
134
Lines 144-158 is( $rule->{branchcode}, '*', 'Got rule with universal branchcode' ); Link Here
144
is( $rule->{reservesallowed},  1,   'Got reservesallowed of 1' );
145
is( $rule->{reservesallowed},  1,   'Got reservesallowed of 1' );
145
is( $rule->{holds_per_record}, 1,   'Got holds_per_record of 1' );
146
is( $rule->{holds_per_record}, 1,   'Got holds_per_record of 1' );
146
147
147
my $rule2 = $rules_rs->new(
148
Koha::CirculationRules->set_rules(
148
    {
149
    {
149
        categorycode     => $category->{categorycode},
150
        categorycode => $category->{categorycode},
150
        itemtype         => '*',
151
        itemtype     => '*',
151
        branchcode       => '*',
152
        branchcode   => '*',
152
        reservesallowed  => 2,
153
        rules        => {
153
        holds_per_record => 2,
154
            reservesallowed  => 2,
155
            holds_per_record => 2,
156
        }
154
    }
157
    }
155
)->insert();
158
);
156
159
157
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
160
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
158
is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
161
is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
Lines 167-181 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
167
is( $rule->{reservesallowed},  2,                         'Got reservesallowed of 2' );
170
is( $rule->{reservesallowed},  2,                         'Got reservesallowed of 2' );
168
is( $rule->{holds_per_record}, 2,                         'Got holds_per_record of 2' );
171
is( $rule->{holds_per_record}, 2,                         'Got holds_per_record of 2' );
169
172
170
my $rule3 = $rules_rs->new(
173
Koha::CirculationRules->set_rules(
171
    {
174
    {
172
        categorycode     => $category->{categorycode},
175
        categorycode => $category->{categorycode},
173
        itemtype         => $itemtype1->{itemtype},
176
        itemtype     => $itemtype1->{itemtype},
174
        branchcode       => '*',
177
        branchcode   => '*',
175
        reservesallowed  => 3,
178
        rules        => {
176
        holds_per_record => 3,
179
            reservesallowed  => 3,
180
            holds_per_record => 3,
181
        }
177
    }
182
    }
178
)->insert();
183
);
179
184
180
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
185
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
181
is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
186
is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
Lines 190-204 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
190
is( $rule->{reservesallowed},  3,                         'Got reservesallowed of 3' );
195
is( $rule->{reservesallowed},  3,                         'Got reservesallowed of 3' );
191
is( $rule->{holds_per_record}, 3,                         'Got holds_per_record of 3' );
196
is( $rule->{holds_per_record}, 3,                         'Got holds_per_record of 3' );
192
197
193
my $rule4 = $rules_rs->new(
198
Koha::CirculationRules->set_rules(
194
    {
199
    {
195
        categorycode     => $category->{categorycode},
200
        categorycode => $category->{categorycode},
196
        itemtype         => $itemtype2->{itemtype},
201
        itemtype     => $itemtype2->{itemtype},
197
        branchcode       => '*',
202
        branchcode   => '*',
198
        reservesallowed  => 4,
203
        rules        => {
199
        holds_per_record => 4,
204
            reservesallowed  => 4,
205
            holds_per_record => 4,
206
        }
200
    }
207
    }
201
)->insert();
208
);
202
209
203
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
210
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
204
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
211
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
Lines 213-227 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
213
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
220
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
214
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
221
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
215
222
216
my $rule5 = $rules_rs->new(
223
Koha::CirculationRules->set_rules(
217
    {
224
    {
218
        categorycode     => $category->{categorycode},
225
        categorycode => $category->{categorycode},
219
        itemtype         => $itemtype2->{itemtype},
226
        itemtype     => $itemtype2->{itemtype},
220
        branchcode       => $library->{branchcode},
227
        branchcode   => $library->{branchcode},
221
        reservesallowed  => 5,
228
        rules        => {
222
        holds_per_record => 5,
229
            reservesallowed  => 5,
230
            holds_per_record => 5,
231
        }
223
    }
232
    }
224
)->insert();
233
);
225
234
226
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
235
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
227
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
236
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
Lines 236-246 is( $rule->{branchcode}, $library->{branchcode}, 'Got rule with specifi Link Here
236
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
245
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
237
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
246
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
238
247
239
$rule1->delete();
248
Koha::CirculationRules->delete();
240
$rule2->delete();
241
$rule3->delete();
242
$rule4->delete();
243
$rule5->delete();
244
249
245
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
250
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
246
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
251
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
Lines 266-280 is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds" Link Here
266
$hold->delete();
271
$hold->delete();
267
272
268
# Test multi-hold via AddReserve
273
# Test multi-hold via AddReserve
269
$rule = $rules_rs->new(
274
Koha::CirculationRules->set_rules(
270
    {
275
    {
271
        categorycode     => '*',
276
        categorycode => '*',
272
        itemtype         => '*',
277
        itemtype     => '*',
273
        branchcode       => '*',
278
        branchcode   => '*',
274
        reservesallowed  => 2,
279
        rules        => {
275
        holds_per_record => 2,
280
            reservesallowed  => 2,
281
            holds_per_record => 2,
282
        }
276
    }
283
    }
277
)->insert();
284
);
278
285
279
my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
286
my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
280
is( $can->{status}, 'OK', 'Hold can be placed with 0 holds' );
287
is( $can->{status}, 'OK', 'Hold can be placed with 0 holds' );
(-)a/t/db_dependent/TestBuilder.t (-2 / +2 lines)
Lines 357-363 subtest 'build_object() tests' => sub { Link Here
357
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
357
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
358
358
359
    my $issuing_rule = $builder->build_object(
359
    my $issuing_rule = $builder->build_object(
360
        {   class => 'Koha::IssuingRules',
360
        {   class => 'Koha::CirculationRules',
361
            value => {
361
            value => {
362
                categorycode => $categorycode,
362
                categorycode => $categorycode,
363
                itemtype     => $itemtype
363
                itemtype     => $itemtype
Lines 365-371 subtest 'build_object() tests' => sub { Link Here
365
        }
365
        }
366
    );
366
    );
367
367
368
    is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
368
    is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
369
    is( $issuing_rule->categorycode,
369
    is( $issuing_rule->categorycode,
370
        $categorycode, 'Category code correctly set' );
370
        $categorycode, 'Category code correctly set' );
371
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
371
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
(-)a/t/db_dependent/api/v1/holds.t (-6 / +12 lines)
Lines 34-39 use Koha::DateUtils; Link Here
34
use Koha::Biblios;
34
use Koha::Biblios;
35
use Koha::Biblioitems;
35
use Koha::Biblioitems;
36
use Koha::Items;
36
use Koha::Items;
37
use Koha::CirculationRules;
37
38
38
my $schema  = Koha::Database->new->schema;
39
my $schema  = Koha::Database->new->schema;
39
my $builder = t::lib::TestBuilder->new();
40
my $builder = t::lib::TestBuilder->new();
Lines 136-146 my $itemnumber2 = $item2->{itemnumber}; Link Here
136
137
137
my $dbh = C4::Context->dbh;
138
my $dbh = C4::Context->dbh;
138
$dbh->do('DELETE FROM reserves');
139
$dbh->do('DELETE FROM reserves');
139
$dbh->do('DELETE FROM issuingrules');
140
$dbh->do('DELETE FROM circulation_rules');
140
    $dbh->do(q{
141
Koha::CirculationRules->set_rules(
141
        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
142
    {
142
        VALUES (?, ?, ?, ?)
143
        categorycode => '*',
143
    }, {}, '*', '*', '*', 1);
144
        branchcode   => '*',
145
        itemtype     => '*',
146
        rules        => {
147
            reservesallowed => 1
148
        }
149
    }
150
);
144
151
145
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
152
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
146
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
153
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
147
- 

Return to bug 18936