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

(-)a/C4/Circulation.pm (-160 / +198 lines)
Lines 44-50 use Koha::Biblioitems; Link Here
44
use Koha::DateUtils;
44
use Koha::DateUtils;
45
use Koha::Calendar;
45
use Koha::Calendar;
46
use Koha::Checkouts;
46
use Koha::Checkouts;
47
use Koha::IssuingRules;
48
use Koha::Items;
47
use Koha::Items;
49
use Koha::Patrons;
48
use Koha::Patrons;
50
use Koha::Patron::Debarments;
49
use Koha::Patron::Debarments;
Lines 423-440 sub TooMany { Link Here
423
            # specific rule
422
            # specific rule
424
            if (C4::Context->preference('item-level_itypes')) {
423
            if (C4::Context->preference('item-level_itypes')) {
425
                $count_query .= " WHERE items.itype NOT IN (
424
                $count_query .= " WHERE items.itype NOT IN (
426
                                    SELECT itemtype FROM issuingrules
425
                                    SELECT itemtype FROM circulation_rules
427
                                    WHERE branchcode = ?
426
                                    WHERE branchcode = ?
428
                                    AND   (categorycode = ? OR categorycode = ?)
427
                                    AND   (categorycode = ? OR categorycode = ?)
429
                                    AND   itemtype <> '*'
428
                                    AND   itemtype <> '*'
429
                                    AND   rule_name = 'maxissueqty'
430
                                  ) ";
430
                                  ) ";
431
            } else { 
431
            } else {
432
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
432
                $count_query .= " JOIN  biblioitems USING (biblionumber)
433
                                  WHERE biblioitems.itemtype NOT IN (
433
                                  WHERE biblioitems.itemtype NOT IN (
434
                                    SELECT itemtype FROM issuingrules
434
                                    SELECT itemtype FROM circulation_rules
435
                                    WHERE branchcode = ?
435
                                    WHERE branchcode = ?
436
                                    AND   (categorycode = ? OR categorycode = ?)
436
                                    AND   (categorycode = ? OR categorycode = ?)
437
                                    AND   itemtype <> '*'
437
                                    AND   itemtype <> '*'
438
                                    AND   rule_name = 'maxissueqty'
438
                                  ) ";
439
                                  ) ";
439
            }
440
            }
440
            push @bind_params, $maxissueqty_rule->branchcode;
441
            push @bind_params, $maxissueqty_rule->branchcode;
Lines 1391-1404 sub AddIssue { Link Here
1391
1392
1392
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1393
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1393
            unless ($auto_renew) {
1394
            unless ($auto_renew) {
1394
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1395
                my $rule = Koha::CirculationRules->get_effective_rule(
1395
                    {   categorycode => $borrower->{categorycode},
1396
                    {
1397
                        categorycode => $borrower->{categorycode},
1396
                        itemtype     => $item_object->effective_itemtype,
1398
                        itemtype     => $item_object->effective_itemtype,
1397
                        branchcode   => $branchcode
1399
                        branchcode   => $branchcode,
1400
                        rule_name    => 'auto_renew'
1398
                    }
1401
                    }
1399
                );
1402
                );
1400
1403
1401
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1404
                $auto_renew = $rule->rule_value if $rule;
1402
            }
1405
            }
1403
1406
1404
            # Record in the database the fact that the book was issued.
1407
            # Record in the database the fact that the book was issued.
Lines 1539-1605 Get loan length for an itemtype, a borrower type and a branch Link Here
1539
=cut
1542
=cut
1540
1543
1541
sub GetLoanLength {
1544
sub GetLoanLength {
1542
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1545
    my ( $categorycode, $itemtype, $branchcode ) = @_;
1543
    my $dbh = C4::Context->dbh;
1546
1544
    my $sth = $dbh->prepare(qq{
1547
    # Set search precedences
1545
        SELECT issuelength, lengthunit, renewalperiod
1548
    my @params = (
1546
        FROM issuingrules
1549
        {
1547
        WHERE   categorycode=?
1550
            categorycode => $categorycode,
1548
            AND itemtype=?
1551
            itemtype     => $itemtype,
1549
            AND branchcode=?
1552
            branchcode   => $branchcode,
1550
            AND issuelength IS NOT NULL
1553
        },
1551
    });
1554
        {
1555
            categorycode => $categorycode,
1556
            itemtype     => '*',
1557
            branchcode   => $branchcode,
1558
        },
1559
        {
1560
            categorycode => '*',
1561
            itemtype     => $itemtype,
1562
            branchcode   => $branchcode,
1563
        },
1564
        {
1565
            categorycode => '*',
1566
            itemtype     => '*',
1567
            branchcode   => $branchcode,
1568
        },
1569
        {
1570
            categorycode => $categorycode,
1571
            itemtype     => $itemtype,
1572
            branchcode   => '*',
1573
        },
1574
        {
1575
            categorycode => $categorycode,
1576
            itemtype     => '*',
1577
            branchcode   => '*',
1578
        },
1579
        {
1580
            categorycode => '*',
1581
            itemtype     => $itemtype,
1582
            branchcode   => '*',
1583
        },
1584
        {
1585
            categorycode => '*',
1586
            itemtype     => '*',
1587
            branchcode   => '*',
1588
        },
1589
    );
1552
1590
1553
    # try to find issuelength & return the 1st available.
1591
    # Initialize default values
1554
    # check with borrowertype, itemtype and branchcode, then without one of those parameters
1592
    my $rules = {
1555
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1593
        issuelength   => 0,
1556
    my $loanlength = $sth->fetchrow_hashref;
1557
1558
    return $loanlength
1559
      if defined($loanlength) && defined $loanlength->{issuelength};
1560
1561
    $sth->execute( $borrowertype, '*', $branchcode );
1562
    $loanlength = $sth->fetchrow_hashref;
1563
    return $loanlength
1564
      if defined($loanlength) && defined $loanlength->{issuelength};
1565
1566
    $sth->execute( '*', $itemtype, $branchcode );
1567
    $loanlength = $sth->fetchrow_hashref;
1568
    return $loanlength
1569
      if defined($loanlength) && defined $loanlength->{issuelength};
1570
1571
    $sth->execute( '*', '*', $branchcode );
1572
    $loanlength = $sth->fetchrow_hashref;
1573
    return $loanlength
1574
      if defined($loanlength) && defined $loanlength->{issuelength};
1575
1576
    $sth->execute( $borrowertype, $itemtype, '*' );
1577
    $loanlength = $sth->fetchrow_hashref;
1578
    return $loanlength
1579
      if defined($loanlength) && defined $loanlength->{issuelength};
1580
1581
    $sth->execute( $borrowertype, '*', '*' );
1582
    $loanlength = $sth->fetchrow_hashref;
1583
    return $loanlength
1584
      if defined($loanlength) && defined $loanlength->{issuelength};
1585
1586
    $sth->execute( '*', $itemtype, '*' );
1587
    $loanlength = $sth->fetchrow_hashref;
1588
    return $loanlength
1589
      if defined($loanlength) && defined $loanlength->{issuelength};
1590
1591
    $sth->execute( '*', '*', '*' );
1592
    $loanlength = $sth->fetchrow_hashref;
1593
    return $loanlength
1594
      if defined($loanlength) && defined $loanlength->{issuelength};
1595
1596
    # if no rule is set => 0 day (hardcoded)
1597
    return {
1598
        issuelength => 0,
1599
        renewalperiod => 0,
1594
        renewalperiod => 0,
1600
        lengthunit => 'days',
1595
        lengthunit    => 'days',
1601
    };
1596
    };
1602
1597
1598
    # Search for rules!
1599
    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
1600
        foreach my $params (@params) {
1601
            my $rule = Koha::CirculationRules->search(
1602
                {
1603
                    rule_name => $rule_name,
1604
                    %$params,
1605
                }
1606
            )->next();
1607
1608
            if ($rule) {
1609
                $rules->{$rule_name} = $rule->rule_value;
1610
                last;
1611
            }
1612
        }
1613
    }
1614
1615
    return $rules;
1603
}
1616
}
1604
1617
1605
1618
Lines 1614-1632 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1614
sub GetHardDueDate {
1627
sub GetHardDueDate {
1615
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1628
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1616
1629
1617
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1630
    my $rules = Koha::CirculationRules->get_effective_rules(
1618
        {   categorycode => $borrowertype,
1631
        {
1632
            categorycode => $borrowertype,
1619
            itemtype     => $itemtype,
1633
            itemtype     => $itemtype,
1620
            branchcode   => $branchcode
1634
            branchcode   => $branchcode,
1635
            rules        => [ 'hardduedate', 'hardduedatecompare' ],
1621
        }
1636
        }
1622
    );
1637
    );
1623
1638
1624
1639
    if ( defined( $rules->{hardduedate} ) ) {
1625
    if ( defined( $issuing_rule ) ) {
1640
        if ( $rules->{hardduedate} ) {
1626
        if ( $issuing_rule->hardduedate ) {
1641
            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
1627
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1642
        }
1628
        } else {
1643
        else {
1629
            return (undef, undef);
1644
            return ( undef, undef );
1630
        }
1645
        }
1631
    }
1646
    }
1632
}
1647
}
Lines 2245-2258 sub _calculate_new_debar_dt { Link Here
2245
2260
2246
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2261
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2247
    my $circcontrol = C4::Context->preference('CircControl');
2262
    my $circcontrol = C4::Context->preference('CircControl');
2248
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2263
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2249
        {   categorycode => $borrower->{categorycode},
2264
        {   categorycode => $borrower->{categorycode},
2250
            itemtype     => $item->{itype},
2265
            itemtype     => $item->{itype},
2251
            branchcode   => $branchcode
2266
            branchcode   => $branchcode,
2267
            rules => [
2268
                'finedays',
2269
                'lengthunit',
2270
                'firstremind',
2271
                'maxsuspensiondays',
2272
            ]
2252
        }
2273
        }
2253
    );
2274
    );
2254
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2275
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2255
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2276
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2256
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2277
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2257
2278
2258
    return unless $finedays;
2279
    return unless $finedays;
Lines 2263-2269 sub _calculate_new_debar_dt { Link Here
2263
2284
2264
    # grace period is measured in the same units as the loan
2285
    # grace period is measured in the same units as the loan
2265
    my $grace =
2286
    my $grace =
2266
      DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2287
      DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
2267
2288
2268
    my $deltadays = DateTime::Duration->new(
2289
    my $deltadays = DateTime::Duration->new(
2269
        days => $chargeable_units
2290
        days => $chargeable_units
Lines 2272-2287 sub _calculate_new_debar_dt { Link Here
2272
    if ( $deltadays->subtract($grace)->is_positive() ) {
2293
    if ( $deltadays->subtract($grace)->is_positive() ) {
2273
        my $suspension_days = $deltadays * $finedays;
2294
        my $suspension_days = $deltadays * $finedays;
2274
2295
2275
        if ( $issuing_rule->suspension_chargeperiod > 1 ) {
2296
        if ( $issuing_rule->{suspension_chargeperiod} > 1 ) {
2276
            # No need to / 1 and do not consider / 0
2297
            # No need to / 1 and do not consider / 0
2277
            $suspension_days = DateTime::Duration->new(
2298
            $suspension_days = DateTime::Duration->new(
2278
                days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod )
2299
                days => floor( $suspension_days->in_units('days') / $issuing_rule->{suspension_chargeperiod} )
2279
            );
2300
            );
2280
        }
2301
        }
2281
2302
2282
        # If the max suspension days is < than the suspension days
2303
        # If the max suspension days is < than the suspension days
2283
        # the suspension days is limited to this maximum period.
2304
        # the suspension days is limited to this maximum period.
2284
        my $max_sd = $issuing_rule->maxsuspensiondays;
2305
        my $max_sd = $issuing_rule->{maxsuspensiondays};
2285
        if ( defined $max_sd ) {
2306
        if ( defined $max_sd ) {
2286
            $max_sd = DateTime::Duration->new( days => $max_sd );
2307
            $max_sd = DateTime::Duration->new( days => $max_sd );
2287
            $suspension_days = $max_sd
2308
            $suspension_days = $max_sd
Lines 2749-2763 sub CanBookBeRenewed { Link Here
2749
    return ( 1, undef ) if $override_limit;
2770
    return ( 1, undef ) if $override_limit;
2750
2771
2751
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2772
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2752
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2773
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2753
        {   categorycode => $patron->categorycode,
2774
        {
2775
            categorycode => $patron->categorycode,
2754
            itemtype     => $item->effective_itemtype,
2776
            itemtype     => $item->effective_itemtype,
2755
            branchcode   => $branchcode
2777
            branchcode   => $branchcode,
2778
            rules => [
2779
                'renewalsallowed',
2780
                'no_auto_renewal_after',
2781
                'no_auto_renewal_after_hard_limit',
2782
                'lengthunit',
2783
                'norenewalbefore',
2784
            ]
2756
        }
2785
        }
2757
    );
2786
    );
2758
2787
2759
    return ( 0, "too_many" )
2788
    return ( 0, "too_many" )
2760
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2789
      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
2761
2790
2762
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2791
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2763
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2792
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2777-2799 sub CanBookBeRenewed { Link Here
2777
            return ( 0, 'auto_account_expired' );
2806
            return ( 0, 'auto_account_expired' );
2778
        }
2807
        }
2779
2808
2780
        if ( defined $issuing_rule->no_auto_renewal_after
2809
        if ( defined $issuing_rule->{no_auto_renewal_after}
2781
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2810
                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
2782
            # Get issue_date and add no_auto_renewal_after
2811
            # Get issue_date and add no_auto_renewal_after
2783
            # If this is greater than today, it's too late for renewal.
2812
            # If this is greater than today, it's too late for renewal.
2784
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2813
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2785
            $maximum_renewal_date->add(
2814
            $maximum_renewal_date->add(
2786
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2815
                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
2787
            );
2816
            );
2788
            my $now = dt_from_string;
2817
            my $now = dt_from_string;
2789
            if ( $now >= $maximum_renewal_date ) {
2818
            if ( $now >= $maximum_renewal_date ) {
2790
                return ( 0, "auto_too_late" );
2819
                return ( 0, "auto_too_late" );
2791
            }
2820
            }
2792
        }
2821
        }
2793
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2822
        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
2794
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2823
                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
2795
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2824
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2796
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2825
            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
2797
                return ( 0, "auto_too_late" );
2826
                return ( 0, "auto_too_late" );
2798
            }
2827
            }
2799
        }
2828
        }
Lines 2810-2826 sub CanBookBeRenewed { Link Here
2810
        }
2839
        }
2811
    }
2840
    }
2812
2841
2813
    if ( defined $issuing_rule->norenewalbefore
2842
    if ( defined $issuing_rule->{norenewalbefore}
2814
        and $issuing_rule->norenewalbefore ne "" )
2843
        and $issuing_rule->{norenewalbefore} ne "" )
2815
    {
2844
    {
2816
2845
2817
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2846
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2818
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2847
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2819
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2848
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
2820
2849
2821
        # Depending on syspref reset the exact time, only check the date
2850
        # Depending on syspref reset the exact time, only check the date
2822
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2851
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2823
            and $issuing_rule->lengthunit eq 'days' )
2852
            and $issuing_rule->{lengthunit} eq 'days' )
2824
        {
2853
        {
2825
            $soonestrenewal->truncate( to => 'day' );
2854
            $soonestrenewal->truncate( to => 'day' );
2826
        }
2855
        }
Lines 3042-3055 sub GetRenewCount { Link Here
3042
    # $item and $borrower should be calculated
3071
    # $item and $borrower should be calculated
3043
    my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
3072
    my $branchcode = _GetCircControlBranch($item->unblessed, $patron->unblessed);
3044
3073
3045
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3074
    my $rule = Koha::CirculationRules->get_effective_rule(
3046
        {   categorycode => $patron->categorycode,
3075
        {
3076
            categorycode => $patron->categorycode,
3047
            itemtype     => $item->effective_itemtype,
3077
            itemtype     => $item->effective_itemtype,
3048
            branchcode   => $branchcode
3078
            branchcode   => $branchcode,
3079
            rule_name    => 'renewalsallowed',
3049
        }
3080
        }
3050
    );
3081
    );
3051
3082
3052
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
3083
    $renewsallowed = $rule ? $rule->rule_value : 0;
3053
    $renewsleft    = $renewsallowed - $renewcount;
3084
    $renewsleft    = $renewsallowed - $renewcount;
3054
    if($renewsleft < 0){ $renewsleft = 0; }
3085
    if($renewsleft < 0){ $renewsleft = 0; }
3055
    return ( $renewcount, $renewsallowed, $renewsleft );
3086
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3087-3111 sub GetSoonestRenewDate { Link Here
3087
      or return;
3118
      or return;
3088
3119
3089
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3120
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3090
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3121
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3091
        {   categorycode => $patron->categorycode,
3122
        {   categorycode => $patron->categorycode,
3092
            itemtype     => $item->effective_itemtype,
3123
            itemtype     => $item->effective_itemtype,
3093
            branchcode   => $branchcode
3124
            branchcode   => $branchcode,
3125
            rules => [
3126
                'norenewalbefore',
3127
                'lengthunit',
3128
            ]
3094
        }
3129
        }
3095
    );
3130
    );
3096
3131
3097
    my $now = dt_from_string;
3132
    my $now = dt_from_string;
3098
    return $now unless $issuing_rule;
3133
    return $now unless $issuing_rule;
3099
3134
3100
    if ( defined $issuing_rule->norenewalbefore
3135
    if ( defined $issuing_rule->{norenewalbefore}
3101
        and $issuing_rule->norenewalbefore ne "" )
3136
        and $issuing_rule->{norenewalbefore} ne "" )
3102
    {
3137
    {
3103
        my $soonestrenewal =
3138
        my $soonestrenewal =
3104
          dt_from_string( $itemissue->date_due )->subtract(
3139
          dt_from_string( $itemissue->date_due )->subtract(
3105
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3140
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3106
3141
3107
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3142
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3108
            and $issuing_rule->lengthunit eq 'days' )
3143
            and $issuing_rule->{lengthunit} eq 'days' )
3109
        {
3144
        {
3110
            $soonestrenewal->truncate( to => 'day' );
3145
            $soonestrenewal->truncate( to => 'day' );
3111
        }
3146
        }
Lines 3146-3175 sub GetLatestAutoRenewDate { Link Here
3146
      or return;
3181
      or return;
3147
3182
3148
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3183
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3149
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3184
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3150
        {   categorycode => $patron->categorycode,
3185
        {
3186
            categorycode => $patron->categorycode,
3151
            itemtype     => $item->effective_itemtype,
3187
            itemtype     => $item->effective_itemtype,
3152
            branchcode   => $branchcode
3188
            branchcode   => $branchcode,
3189
            rules => [
3190
                'no_auto_renewal_after',
3191
                'no_auto_renewal_after_hard_limit',
3192
                'lengthunit',
3193
            ]
3153
        }
3194
        }
3154
    );
3195
    );
3155
3196
3156
    return unless $issuing_rule;
3197
    return unless $circulation_rules;
3157
    return
3198
    return
3158
      if ( not $issuing_rule->no_auto_renewal_after
3199
      if ( not $circulation_rules->{no_auto_renewal_after}
3159
            or $issuing_rule->no_auto_renewal_after eq '' )
3200
            or $circulation_rules->{no_auto_renewal_after} eq '' )
3160
      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
3201
      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
3161
             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
3202
             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
3162
3203
3163
    my $maximum_renewal_date;
3204
    my $maximum_renewal_date;
3164
    if ( $issuing_rule->no_auto_renewal_after ) {
3205
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3165
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3206
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3166
        $maximum_renewal_date->add(
3207
        $maximum_renewal_date->add(
3167
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3208
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3168
        );
3209
        );
3169
    }
3210
    }
3170
3211
3171
    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
3212
    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
3172
        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
3213
        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
3173
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3214
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3174
    }
3215
    }
3175
    return $maximum_renewal_date;
3216
    return $maximum_renewal_date;
Lines 3216-3234 sub GetIssuingCharges { Link Here
3216
        $item_type = $item_data->{itemtype};
3257
        $item_type = $item_data->{itemtype};
3217
        $charge    = $item_data->{rentalcharge};
3258
        $charge    = $item_data->{rentalcharge};
3218
        my $branch = C4::Context::mybranch();
3259
        my $branch = C4::Context::mybranch();
3219
        my $discount_query = q|SELECT rentaldiscount,
3260
        my $patron = Koha::Patrons->find( $borrowernumber );
3220
            issuingrules.itemtype, issuingrules.branchcode
3261
        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
3221
            FROM borrowers
3262
        if ($discount) {
3222
            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
3223
            WHERE borrowers.borrowernumber = ?
3224
            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
3225
            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
3226
        my $discount_sth = $dbh->prepare($discount_query);
3227
        $discount_sth->execute( $borrowernumber, $item_type, $branch );
3228
        my $discount_rules = $discount_sth->fetchall_arrayref({});
3229
        if (@{$discount_rules}) {
3230
            # We may have multiple rules so get the most specific
3263
            # We may have multiple rules so get the most specific
3231
            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
3232
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3264
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3233
        }
3265
        }
3234
        if ($charge) {
3266
        if ($charge) {
Lines 3241-3277 sub GetIssuingCharges { Link Here
3241
3273
3242
# Select most appropriate discount rule from those returned
3274
# Select most appropriate discount rule from those returned
3243
sub _get_discount_from_rule {
3275
sub _get_discount_from_rule {
3244
    my ($rules_ref, $branch, $itemtype) = @_;
3276
    my ($categorycode, $branchcode, $itemtype) = @_;
3245
    my $discount;
3246
3277
3247
    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
3278
    # Set search precedences
3248
        $discount = $rules_ref->[0]->{rentaldiscount};
3279
    my @params = (
3249
        return (defined $discount) ? $discount : 0;
3280
        {
3250
    }
3281
            branchcode   => $branchcode,
3251
    # could have up to 4 does one match $branch and $itemtype
3282
            itemtype     => $itemtype,
3252
    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
3283
            categorycode => $categorycode,
3253
    if (@d) {
3284
        },
3254
        $discount = $d[0]->{rentaldiscount};
3285
        {
3255
        return (defined $discount) ? $discount : 0;
3286
            branchcode   => '*',
3256
    }
3287
            categorycode => $categorycode,
3257
    # do we have item type + all branches
3288
            itemtype     => $itemtype,
3258
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
3289
        },
3259
    if (@d) {
3290
        {
3260
        $discount = $d[0]->{rentaldiscount};
3291
            branchcode   => $branchcode,
3261
        return (defined $discount) ? $discount : 0;
3292
            categorycode => $categorycode,
3262
    }
3293
            itemtype     => '*',
3263
    # do we all item types + this branch
3294
        },
3264
    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
3295
        {
3265
    if (@d) {
3296
            branchcode   => '*',
3266
        $discount = $d[0]->{rentaldiscount};
3297
            categorycode => $categorycode,
3267
        return (defined $discount) ? $discount : 0;
3298
            itemtype     => '*',
3268
    }
3299
        },
3269
    # so all and all (surely we wont get here)
3300
    );
3270
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
3301
3271
    if (@d) {
3302
    foreach my $params (@params) {
3272
        $discount = $d[0]->{rentaldiscount};
3303
        my $rule = Koha::CirculationRules->search(
3273
        return (defined $discount) ? $discount : 0;
3304
            {
3305
                rule_name => 'rentaldiscount',
3306
                %$params,
3307
            }
3308
        )->next();
3309
3310
        return $rule->rule_value if $rule;
3274
    }
3311
    }
3312
3275
    # none of the above
3313
    # none of the above
3276
    return 0;
3314
    return 0;
3277
}
3315
}
(-)a/C4/Overdues.pm (-10 / +25 lines)
Lines 35-41 use C4::Debug; Link Here
35
use Koha::DateUtils;
35
use Koha::DateUtils;
36
use Koha::Account::Lines;
36
use Koha::Account::Lines;
37
use Koha::Account::Offsets;
37
use Koha::Account::Offsets;
38
use Koha::IssuingRules;
39
use Koha::Libraries;
38
use Koha::Libraries;
40
39
41
use vars qw(@ISA @EXPORT);
40
use vars qw(@ISA @EXPORT);
Lines 238-264 sub CalcFine { Link Here
238
    my $start_date = $due_dt->clone();
237
    my $start_date = $due_dt->clone();
239
    # get issuingrules (fines part will be used)
238
    # get issuingrules (fines part will be used)
240
    my $itemtype = $item->{itemtype} || $item->{itype};
239
    my $itemtype = $item->{itemtype} || $item->{itype};
241
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
240
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
241
        {
242
            categorycode => $bortype,
243
            itemtype     => $itemtype,
244
            branchcode   => $branchcode,
245
            rules => [
246
                'lengthunit',
247
                'firstremind',
248
                'chargeperiod',
249
                'chargeperiod_charge_at',
250
                'fine',
251
                'overduefinescap',
252
                'cap_fine_to_replacement_price',
253
                'chargename',
254
            ]
255
        }
256
    );
242
257
243
    $itemtype = Koha::ItemTypes->find($itemtype);
258
    $itemtype = Koha::ItemTypes->find($itemtype);
244
259
245
    return unless $issuing_rule; # If not rule exist, there is no fine
260
    return unless $issuing_rule; # If not rule exist, there is no fine
246
261
247
    my $fine_unit = $issuing_rule->lengthunit || 'days';
262
    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
248
263
249
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
264
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
250
    my $units_minus_grace = $chargeable_units - ($issuing_rule->firstremind || 0);
265
    my $units_minus_grace = $chargeable_units - ($issuing_rule->{firstremind} || 0);
251
    my $amount = 0;
266
    my $amount = 0;
252
    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
267
    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
253
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
268
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
254
        my $charge_periods = $units / $issuing_rule->chargeperiod;
269
        my $charge_periods = $units / $issuing_rule->{chargeperiod};
255
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
270
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
256
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
271
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
257
        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
272
        $charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
258
        $amount = $charge_periods * $issuing_rule->fine;
273
        $amount = $charge_periods * $issuing_rule->{fine};
259
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
274
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
260
275
261
    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
276
    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
262
277
263
    # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
278
    # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
264
    $item->{replacementprice} ||= $itemtype->defaultreplacecost
279
    $item->{replacementprice} ||= $itemtype->defaultreplacecost
Lines 266-272 sub CalcFine { Link Here
266
      && ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
281
      && ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
267
      && C4::Context->preference("useDefaultReplacementCost");
282
      && C4::Context->preference("useDefaultReplacementCost");
268
283
269
    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
284
    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
270
285
271
    $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
286
    $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
272
    return ($amount, $units_minus_grace, $chargeable_units);
287
    return ($amount, $units_minus_grace, $chargeable_units);
(-)a/C4/Reserves.pm (-15 / +30 lines)
Lines 40-46 use Koha::Database; Link Here
40
use Koha::DateUtils;
40
use Koha::DateUtils;
41
use Koha::Hold;
41
use Koha::Hold;
42
use Koha::Holds;
42
use Koha::Holds;
43
use Koha::IssuingRules;
44
use Koha::ItemTypes;
43
use Koha::ItemTypes;
45
use Koha::Items;
44
use Koha::Items;
46
use Koha::Libraries;
45
use Koha::Libraries;
Lines 2206-2229 patron category, itemtype, and library. Link Here
2206
sub GetHoldRule {
2205
sub GetHoldRule {
2207
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2206
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2208
2207
2209
    my $dbh = C4::Context->dbh;
2208
    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
2210
2209
        {
2211
    my $sth = $dbh->prepare(
2210
            itemtype     => $itemtype,
2212
        q{
2211
            categorycode => $categorycode,
2213
         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record, holds_per_day
2212
            branchcode   => $branchcode,
2214
           FROM issuingrules
2213
            rule_name    => 'reservesallowed',
2215
          WHERE (categorycode in (?,'*') )
2214
            order_by     => {
2216
            AND (itemtype IN (?,'*'))
2215
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2217
            AND (branchcode IN (?,'*'))
2216
            }
2218
       ORDER BY categorycode DESC,
2219
                itemtype     DESC,
2220
                branchcode   DESC
2221
        }
2217
        }
2222
    );
2218
    );
2219
    return unless $reservesallowed;;
2223
2220
2224
    $sth->execute( $categorycode, $itemtype, $branchcode );
2221
    my $rules;
2222
    $rules->{reservesallowed} = $reservesallowed->rule_value;
2223
    $rules->{itemtype}        = $reservesallowed->itemtype;
2224
    $rules->{categorycode}    = $reservesallowed->categorycode;
2225
    $rules->{branchcode}      = $reservesallowed->branchcode;
2226
2227
    my $holds_per_x_rules = Koha::CirculationRules->get_effective_rules(
2228
        {
2229
            itemtype     => $itemtype,
2230
            categorycode => $categorycode,
2231
            branchcode   => $branchcode,
2232
            rules        => ['holds_per_record', 'holds_per_day'],
2233
            order_by     => {
2234
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2235
            }
2236
        }
2237
    );
2238
    $rules->{holds_per_record} = $holds_per_x_rules->{holds_per_record};
2239
    $rules->{holds_per_day} = $holds_per_x_rules->{holds_per_day};
2225
2240
2226
    return $sth->fetchrow_hashref();
2241
    return $rules;
2227
}
2242
}
2228
2243
2229
=head1 AUTHOR
2244
=head1 AUTHOR
(-)a/Koha/Biblio.pm (-4 / +10 lines)
Lines 37-43 use Koha::ArticleRequest::Status; Link Here
37
use Koha::ArticleRequests;
37
use Koha::ArticleRequests;
38
use Koha::Biblio::Metadatas;
38
use Koha::Biblio::Metadatas;
39
use Koha::Biblioitems;
39
use Koha::Biblioitems;
40
use Koha::IssuingRules;
40
use Koha::CirculationRules;
41
use Koha::Item::Transfer::Limits;
41
use Koha::Item::Transfer::Limits;
42
use Koha::Items;
42
use Koha::Items;
43
use Koha::Libraries;
43
use Koha::Libraries;
Lines 299-308 sub article_request_type_for_bib { Link Here
299
    my $borrowertype = $borrower->categorycode;
299
    my $borrowertype = $borrower->categorycode;
300
    my $itemtype     = $self->itemtype();
300
    my $itemtype     = $self->itemtype();
301
301
302
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
302
    my $rule = Koha::CirculationRules->get_effective_rule(
303
        {
304
            rule_name    => 'article_requests',
305
            categorycode => $borrowertype,
306
            itemtype     => $itemtype,
307
        }
308
    );
303
309
304
    return q{} unless $issuing_rule;
310
    return q{} unless $rule;
305
    return $issuing_rule->article_requests || q{}
311
    return $rule->rule_value || q{}
306
}
312
}
307
313
308
=head3 article_request_type_for_items
314
=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 29-35 use C4::Context; Link Here
29
use C4::Circulation;
29
use C4::Circulation;
30
use C4::Reserves;
30
use C4::Reserves;
31
use Koha::Checkouts;
31
use Koha::Checkouts;
32
use Koha::IssuingRules;
32
use Koha::CirculationRules;
33
use Koha::Item::Transfer::Limits;
33
use Koha::Item::Transfer::Limits;
34
use Koha::Item::Transfers;
34
use Koha::Item::Transfers;
35
use Koha::Patrons;
35
use Koha::Patrons;
Lines 369-378 sub article_request_type { Link Here
369
      :                                      undef;
369
      :                                      undef;
370
    my $borrowertype = $borrower->categorycode;
370
    my $borrowertype = $borrower->categorycode;
371
    my $itemtype = $self->effective_itemtype();
371
    my $itemtype = $self->effective_itemtype();
372
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
372
    my $rule = Koha::CirculationRules->get_effective_rule(
373
        {
374
            rule_name    => 'article_requests',
375
            categorycode => $borrowertype,
376
            itemtype     => $itemtype,
377
            branchcode   => $branchcode
378
        }
379
    );
373
380
374
    return q{} unless $issuing_rule;
381
    return q{} unless $rule;
375
    return $issuing_rule->article_requests || q{}
382
    return $rule->rule_value || q{}
376
}
383
}
377
384
378
=head3 current_holds
385
=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 (-146 / +184 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-261 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.Search( 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.Search( 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
                                [% IF ( rule.lengthunit == 'days' ) %]
166
                                            <em>All</em>
158
                                    Days
167
                                        [% ELSE %]
159
                                [% ELSIF ( rule.lengthunit == 'hours') %]
168
                                            [% Categories.GetName(c) %]
160
                                    Hours
169
                                        [% END %]
161
                                [% ELSE %]
170
                                    </td>
162
                                    Undefined
171
                                    <td>
163
                                [% END %]
172
                                        [% IF i == '*' %]
164
                            </td>
173
                                            <em>All</em>
165
                            <td>
174
                                        [% ELSE %]
166
                              [% IF ( rule.hardduedate ) %]
175
                                            [% ItemTypes.GetDescription(i) %]
167
                                [% IF ( rule.hardduedatebefore ) %]
176
                                        [% END %]
168
                                  before [% rule.hardduedate | html %]
177
                                    </td>
169
                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
178
                                    <td>
170
                                [% ELSIF ( rule.hardduedateexact ) %]
179
                                        [% IF rule.note %]
171
                                  on [% rule.hardduedate | html %]
180
                                            <a name="viewnote" data-toggle="popover" title="Note" data-content="[% rule.note | html %]" data-placement="top" data-trigger="hover">View note</a>
172
                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
181
                                        [% ELSE %]<span>&nbsp;</span>[% END %]
173
                                [% ELSIF ( rule.hardduedateafter ) %]
182
                                    </td>
174
                                  after [% rule.hardduedate | html %]
183
                                    <td>
175
                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
184
                                        [% IF maxissueqty  %]
176
                                [% END %]
185
                                            [% maxissueqty %]
177
                              [% ELSE %]
186
                                        [% ELSE %]
178
                                <span>None defined</span>
187
                                            <span>Unlimited</span>
179
                              [% END %]
188
                                        [% END %]
180
                            </td>
189
                                    </td>
181
							<td>[% rule.fine | html %]</td>
190
                                    <td>
182
							<td>[% rule.chargeperiod | html %]</td>
191
                                        [% IF maxonsiteissueqty  %]
183
                            <td>
192
                                            [% maxonsiteissueqty %]
184
                                [% IF rule.chargeperiod_charge_at %]
193
                                        [% ELSE %]
185
                                    <span>Start of interval</span>
194
                                            <span>Unlimited</span>
186
                                [% ELSE %]
195
                                        [% END %]
187
                                    <span>End of interval</span>
196
                                    </td>
188
                                [% END %]
197
                                    <td>[% issuelength %]</td>
189
                            </td>
198
                                    <td>
190
							<td>[% rule.firstremind | html %]</td>
199
                                        [% IF ( lengthunit == 'days' ) %]
191
                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
200
                                            Days
192
                            <td>
201
                                        [% ELSIF ( lengthunit == 'hours') %]
193
                                [% IF rule.cap_fine_to_replacement_price %]
202
                                            Hours
194
                                    <input type="checkbox" checked="checked" disabled="disabled" />
203
                                        [% ELSE %]
195
                                [% ELSE %]
204
                                            Undefined
196
                                    <input type="checkbox" disabled="disabled" />
205
                                        [% END %]
197
                                [% END %]
206
                                    </td>
198
                            </td>
207
                                    <td>
199
							<td>[% rule.finedays | html %]</td>
208
                                      [% IF ( hardduedate ) %]
200
                            <td>[% rule.maxsuspensiondays | html %]</td>
209
                                        [% IF ( hardduedatecompare == '-1' ) %]
201
                            <td>[% rule.suspension_chargeperiod | html %]</td>
210
                                          before [% hardduedate | $KohaDates %]
202
							<td>[% rule.renewalsallowed | html %]</td>
211
                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
203
                            <td>[% rule.renewalperiod | html %]</td>
212
                                        [% ELSIF ( hardduedatecompare == '0' ) %]
204
                            <td>[% rule.norenewalbefore | html %]</td>
213
                                          on [% hardduedate | $KohaDates %]
205
                            <td>
214
                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
206
                                [% IF ( rule.auto_renew ) %]
215
                                        [% ELSIF ( hardduedatecompare == '1' ) %]
207
                                    <span>Yes</span>
216
                                          after [% hardduedate | $KohaDates %]
208
                                [% ELSE %]
217
                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
209
                                    <span>No</span>
218
                                        [% END %]
210
                                [% END %]
219
                                      [% ELSE %]
211
                            </td>
220
                                        <span>None defined</span>
212
                            <td>[% rule.no_auto_renewal_after | html %]</td>
221
                                      [% END %]
213
                            <td>[% rule.no_auto_renewal_after_hard_limit | html %]</td>
222
                                    </td>
214
							<td>[% rule.reservesallowed | html %]</td>
223
                                    <td>[% fine %]</td>
215
                            <td>[% IF rule.unlimited_holds_per_day %]
224
                                    <td>[% chargeperiod %]</td>
216
                                    <span>Unlimited</span>
225
                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
217
                                [% ELSE %]
226
                                    <td>[% firstremind %]</td>
218
                                    [% rule.holds_per_day | html %]
227
                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
219
                                [% END %]
228
                                    <td>
220
                            </td>
229
                                        [% IF cap_fine_to_replacement_price %]
221
                            <td>[% rule.holds_per_record | html %]</td>
230
                                            <input type="checkbox" checked="checked" disabled="disabled" />
222
                                                        <td>
231
                                        [% ELSE %]
223
                                                            [% IF rule.onshelfholds == 1 %]
232
                                            <input type="checkbox" disabled="disabled" />
224
                                                                <span>Yes</span>
233
                                        [% END %]
225
                                                            [% ELSIF rule.onshelfholds == 2 %]
234
                                    </td>
226
                                                                <span>If all unavailable</span>
235
                                    <td>[% finedays %]</td>
227
                                                            [% ELSE %]
236
                                    <td>[% maxsuspensiondays %]</td>
228
                                                                <span>If any unavailable</span>
237
                                    <td>[% suspension_chargeperiod %]</td>
229
                                                            [% END %]
238
                                    <td>[% renewalsallowed %]</td>
230
                                                        </td>
239
                                    <td>[% renewalperiod %]</td>
231
                                                        <td>
240
                                    <td>[% norenewalbefore %]</td>
232
                                                            [% IF rule.opacitemholds == 'F'%]
241
                                    <td>
233
                                                                <span>Force</span>
242
                                        [% IF auto_renew %]
234
                                                            [% ELSIF rule.opacitemholds == 'Y'%]
243
                                            <span>Yes</span>
235
                                                                <span>Allow</span>
244
                                        [% ELSE %]
236
                                                            [% ELSE %]
245
                                            <span>No</span>
237
                                                                <span>Don't allow</span>
246
                                        [% END %]
238
                                                            [% END %]
247
                                    </td>
239
                                                        </td>
248
                                    <td>[% no_auto_renewal_after %]</td>
240
                                                        <td>
249
                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
241
                                                            [% IF rule.article_requests == 'no' %]
250
                                    <td>[% reservesallowed %]</td>
242
                                                                <span>No</span>
251
                                    <td>
243
                                                            [% ELSIF rule.article_requests == 'yes' %]
252
                                        [% IF holds_per_day.defined && holds != '' %]
244
                                                                <span>Yes</span>
253
                                            [% holds_per_day %]
245
                                                            [% ELSIF rule.article_requests == 'bib_only' %]
254
                                        [% ELSE %]
246
                                                                <span>Record only</span>
255
                                            <span>Unlimited</span>
247
                                                            [% ELSIF rule.article_requests == 'item_only' %]
256
                                        [% END %]
248
                                                                <span>Item only</span>
257
                                    </td>
249
                                                            [% END %]
258
                                    <td>[% holds_per_record %]</td>
250
                                                        </td>
259
                                    <td>
251
                                                        <td>[% rule.rentaldiscount | html %]</td>
260
                                        [% IF onshelfholds == 1 %]
252
                                                        <td class="actions">
261
                                            <span>Yes</span>
253
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
262
                                        [% ELSIF onshelfholds == 2 %]
254
                                                          <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>
263
                                            <span>If all unavailable</span>
255
                                                        </td>
264
                                        [% ELSE %]
256
265
                                            <span>If any unavailable</span>
257
                	</tr>
266
                                        [% END %]
258
            	[% END %]
267
                                    </td>
268
                                    <td>
269
                                        [% IF opacitemholds == 'F'%]
270
                                            <span>Force</span>
271
                                        [% ELSIF opacitemholds == 'Y'%]
272
                                            <span>Allow</span>
273
                                        [% ELSE %]
274
                                            <span>Don't allow</span>
275
                                        [% END %]
276
                                    </td>
277
                                    <td>
278
                                        [% IF article_requests == 'no' %]
279
                                            <span>No</span>
280
                                        [% ELSIF article_requests == 'yes' %]
281
                                            <span>Yes</span>
282
                                        [% ELSIF article_requests == 'bib_only' %]
283
                                            <span>Record only</span>
284
                                        [% ELSIF article_requests == 'item_only' %]
285
                                            <span>Item only</span>
286
                                        [% END %]
287
                                    </td>
288
                                    <td>[% rentaldiscount %]</td>
289
                                    <td class="actions">
290
                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
291
                                      <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>
292
                                    </td>
293
                            </tr>
294
                        [% END %]
295
                    [% END %]
296
                [% END %]
259
                <tr id="edit_row">
297
                <tr id="edit_row">
260
                    <td>
298
                    <td>
261
                        <select name="categorycode" id="categorycode">
299
                        <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
        C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','1');
837
        C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','1');
Lines 874-904 subtest "CanBookBeRenewed tests" => sub { Link Here
874
        my $ten_days_before = dt_from_string->add( days => -10 );
969
        my $ten_days_before = dt_from_string->add( days => -10 );
875
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
970
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
876
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
971
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
877
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = NULL, no_auto_renewal_after_hard_limit = NULL');
972
        Koha::CirculationRules->set_rules(
973
            {
974
                categorycode => '*',
975
                branchcode   => '*',
976
                itemtype     => '*',
977
                rules        => {
978
                    norenewalbefore       => '7',
979
                    no_auto_renewal_after => '',
980
                    no_auto_renewal_after_hard_limit => undef,
981
                }
982
            }
983
        );
878
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
984
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
879
        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' );
985
        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' );
880
        my $five_days_before = dt_from_string->add( days => -5 );
986
        my $five_days_before = dt_from_string->add( days => -5 );
881
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
987
        Koha::CirculationRules->set_rules(
988
            {
989
                categorycode => '*',
990
                branchcode   => '*',
991
                itemtype     => '*',
992
                rules        => {
993
                    norenewalbefore       => '10',
994
                    no_auto_renewal_after => '5',
995
                    no_auto_renewal_after_hard_limit => undef,
996
                }
997
            }
998
        );
882
        $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} );
883
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1000
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
884
            $five_days_before->truncate( to => 'minute' ),
1001
            $five_days_before->truncate( to => 'minute' ),
885
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
1002
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
886
        );
1003
        );
887
        my $five_days_ahead = dt_from_string->add( days => 5 );
1004
        my $five_days_ahead = dt_from_string->add( days => 5 );
888
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
1005
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
1006
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
1007
        $dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
1008
        Koha::CirculationRules->set_rules(
1009
            {
1010
                categorycode => '*',
1011
                branchcode   => '*',
1012
                itemtype     => '*',
1013
                rules        => {
1014
                    norenewalbefore       => '10',
1015
                    no_auto_renewal_after => '15',
1016
                    no_auto_renewal_after_hard_limit => undef,
1017
                }
1018
            }
1019
        );
889
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
1020
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
890
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1021
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
891
            $five_days_ahead->truncate( to => 'minute' ),
1022
            $five_days_ahead->truncate( to => 'minute' ),
892
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
1023
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
893
        );
1024
        );
894
        my $two_days_ahead = dt_from_string->add( days => 2 );
1025
        my $two_days_ahead = dt_from_string->add( days => 2 );
895
        $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 ) );
1026
        Koha::CirculationRules->set_rules(
1027
            {
1028
                categorycode => '*',
1029
                branchcode   => '*',
1030
                itemtype     => '*',
1031
                rules        => {
1032
                    norenewalbefore       => '10',
1033
                    no_auto_renewal_after => '',
1034
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
1035
                }
1036
            }
1037
        );
896
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
1038
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
897
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1039
        is( $latest_auto_renew_date->truncate( to => 'day' ),
898
            $two_days_ahead->truncate( to => 'day' ),
1040
            $two_days_ahead->truncate( to => 'day' ),
899
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
1041
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
900
        );
1042
        );
901
        $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 ) );
1043
        Koha::CirculationRules->set_rules(
1044
            {
1045
                categorycode => '*',
1046
                branchcode   => '*',
1047
                itemtype     => '*',
1048
                rules        => {
1049
                    norenewalbefore       => '10',
1050
                    no_auto_renewal_after => '15',
1051
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
1052
                }
1053
            }
1054
        );
902
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
1055
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
903
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1056
        is( $latest_auto_renew_date->truncate( to => 'day' ),
904
            $two_days_ahead->truncate( to => 'day' ),
1057
            $two_days_ahead->truncate( to => 'day' ),
Lines 906-916 subtest "CanBookBeRenewed tests" => sub { Link Here
906
        );
1059
        );
907
1060
908
    };
1061
    };
909
910
    # Too many renewals
1062
    # Too many renewals
911
1063
912
    # set policy to forbid renewals
1064
    # set policy to forbid renewals
913
    $dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
1065
    Koha::CirculationRules->set_rules(
1066
        {
1067
            categorycode => '*',
1068
            branchcode   => '*',
1069
            itemtype     => '*',
1070
            rules        => {
1071
                norenewalbefore => undef,
1072
                renewalsallowed => 0,
1073
            }
1074
        }
1075
    );
914
1076
915
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
1077
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
916
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
1078
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
Lines 1145-1171 subtest "Bug 13841 - Do not create new 0 amount fines" => sub { Link Here
1145
subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
1307
subtest "AllowRenewalIfOtherItemsAvailable tests" => sub {
1146
    $dbh->do('DELETE FROM issues');
1308
    $dbh->do('DELETE FROM issues');
1147
    $dbh->do('DELETE FROM items');
1309
    $dbh->do('DELETE FROM items');
1148
    $dbh->do('DELETE FROM issuingrules');
1310
    $dbh->do('DELETE FROM circulation_rules');
1149
    Koha::CirculationRules->search()->delete();
1150
    $dbh->do(
1151
        q{
1152
        INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
1153
                    norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
1154
        },
1155
        {},
1156
        '*', '*', '*', 25,
1157
        14,  'days',
1158
        1,   7,
1159
        undef,  0,
1160
        .10, 1
1161
    );
1162
    Koha::CirculationRules->set_rules(
1311
    Koha::CirculationRules->set_rules(
1163
        {
1312
        {
1164
            categorycode => '*',
1313
            categorycode => '*',
1165
            itemtype     => '*',
1314
            itemtype     => '*',
1166
            branchcode   => '*',
1315
            branchcode   => '*',
1167
            rules        => {
1316
            rules        => {
1168
                maxissueqty => 20
1317
                reservesallowed => 25,
1318
                issuelength     => 14,
1319
                lengthunit      => 'days',
1320
                renewalsallowed => 1,
1321
                renewalperiod   => 7,
1322
                norenewalbefore => undef,
1323
                auto_renew      => 0,
1324
                fine            => .10,
1325
                chargeperiod    => 1,
1326
                maxissueqty     => 20
1169
            }
1327
            }
1170
        }
1328
        }
1171
    );
1329
    );
Lines 1214-1235 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1214
        undef, undef, undef
1372
        undef, undef, undef
1215
    );
1373
    );
1216
1374
1217
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1375
    Koha::CirculationRules->set_rules(
1376
        {
1377
            categorycode => '*',
1378
            itemtype     => '*',
1379
            branchcode   => '*',
1380
            rules        => {
1381
                onshelfholds => 0,
1382
            }
1383
        }
1384
    );
1218
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1385
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1219
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1386
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1220
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1387
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1221
1388
1222
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1389
    Koha::CirculationRules->set_rules(
1390
        {
1391
            categorycode => '*',
1392
            itemtype     => '*',
1393
            branchcode   => '*',
1394
            rules        => {
1395
                onshelfholds => 0,
1396
            }
1397
        }
1398
    );
1223
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1399
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1224
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1400
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1225
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1401
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1226
1402
1227
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1403
    Koha::CirculationRules->set_rules(
1404
        {
1405
            categorycode => '*',
1406
            itemtype     => '*',
1407
            branchcode   => '*',
1408
            rules        => {
1409
                onshelfholds => 1,
1410
            }
1411
        }
1412
    );
1228
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1413
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1229
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1414
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1230
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1415
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1231
1416
1232
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1417
    Koha::CirculationRules->set_rules(
1418
        {
1419
            categorycode => '*',
1420
            itemtype     => '*',
1421
            branchcode   => '*',
1422
            rules        => {
1423
                onshelfholds => 1,
1424
            }
1425
        }
1426
    );
1233
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1427
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1234
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1428
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1235
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1429
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
Lines 1706-1725 subtest 'AddReturn + CumulativeRestrictionPeriods' => sub { Link Here
1706
        }
1900
        }
1707
    )->unblessed;
1901
    )->unblessed;
1708
1902
1709
    # And the issuing rule
1903
    # And the circulation rule
1710
    Koha::IssuingRules->search->delete;
1904
    Koha::CirculationRules->search->delete;
1711
    my $rule = Koha::IssuingRule->new(
1905
    Koha::CirculationRules->set_rules(
1712
        {
1906
        {
1713
            categorycode => '*',
1907
            categorycode => '*',
1714
            itemtype     => '*',
1908
            itemtype     => '*',
1715
            branchcode   => '*',
1909
            branchcode   => '*',
1716
            issuelength  => 1,
1910
            rules        => {
1717
            firstremind  => 1,        # 1 day of grace
1911
                issuelength => 1,
1718
            finedays     => 2,        # 2 days of fine per day of overdue
1912
                firstremind => 1,        # 1 day of grace
1719
            lengthunit   => 'days',
1913
                finedays    => 2,        # 2 days of fine per day of overdue
1914
                lengthunit  => 'days',
1915
            }
1720
        }
1916
        }
1721
    );
1917
    );
1722
    $rule->store();
1723
1918
1724
    # Patron cannot issue item_1, they have overdues
1919
    # Patron cannot issue item_1, they have overdues
1725
    my $five_days_ago = dt_from_string->subtract( days => 5 );
1920
    my $five_days_ago = dt_from_string->subtract( days => 5 );
Lines 2017-2035 subtest 'AddReturn | is_overdue' => sub { Link Here
2017
        }
2212
        }
2018
    )->unblessed;
2213
    )->unblessed;
2019
2214
2020
    Koha::IssuingRules->search->delete;
2215
    Koha::CirculationRules->search->delete;
2021
    my $rule = Koha::IssuingRule->new(
2216
    my $rule = Koha::CirculationRules->set_rules(
2022
        {
2217
        {
2023
            categorycode => '*',
2218
            categorycode => '*',
2024
            itemtype     => '*',
2219
            itemtype     => '*',
2025
            branchcode   => '*',
2220
            branchcode   => '*',
2026
            issuelength  => 6,
2221
            rules        => {
2027
            lengthunit   => 'days',
2222
                issuelength  => 6,
2028
            fine         => 1, # Charge 1 every day of overdue
2223
                lengthunit   => 'days',
2029
            chargeperiod => 1,
2224
                fine         => 1,        # Charge 1 every day of overdue
2225
                chargeperiod => 1,
2226
            }
2030
        }
2227
        }
2031
    );
2228
    );
2032
    $rule->store();
2033
2229
2034
    my $now   = dt_from_string;
2230
    my $now   = dt_from_string;
2035
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
2231
    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,
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,
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,
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,
131
        rentaldiscount                   => 2,
132
    hardduedatecompare => 0,
132
        reservesallowed                  => 0,
133
    overduefinescap    => 0,
133
        hardduedate                      => '2013-01-01',
134
    renewalsallowed    => 0,
134
        fine                             => 0,
135
    firstremind        => 0,
135
        hardduedatecompare               => 5,
136
    itemtype           => 'BOOK',
136
        overduefinescap                  => 0,
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 423-428 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub { Link Here
423
    );
422
    );
424
423
425
    teardown();
424
    teardown();
425
    Koha::CirculationRules->set_rules(
426
        {
427
            branchcode   => $branch->{branchcode},
428
            categorycode => $category->{categorycode},
429
            itemtype     => undef,
430
            rules        => {
431
                maxissueqty       => 1,
432
                maxonsiteissueqty => 1,
433
            }
434
        }
435
    );
426
436
427
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
437
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
428
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
438
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
Lines 705-710 $schema->storage->txn_rollback; Link Here
705
715
706
sub teardown {
716
sub teardown {
707
    $dbh->do(q|DELETE FROM issues|);
717
    $dbh->do(q|DELETE FROM issues|);
708
    $dbh->do(q|DELETE FROM issuingrules|);
718
    $dbh->do(q|DELETE FROM circulation_rules|);
709
}
719
}
710
720
(-)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 (-34 / +53 lines)
Lines 244-262 is( $hold->priority, '6', "Test AlterPriority(), move to bottom" ); Link Here
244
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
244
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
245
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
245
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
246
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
246
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
247
# Cleanup circulation rules
247
Koha::CirculationRules->set_rules(
248
$dbh->do('DELETE FROM circulation_rules');
248
    {
249
# $dbh->do(
249
        categorycode => '*',
250
#     q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
250
        branchcode   => '*',
251
#       VALUES (?, ?, ?, ?, ?)},
251
        itemtype     => '*',
252
#     {},
252
        rules        => {
253
#     '*', '*', '*', 25, 99
253
            reservesallowed  => 25,
254
# );
254
            holds_per_record => 99,
255
$dbh->do(
255
        }
256
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
256
    }
257
      VALUES (?, ?, ?, ?, ?)},
257
);
258
    {},
258
Koha::CirculationRules->set_rules(
259
    '*', '*', 'CANNOT', 0, 99
259
    {
260
        categorycode => '*',
261
        branchcode   => '*',
262
        itemtype     => 'CANNOT',
263
        rules        => {
264
            reservesallowed  => 0,
265
            holds_per_record => 99,
266
        }
267
    }
260
);
268
);
261
269
262
# make sure some basic sysprefs are set
270
# make sure some basic sysprefs are set
Lines 266-273 t::lib::Mocks::mock_preference('item-level_itypes', 1); Link Here
266
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
274
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
267
t::lib::Mocks::mock_preference('IndependentBranches', 0);
275
t::lib::Mocks::mock_preference('IndependentBranches', 0);
268
276
269
ok(
277
is(
270
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'OK',
278
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status}, 'OK',
271
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
279
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
272
);
280
);
273
281
Lines 354-366 ok( Link Here
354
362
355
# Test branch item rules
363
# Test branch item rules
356
364
357
$dbh->do('DELETE FROM issuingrules');
358
$dbh->do('DELETE FROM circulation_rules');
365
$dbh->do('DELETE FROM circulation_rules');
359
$dbh->do(
366
Koha::CirculationRules->set_rules(
360
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
367
    {
361
      VALUES (?, ?, ?, ?)},
368
        categorycode => '*',
362
    {},
369
        branchcode   => '*',
363
    '*', '*', '*', 25
370
        itemtype     => '*',
371
        rules        => {
372
            reservesallowed  => 25,
373
            holds_per_record => 99,
374
        }
375
    }
364
);
376
);
365
Koha::CirculationRules->set_rules(
377
Koha::CirculationRules->set_rules(
366
    {
378
    {
Lines 419-429 $biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); Link Here
419
( $item_bibnum, $item_bibitemnum, $itemnumber )
431
( $item_bibnum, $item_bibitemnum, $itemnumber )
420
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
432
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $biblio->biblionumber );
421
433
422
$dbh->do(
434
Koha::CirculationRules->set_rules(
423
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
435
    {
424
      VALUES (?, ?, ?, ?, ?)},
436
        categorycode => '*',
425
    {},
437
        branchcode   => '*',
426
    '*', '*', 'ONLY1', 1, 99
438
        itemtype     => 'ONLY1',
439
        rules        => {
440
            reservesallowed  => 1,
441
            holds_per_record => 99,
442
        }
443
    }
427
);
444
);
428
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
445
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
429
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
446
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
Lines 444-463 subtest 'Test max_holds per library/patron category' => sub { Link Here
444
    plan tests => 6;
461
    plan tests => 6;
445
462
446
    $dbh->do('DELETE FROM reserves');
463
    $dbh->do('DELETE FROM reserves');
447
    $dbh->do('DELETE FROM issuingrules');
448
    $dbh->do('DELETE FROM circulation_rules');
464
    $dbh->do('DELETE FROM circulation_rules');
449
465
450
    $biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
466
    $biblio = $builder->build_sample_biblio({ itemtype => 'TEST' });
451
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
467
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
452
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
468
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
453
        $biblio->biblionumber );
469
        $biblio->biblionumber );
454
    $dbh->do(
470
    Koha::CirculationRules->set_rules(
455
        q{
471
        {
456
            INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
472
            categorycode => '*',
457
            VALUES (?, ?, ?, ?, ?)
473
            branchcode   => '*',
458
        },
474
            itemtype     => 'TEST',
459
        {},
475
            rules        => {
460
        '*', '*', 'TEST', 99, 99
476
                reservesallowed  => 99,
477
                holds_per_record => 99,
478
            }
479
        }
461
    );
480
    );
462
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
481
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
463
    AddReserve( $branch_1, $borrowernumbers[0], $biblio->biblionumber, '', 1, );
482
    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 114-120 subtest 'new' => sub { Link Here
114
};
113
};
115
114
116
subtest 'find' => sub {
115
subtest 'find' => sub {
117
    plan tests => 5;
116
    plan tests => 4;
118
117
119
    # check find on a single PK
118
    # check find on a single PK
120
    my $patron = $builder->build({ source => 'Borrower' });
119
    my $patron = $builder->build({ source => 'Borrower' });
Lines 132-143 subtest 'find' => sub { Link Here
132
        { where => { surname => { '!=', $patron->{surname} }}},
131
        { where => { surname => { '!=', $patron->{surname} }}},
133
    ), undef, 'Additional where clause in find call' );
132
    ), undef, 'Additional where clause in find call' );
134
133
135
    # check find with a composite FK
136
    my $rule = $builder->build({ source => 'Issuingrule' });
137
    my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
138
    is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
139
        'Find returned a Koha object for composite primary key' );
140
141
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
134
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
142
};
135
};
143
136
(-)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 368-374 subtest 'build_object() tests' => sub { Link Here
368
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
368
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
369
369
370
    my $issuing_rule = $builder->build_object(
370
    my $issuing_rule = $builder->build_object(
371
        {   class => 'Koha::IssuingRules',
371
        {   class => 'Koha::CirculationRules',
372
            value => {
372
            value => {
373
                categorycode => $categorycode,
373
                categorycode => $categorycode,
374
                itemtype     => $itemtype
374
                itemtype     => $itemtype
Lines 376-382 subtest 'build_object() tests' => sub { Link Here
376
        }
376
        }
377
    );
377
    );
378
378
379
    is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
379
    is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
380
    is( $issuing_rule->categorycode,
380
    is( $issuing_rule->categorycode,
381
        $categorycode, 'Category code correctly set' );
381
        $categorycode, 'Category code correctly set' );
382
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
382
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
(-)a/t/db_dependent/api/v1/holds.t (-6 / +11 lines)
Lines 114-124 my $item_2 = $builder->build_sample_item({ biblionumber => $biblio_2->biblionu Link Here
114
114
115
my $dbh = C4::Context->dbh;
115
my $dbh = C4::Context->dbh;
116
$dbh->do('DELETE FROM reserves');
116
$dbh->do('DELETE FROM reserves');
117
$dbh->do('DELETE FROM issuingrules');
117
$dbh->do('DELETE FROM circulation_rules');
118
    $dbh->do(q{
118
Koha::CirculationRules->set_rules(
119
        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
119
    {
120
        VALUES (?, ?, ?, ?)
120
        categorycode => '*',
121
    }, {}, '*', '*', '*', 1);
121
        branchcode   => '*',
122
        itemtype     => '*',
123
        rules        => {
124
            reservesallowed => 1
125
        }
126
    }
127
);
122
128
123
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
129
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
124
    $biblio_1->biblionumber, undef, 1, undef, undef, undef, '', $item_1->itemnumber);
130
    $biblio_1->biblionumber, undef, 1, undef, undef, undef, '', $item_1->itemnumber);
125
- 

Return to bug 18936