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

(-)a/C4/Circulation.pm (-156 / +194 lines)
Lines 44-50 use Koha::AuthorisedValues; 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 431-448 sub TooMany { Link Here
431
            # specific rule
430
            # specific rule
432
            if (C4::Context->preference('item-level_itypes')) {
431
            if (C4::Context->preference('item-level_itypes')) {
433
                $count_query .= " WHERE items.itype NOT IN (
432
                $count_query .= " WHERE items.itype NOT IN (
434
                                    SELECT itemtype FROM issuingrules
433
                                    SELECT itemtype FROM circulation_rules
435
                                    WHERE branchcode = ?
434
                                    WHERE branchcode = ?
436
                                    AND   (categorycode = ? OR categorycode = ?)
435
                                    AND   (categorycode = ? OR categorycode = ?)
437
                                    AND   itemtype <> '*'
436
                                    AND   itemtype <> '*'
437
                                    AND   rule_name = 'maxissueqty'
438
                                  ) ";
438
                                  ) ";
439
            } else { 
439
            } else { 
440
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
440
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
441
                                  WHERE biblioitems.itemtype NOT IN (
441
                                  WHERE biblioitems.itemtype NOT IN (
442
                                    SELECT itemtype FROM issuingrules
442
                                    SELECT itemtype FROM circulation_rules
443
                                    WHERE branchcode = ?
443
                                    WHERE branchcode = ?
444
                                    AND   (categorycode = ? OR categorycode = ?)
444
                                    AND   (categorycode = ? OR categorycode = ?)
445
                                    AND   itemtype <> '*'
445
                                    AND   itemtype <> '*'
446
                                    AND   rule_name = 'maxissueqty'
446
                                  ) ";
447
                                  ) ";
447
            }
448
            }
448
            push @bind_params, $maxissueqty_rule->branchcode;
449
            push @bind_params, $maxissueqty_rule->branchcode;
Lines 1352-1365 sub AddIssue { Link Here
1352
1353
1353
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1354
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1354
            unless ($auto_renew) {
1355
            unless ($auto_renew) {
1355
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1356
                my $rule = Koha::CirculationRules->get_effective_rule(
1356
                    {   categorycode => $borrower->{categorycode},
1357
                    {
1358
                        categorycode => $borrower->{categorycode},
1357
                        itemtype     => $item->{itype},
1359
                        itemtype     => $item->{itype},
1358
                        branchcode   => $branch
1360
                        branchcode   => $branch,
1361
                        rule_name    => 'auto_renew'
1359
                    }
1362
                    }
1360
                );
1363
                );
1361
1364
1362
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1365
                $auto_renew = $rule->rule_value if $rule;
1363
            }
1366
            }
1364
1367
1365
            # Record in the database the fact that the book was issued.
1368
            # Record in the database the fact that the book was issued.
Lines 1480-1546 Get loan length for an itemtype, a borrower type and a branch Link Here
1480
=cut
1483
=cut
1481
1484
1482
sub GetLoanLength {
1485
sub GetLoanLength {
1483
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1486
    my ( $categorycode, $itemtype, $branchcode ) = @_;
1484
    my $dbh = C4::Context->dbh;
1487
1485
    my $sth = $dbh->prepare(qq{
1488
    # Set search precedences
1486
        SELECT issuelength, lengthunit, renewalperiod
1489
    my @params = (
1487
        FROM issuingrules
1490
        {
1488
        WHERE   categorycode=?
1491
            categorycode => $categorycode,
1489
            AND itemtype=?
1492
            itemtype     => $itemtype,
1490
            AND branchcode=?
1493
            branchcode   => $branchcode,
1491
            AND issuelength IS NOT NULL
1494
        },
1492
    });
1495
        {
1496
            categorycode => $categorycode,
1497
            itemtype     => '*',
1498
            branchcode   => $branchcode,
1499
        },
1500
        {
1501
            categorycode => '*',
1502
            itemtype     => $itemtype,
1503
            branchcode   => $branchcode,
1504
        },
1505
        {
1506
            categorycode => '*',
1507
            itemtype     => '*',
1508
            branchcode   => $branchcode,
1509
        },
1510
        {
1511
            categorycode => $categorycode,
1512
            itemtype     => $itemtype,
1513
            branchcode   => '*',
1514
        },
1515
        {
1516
            categorycode => $categorycode,
1517
            itemtype     => '*',
1518
            branchcode   => '*',
1519
        },
1520
        {
1521
            categorycode => '*',
1522
            itemtype     => $itemtype,
1523
            branchcode   => '*',
1524
        },
1525
        {
1526
            categorycode => '*',
1527
            itemtype     => '*',
1528
            branchcode   => '*',
1529
        },
1530
    );
1493
1531
1494
    # try to find issuelength & return the 1st available.
1532
    # Initialize default values
1495
    # check with borrowertype, itemtype and branchcode, then without one of those parameters
1533
    my $rules = {
1496
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1534
        issuelength   => 0,
1497
    my $loanlength = $sth->fetchrow_hashref;
1498
1499
    return $loanlength
1500
      if defined($loanlength) && defined $loanlength->{issuelength};
1501
1502
    $sth->execute( $borrowertype, '*', $branchcode );
1503
    $loanlength = $sth->fetchrow_hashref;
1504
    return $loanlength
1505
      if defined($loanlength) && defined $loanlength->{issuelength};
1506
1507
    $sth->execute( '*', $itemtype, $branchcode );
1508
    $loanlength = $sth->fetchrow_hashref;
1509
    return $loanlength
1510
      if defined($loanlength) && defined $loanlength->{issuelength};
1511
1512
    $sth->execute( '*', '*', $branchcode );
1513
    $loanlength = $sth->fetchrow_hashref;
1514
    return $loanlength
1515
      if defined($loanlength) && defined $loanlength->{issuelength};
1516
1517
    $sth->execute( $borrowertype, $itemtype, '*' );
1518
    $loanlength = $sth->fetchrow_hashref;
1519
    return $loanlength
1520
      if defined($loanlength) && defined $loanlength->{issuelength};
1521
1522
    $sth->execute( $borrowertype, '*', '*' );
1523
    $loanlength = $sth->fetchrow_hashref;
1524
    return $loanlength
1525
      if defined($loanlength) && defined $loanlength->{issuelength};
1526
1527
    $sth->execute( '*', $itemtype, '*' );
1528
    $loanlength = $sth->fetchrow_hashref;
1529
    return $loanlength
1530
      if defined($loanlength) && defined $loanlength->{issuelength};
1531
1532
    $sth->execute( '*', '*', '*' );
1533
    $loanlength = $sth->fetchrow_hashref;
1534
    return $loanlength
1535
      if defined($loanlength) && defined $loanlength->{issuelength};
1536
1537
    # if no rule is set => 0 day (hardcoded)
1538
    return {
1539
        issuelength => 0,
1540
        renewalperiod => 0,
1535
        renewalperiod => 0,
1541
        lengthunit => 'days',
1536
        lengthunit    => 'days',
1542
    };
1537
    };
1543
1538
1539
    # Search for rules!
1540
    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
1541
        foreach my $params (@params) {
1542
            my $rule = Koha::CirculationRules->search(
1543
                {
1544
                    rule_name => $rule_name,
1545
                    %$params,
1546
                }
1547
            )->next();
1548
1549
            if ($rule) {
1550
                $rules->{$rule_name} = $rule->rule_value;
1551
                last;
1552
            }
1553
        }
1554
    }
1555
1556
    return $rules;
1544
}
1557
}
1545
1558
1546
1559
Lines 1555-1573 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1555
sub GetHardDueDate {
1568
sub GetHardDueDate {
1556
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1569
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1557
1570
1558
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1571
    my $rules = Koha::CirculationRules->get_effective_rules(
1559
        {   categorycode => $borrowertype,
1572
        {
1573
            categorycode => $borrowertype,
1560
            itemtype     => $itemtype,
1574
            itemtype     => $itemtype,
1561
            branchcode   => $branchcode
1575
            branchcode   => $branchcode,
1576
            rules        => [ 'hardduedate', 'hardduedatecompare' ],
1562
        }
1577
        }
1563
    );
1578
    );
1564
1579
1565
1580
    if ( defined( $rules->{hardduedate} ) ) {
1566
    if ( defined( $issuing_rule ) ) {
1581
        if ( $rules->{hardduedate} ) {
1567
        if ( $issuing_rule->hardduedate ) {
1582
            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
1568
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1583
        }
1569
        } else {
1584
        else {
1570
            return (undef, undef);
1585
            return ( undef, undef );
1571
        }
1586
        }
1572
    }
1587
    }
1573
}
1588
}
Lines 2269-2282 sub _debar_user_on_return { Link Here
2269
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2284
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2270
2285
2271
    my $circcontrol = C4::Context->preference('CircControl');
2286
    my $circcontrol = C4::Context->preference('CircControl');
2272
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2287
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2273
        {   categorycode => $borrower->{categorycode},
2288
        {   categorycode => $borrower->{categorycode},
2274
            itemtype     => $item->{itype},
2289
            itemtype     => $item->{itype},
2275
            branchcode   => $branchcode
2290
            branchcode   => $branchcode,
2291
            rules => [
2292
                'finedays',
2293
                'lengthunit',
2294
                'firstremind',
2295
                'maxsuspensiondays',
2296
            ]
2276
        }
2297
        }
2277
    );
2298
    );
2278
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2299
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2279
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2300
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2280
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2301
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2281
2302
2282
    if ($finedays) {
2303
    if ($finedays) {
Lines 2287-2293 sub _debar_user_on_return { Link Here
2287
2308
2288
        # grace period is measured in the same units as the loan
2309
        # grace period is measured in the same units as the loan
2289
        my $grace =
2310
        my $grace =
2290
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2311
          DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
2291
2312
2292
        my $deltadays = DateTime::Duration->new(
2313
        my $deltadays = DateTime::Duration->new(
2293
            days => $chargeable_units
2314
            days => $chargeable_units
Lines 2297-2303 sub _debar_user_on_return { Link Here
2297
2318
2298
            # If the max suspension days is < than the suspension days
2319
            # If the max suspension days is < than the suspension days
2299
            # the suspension days is limited to this maximum period.
2320
            # the suspension days is limited to this maximum period.
2300
            my $max_sd = $issuing_rule->maxsuspensiondays;
2321
            my $max_sd = $issuing_rule->{maxsuspensiondays};
2301
            if ( defined $max_sd ) {
2322
            if ( defined $max_sd ) {
2302
                $max_sd = DateTime::Duration->new( days => $max_sd );
2323
                $max_sd = DateTime::Duration->new( days => $max_sd );
2303
                $suspension_days = $max_sd
2324
                $suspension_days = $max_sd
Lines 2729-2743 sub CanBookBeRenewed { Link Here
2729
    return ( 1, undef ) if $override_limit;
2750
    return ( 1, undef ) if $override_limit;
2730
2751
2731
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2752
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2732
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2753
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2733
        {   categorycode => $patron->categorycode,
2754
        {
2755
            categorycode => $patron->categorycode,
2734
            itemtype     => $item->{itype},
2756
            itemtype     => $item->{itype},
2735
            branchcode   => $branchcode
2757
            branchcode   => $branchcode,
2758
            rules => [
2759
                'renewalsallowed',
2760
                'no_auto_renewal_after',
2761
                'no_auto_renewal_after_hard_limit',
2762
                'lengthunit',
2763
                'norenewalbefore',
2764
            ]
2736
        }
2765
        }
2737
    );
2766
    );
2738
2767
2739
    return ( 0, "too_many" )
2768
    return ( 0, "too_many" )
2740
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2769
      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
2741
2770
2742
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2771
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2743
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2772
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2752-2774 sub CanBookBeRenewed { Link Here
2752
    }
2781
    }
2753
2782
2754
    if ( $issue->auto_renew ) {
2783
    if ( $issue->auto_renew ) {
2755
        if ( defined $issuing_rule->no_auto_renewal_after
2784
        if ( defined $issuing_rule->{no_auto_renewal_after}
2756
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2785
                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
2757
            # Get issue_date and add no_auto_renewal_after
2786
            # Get issue_date and add no_auto_renewal_after
2758
            # If this is greater than today, it's too late for renewal.
2787
            # If this is greater than today, it's too late for renewal.
2759
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2788
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2760
            $maximum_renewal_date->add(
2789
            $maximum_renewal_date->add(
2761
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2790
                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
2762
            );
2791
            );
2763
            my $now = dt_from_string;
2792
            my $now = dt_from_string;
2764
            if ( $now >= $maximum_renewal_date ) {
2793
            if ( $now >= $maximum_renewal_date ) {
2765
                return ( 0, "auto_too_late" );
2794
                return ( 0, "auto_too_late" );
2766
            }
2795
            }
2767
        }
2796
        }
2768
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2797
        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
2769
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2798
                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
2770
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2799
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2771
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2800
            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
2772
                return ( 0, "auto_too_late" );
2801
                return ( 0, "auto_too_late" );
2773
            }
2802
            }
2774
        }
2803
        }
Lines 2782-2798 sub CanBookBeRenewed { Link Here
2782
        }
2811
        }
2783
    }
2812
    }
2784
2813
2785
    if ( defined $issuing_rule->norenewalbefore
2814
    if ( defined $issuing_rule->{norenewalbefore}
2786
        and $issuing_rule->norenewalbefore ne "" )
2815
        and $issuing_rule->{norenewalbefore} ne "" )
2787
    {
2816
    {
2788
2817
2789
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2818
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2790
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2819
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2791
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2820
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
2792
2821
2793
        # Depending on syspref reset the exact time, only check the date
2822
        # Depending on syspref reset the exact time, only check the date
2794
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2823
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2795
            and $issuing_rule->lengthunit eq 'days' )
2824
            and $issuing_rule->{lengthunit} eq 'days' )
2796
        {
2825
        {
2797
            $soonestrenewal->truncate( to => 'day' );
2826
            $soonestrenewal->truncate( to => 'day' );
2798
        }
2827
        }
Lines 2999-3012 sub GetRenewCount { Link Here
2999
    # $item and $borrower should be calculated
3028
    # $item and $borrower should be calculated
3000
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
3029
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
3001
3030
3002
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3031
    my $rule = Koha::CirculationRules->get_effective_rule(
3003
        {   categorycode => $patron->categorycode,
3032
        {
3033
            categorycode => $patron->categorycode,
3004
            itemtype     => $item->{itype},
3034
            itemtype     => $item->{itype},
3005
            branchcode   => $branchcode
3035
            branchcode   => $branchcode,
3036
            rule_name    => 'renewalsallowed',
3006
        }
3037
        }
3007
    );
3038
    );
3008
3039
3009
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
3040
    $renewsallowed = $rule ? $rule->rule_value : 0;
3010
    $renewsleft    = $renewsallowed - $renewcount;
3041
    $renewsleft    = $renewsallowed - $renewcount;
3011
    if($renewsleft < 0){ $renewsleft = 0; }
3042
    if($renewsleft < 0){ $renewsleft = 0; }
3012
    return ( $renewcount, $renewsallowed, $renewsleft );
3043
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3044-3068 sub GetSoonestRenewDate { Link Here
3044
      or return;
3075
      or return;
3045
3076
3046
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3077
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3047
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3078
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3048
        {   categorycode => $patron->categorycode,
3079
        {   categorycode => $patron->categorycode,
3049
            itemtype     => $item->{itype},
3080
            itemtype     => $item->{itype},
3050
            branchcode   => $branchcode
3081
            branchcode   => $branchcode,
3082
            rules => [
3083
                'norenewalbefore',
3084
                'lengthunit',
3085
            ]
3051
        }
3086
        }
3052
    );
3087
    );
3053
3088
3054
    my $now = dt_from_string;
3089
    my $now = dt_from_string;
3055
    return $now unless $issuing_rule;
3090
    return $now unless $issuing_rule;
3056
3091
3057
    if ( defined $issuing_rule->norenewalbefore
3092
    if ( defined $issuing_rule->{norenewalbefore}
3058
        and $issuing_rule->norenewalbefore ne "" )
3093
        and $issuing_rule->{norenewalbefore} ne "" )
3059
    {
3094
    {
3060
        my $soonestrenewal =
3095
        my $soonestrenewal =
3061
          dt_from_string( $itemissue->date_due )->subtract(
3096
          dt_from_string( $itemissue->date_due )->subtract(
3062
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3097
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3063
3098
3064
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3099
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3065
            and $issuing_rule->lengthunit eq 'days' )
3100
            and $issuing_rule->{lengthunit} eq 'days' )
3066
        {
3101
        {
3067
            $soonestrenewal->truncate( to => 'day' );
3102
            $soonestrenewal->truncate( to => 'day' );
3068
        }
3103
        }
Lines 3103-3132 sub GetLatestAutoRenewDate { Link Here
3103
      or return;
3138
      or return;
3104
3139
3105
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3140
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3106
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3141
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3107
        {   categorycode => $patron->categorycode,
3142
        {
3143
            categorycode => $patron->categorycode,
3108
            itemtype     => $item->{itype},
3144
            itemtype     => $item->{itype},
3109
            branchcode   => $branchcode
3145
            branchcode   => $branchcode,
3146
            rules => [
3147
                'no_auto_renewal_after',
3148
                'no_auto_renewal_after_hard_limit',
3149
                'lengthunit',
3150
            ]
3110
        }
3151
        }
3111
    );
3152
    );
3112
3153
3113
    return unless $issuing_rule;
3154
    return unless $circulation_rules;
3114
    return
3155
    return
3115
      if ( not $issuing_rule->no_auto_renewal_after
3156
      if ( not $circulation_rules->{no_auto_renewal_after}
3116
            or $issuing_rule->no_auto_renewal_after eq '' )
3157
            or $circulation_rules->{no_auto_renewal_after} eq '' )
3117
      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
3158
      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
3118
             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
3159
             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
3119
3160
3120
    my $maximum_renewal_date;
3161
    my $maximum_renewal_date;
3121
    if ( $issuing_rule->no_auto_renewal_after ) {
3162
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3122
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3163
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3123
        $maximum_renewal_date->add(
3164
        $maximum_renewal_date->add(
3124
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3165
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3125
        );
3166
        );
3126
    }
3167
    }
3127
3168
3128
    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
3169
    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
3129
        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
3170
        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
3130
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3171
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3131
    }
3172
    }
3132
    return $maximum_renewal_date;
3173
    return $maximum_renewal_date;
Lines 3173-3191 sub GetIssuingCharges { Link Here
3173
        $item_type = $item_data->{itemtype};
3214
        $item_type = $item_data->{itemtype};
3174
        $charge    = $item_data->{rentalcharge};
3215
        $charge    = $item_data->{rentalcharge};
3175
        my $branch = C4::Context::mybranch();
3216
        my $branch = C4::Context::mybranch();
3176
        my $discount_query = q|SELECT rentaldiscount,
3217
        my $patron = Koha::Patrons->find( $borrowernumber );
3177
            issuingrules.itemtype, issuingrules.branchcode
3218
        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
3178
            FROM borrowers
3219
        if ($discount) {
3179
            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
3180
            WHERE borrowers.borrowernumber = ?
3181
            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
3182
            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
3183
        my $discount_sth = $dbh->prepare($discount_query);
3184
        $discount_sth->execute( $borrowernumber, $item_type, $branch );
3185
        my $discount_rules = $discount_sth->fetchall_arrayref({});
3186
        if (@{$discount_rules}) {
3187
            # We may have multiple rules so get the most specific
3220
            # We may have multiple rules so get the most specific
3188
            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
3189
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3221
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3190
        }
3222
        }
3191
        if ($charge) {
3223
        if ($charge) {
Lines 3198-3234 sub GetIssuingCharges { Link Here
3198
3230
3199
# Select most appropriate discount rule from those returned
3231
# Select most appropriate discount rule from those returned
3200
sub _get_discount_from_rule {
3232
sub _get_discount_from_rule {
3201
    my ($rules_ref, $branch, $itemtype) = @_;
3233
    my ($categorycode, $branchcode, $itemtype) = @_;
3202
    my $discount;
3203
3234
3204
    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
3235
    # Set search precedences
3205
        $discount = $rules_ref->[0]->{rentaldiscount};
3236
    my @params = (
3206
        return (defined $discount) ? $discount : 0;
3237
        {
3207
    }
3238
            branchcode   => $branchcode,
3208
    # could have up to 4 does one match $branch and $itemtype
3239
            itemtype     => $itemtype,
3209
    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
3240
            categorycode => $categorycode,
3210
    if (@d) {
3241
        },
3211
        $discount = $d[0]->{rentaldiscount};
3242
        {
3212
        return (defined $discount) ? $discount : 0;
3243
            branchcode   => '*',
3213
    }
3244
            categorycode => $categorycode,
3214
    # do we have item type + all branches
3245
            itemtype     => $itemtype,
3215
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
3246
        },
3216
    if (@d) {
3247
        {
3217
        $discount = $d[0]->{rentaldiscount};
3248
            branchcode   => $branchcode,
3218
        return (defined $discount) ? $discount : 0;
3249
            categorycode => $categorycode,
3219
    }
3250
            itemtype     => '*',
3220
    # do we all item types + this branch
3251
        },
3221
    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
3252
        {
3222
    if (@d) {
3253
            branchcode   => '*',
3223
        $discount = $d[0]->{rentaldiscount};
3254
            categorycode => $categorycode,
3224
        return (defined $discount) ? $discount : 0;
3255
            itemtype     => '*',
3225
    }
3256
        },
3226
    # so all and all (surely we wont get here)
3257
    );
3227
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
3258
3228
    if (@d) {
3259
    foreach my $params (@params) {
3229
        $discount = $d[0]->{rentaldiscount};
3260
        my $rule = Koha::CirculationRules->search(
3230
        return (defined $discount) ? $discount : 0;
3261
            {
3262
                rule_name => 'rentaldiscount',
3263
                %$params,
3264
            }
3265
        )->next();
3266
3267
        return $rule->rule_value if $rule;
3231
    }
3268
    }
3269
3232
    # none of the above
3270
    # none of the above
3233
    return 0;
3271
    return 0;
3234
}
3272
}
(-)a/C4/Overdues.pm (-11 / +26 lines)
Lines 36-42 use C4::Debug; Link Here
36
use Koha::DateUtils;
36
use Koha::DateUtils;
37
use Koha::Account::Line;
37
use Koha::Account::Line;
38
use Koha::Account::Lines;
38
use Koha::Account::Lines;
39
use Koha::IssuingRules;
40
use Koha::Libraries;
39
use Koha::Libraries;
41
40
42
use vars qw(@ISA @EXPORT);
41
use vars qw(@ISA @EXPORT);
Lines 248-275 sub CalcFine { Link Here
248
    my $start_date = $due_dt->clone();
247
    my $start_date = $due_dt->clone();
249
    # get issuingrules (fines part will be used)
248
    # get issuingrules (fines part will be used)
250
    my $itemtype = $item->{itemtype} || $item->{itype};
249
    my $itemtype = $item->{itemtype} || $item->{itype};
251
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
250
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
251
        {
252
            categorycode => $bortype,
253
            itemtype     => $itemtype,
254
            branchcode   => $branchcode,
255
            rules => [
256
                'lengthunit',
257
                'firstremind',
258
                'chargeperiod',
259
                'chargeperiod_charge_at',
260
                'fine',
261
                'overduefinescap',
262
                'cap_fine_to_replacement_price',
263
                'chargename',
264
            ]
265
        }
266
    );
252
267
253
    return unless $issuing_rule; # If not rule exist, there is no fine
268
    return unless $issuing_rule; # If not rule exist, there is no fine
254
269
255
    my $fine_unit = $issuing_rule->lengthunit || 'days';
270
    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
256
271
257
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
272
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
258
    my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
273
    my $units_minus_grace = $chargeable_units - $issuing_rule->{firstremind};
259
    my $amount = 0;
274
    my $amount = 0;
260
    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
275
    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
261
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
276
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
262
        my $charge_periods = $units / $issuing_rule->chargeperiod;
277
        my $charge_periods = $units / $issuing_rule->{chargeperiod};
263
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
278
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
264
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
279
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
265
        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
280
        $charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
266
        $amount = $charge_periods * $issuing_rule->fine;
281
        $amount = $charge_periods * $issuing_rule->{fine};
267
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
282
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
268
283
269
    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
284
    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
270
    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
285
    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
271
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
286
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
272
    return ($amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
287
    return ($amount, $issuing_rule->{chargename}, $units_minus_grace, $chargeable_units);
273
    # FIXME: chargename is NEVER populated anywhere.
288
    # FIXME: chargename is NEVER populated anywhere.
274
}
289
}
275
290
(-)a/C4/Reserves.pm (-18 / +39 lines)
Lines 44-50 use Koha::Hold; Link Here
44
use Koha::Old::Hold;
44
use Koha::Old::Hold;
45
use Koha::Holds;
45
use Koha::Holds;
46
use Koha::Libraries;
46
use Koha::Libraries;
47
use Koha::IssuingRules;
48
use Koha::Items;
47
use Koha::Items;
49
use Koha::ItemTypes;
48
use Koha::ItemTypes;
50
use Koha::Patrons;
49
use Koha::Patrons;
Lines 1428-1437 sub _get_itype { Link Here
1428
}
1427
}
1429
1428
1430
sub _OnShelfHoldsAllowed {
1429
sub _OnShelfHoldsAllowed {
1431
    my ($itype,$borrowercategory,$branchcode) = @_;
1430
    my ( $itype, $borrowercategory, $branchcode ) = @_;
1432
1431
1433
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowercategory, itemtype => $itype, branchcode => $branchcode });
1432
    my $rule = Koha::CirculationRules->get_effective_rule(
1434
    return $issuing_rule ? $issuing_rule->onshelfholds : undef;
1433
        {
1434
            categorycode => $borrowercategory,
1435
            itemtype     => $itype,
1436
            branchcode   => $branchcode,
1437
            rule_name    => 'onshelfholds',
1438
        }
1439
    );
1440
    return $rule ? $rule->rule_value : undef;
1435
}
1441
}
1436
1442
1437
=head2 AlterPriority
1443
=head2 AlterPriority
Lines 2369-2392 patron category, itemtype, and library. Link Here
2369
sub GetHoldRule {
2375
sub GetHoldRule {
2370
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2376
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2371
2377
2372
    my $dbh = C4::Context->dbh;
2378
    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
2373
2379
        {
2374
    my $sth = $dbh->prepare(
2380
            itemtype     => $itemtype,
2375
        q{
2381
            categorycode => $categorycode,
2376
         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record
2382
            branchcode   => $branchcode,
2377
           FROM issuingrules
2383
            rule_name    => 'reservesallowed',
2378
          WHERE (categorycode in (?,'*') )
2384
            order_by     => {
2379
            AND (itemtype IN (?,'*'))
2385
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2380
            AND (branchcode IN (?,'*'))
2386
            }
2381
       ORDER BY categorycode DESC,
2382
                itemtype     DESC,
2383
                branchcode   DESC
2384
        }
2387
        }
2385
    );
2388
    );
2389
    return unless $reservesallowed;;
2386
2390
2387
    $sth->execute( $categorycode, $itemtype, $branchcode );
2391
    my $rules;
2392
    $rules->{reservesallowed} = $reservesallowed->rule_value;
2393
    $rules->{itemtype}        = $reservesallowed->itemtype;
2394
    $rules->{categorycode}    = $reservesallowed->categorycode;
2395
    $rules->{branchcode}      = $reservesallowed->branchcode;
2388
2396
2389
    return $sth->fetchrow_hashref();
2397
    my $holds_per_record = Koha::CirculationRules->get_effective_rule(
2398
        {
2399
            itemtype     => $itemtype,
2400
            categorycode => $categorycode,
2401
            branchcode   => $branchcode,
2402
            rule_name    => 'holds_per_record',
2403
            order_by     => {
2404
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2405
            }
2406
        }
2407
    );
2408
    $rules->{holds_per_record} = $holds_per_record->rule_value if $holds_per_record;
2409
2410
    return $rules;
2390
}
2411
}
2391
2412
2392
=head1 AUTHOR
2413
=head1 AUTHOR
(-)a/Koha/Biblio.pm (-4 / +10 lines)
Lines 32-38 use Koha::Items; Link Here
32
use Koha::Biblioitems;
32
use Koha::Biblioitems;
33
use Koha::ArticleRequests;
33
use Koha::ArticleRequests;
34
use Koha::ArticleRequest::Status;
34
use Koha::ArticleRequest::Status;
35
use Koha::IssuingRules;
35
use Koha::CirculationRules;
36
use Koha::Subscriptions;
36
use Koha::Subscriptions;
37
37
38
=head1 NAME
38
=head1 NAME
Lines 123-132 sub article_request_type_for_bib { Link Here
123
    my $borrowertype = $borrower->categorycode;
123
    my $borrowertype = $borrower->categorycode;
124
    my $itemtype     = $self->itemtype();
124
    my $itemtype     = $self->itemtype();
125
125
126
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
126
    my $rule = Koha::CirculationRules->get_effective_rule(
127
        {
128
            rule_name    => 'article_requests',
129
            categorycode => $borrowertype,
130
            itemtype     => $itemtype,
131
        }
132
    );
127
133
128
    return q{} unless $issuing_rule;
134
    return q{} unless $rule;
129
    return $issuing_rule->article_requests || q{}
135
    return $rule->rule_value || q{}
130
}
136
}
131
137
132
=head3 article_request_type_for_items
138
=head3 article_request_type_for_items
(-)a/Koha/CirculationRules.pm (-6 / +39 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 28-34 use base qw(Koha::Objects); Link Here
28
27
29
=head1 NAME
28
=head1 NAME
30
29
31
Koha::IssuingRules - Koha IssuingRule Object set class
30
Koha::CirculationRules - Koha CirculationRule Object set class
32
31
33
=head1 API
32
=head1 API
34
33
Lines 43-53 Koha::IssuingRules - Koha IssuingRule Object set class Link Here
43
sub get_effective_rule {
42
sub get_effective_rule {
44
    my ( $self, $params ) = @_;
43
    my ( $self, $params ) = @_;
45
44
45
    $params->{categorycode} = '*' if exists($params->{categorycode}) && !defined($params->{categorycode});
46
    $params->{branchcode}   = '*' if exists($params->{branchcode})   && !defined($params->{branchcode});
47
    $params->{itemtype}     = '*' if exists($params->{itemtype})     && !defined($params->{itemtype});
48
46
    my $rule_name    = $params->{rule_name};
49
    my $rule_name    = $params->{rule_name};
47
    my $categorycode = $params->{categorycode};
50
    my $categorycode = $params->{categorycode};
48
    my $itemtype     = $params->{itemtype};
51
    my $itemtype     = $params->{itemtype};
49
    my $branchcode   = $params->{branchcode};
52
    my $branchcode   = $params->{branchcode};
50
53
54
    my $order_by = $params->{order_by}
55
      // { -desc => [ 'branchcode', 'categorycode', 'itemtype' ] };
56
51
    croak q{No rule name passed in!} unless $rule_name;
57
    croak q{No rule name passed in!} unless $rule_name;
52
58
53
    my $search_params;
59
    my $search_params;
Lines 60-68 sub get_effective_rule { Link Here
60
    my $rule = $self->search(
66
    my $rule = $self->search(
61
        $search_params,
67
        $search_params,
62
        {
68
        {
63
            order_by => {
69
            order_by => $order_by,
64
                -desc => [ 'branchcode', 'categorycode', 'itemtype' ]
65
            },
66
            rows => 1,
70
            rows => 1,
67
        }
71
        }
68
    )->single;
72
    )->single;
Lines 70-75 sub get_effective_rule { Link Here
70
    return $rule;
74
    return $rule;
71
}
75
}
72
76
77
=head3 get_effective_rule
78
79
=cut
80
81
sub get_effective_rules {
82
    my ( $self, $params ) = @_;
83
84
    my $rules        = $params->{rules};
85
    my $categorycode = $params->{categorycode};
86
    my $itemtype     = $params->{itemtype};
87
    my $branchcode   = $params->{branchcode};
88
89
    my $r;
90
    foreach my $rule (@$rules) {
91
        my $effective_rule = $self->get_effective_rule(
92
            {
93
                rule_name    => $rule,
94
                categorycode => $categorycode,
95
                itemtype     => $itemtype,
96
                branchcode   => $branchcode,
97
            }
98
        );
99
100
        $r->{$rule} = $effective_rule->rule_value if $effective_rule;
101
    }
102
103
    return $r;
104
}
105
73
=head3 set_rule
106
=head3 set_rule
74
107
75
=cut
108
=cut
(-)a/Koha/IssuingRule.pm (-42 lines)
Lines 1-42 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 type
35
36
=cut
37
38
sub _type {
39
    return 'Issuingrule';
40
}
41
42
1;
(-)a/Koha/IssuingRules.pm (-86 lines)
Lines 1-86 Link Here
1
package Koha::IssuingRules;
2
3
# Copyright Vaara-kirjastot 2015
4
# Copyright Koha Development Team 2016
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 3 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
use Modern::Perl;
22
23
use Koha::Database;
24
25
use Koha::IssuingRule;
26
27
use base qw(Koha::Objects);
28
29
=head1 NAME
30
31
Koha::IssuingRules - Koha IssuingRule Object set class
32
33
=head1 API
34
35
=head2 Class Methods
36
37
=cut
38
39
sub get_effective_issuing_rule {
40
    my ( $self, $params ) = @_;
41
42
    my $default      = '*';
43
    my $categorycode = $params->{categorycode};
44
    my $itemtype     = $params->{itemtype};
45
    my $branchcode   = $params->{branchcode};
46
47
    my $search_categorycode = $default;
48
    my $search_itemtype     = $default;
49
    my $search_branchcode   = $default;
50
51
    if ($categorycode) {
52
        $search_categorycode = { 'in' => [ $categorycode, $default ] };
53
    }
54
    if ($itemtype) {
55
        $search_itemtype = { 'in' => [ $itemtype, $default ] };
56
    }
57
    if ($branchcode) {
58
        $search_branchcode = { 'in' => [ $branchcode, $default ] };
59
    }
60
61
    my $rule = $self->search({
62
        categorycode => $search_categorycode,
63
        itemtype     => $search_itemtype,
64
        branchcode   => $search_branchcode,
65
    }, {
66
        order_by => {
67
            -desc => ['branchcode', 'categorycode', 'itemtype']
68
        },
69
        rows => 1,
70
    })->single;
71
    return $rule;
72
}
73
74
=head3 type
75
76
=cut
77
78
sub _type {
79
    return 'Issuingrule';
80
}
81
82
sub object_class {
83
    return 'Koha::IssuingRule';
84
}
85
86
1;
(-)a/Koha/Item.pm (-4 / +11 lines)
Lines 26-32 use Koha::DateUtils qw( dt_from_string ); Link Here
26
26
27
use C4::Context;
27
use C4::Context;
28
use Koha::Checkouts;
28
use Koha::Checkouts;
29
use Koha::IssuingRules;
29
use Koha::CirculationRules;
30
use Koha::Item::Transfer;
30
use Koha::Item::Transfer;
31
use Koha::Patrons;
31
use Koha::Patrons;
32
use Koha::Libraries;
32
use Koha::Libraries;
Lines 209-218 sub article_request_type { Link Here
209
      :                                      undef;
209
      :                                      undef;
210
    my $borrowertype = $borrower->categorycode;
210
    my $borrowertype = $borrower->categorycode;
211
    my $itemtype = $self->effective_itemtype();
211
    my $itemtype = $self->effective_itemtype();
212
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype, branchcode => $branchcode });
212
    my $rule = Koha::CirculationRules->get_effective_rule(
213
        {
214
            rule_name    => 'article_requests',
215
            categorycode => $borrowertype,
216
            itemtype     => $itemtype,
217
            branchcode   => $branchcode
218
        }
219
    );
213
220
214
    return q{} unless $issuing_rule;
221
    return q{} unless $rule;
215
    return $issuing_rule->article_requests || q{}
222
    return $rule->rule_value || q{}
216
}
223
}
217
224
218
=head3 current_holds
225
=head3 current_holds
(-)a/Koha/Schema/Result/Issuingrule.pm (-307 lines)
Lines 1-307 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 firstremind
74
75
  data_type: 'integer'
76
  is_nullable: 1
77
78
=head2 chargeperiod
79
80
  data_type: 'integer'
81
  is_nullable: 1
82
83
=head2 chargeperiod_charge_at
84
85
  data_type: 'tinyint'
86
  default_value: 0
87
  is_nullable: 0
88
89
=head2 accountsent
90
91
  data_type: 'integer'
92
  is_nullable: 1
93
94
=head2 chargename
95
96
  data_type: 'varchar'
97
  is_nullable: 1
98
  size: 100
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 branchcode
170
171
  data_type: 'varchar'
172
  default_value: (empty string)
173
  is_nullable: 0
174
  size: 10
175
176
=head2 overduefinescap
177
178
  data_type: 'decimal'
179
  is_nullable: 1
180
  size: [28,6]
181
182
=head2 cap_fine_to_replacement_price
183
184
  data_type: 'tinyint'
185
  default_value: 0
186
  is_nullable: 0
187
188
=head2 onshelfholds
189
190
  data_type: 'tinyint'
191
  default_value: 0
192
  is_nullable: 0
193
194
=head2 opacitemholds
195
196
  data_type: 'char'
197
  default_value: 'N'
198
  is_nullable: 0
199
  size: 1
200
201
=head2 article_requests
202
203
  data_type: 'enum'
204
  default_value: 'no'
205
  extra: {list => ["no","yes","bib_only","item_only"]}
206
  is_nullable: 0
207
208
=cut
209
210
__PACKAGE__->add_columns(
211
  "categorycode",
212
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
213
  "itemtype",
214
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
215
  "restrictedtype",
216
  { data_type => "tinyint", is_nullable => 1 },
217
  "rentaldiscount",
218
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
219
  "reservecharge",
220
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
221
  "fine",
222
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
223
  "finedays",
224
  { data_type => "integer", is_nullable => 1 },
225
  "maxsuspensiondays",
226
  { data_type => "integer", is_nullable => 1 },
227
  "firstremind",
228
  { data_type => "integer", is_nullable => 1 },
229
  "chargeperiod",
230
  { data_type => "integer", is_nullable => 1 },
231
  "chargeperiod_charge_at",
232
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
233
  "accountsent",
234
  { data_type => "integer", is_nullable => 1 },
235
  "chargename",
236
  { data_type => "varchar", is_nullable => 1, size => 100 },
237
  "issuelength",
238
  { data_type => "integer", is_nullable => 1 },
239
  "lengthunit",
240
  {
241
    data_type => "varchar",
242
    default_value => "days",
243
    is_nullable => 1,
244
    size => 10,
245
  },
246
  "hardduedate",
247
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
248
  "hardduedatecompare",
249
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
250
  "renewalsallowed",
251
  { data_type => "smallint", default_value => 0, is_nullable => 0 },
252
  "renewalperiod",
253
  { data_type => "integer", is_nullable => 1 },
254
  "norenewalbefore",
255
  { data_type => "integer", is_nullable => 1 },
256
  "auto_renew",
257
  { data_type => "tinyint", default_value => 0, is_nullable => 1 },
258
  "no_auto_renewal_after",
259
  { data_type => "integer", is_nullable => 1 },
260
  "no_auto_renewal_after_hard_limit",
261
  { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 },
262
  "reservesallowed",
263
  { data_type => "smallint", default_value => 0, is_nullable => 0 },
264
  "holds_per_record",
265
  { data_type => "smallint", default_value => 1, is_nullable => 0 },
266
  "branchcode",
267
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 10 },
268
  "overduefinescap",
269
  { data_type => "decimal", is_nullable => 1, size => [28, 6] },
270
  "cap_fine_to_replacement_price",
271
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
272
  "onshelfholds",
273
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
274
  "opacitemholds",
275
  { data_type => "char", default_value => "N", is_nullable => 0, size => 1 },
276
  "article_requests",
277
  {
278
    data_type => "enum",
279
    default_value => "no",
280
    extra => { list => ["no", "yes", "bib_only", "item_only"] },
281
    is_nullable => 0,
282
  },
283
);
284
285
=head1 PRIMARY KEY
286
287
=over 4
288
289
=item * L</branchcode>
290
291
=item * L</categorycode>
292
293
=item * L</itemtype>
294
295
=back
296
297
=cut
298
299
__PACKAGE__->set_primary_key("branchcode", "categorycode", "itemtype");
300
301
302
# Created by DBIx::Class::Schema::Loader v0.07042 @ 2017-07-03 15:35:15
303
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dxv4gdxTEP+dd6MY0Y/lcw
304
305
306
# You can replace this text with custom code or comments, and it will be preserved on regeneration
307
1;
(-)a/admin/smart-rules.pl (-61 / +40 lines)
Lines 27-34 use C4::Koha; Link Here
27
use C4::Debug;
27
use C4::Debug;
28
use Koha::DateUtils;
28
use Koha::DateUtils;
29
use Koha::Database;
29
use Koha::Database;
30
use Koha::IssuingRule;
31
use Koha::IssuingRules;
32
use Koha::Logger;
30
use Koha::Logger;
33
use Koha::RefundLostItemFeeRules;
31
use Koha::RefundLostItemFeeRules;
34
use Koha::Libraries;
32
use Koha::Libraries;
Lines 70-77 if ($op eq 'delete') { Link Here
70
    my $categorycode = $input->param('categorycode');
68
    my $categorycode = $input->param('categorycode');
71
    $debug and warn "deleting $1 $2 $branch";
69
    $debug and warn "deleting $1 $2 $branch";
72
70
73
    my $sth_Idelete = $dbh->prepare("delete from issuingrules where branchcode=? and categorycode=? and itemtype=?");
71
    Koha::CirculationRules->set_rules(
74
    $sth_Idelete->execute($branch, $categorycode, $itemtype);
72
        {
73
            categorycode => $categorycode,
74
            branchcode   => $branch,
75
            itemtype     => $itemtype,
76
            rules        => {
77
                restrictedtype                   => undef,
78
                rentaldiscount                   => undef,
79
                fine                             => undef,
80
                finedays                         => undef,
81
                maxsuspensiondays                => undef,
82
                firstremind                      => undef,
83
                chargeperiod                     => undef,
84
                chargeperiod_charge_at           => undef,
85
                accountsent                      => undef,
86
                issuelength                      => undef,
87
                lengthunit                       => undef,
88
                hardduedate                      => undef,
89
                hardduedatecompare               => undef,
90
                renewalsallowed                  => undef,
91
                renewalperiod                    => undef,
92
                norenewalbefore                  => undef,
93
                auto_renew                       => undef,
94
                no_auto_renewal_after            => undef,
95
                no_auto_renewal_after_hard_limit => undef,
96
                reservesallowed                  => undef,
97
                holds_per_record                 => undef,
98
                overduefinescap                  => undef,
99
                cap_fine_to_replacement_price    => undef,
100
                onshelfholds                     => undef,
101
                opacitemholds                    => undef,
102
                article_requests                 => undef,
103
            }
104
        }
105
    );
75
}
106
}
76
elsif ($op eq 'delete-branch-cat') {
107
elsif ($op eq 'delete-branch-cat') {
77
    my $categorycode  = $input->param('categorycode');
108
    my $categorycode  = $input->param('categorycode');
Lines 272-284 elsif ($op eq 'add') { Link Here
272
        article_requests              => $article_requests,
303
        article_requests              => $article_requests,
273
    };
304
    };
274
305
275
    my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
276
    if ($issuingrule) {
277
        $issuingrule->set($params)->store();
278
    } else {
279
        Koha::IssuingRule->new()->set($params)->store();
280
    }
281
282
    Koha::CirculationRules->set_rules(
306
    Koha::CirculationRules->set_rules(
283
        {
307
        {
284
            categorycode => $bor,
308
            categorycode => $bor,
Lines 287-292 elsif ($op eq 'add') { Link Here
287
            rules        => {
311
            rules        => {
288
                maxissueqty       => $maxissueqty,
312
                maxissueqty       => $maxissueqty,
289
                maxonsiteissueqty => $maxonsiteissueqty,
313
                maxonsiteissueqty => $maxonsiteissueqty,
314
                %$params,
290
            }
315
            }
291
        }
316
        }
292
    );
317
    );
Lines 511-572 $template->param( Link Here
511
536
512
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
537
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
513
538
514
my @row_loop;
515
my $itemtypes = Koha::ItemTypes->search_with_localization;
539
my $itemtypes = Koha::ItemTypes->search_with_localization;
516
540
517
my $sth2 = $dbh->prepare("
518
    SELECT  issuingrules.*,
519
            itemtypes.description AS humanitemtype,
520
            categories.description AS humancategorycode,
521
            COALESCE( localization.translation, itemtypes.description ) AS translated_description
522
    FROM issuingrules
523
    LEFT JOIN itemtypes
524
        ON (itemtypes.itemtype = issuingrules.itemtype)
525
    LEFT JOIN categories
526
        ON (categories.categorycode = issuingrules.categorycode)
527
    LEFT JOIN localization ON issuingrules.itemtype = localization.code
528
        AND localization.entity = 'itemtypes'
529
        AND localization.lang = ?
530
    WHERE issuingrules.branchcode = ?
531
");
532
$sth2->execute($language, $branch);
533
534
while (my $row = $sth2->fetchrow_hashref) {
535
    $row->{'current_branch'} ||= $row->{'branchcode'};
536
    $row->{humanitemtype} ||= $row->{itemtype};
537
    $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
538
    $row->{'humancategorycode'} ||= $row->{'categorycode'};
539
    $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
540
    $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
541
    if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
542
       my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
543
       $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
544
       $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
545
       $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
546
       $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
547
    } else {
548
       $row->{'hardduedate'} = 0;
549
    }
550
    if ($row->{no_auto_renewal_after_hard_limit}) {
551
       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
552
       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
553
    }
554
555
    push @row_loop, $row;
556
}
557
558
my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
559
560
$template->param(show_branch_cat_rule_form => 1);
541
$template->param(show_branch_cat_rule_form => 1);
561
542
562
$template->param(
543
$template->param(
563
    patron_categories => $patron_categories,
544
    patron_categories => $patron_categories,
564
                        itemtypeloop => $itemtypes,
545
    itemtypeloop      => $itemtypes,
565
                        rules => \@sorted_row_loop,
546
    humanbranch       => ( $branch ne '*' ? $branch : '' ),
566
                        humanbranch => ($branch ne '*' ? $branch : ''),
547
    current_branch    => $branch,
567
                        current_branch => $branch,
548
);
568
                        definedbranch => scalar(@sorted_row_loop)>0
569
                        );
570
output_html_with_http_headers $input, $cookie, $template->output;
549
output_html_with_http_headers $input, $cookie, $template->output;
571
550
572
exit 0;
551
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 (-106 / +153 lines)
Lines 1-13 Link Here
1
[% USE KohaDates %]
1
[% USE Branches %]
2
[% USE Branches %]
2
[% USE Categories %]
3
[% USE Categories %]
4
[% USE ItemTypes %]
3
[% USE CirculationRules %]
5
[% USE CirculationRules %]
4
6
5
[% SET branchcode = humanbranch %]
7
[% SET branchcode = humanbranch || '*' %]
6
8
7
[% SET categorycodes = ['*'] %]
9
[% SET categorycodes = [] %]
8
[% FOREACH pc IN patron_categories %]
10
[% FOREACH pc IN patron_categories %]
9
    [% categorycodes.push( pc.id ) %]
11
    [% categorycodes.push( pc.id ) %]
10
[% END %]
12
[% END %]
13
[% categorycodes.push('*') %]
14
15
[% SET itemtypes = [] %]
16
[% FOREACH i IN itemtypeloop %]
17
    [% itemtypes.push( i.itemtype ) %]
18
[% END %]
19
[% itemtypes.push('*') %]
11
20
12
[% INCLUDE 'doc-head-open.inc' %]
21
[% INCLUDE 'doc-head-open.inc' %]
13
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
22
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
Lines 207-316 $(document).ready(function() { Link Here
207
            </tr>
216
            </tr>
208
            </thead>
217
            </thead>
209
            <tbody>
218
            <tbody>
210
				[% FOREACH rule IN rules %]
219
                [% SET row_count = 0 %]
211
					<tr id="row_[% loop.count %]">
220
                [% FOREACH c IN categorycodes %]
212
							<td>[% IF ( rule.default_humancategorycode ) %]
221
                    [% FOREACH i IN itemtypes %]
213
									<em>All</em>
222
                        [% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
214
								[% ELSE %]
223
                        [% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
215
									[% rule.humancategorycode %]
224
                        [% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
216
								[% END %]
225
                        [% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
217
							</td>
226
                        [% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
218
                            <td>[% IF rule.default_translated_description %]
227
                        [% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
219
									<em>All</em>
228
                        [% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
220
								[% ELSE %]
229
                        [% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
221
									[% rule.translated_description %]
230
                        [% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
222
								[% END %]
231
                        [% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
223
							</td>
232
                        [% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
224
							<td>
233
                        [% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
225
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
234
                        [% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
226
                                [% IF rule_value  %]
235
                        [% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
227
                                    [% rule_value %]
236
                        [% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
228
                                [% ELSE %]
237
                        [% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
229
                                    Unlimited
238
                        [% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
230
                                [% END %]
239
                        [% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
231
							</td>
240
                        [% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
232
							<td>
241
                        [% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
233
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
242
                        [% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
234
                                [% IF rule_value  %]
243
                        [% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
235
                                    [% rule_value %]
244
                        [% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
236
                                [% ELSE %]
245
                        [% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
237
                                    Unlimited
246
                        [% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
238
                                [% END %]
247
                        [% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
239
							</td>
248
240
							<td>[% rule.issuelength %]</td>
249
                        [% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
241
							<td>
250
                                        || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || renewalsallowed
242
							    [% rule.lengthunit %]
251
                                        || renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
243
							</td>
252
                                        || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
244
                            <td>
253
                        [% IF show_rule %]
245
                              [% IF ( rule.hardduedate ) %]
254
                            [% SET row_count = row_count + 1 %]
246
                                [% IF ( rule.hardduedatebefore ) %]
255
                            <tr row_countd="row_[% row_count %]">
247
                                  before [% rule.hardduedate %]
256
                                    <td>
248
                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
257
                                        [% IF c == '*' %]
249
                                [% ELSIF ( rule.hardduedateexact ) %]
258
                                            <em>All</em>
250
                                  on [% rule.hardduedate %]
259
                                        [% ELSE %]
251
                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
260
                                            [% Categories.GetName(c) %]
252
                                [% ELSIF ( rule.hardduedateafter ) %]
261
                                        [% END %]
253
                                  after [% rule.hardduedate %]
262
                                    </td>
254
                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
263
                                    <td>
255
                                [% END %]
264
                                        [% IF i == '*' %]
256
                              [% ELSE %]
265
                                            <em>All</em>
257
                                None defined
266
                                        [% ELSE %]
258
                              [% END %]
267
                                            [% ItemTypes.GetDescription(i) %]
259
                            </td>
268
                                        [% END %]
260
							<td>[% rule.fine %]</td>
269
                                    </td>
261
							<td>[% rule.chargeperiod %]</td>
270
                                    <td>
262
                <td>[% IF rule.chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
271
                                        [% IF maxissueqty  %]
263
							<td>[% rule.firstremind %]</td>
272
                                            [% maxissueqty %]
264
                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
273
                                        [% ELSE %]
265
                            <td>
274
                                            Unlimited
266
                                [% IF rule.cap_fine_to_replacement_price %]
275
                                        [% END %]
267
                                    <input type="checkbox" checked="checked" disabled="disabled" />
276
                                    </td>
268
                                [% ELSE %]
277
                                    <td>
269
                                    <input type="checkbox" disabled="disabled" />
278
                                        [% IF maxonsiteissueqty  %]
270
                                [% END %]
279
                                            [% maxonsiteissueqty %]
271
                            </td>
280
                                        [% ELSE %]
272
							<td>[% rule.finedays %]</td>
281
                                            Unlimited
273
                            <td>[% rule.maxsuspensiondays %]</td>
282
                                        [% END %]
274
							<td>[% rule.renewalsallowed %]</td>
283
                                    </td>
275
                            <td>[% rule.renewalperiod %]</td>
284
                                    <td>[% issuelength %]</td>
276
                            <td>[% rule.norenewalbefore %]</td>
285
                                    <td>
277
                            <td>
286
                                        [% lengthunit %]
278
                                [% IF ( rule.auto_renew ) %]
287
                                    </td>
279
                                Yes
288
                                    <td>
280
                                [% ELSE %]
289
                                      [% IF ( hardduedate ) %]
281
                                No
290
                                        [% IF ( hardduedatecompare == '-1' ) %]
282
                                [% END %]
291
                                          before [% hardduedate | $KohaDates %]
283
                            </td>
292
                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
284
                            <td>[% rule.no_auto_renewal_after %]</td>
293
                                        [% ELSIF ( hardduedatecompare == '0' ) %]
285
                            <td>[% rule.no_auto_renewal_after_hard_limit %]</td>
294
                                          on [% hardduedate | $KohaDates %]
286
							<td>[% rule.reservesallowed %]</td>
295
                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
287
                                                        <td>[% rule.holds_per_record %]</td>
296
                                        [% ELSIF ( hardduedatecompare == '1' ) %]
288
                                                        <td>
297
                                          after [% hardduedate | $KohaDates %]
289
                                                            [% IF rule.onshelfholds == 1 %]
298
                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
290
                                                                Yes
299
                                        [% END %]
291
                                                            [% ELSIF rule.onshelfholds == 2 %]
300
                                      [% ELSE %]
292
                                                                If all unavailable
301
                                        None defined
293
                                                            [% ELSE %]
302
                                      [% END %]
294
                                                                If any unavailable
303
                                    </td>
295
                                                            [% END %]</td>
304
                                    <td>[% fine %]</td>
296
                                                        <td>[% IF rule.opacitemholds == 'F'%]Force[% ELSIF rule.opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
305
                                    <td>[% chargeperiod %]</td>
297
                                                        <td>
306
                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
298
                                                            [% IF rule.article_requests == 'no' %]
307
                                    <td>[% firstremind %]</td>
299
                                                                No
308
                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
300
                                                            [% ELSIF rule.article_requests == 'yes' %]
309
                                    <td>
301
                                                                Yes
310
                                        [% IF cap_fine_to_replacement_price %]
302
                                                            [% ELSIF rule.article_requests == 'bib_only' %]
311
                                            <input type="checkbox" checked="checked" disabled="disabled" />
303
                                                                Record only
312
                                        [% ELSE %]
304
                                                            [% ELSIF rule.article_requests == 'item_only' %]
313
                                            <input type="checkbox" disabled="disabled" />
305
                                                                Item only
314
                                        [% END %]
306
                                                            [% END %]
315
                                    </td>
307
                                                        </td>
316
                                    <td>[% finedays %]</td>
308
							<td>[% rule.rentaldiscount %]</td>
317
                                    <td>[% maxsuspensiondays %]</td>
309
                                                        <td class="actions">
318
                                    <td>[% renewalsallowed %]</td>
310
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
319
                                    <td>[% renewalperiod %]</td>
311
                                                          <a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype %]&amp;categorycode=[% rule.categorycode %]&amp;branch=[% rule.current_branch %]"><i class="fa fa-trash"></i> Delete</a>
320
                                    <td>[% norenewalbefore %]</td>
312
							</td>
321
                                    <td>
313
                	</tr>
322
                                        [% IF auto_renew %]
323
                                            Yes
324
                                        [% ELSE %]
325
                                            No
326
                                        [% END %]
327
                                    </td>
328
                                    <td>[% no_auto_renewal_after %]</td>
329
                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
330
                                    <td>[% reservesallowed %]</td>
331
                                    <td>[% holds_per_record %]</td>
332
                                    <td>
333
                                        [% IF onshelfholds == 1 %]
334
                                            Yes
335
                                        [% ELSIF onshelfholds == 2 %]
336
                                            If all unavailable
337
                                        [% ELSE %]
338
                                            If any unavailable
339
                                        [% END %]
340
                                    </td>
341
                                    <td>[% IF opacitemholds == 'F'%]Force[% ELSIF opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
342
                                    <td>
343
                                        [% IF article_requests == 'no' %]
344
                                            No
345
                                        [% ELSIF article_requests == 'yes' %]
346
                                            Yes
347
                                        [% ELSIF article_requests == 'bib_only' %]
348
                                            Record only
349
                                        [% ELSIF article_requests == 'item_only' %]
350
                                            Item only
351
                                        [% END %]
352
                                    </td>
353
                                    <td>[% rentaldiscount %]</td>
354
                                    <td class="actions">
355
                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
356
                                      <a class="btn btn-default btn-xs delete" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&amp;itemtype=[% rule.itemtype %]&amp;categorycode=[% rule.categorycode %]&amp;branch=[% rule.current_branch %]"><i class="fa fa-trash"></i> Delete</a>
357
                                    </td>
358
                            </tr>
359
                        [% END %]
360
                    [% END %]
314
            	[% END %]
361
            	[% END %]
315
                <tr id="edit_row">
362
                <tr id="edit_row">
316
                    <td>
363
                    <td>
(-)a/t/db_dependent/ArticleRequests.t (-10 / +38 lines)
Lines 27-32 use Koha::Database; Link Here
27
use Koha::Biblio;
27
use Koha::Biblio;
28
use Koha::Patron;
28
use Koha::Patron;
29
use Koha::Library;
29
use Koha::Library;
30
use Koha::CirculationRules;
30
31
31
BEGIN {
32
BEGIN {
32
    use_ok('Koha::ArticleRequest');
33
    use_ok('Koha::ArticleRequest');
Lines 41-47 my $builder = t::lib::TestBuilder->new; Link Here
41
my $dbh = C4::Context->dbh;
42
my $dbh = C4::Context->dbh;
42
$dbh->{RaiseError} = 1;
43
$dbh->{RaiseError} = 1;
43
44
44
$dbh->do("DELETE FROM issuingrules");
45
$dbh->do("DELETE FROM circulation_rules");
45
46
46
my $biblio = Koha::Biblio->new()->store();
47
my $biblio = Koha::Biblio->new()->store();
47
ok( $biblio->id, 'Koha::Biblio created' );
48
ok( $biblio->id, 'Koha::Biblio created' );
Lines 144-176 $article_request->complete(); Link Here
144
$article_request->cancel();
145
$article_request->cancel();
145
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
146
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
146
147
147
my $rule;
148
my $rule = Koha::CirculationRules->set_rule(
148
$rule = $schema->resultset('Issuingrule')
149
    {
149
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
150
        categorycode => '*',
151
        itemtype     => '*',
152
        branchcode   => '*',
153
        rule_name    => 'article_requests',
154
        rule_value   => 'yes',
155
    }
156
);
150
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
157
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
151
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
158
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
152
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
159
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
153
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
160
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
154
$rule->delete();
161
$rule->delete();
155
162
156
$rule = $schema->resultset('Issuingrule')
163
$rule = Koha::CirculationRules->set_rule(
157
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
164
    {
165
        categorycode => '*',
166
        itemtype     => '*',
167
        branchcode   => '*',
168
        rule_name    => 'article_requests',
169
        rule_value   => 'bib_only',
170
    }
171
);
158
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
172
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
159
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
173
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
160
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
174
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
161
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
175
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
162
$rule->delete();
176
$rule->delete();
163
177
164
$rule = $schema->resultset('Issuingrule')
178
$rule = Koha::CirculationRules->set_rule(
165
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
179
    {
180
        categorycode => '*',
181
        itemtype     => '*',
182
        branchcode   => '*',
183
        rule_name    => 'article_requests',
184
        rule_value   => 'item_only',
185
    }
186
);
166
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
187
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
167
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
188
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
168
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
189
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
169
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
190
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
170
$rule->delete();
191
$rule->delete();
171
192
172
$rule = $schema->resultset('Issuingrule')
193
$rule = Koha::CirculationRules->set_rule(
173
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
194
    {
195
        categorycode => '*',
196
        itemtype     => '*',
197
        branchcode   => '*',
198
        rule_name    => 'article_requests',
199
        rule_value   => 'no',
200
    }
201
);
174
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
202
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
175
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
203
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
176
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
204
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
(-)a/t/db_dependent/Circulation.t (-85 / +281 lines)
Lines 33-39 use C4::Reserves; Link Here
33
use C4::Overdues qw(UpdateFine CalcFine);
33
use C4::Overdues qw(UpdateFine CalcFine);
34
use Koha::DateUtils;
34
use Koha::DateUtils;
35
use Koha::Database;
35
use Koha::Database;
36
use Koha::IssuingRules;
37
use Koha::Checkouts;
36
use Koha::Checkouts;
38
use Koha::Patrons;
37
use Koha::Patrons;
39
use Koha::CirculationRules;
38
use Koha::CirculationRules;
Lines 168-194 is( Link Here
168
);
167
);
169
168
170
# Set a simple circ policy
169
# Set a simple circ policy
171
$dbh->do('DELETE FROM issuingrules');
170
$dbh->do('DELETE FROM circulation_rules');
172
Koha::CirculationRules->search()->delete();
171
Koha::CirculationRules->set_rules(
173
$dbh->do(
172
    {
174
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed,
173
        categorycode => '*',
175
                                issuelength, lengthunit,
174
        branchcode   => '*',
176
                                renewalsallowed, renewalperiod,
175
        itemtype     => '*',
177
                                norenewalbefore, auto_renew,
176
        rules        => {
178
                                fine, chargeperiod)
177
            reservesallowed => 25,
179
      VALUES (?, ?, ?, ?,
178
            issuelength     => 14,
180
              ?, ?,
179
            lengthunit      => 'days',
181
              ?, ?,
180
            renewalsallowed => 1,
182
              ?, ?,
181
            renewalperiod   => 7,
183
              ?, ?
182
            norenewalbefore => undef,
184
             )
183
            auto_renew      => 0,
185
    },
184
            fine            => .10,
186
    {},
185
            chargeperiod    => 1,
187
    '*', '*', '*', 25,
186
        }
188
    14, 'days',
187
    }
189
    1, 7,
190
    undef, 0,
191
    .10, 1
192
);
188
);
193
189
194
# Test C4::Circulation::ProcessOfflinePayment
190
# Test C4::Circulation::ProcessOfflinePayment
Lines 332-338 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
332
    );
328
    );
333
329
334
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
330
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
335
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
331
    Koha::CirculationRules->set_rule(
332
        {
333
            categorycode => '*',
334
            branchcode   => '*',
335
            itemtype     => '*',
336
            rule_name    => 'onshelfholds',
337
            rule_value   => '1',
338
        }
339
    );
336
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
340
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
337
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
341
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
338
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
342
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
Lines 530-536 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
530
534
531
    # Bug 7413
535
    # Bug 7413
532
    # Test premature manual renewal
536
    # Test premature manual renewal
533
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 7');
537
    Koha::CirculationRules->set_rule(
538
        {
539
            categorycode => '*',
540
            branchcode   => '*',
541
            itemtype     => '*',
542
            rule_name    => 'norenewalbefore',
543
            rule_value   => '7',
544
        }
545
    );
534
546
535
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
547
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
536
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
548
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
Lines 565-571 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
565
577
566
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
578
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
567
    # and test automatic renewal again
579
    # and test automatic renewal again
568
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 0');
580
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
569
    ( $renewokay, $error ) =
581
    ( $renewokay, $error ) =
570
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
582
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
571
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
583
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
Lines 575-581 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
575
587
576
    # Change policy so that loans can be renewed 99 days prior to the due date
588
    # Change policy so that loans can be renewed 99 days prior to the due date
577
    # and test automatic renewal again
589
    # and test automatic renewal again
578
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 99');
590
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
579
    ( $renewokay, $error ) =
591
    ( $renewokay, $error ) =
580
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
592
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
581
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
593
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
Lines 599-641 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
599
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
611
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
600
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
612
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
601
613
602
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9');
614
        Koha::CirculationRules->set_rules(
615
            {
616
                categorycode => '*',
617
                branchcode   => '*',
618
                itemtype     => '*',
619
                rules        => {
620
                    norenewalbefore       => '7',
621
                    no_auto_renewal_after => '9',
622
                }
623
            }
624
        );
603
        ( $renewokay, $error ) =
625
        ( $renewokay, $error ) =
604
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
626
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
605
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
627
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
606
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
628
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
607
629
608
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10');
630
        Koha::CirculationRules->set_rules(
631
            {
632
                categorycode => '*',
633
                branchcode   => '*',
634
                itemtype     => '*',
635
                rules        => {
636
                    norenewalbefore       => '7',
637
                    no_auto_renewal_after => '10',
638
                }
639
            }
640
        );
609
        ( $renewokay, $error ) =
641
        ( $renewokay, $error ) =
610
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
642
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
611
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
643
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
612
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
644
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
613
645
614
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11');
646
        Koha::CirculationRules->set_rules(
647
            {
648
                categorycode => '*',
649
                branchcode   => '*',
650
                itemtype     => '*',
651
                rules        => {
652
                    norenewalbefore       => '7',
653
                    no_auto_renewal_after => '11',
654
                }
655
            }
656
        );
615
        ( $renewokay, $error ) =
657
        ( $renewokay, $error ) =
616
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
658
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
617
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
659
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
618
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
660
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
619
661
620
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
662
        Koha::CirculationRules->set_rules(
663
            {
664
                categorycode => '*',
665
                branchcode   => '*',
666
                itemtype     => '*',
667
                rules        => {
668
                    norenewalbefore       => '10',
669
                    no_auto_renewal_after => '11',
670
                }
671
            }
672
        );
621
        ( $renewokay, $error ) =
673
        ( $renewokay, $error ) =
622
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
674
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
623
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
675
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
624
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
676
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
625
677
626
        $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 ) );
678
        Koha::CirculationRules->set_rules(
679
            {
680
                categorycode => '*',
681
                branchcode   => '*',
682
                itemtype     => '*',
683
                rules        => {
684
                    norenewalbefore       => '10',
685
                    no_auto_renewal_after => undef,
686
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
687
                }
688
            }
689
        );
627
        ( $renewokay, $error ) =
690
        ( $renewokay, $error ) =
628
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
691
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
629
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
692
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
630
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
693
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
631
694
632
        $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 ) );
695
        Koha::CirculationRules->set_rules(
696
            {
697
                categorycode => '*',
698
                branchcode   => '*',
699
                itemtype     => '*',
700
                rules        => {
701
                    norenewalbefore       => '7',
702
                    no_auto_renewal_after => '15',
703
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
704
                }
705
            }
706
        );
633
        ( $renewokay, $error ) =
707
        ( $renewokay, $error ) =
634
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
708
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
635
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
709
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
636
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
710
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
637
711
638
        $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 ) );
712
        Koha::CirculationRules->set_rules(
713
            {
714
                categorycode => '*',
715
                branchcode   => '*',
716
                itemtype     => '*',
717
                rules        => {
718
                    norenewalbefore       => '10',
719
                    no_auto_renewal_after => undef,
720
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 1 ),
721
                }
722
            }
723
        );
639
        ( $renewokay, $error ) =
724
        ( $renewokay, $error ) =
640
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
725
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
641
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
726
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
Lines 657-663 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
657
        my $ten_days_ahead = dt_from_string->add( days => 10 );
742
        my $ten_days_ahead = dt_from_string->add( days => 10 );
658
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
743
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
659
744
660
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
745
        Koha::CirculationRules->set_rules(
746
            {
747
                categorycode => '*',
748
                branchcode   => '*',
749
                itemtype     => '*',
750
                rules        => {
751
                    norenewalbefore       => '10',
752
                    no_auto_renewal_after => '11',
753
                }
754
            }
755
        );
661
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
756
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
662
        C4::Context->set_preference('OPACFineNoRenewals','10');
757
        C4::Context->set_preference('OPACFineNoRenewals','10');
663
        my $fines_amount = 5;
758
        my $fines_amount = 5;
Lines 697-727 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
697
        my $ten_days_before = dt_from_string->add( days => -10 );
792
        my $ten_days_before = dt_from_string->add( days => -10 );
698
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
793
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
699
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
794
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
700
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = NULL');
795
        Koha::CirculationRules->set_rules(
796
            {
797
                categorycode => '*',
798
                branchcode   => '*',
799
                itemtype     => '*',
800
                rules        => {
801
                    norenewalbefore       => '7',
802
                    no_auto_renewal_after => '',
803
                    no_auto_renewal_after_hard_limit => undef,
804
                }
805
            }
806
        );
701
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
807
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
702
        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' );
808
        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' );
703
        my $five_days_before = dt_from_string->add( days => -5 );
809
        my $five_days_before = dt_from_string->add( days => -5 );
704
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
810
        Koha::CirculationRules->set_rules(
811
            {
812
                categorycode => '*',
813
                branchcode   => '*',
814
                itemtype     => '*',
815
                rules        => {
816
                    norenewalbefore       => '10',
817
                    no_auto_renewal_after => '5',
818
                    no_auto_renewal_after_hard_limit => undef,
819
                }
820
            }
821
        );
705
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
822
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
706
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
823
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
707
            $five_days_before->truncate( to => 'minute' ),
824
            $five_days_before->truncate( to => 'minute' ),
708
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
825
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
709
        );
826
        );
710
        my $five_days_ahead = dt_from_string->add( days => 5 );
827
        my $five_days_ahead = dt_from_string->add( days => 5 );
711
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
828
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
829
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
830
        $dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
831
        Koha::CirculationRules->set_rules(
832
            {
833
                categorycode => '*',
834
                branchcode   => '*',
835
                itemtype     => '*',
836
                rules        => {
837
                    norenewalbefore       => '10',
838
                    no_auto_renewal_after => '15',
839
                    no_auto_renewal_after_hard_limit => undef,
840
                }
841
            }
842
        );
712
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
843
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
713
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
844
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
714
            $five_days_ahead->truncate( to => 'minute' ),
845
            $five_days_ahead->truncate( to => 'minute' ),
715
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
846
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
716
        );
847
        );
717
        my $two_days_ahead = dt_from_string->add( days => 2 );
848
        my $two_days_ahead = dt_from_string->add( days => 2 );
718
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
849
        Koha::CirculationRules->set_rules(
850
            {
851
                categorycode => '*',
852
                branchcode   => '*',
853
                itemtype     => '*',
854
                rules        => {
855
                    norenewalbefore       => '10',
856
                    no_auto_renewal_after => '',
857
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
858
                }
859
            }
860
        );
719
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
861
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
720
        is( $latest_auto_renew_date->truncate( to => 'day' ),
862
        is( $latest_auto_renew_date->truncate( to => 'day' ),
721
            $two_days_ahead->truncate( to => 'day' ),
863
            $two_days_ahead->truncate( to => 'day' ),
722
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
864
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
723
        );
865
        );
724
        $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 ) );
866
        Koha::CirculationRules->set_rules(
867
            {
868
                categorycode => '*',
869
                branchcode   => '*',
870
                itemtype     => '*',
871
                rules        => {
872
                    norenewalbefore       => '10',
873
                    no_auto_renewal_after => '15',
874
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
875
                }
876
            }
877
        );
725
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
878
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
726
        is( $latest_auto_renew_date->truncate( to => 'day' ),
879
        is( $latest_auto_renew_date->truncate( to => 'day' ),
727
            $two_days_ahead->truncate( to => 'day' ),
880
            $two_days_ahead->truncate( to => 'day' ),
Lines 729-739 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
729
        );
882
        );
730
883
731
    };
884
    };
732
733
    # Too many renewals
885
    # Too many renewals
734
886
735
    # set policy to forbid renewals
887
    # set policy to forbid renewals
736
    $dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
888
    Koha::CirculationRules->set_rules(
889
        {
890
            categorycode => '*',
891
            branchcode   => '*',
892
            itemtype     => '*',
893
            rules        => {
894
                norenewalbefore => undef,
895
                renewalsallowed => 0,
896
            }
897
        }
898
    );
737
899
738
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
900
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
739
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
901
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
Lines 946-975 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
946
{
1108
{
947
    $dbh->do('DELETE FROM issues');
1109
    $dbh->do('DELETE FROM issues');
948
    $dbh->do('DELETE FROM items');
1110
    $dbh->do('DELETE FROM items');
949
    $dbh->do('DELETE FROM issuingrules');
1111
    $dbh->do('DELETE FROM circulation_rules');
950
	Koha::CirculationRules->search()->delete();
1112
    Koha::CirculationRules->set_rules(
951
    $dbh->do(
1113
        {
952
        q{
1114
            categorycode => '*',
953
        INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
1115
            itemtype     => '*',
954
                    norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
1116
            branchcode   => '*',
955
        },
1117
            rules        => {
956
        {},
1118
                reservesallowed => 25,
957
        '*', '*', '*', 25,
1119
                issuelength     => 14,
958
        14,  'days',
1120
                lengthunit      => 'days',
959
        1,   7,
1121
                renewalsallowed => 1,
960
        undef,  0,
1122
                renewalperiod   => 7,
961
        .10, 1
1123
                norenewalbefore => undef,
962
    );
1124
                auto_renew      => 0,
963
	Koha::CirculationRules->set_rules(
1125
                fine            => .10,
964
		{
1126
                chargeperiod    => 1,
965
			categorycode => '*',
1127
                maxissueqty     => 20
966
			itemtype     => '*',
1128
            }
967
			branchcode   => '*',
1129
        }
968
			rules        => {
1130
    );
969
				maxissueqty => 20
970
			}
971
		}
972
	);
973
    my $biblio = MARC::Record->new();
1131
    my $biblio = MARC::Record->new();
974
    my ( $biblionumber, $biblioitemnumber ) = AddBiblio( $biblio, '' );
1132
    my ( $biblionumber, $biblioitemnumber ) = AddBiblio( $biblio, '' );
975
1133
Lines 1021-1042 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
1021
        undef, undef, undef
1179
        undef, undef, undef
1022
    );
1180
    );
1023
1181
1024
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1182
    Koha::CirculationRules->set_rules(
1183
        {
1184
            categorycode => '*',
1185
            itemtype     => '*',
1186
            branchcode   => '*',
1187
            rules        => {
1188
                onshelfholds => 0,
1189
            }
1190
        }
1191
    );
1025
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1192
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1026
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1193
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1027
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1194
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1028
1195
1029
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1196
    Koha::CirculationRules->set_rules(
1197
        {
1198
            categorycode => '*',
1199
            itemtype     => '*',
1200
            branchcode   => '*',
1201
            rules        => {
1202
                onshelfholds => 0,
1203
            }
1204
        }
1205
    );
1030
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1206
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1031
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1207
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1032
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1208
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1033
1209
1034
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1210
    Koha::CirculationRules->set_rules(
1211
        {
1212
            categorycode => '*',
1213
            itemtype     => '*',
1214
            branchcode   => '*',
1215
            rules        => {
1216
                onshelfholds => 1,
1217
            }
1218
        }
1219
    );
1035
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1220
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1036
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1221
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1037
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1222
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1038
1223
1039
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1224
    Koha::CirculationRules->set_rules(
1225
        {
1226
            categorycode => '*',
1227
            itemtype     => '*',
1228
            branchcode   => '*',
1229
            rules        => {
1230
                onshelfholds => 1,
1231
            }
1232
        }
1233
    );
1040
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1234
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1041
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1235
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1042
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1236
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
Lines 1557-1576 subtest 'AddReturn + CumulativeRestrictionPeriods' => sub { Link Here
1557
        }
1751
        }
1558
    );
1752
    );
1559
1753
1560
    # And the issuing rule
1754
    # And the circulation rule
1561
    Koha::IssuingRules->search->delete;
1755
    Koha::CirculationRules->search->delete;
1562
    my $rule = Koha::IssuingRule->new(
1756
    Koha::CirculationRules->set_rules(
1563
        {
1757
        {
1564
            categorycode => '*',
1758
            categorycode => '*',
1565
            itemtype     => '*',
1759
            itemtype     => '*',
1566
            branchcode   => '*',
1760
            branchcode   => '*',
1567
            issuelength  => 1,
1761
            rules        => {
1568
            firstremind  => 1,        # 1 day of grace
1762
                issuelength => 1,
1569
            finedays     => 2,        # 2 days of fine per day of overdue
1763
                firstremind => 1,        # 1 day of grace
1570
            lengthunit   => 'days',
1764
                finedays    => 2,        # 2 days of fine per day of overdue
1765
                lengthunit  => 'days',
1766
            }
1571
        }
1767
        }
1572
    );
1768
    );
1573
    $rule->store();
1574
1769
1575
    # Patron cannot issue item_1, they have overdues
1770
    # Patron cannot issue item_1, they have overdues
1576
    my $five_days_ago = dt_from_string->subtract( days => 5 );
1771
    my $five_days_ago = dt_from_string->subtract( days => 5 );
Lines 1672-1691 subtest 'AddReturn | is_overdue' => sub { Link Here
1672
        }
1867
        }
1673
    );
1868
    );
1674
1869
1675
    Koha::IssuingRules->search->delete;
1870
    Koha::CirculationRules->search->delete;
1676
    my $rule = Koha::IssuingRule->new(
1871
    my $rule = Koha::CirculationRules->set_rules(
1677
        {
1872
        {
1678
            categorycode => '*',
1873
            categorycode => '*',
1679
            itemtype     => '*',
1874
            itemtype     => '*',
1680
            branchcode   => '*',
1875
            branchcode   => '*',
1681
            maxissueqty  => 99,
1876
            rules        => {
1682
            issuelength  => 6,
1877
                maxissueqty  => 99,
1683
            lengthunit   => 'days',
1878
                issuelength  => 6,
1684
            fine         => 1, # Charge 1 every day of overdue
1879
                lengthunit   => 'days',
1685
            chargeperiod => 1,
1880
                fine         => 1,        # Charge 1 every day of overdue
1881
                chargeperiod => 1,
1882
            }
1686
        }
1883
        }
1687
    );
1884
    );
1688
    $rule->store();
1689
1885
1690
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
1886
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
1691
    my $five_days_ago = dt_from_string->subtract( days => 5 );
1887
    my $five_days_ago = dt_from_string->subtract( days => 5 );
(-)a/t/db_dependent/Circulation/CalcDateDue.t (-8 / +15 lines)
Lines 9-14 use DateTime; Link Here
9
use t::lib::Mocks;
9
use t::lib::Mocks;
10
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
11
11
12
use Koha::CirculationRules;
13
12
use_ok('C4::Circulation');
14
use_ok('C4::Circulation');
13
15
14
my $schema = Koha::Database->new->schema;
16
my $schema = Koha::Database->new->schema;
Lines 22-35 my $issuelength = 10; Link Here
22
my $renewalperiod = 5;
24
my $renewalperiod = 5;
23
my $lengthunit = 'days';
25
my $lengthunit = 'days';
24
26
25
Koha::Database->schema->resultset('Issuingrule')->create({
27
Koha::CirculationRules->search()->delete();
26
  categorycode => $categorycode,
28
Koha::CirculationRules->set_rules(
27
  itemtype => $itemtype,
29
    {
28
  branchcode => $branchcode,
30
        categorycode => $categorycode,
29
  issuelength => $issuelength,
31
        itemtype     => $itemtype,
30
  renewalperiod => $renewalperiod,
32
        branchcode   => $branchcode,
31
  lengthunit => $lengthunit,
33
        rules        => {
32
});
34
            issuelength   => $issuelength,
35
            renewalperiod => $renewalperiod,
36
            lengthunit    => $lengthunit,
37
        }
38
    }
39
);
33
40
34
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
41
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
35
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
42
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
(-)a/t/db_dependent/Circulation/CalcFine.t (-21 / +13 lines)
Lines 66-84 my $item = $builder->build( Link Here
66
subtest 'Test basic functionality' => sub {
66
subtest 'Test basic functionality' => sub {
67
    plan tests => 1;
67
    plan tests => 1;
68
68
69
    my $rule = $builder->schema->resultset('Issuingrule')->find({
69
    Koha::CirculationRules->set_rules(
70
        branchcode                    => '*',
71
        categorycode                  => '*',
72
        itemtype                      => '*',
73
    });
74
    $rule->delete if $rule;
75
    my $issuingrule = $builder->build(
76
        {
70
        {
77
            source => 'Issuingrule',
71
            branchcode   => '*',
78
            value  => {
72
            categorycode => '*',
79
                branchcode                    => '*',
73
            itemtype     => '*',
80
                categorycode                  => '*',
74
            rules        => {
81
                itemtype                      => '*',
82
                fine                          => '1.00',
75
                fine                          => '1.00',
83
                lengthunit                    => 'days',
76
                lengthunit                    => 'days',
84
                finedays                      => 0,
77
                finedays                      => 0,
Lines 86-93 subtest 'Test basic functionality' => sub { Link Here
86
                chargeperiod                  => 1,
79
                chargeperiod                  => 1,
87
                overduefinescap               => undef,
80
                overduefinescap               => undef,
88
                cap_fine_to_replacement_price => 0,
81
                cap_fine_to_replacement_price => 0,
89
            },
82
            }
90
        }
83
        },
91
    );
84
    );
92
85
93
    my $start_dt = DateTime->new(
86
    my $start_dt = DateTime->new(
Lines 111-123 subtest 'Test basic functionality' => sub { Link Here
111
104
112
subtest 'Test cap_fine_to_replacement_price' => sub {
105
subtest 'Test cap_fine_to_replacement_price' => sub {
113
    plan tests => 1;
106
    plan tests => 1;
114
    my $issuingrule = $builder->build(
107
    Koha::CirculationRules->set_rules(
115
        {
108
        {
116
            source => 'Issuingrule',
109
            branchcode   => '*',
117
            value  => {
110
            categorycode => '*',
118
                branchcode                    => '*',
111
            itemtype     => '*',
119
                categorycode                  => '*',
112
            rules        => {
120
                itemtype                      => '*',
121
                fine                          => '1.00',
113
                fine                          => '1.00',
122
                lengthunit                    => 'days',
114
                lengthunit                    => 'days',
123
                finedays                      => 0,
115
                finedays                      => 0,
Lines 149-153 subtest 'Test cap_fine_to_replacement_price' => sub { Link Here
149
};
141
};
150
142
151
sub teardown {
143
sub teardown {
152
    $dbh->do(q|DELETE FROM issuingrules|);
144
    $dbh->do(q|DELETE FROM circulation_rules|);
153
}
145
}
(-)a/t/db_dependent/Circulation/GetHardDueDate.t (-217 / +112 lines)
Lines 4-10 use Modern::Perl; Link Here
4
use C4::Context;
4
use C4::Context;
5
use DateTime;
5
use DateTime;
6
use Koha::DateUtils;
6
use Koha::DateUtils;
7
use Koha::IssuingRules;
7
use Koha::CirculationRules;
8
use Koha::Library;
8
use Koha::Library;
9
9
10
use Test::More tests => 10;
10
use Test::More tests => 10;
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-338 my $default = { Link Here
111
    lengthunit => 'days'
111
    lengthunit => 'days'
112
};
112
};
113
113
114
#Test GetIssuingRule
114
#Test get_effective_rules
115
my $sampleissuingrule1 = {
115
my $sampleissuingrule1 = {
116
    reservecharge      => '0.000000',
116
    branchcode   => $samplebranch1->{branchcode},
117
    chargename         => 'Null',
117
    categorycode => $samplecat->{categorycode},
118
    restrictedtype     => 0,
118
    itemtype     => 'BOOK',
119
    accountsent        => 0,
119
    rules        => {
120
    finedays           => 0,
120
        reservecharge                    => '0.000000',
121
    lengthunit         => 'days',
121
        chargename                       => 'Null',
122
    renewalperiod      => 5,
122
        restrictedtype                   => 0,
123
    norenewalbefore    => 6,
123
        accountsent                      => 0,
124
    auto_renew         => 0,
124
        finedays                         => 0,
125
    issuelength        => 5,
125
        lengthunit                       => 'days',
126
    chargeperiod       => 0,
126
        renewalperiod                    => 5,
127
    chargeperiod_charge_at => 0,
127
        norenewalbefore                  => 6,
128
    rentaldiscount     => '2.000000',
128
        auto_renew                       => 0,
129
    reservesallowed    => 0,
129
        issuelength                      => 5,
130
    hardduedate        => '2013-01-01',
130
        chargeperiod                     => 0,
131
    branchcode         => $samplebranch1->{branchcode},
131
        chargeperiod_charge_at           => 0,
132
    fine               => '0.000000',
132
        rentaldiscount                   => '2.000000',
133
    hardduedatecompare => 5,
133
        reservesallowed                  => 0,
134
    overduefinescap    => '0.000000',
134
        hardduedate                      => '2013-01-01',
135
    renewalsallowed    => 0,
135
        fine                             => '0.000000',
136
    firstremind        => 0,
136
        hardduedatecompare               => 5,
137
    itemtype           => 'BOOK',
137
        overduefinescap                  => '0.000000',
138
    categorycode       => $samplecat->{categorycode},
138
        renewalsallowed                  => 0,
139
    maxsuspensiondays  => 0,
139
        firstremind                      => 0,
140
    onshelfholds       => 0,
140
        maxsuspensiondays                => 0,
141
    opacitemholds      => 'N',
141
        onshelfholds                     => 0,
142
    cap_fine_to_replacement_price => 0,
142
        opacitemholds                    => 'N',
143
    holds_per_record   => 1,
143
        cap_fine_to_replacement_price    => 0,
144
    article_requests   => 'yes',
144
        holds_per_record                 => 1,
145
    no_auto_renewal_after => undef,
145
        article_requests                 => 'yes',
146
    no_auto_renewal_after_hard_limit => undef,
146
    }
147
};
147
};
148
my $sampleissuingrule2 = {
148
my $sampleissuingrule2 = {
149
    branchcode         => $samplebranch2->{branchcode},
149
    branchcode   => $samplebranch2->{branchcode},
150
    categorycode       => $samplecat->{categorycode},
150
    categorycode => $samplecat->{categorycode},
151
    itemtype           => 'BOOK',
151
    itemtype     => 'BOOK',
152
    renewalsallowed    => 'Null',
152
    rules        => {
153
    renewalperiod      => 2,
153
        renewalsallowed               => 'Null',
154
    norenewalbefore    => 7,
154
        renewalperiod                 => 2,
155
    auto_renew         => 0,
155
        norenewalbefore               => 7,
156
    reservesallowed    => 'Null',
156
        auto_renew                    => 0,
157
    issuelength        => 2,
157
        reservesallowed               => 'Null',
158
    lengthunit         => 'days',
158
        issuelength                   => 2,
159
    hardduedate        => 2,
159
        lengthunit                    => 'days',
160
    hardduedatecompare => 'Null',
160
        hardduedate                   => 2,
161
    fine               => 'Null',
161
        hardduedatecompare            => 'Null',
162
    finedays           => 'Null',
162
        fine                          => 'Null',
163
    firstremind        => 'Null',
163
        finedays                      => 'Null',
164
    chargeperiod       => 'Null',
164
        firstremind                   => 'Null',
165
    chargeperiod_charge_at => 0,
165
        chargeperiod                  => 'Null',
166
    rentaldiscount     => 2.00,
166
        chargeperiod_charge_at        => 0,
167
    overduefinescap    => 'Null',
167
        rentaldiscount                => 2.00,
168
    accountsent        => 'Null',
168
        overduefinescap               => 'Null',
169
    reservecharge      => 'Null',
169
        accountsent                   => 'Null',
170
    chargename         => 'Null',
170
        reservecharge                 => 'Null',
171
    restrictedtype     => 'Null',
171
        chargename                    => 'Null',
172
    maxsuspensiondays  => 0,
172
        restrictedtype                => 'Null',
173
    onshelfholds       => 1,
173
        maxsuspensiondays             => 0,
174
    opacitemholds      => 'Y',
174
        onshelfholds                  => 1,
175
    cap_fine_to_replacement_price => 0,
175
        opacitemholds                 => 'Y',
176
    holds_per_record   => 1,
176
        cap_fine_to_replacement_price => 0,
177
    article_requests   => 'yes',
177
        holds_per_record              => 1,
178
        article_requests              => 'yes',
179
    }
178
};
180
};
179
my $sampleissuingrule3 = {
181
my $sampleissuingrule3 = {
180
    branchcode         => $samplebranch1->{branchcode},
182
    branchcode   => $samplebranch1->{branchcode},
181
    categorycode       => $samplecat->{categorycode},
183
    categorycode => $samplecat->{categorycode},
182
    itemtype           => 'DVD',
184
    itemtype     => 'DVD',
183
    renewalsallowed    => 'Null',
185
    rules        => {
184
    renewalperiod      => 3,
186
        renewalsallowed               => 'Null',
185
    norenewalbefore    => 8,
187
        renewalperiod                 => 3,
186
    auto_renew         => 0,
188
        norenewalbefore               => 8,
187
    reservesallowed    => 'Null',
189
        auto_renew                    => 0,
188
    issuelength        => 3,
190
        reservesallowed               => 'Null',
189
    lengthunit         => 'days',
191
        issuelength                   => 3,
190
    hardduedate        => 3,
192
        lengthunit                    => 'days',
191
    hardduedatecompare => 'Null',
193
        hardduedate                   => 3,
192
    fine               => 'Null',
194
        hardduedatecompare            => 'Null',
193
    finedays           => 'Null',
195
        fine                          => 'Null',
194
    firstremind        => 'Null',
196
        finedays                      => 'Null',
195
    chargeperiod       => 'Null',
197
        firstremind                   => 'Null',
196
    chargeperiod_charge_at => 0,
198
        chargeperiod                  => 'Null',
197
    rentaldiscount     => 3.00,
199
        chargeperiod_charge_at        => 0,
198
    overduefinescap    => 'Null',
200
        rentaldiscount                => 3.00,
199
    accountsent        => 'Null',
201
        overduefinescap               => 'Null',
200
    reservecharge      => 'Null',
202
        accountsent                   => 'Null',
201
    chargename         => 'Null',
203
        reservecharge                 => 'Null',
202
    restrictedtype     => 'Null',
204
        chargename                    => 'Null',
203
    maxsuspensiondays  => 0,
205
        restrictedtype                => 'Null',
204
    onshelfholds       => 1,
206
        maxsuspensiondays             => 0,
205
    opacitemholds      => 'F',
207
        onshelfholds                  => 1,
206
    cap_fine_to_replacement_price => 0,
208
        opacitemholds                 => 'F',
207
    holds_per_record   => 1,
209
        cap_fine_to_replacement_price => 0,
208
    article_requests   => 'yes',
210
        holds_per_record              => 1,
211
        article_requests              => 'yes',
212
    }
209
};
213
};
210
214
211
$query = 'INSERT INTO issuingrules (
215
Koha::CirculationRules->set_rules( $sampleissuingrule1 );
212
                branchcode,
216
Koha::CirculationRules->set_rules( $sampleissuingrule2 );
213
                categorycode,
217
Koha::CirculationRules->set_rules( $sampleissuingrule3 );
214
                itemtype,
218
215
                renewalsallowed,
216
                renewalperiod,
217
                norenewalbefore,
218
                auto_renew,
219
                reservesallowed,
220
                issuelength,
221
                lengthunit,
222
                hardduedate,
223
                hardduedatecompare,
224
                fine,
225
                finedays,
226
                firstremind,
227
                chargeperiod,
228
                chargeperiod_charge_at,
229
                rentaldiscount,
230
                overduefinescap,
231
                accountsent,
232
                reservecharge,
233
                chargename,
234
                restrictedtype,
235
                maxsuspensiondays,
236
                onshelfholds,
237
                opacitemholds,
238
                cap_fine_to_replacement_price,
239
                article_requests
240
                ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
241
my $sth = $dbh->prepare($query);
242
$sth->execute(
243
    $sampleissuingrule1->{branchcode},
244
    $sampleissuingrule1->{categorycode},
245
    $sampleissuingrule1->{itemtype},
246
    $sampleissuingrule1->{renewalsallowed},
247
    $sampleissuingrule1->{renewalperiod},
248
    $sampleissuingrule1->{norenewalbefore},
249
    $sampleissuingrule1->{auto_renew},
250
    $sampleissuingrule1->{reservesallowed},
251
    $sampleissuingrule1->{issuelength},
252
    $sampleissuingrule1->{lengthunit},
253
    $sampleissuingrule1->{hardduedate},
254
    $sampleissuingrule1->{hardduedatecompare},
255
    $sampleissuingrule1->{fine},
256
    $sampleissuingrule1->{finedays},
257
    $sampleissuingrule1->{firstremind},
258
    $sampleissuingrule1->{chargeperiod},
259
    $sampleissuingrule1->{chargeperiod_charge_at},
260
    $sampleissuingrule1->{rentaldiscount},
261
    $sampleissuingrule1->{overduefinescap},
262
    $sampleissuingrule1->{accountsent},
263
    $sampleissuingrule1->{reservecharge},
264
    $sampleissuingrule1->{chargename},
265
    $sampleissuingrule1->{restrictedtype},
266
    $sampleissuingrule1->{maxsuspensiondays},
267
    $sampleissuingrule1->{onshelfholds},
268
    $sampleissuingrule1->{opacitemholds},
269
    $sampleissuingrule1->{cap_fine_to_replacement_price},
270
    $sampleissuingrule1->{article_requests},
271
);
272
$sth->execute(
273
    $sampleissuingrule2->{branchcode},
274
    $sampleissuingrule2->{categorycode},
275
    $sampleissuingrule2->{itemtype},
276
    $sampleissuingrule2->{renewalsallowed},
277
    $sampleissuingrule2->{renewalperiod},
278
    $sampleissuingrule2->{norenewalbefore},
279
    $sampleissuingrule2->{auto_renew},
280
    $sampleissuingrule2->{reservesallowed},
281
    $sampleissuingrule2->{issuelength},
282
    $sampleissuingrule2->{lengthunit},
283
    $sampleissuingrule2->{hardduedate},
284
    $sampleissuingrule2->{hardduedatecompare},
285
    $sampleissuingrule2->{fine},
286
    $sampleissuingrule2->{finedays},
287
    $sampleissuingrule2->{firstremind},
288
    $sampleissuingrule2->{chargeperiod},
289
    $sampleissuingrule2->{chargeperiod_charge_at},
290
    $sampleissuingrule2->{rentaldiscount},
291
    $sampleissuingrule2->{overduefinescap},
292
    $sampleissuingrule2->{accountsent},
293
    $sampleissuingrule2->{reservecharge},
294
    $sampleissuingrule2->{chargename},
295
    $sampleissuingrule2->{restrictedtype},
296
    $sampleissuingrule2->{maxsuspensiondays},
297
    $sampleissuingrule2->{onshelfholds},
298
    $sampleissuingrule2->{opacitemholds},
299
    $sampleissuingrule2->{cap_fine_to_replacement_price},
300
    $sampleissuingrule2->{article_requests},
301
);
302
$sth->execute(
303
    $sampleissuingrule3->{branchcode},
304
    $sampleissuingrule3->{categorycode},
305
    $sampleissuingrule3->{itemtype},
306
    $sampleissuingrule3->{renewalsallowed},
307
    $sampleissuingrule3->{renewalperiod},
308
    $sampleissuingrule3->{norenewalbefore},
309
    $sampleissuingrule3->{auto_renew},
310
    $sampleissuingrule3->{reservesallowed},
311
    $sampleissuingrule3->{issuelength},
312
    $sampleissuingrule3->{lengthunit},
313
    $sampleissuingrule3->{hardduedate},
314
    $sampleissuingrule3->{hardduedatecompare},
315
    $sampleissuingrule3->{fine},
316
    $sampleissuingrule3->{finedays},
317
    $sampleissuingrule3->{firstremind},
318
    $sampleissuingrule3->{chargeperiod},
319
    $sampleissuingrule3->{chargeperiod_charge_at},
320
    $sampleissuingrule3->{rentaldiscount},
321
    $sampleissuingrule3->{overduefinescap},
322
    $sampleissuingrule3->{accountsent},
323
    $sampleissuingrule3->{reservecharge},
324
    $sampleissuingrule3->{chargename},
325
    $sampleissuingrule3->{restrictedtype},
326
    $sampleissuingrule3->{maxsuspensiondays},
327
    $sampleissuingrule3->{onshelfholds},
328
    $sampleissuingrule3->{opacitemholds},
329
    $sampleissuingrule3->{cap_fine_to_replacement_price},
330
    $sampleissuingrule3->{article_requests},
331
);
332
219
220
my $rules = Koha::CirculationRules->get_effective_rules(
221
        {
222
            categorycode => $sampleissuingrule1->{categorycode},
223
            itemtype     => $sampleissuingrule1->{itemtype},
224
            branchcode   => $sampleissuingrule1->{branchcode},
225
            rules        => [ keys %{ $sampleissuingrule1->{rules} } ]
226
        }
227
    );
333
is_deeply(
228
is_deeply(
334
    Koha::IssuingRules->find({ categorycode => $samplecat->{categorycode}, itemtype => 'Book', branchcode => $samplebranch1->{branchcode} })->unblessed,
229
    $rules,
335
    $sampleissuingrule1,
230
    $sampleissuingrule1->{rules},
336
    "GetIssuingCharge returns issuingrule1's informations"
231
    "GetIssuingCharge returns issuingrule1's informations"
337
);
232
);
338
233
Lines 382-389 my @hardduedate = C4::Circulation::GetHardDueDate( $samplecat->{categorycode}, Link Here
382
is_deeply(
277
is_deeply(
383
    \@hardduedate,
278
    \@hardduedate,
384
    [
279
    [
385
        dt_from_string( $sampleissuingrule1->{hardduedate}, 'iso' ),
280
        dt_from_string( $sampleissuingrule1->{rules}->{hardduedate}, 'iso' ),
386
        $sampleissuingrule1->{hardduedatecompare}
281
        $sampleissuingrule1->{rules}->{hardduedatecompare}
387
    ],
282
    ],
388
    "GetHardDueDate returns the duedate and the duedatecompare"
283
    "GetHardDueDate returns the duedate and the duedatecompare"
389
);
284
);
(-)a/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t (-12 / +19 lines)
Lines 30-46 my $userenv->{branch} = $branchcode; Link Here
30
*C4::Context::userenv = \&Mock_userenv;
30
*C4::Context::userenv = \&Mock_userenv;
31
31
32
# Test without maxsuspensiondays set
32
# Test without maxsuspensiondays set
33
Koha::IssuingRules->search->delete;
33
Koha::CirculationRules->search->delete;
34
$builder->build(
34
Koha::CirculationRules->set_rules(
35
    {
35
    {
36
        source => 'Issuingrule',
36
        categorycode => '*',
37
        value  => {
37
        itemtype     => '*',
38
            categorycode => '*',
38
        branchcode   => '*',
39
            itemtype     => '*',
39
        rules        => {
40
            branchcode   => '*',
40
            firstremind => 0,
41
            firstremind  => 0,
41
            finedays    => 2,
42
            finedays     => 2,
42
            lengthunit  => 'days',
43
            lengthunit   => 'days',
44
        }
43
        }
45
    }
44
    }
46
);
45
);
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 48-63 my $schema = Koha::Database->schema; Link Here
48
$schema->storage->txn_begin;
48
$schema->storage->txn_begin;
49
49
50
my $builder = t::lib::TestBuilder->new();
50
my $builder = t::lib::TestBuilder->new();
51
Koha::IssuingRules->search->delete;
51
Koha::CirculationRules->search->delete;
52
my $rule = Koha::IssuingRule->new(
52
Koha::CirculationRules->set_rule(
53
    {
53
    {
54
        categorycode => '*',
54
        categorycode => '*',
55
        itemtype     => '*',
55
        itemtype     => '*',
56
        branchcode   => '*',
56
        branchcode   => '*',
57
        issuelength  => 1,
57
        rule_name    => 'issuelength',
58
        rule_value   => 1,
58
    }
59
    }
59
);
60
);
60
$rule->store();
61
61
62
subtest "InProcessingToShelvingCart tests" => sub {
62
subtest "InProcessingToShelvingCart tests" => sub {
63
63
Lines 281-287 subtest 'Handle ids duplication' => sub { Link Here
281
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
281
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
282
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
282
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
283
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
283
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
284
    Koha::IssuingRules->search->update({ chargeperiod => 1, fine => 1, firstremind => 1, });
284
    Koha::CirculationRules->set_rules(
285
        {
286
            categorycode => '*',
287
            itemtype     => '*',
288
            branchcode   => '*',
289
            rules        => {
290
                chargeperiod => 1,
291
                fine         => 1,
292
                firstremind  => 1,
293
            }
294
        }
295
    );
285
296
286
    my $biblio = $builder->build( { source => 'Biblio' } );
297
    my $biblio = $builder->build( { source => 'Biblio' } );
287
    my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
298
    my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
(-)a/t/db_dependent/Circulation/SwitchOnSiteCheckouts.t (-15 / +6 lines)
Lines 37-48 $schema->storage->txn_begin; Link Here
37
37
38
our $dbh = C4::Context->dbh;
38
our $dbh = C4::Context->dbh;
39
39
40
$dbh->do(q|DELETE FROM branch_item_rules|);
41
$dbh->do(q|DELETE FROM issues|);
40
$dbh->do(q|DELETE FROM issues|);
42
$dbh->do(q|DELETE FROM default_branch_circ_rules|);
41
$dbh->do(q|DELETE FROM circulation_rules|);
43
$dbh->do(q|DELETE FROM default_circ_rules|);
44
$dbh->do(q|DELETE FROM default_branch_item_rules|);
45
$dbh->do(q|DELETE FROM issuingrules|);
46
42
47
my $builder = t::lib::TestBuilder->new();
43
my $builder = t::lib::TestBuilder->new();
48
44
Lines 76-91 my $item = $builder->build({ Link Here
76
    },
72
    },
77
});
73
});
78
74
79
my $issuingrule = $builder->build({
80
    source => 'Issuingrule',
81
    value => {
82
        branchcode         => $branch->{branchcode},
83
        categorycode       => '*',
84
        itemtype           => '*',
85
        lengthunit         => 'days',
86
        issuelength        => 5,
87
    },
88
});
89
Koha::CirculationRules->search()->delete();
75
Koha::CirculationRules->search()->delete();
90
Koha::CirculationRules->set_rules(
76
Koha::CirculationRules->set_rules(
91
    {
77
    {
Lines 95-100 Koha::CirculationRules->set_rules( Link Here
95
        rules        => {
81
        rules        => {
96
            maxissueqty       => 2,
82
            maxissueqty       => 2,
97
            maxonsiteissueqty => 1,
83
            maxonsiteissueqty => 1,
84
            branchcode        => $branch->{branchcode},
85
            categorycode      => '*',
86
            itemtype          => '*',
87
            lengthunit        => 'days',
88
            issuelength       => 5,
98
        }
89
        }
99
    }
90
    }
100
);
91
);
(-)a/t/db_dependent/Circulation/TooMany.t (-7 / +13 lines)
Lines 43-54 $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 branch_item_rules|);
46
$dbh->do(q|DELETE FROM circulation_rules|);
47
$dbh->do(q|DELETE FROM default_branch_circ_rules|);
48
$dbh->do(q|DELETE FROM default_circ_rules|);
49
$dbh->do(q|DELETE FROM default_branch_item_rules|);
50
$dbh->do(q|DELETE FROM issuingrules|);
51
Koha::CirculationRules->search()->delete();
52
47
53
my $builder = t::lib::TestBuilder->new();
48
my $builder = t::lib::TestBuilder->new();
54
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
49
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
Lines 370-375 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub { Link Here
370
    );
365
    );
371
366
372
    teardown();
367
    teardown();
368
    Koha::CirculationRules->set_rules(
369
        {
370
            branchcode   => $branch->{branchcode},
371
            categorycode => $category->{categorycode},
372
            itemtype     => undef,
373
            rules        => {
374
                maxissueqty       => 1,
375
                maxonsiteissueqty => 1,
376
            }
377
        }
378
    );
373
379
374
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
380
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
375
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
381
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
Lines 417-423 $schema->storage->txn_rollback; Link Here
417
423
418
sub teardown {
424
sub teardown {
419
    $dbh->do(q|DELETE FROM issues|);
425
    $dbh->do(q|DELETE FROM issues|);
420
    $dbh->do(q|DELETE FROM issuingrules|);
426
    $dbh->do(q|DELETE FROM circulation_rules|);
421
}
427
}
422
428
423
1;
429
1;
(-)a/t/db_dependent/Circulation/issue.t (-8 / +23 lines)
Lines 33-38 use Koha::Database; Link Here
33
use Koha::DateUtils;
33
use Koha::DateUtils;
34
use Koha::Library;
34
use Koha::Library;
35
use Koha::Patrons;
35
use Koha::Patrons;
36
use Koha::CirculationRules;
36
37
37
BEGIN {
38
BEGIN {
38
    require_ok('C4::Circulation');
39
    require_ok('C4::Circulation');
Lines 65-71 $dbh->do(q|DELETE FROM borrowers|); Link Here
65
$dbh->do(q|DELETE FROM branches|);
66
$dbh->do(q|DELETE FROM branches|);
66
$dbh->do(q|DELETE FROM categories|);
67
$dbh->do(q|DELETE FROM categories|);
67
$dbh->do(q|DELETE FROM accountlines|);
68
$dbh->do(q|DELETE FROM accountlines|);
68
$dbh->do(q|DELETE FROM issuingrules|);
69
$dbh->do(q|DELETE FROM circulation_rules|);
69
$dbh->do(q|DELETE FROM reserves|);
70
$dbh->do(q|DELETE FROM reserves|);
70
$dbh->do(q|DELETE FROM old_reserves|);
71
$dbh->do(q|DELETE FROM old_reserves|);
71
$dbh->do(q|DELETE FROM statistics|);
72
$dbh->do(q|DELETE FROM statistics|);
Lines 287-296 is_deeply( Link Here
287
288
288
#With something in DB
289
#With something in DB
289
# Add a default rule: No renewal allowed
290
# Add a default rule: No renewal allowed
290
$dbh->do(q|
291
Koha::CirculationRules->set_rules(
291
    INSERT INTO issuingrules( categorycode, itemtype, branchcode, issuelength, renewalsallowed )
292
    {
292
    VALUES ( '*', '*', '*', 10, 0 )
293
        categorycode => '*',
293
|);
294
        itemtype     => '*',
295
        branchcode   => '*',
296
        rules        => {
297
            issuelength     => 10,
298
            renewalsallowed => 0,
299
        }
300
    }
301
);
294
@renewcount = C4::Circulation::GetRenewCount();
302
@renewcount = C4::Circulation::GetRenewCount();
295
is_deeply(
303
is_deeply(
296
    \@renewcount,
304
    \@renewcount,
Lines 311-319 is_deeply( Link Here
311
);
319
);
312
320
313
# Add a default rule: renewal is allowed
321
# Add a default rule: renewal is allowed
314
$dbh->do(q|
322
Koha::CirculationRules->set_rules(
315
    UPDATE issuingrules SET renewalsallowed = 3
323
    {
316
|);
324
        categorycode => '*',
325
        itemtype     => '*',
326
        branchcode   => '*',
327
        rules        => {
328
            renewalsallowed => 3,
329
        }
330
    }
331
);
317
@renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
332
@renewcount = C4::Circulation::GetRenewCount($borrower_id1, $item_id1);
318
is_deeply(
333
is_deeply(
319
    \@renewcount,
334
    \@renewcount,
(-)a/t/db_dependent/DecreaseLoanHighHolds.t (-9 / +9 lines)
Lines 24-29 use Koha::Biblio; Link Here
24
use Koha::Item;
24
use Koha::Item;
25
use Koha::Holds;
25
use Koha::Holds;
26
use Koha::Hold;
26
use Koha::Hold;
27
use Koha::CirculationRules;
27
use t::lib::TestBuilder;
28
use t::lib::TestBuilder;
28
use t::lib::Mocks;
29
use t::lib::Mocks;
29
30
Lines 38-44 $dbh->{RaiseError} = 1; Link Here
38
$schema->storage->txn_begin();
39
$schema->storage->txn_begin();
39
40
40
$dbh->do('DELETE FROM issues');
41
$dbh->do('DELETE FROM issues');
41
$dbh->do('DELETE FROM issuingrules');
42
$dbh->do('DELETE FROM circulation_rules');
42
$dbh->do('DELETE FROM borrowers');
43
$dbh->do('DELETE FROM borrowers');
43
$dbh->do('DELETE FROM items');
44
$dbh->do('DELETE FROM items');
44
45
Lines 87-101 for my $i ( 0 .. 5 ) { Link Here
87
    )->store();
88
    )->store();
88
}
89
}
89
90
90
$builder->build(
91
Koha::CirculationRules->set_rules(
91
    {
92
    {
92
        source => 'Issuingrule',
93
        branchcode   => '*',
93
        value => {
94
        categorycode => '*',
94
            branchcode => '*',
95
        itemtype     => '*',
95
            categorycode => '*',
96
        rules        => {
96
            itemtype => '*',
97
            issuelength     => '14',
97
            issuelength => '14',
98
            lengthunit      => 'days',
98
            lengthunit => 'days',
99
            reservesallowed => '99',
99
            reservesallowed => '99',
100
        }
100
        }
101
    }
101
    }
(-)a/t/db_dependent/Fines.t (-12 / +23 lines)
Lines 16-34 my $schema = Koha::Database->new()->schema(); Link Here
16
$dbh->{RaiseError} = 1;
16
$dbh->{RaiseError} = 1;
17
$dbh->{AutoCommit} = 0;
17
$dbh->{AutoCommit} = 0;
18
18
19
$dbh->do(q|DELETE FROM issuingrules|);
19
$dbh->do(q|DELETE FROM circulation_rules|);
20
20
21
my $issuingrule = $schema->resultset('Issuingrule')->create(
21
my $issuingrule = Koha::CirculationRules->set_rules(
22
    {
22
    {
23
        categorycode           => '*',
23
        categorycode => '*',
24
        itemtype               => '*',
24
        itemtype     => '*',
25
        branchcode             => '*',
25
        branchcode   => '*',
26
        fine                   => 1,
26
        rules        => {
27
        finedays               => 0,
27
            fine                   => 1,
28
        chargeperiod           => 7,
28
            finedays               => 0,
29
        chargeperiod_charge_at => 0,
29
            chargeperiod           => 7,
30
        lengthunit             => 'days',
30
            chargeperiod_charge_at => 0,
31
        issuelength            => 1,
31
            lengthunit             => 'days',
32
            issuelength            => 1,
33
        }
32
    }
34
    }
33
);
35
);
34
36
Lines 45-51 $period_end = dt_from_string('2000-01-10'); Link Here
45
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
47
is( $fine, 1, '9 days overdue, charge period 7 days, charge at end of interval gives fine of $1' );
46
48
47
# Test charging fine at the *beginning* of each charge period
49
# Test charging fine at the *beginning* of each charge period
48
$issuingrule->update( { chargeperiod_charge_at => 1 } );
50
my $issuingrule = Koha::CirculationRules->set_rules(
51
    {
52
        categorycode => '*',
53
        itemtype     => '*',
54
        branchcode   => '*',
55
        rules        => {
56
            chargeperiod_charge_at => 1,
57
        }
58
    }
59
);
49
60
50
$period_end = dt_from_string('2000-01-05');
61
$period_end = dt_from_string('2000-01-05');
51
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
62
( $fine ) = CalcFine( {}, q{}, q{}, $period_start, $period_end  );
(-)a/t/db_dependent/Holds.t (-32 / +53 lines)
Lines 250-267 is( $reserve->{'priority'}, '5', "Test AlterPriority(), move to bottom" ); Link Here
250
my ($foreign_bibnum, $foreign_title, $foreign_bibitemnum) = create_helper_biblio('DUMMY');
250
my ($foreign_bibnum, $foreign_title, $foreign_bibitemnum) = create_helper_biblio('DUMMY');
251
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
251
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
252
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_bibnum);
252
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_bibnum);
253
$dbh->do('DELETE FROM issuingrules');
253
$dbh->do('DELETE FROM circulation_rules');
254
$dbh->do(
254
Koha::CirculationRules->set_rules(
255
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
255
    {
256
      VALUES (?, ?, ?, ?, ?)},
256
        categorycode => '*',
257
    {},
257
        branchcode   => '*',
258
    '*', '*', '*', 25, 99
258
        itemtype     => '*',
259
        rules        => {
260
            reservesallowed  => 25,
261
            holds_per_record => 99,
262
        }
263
    }
259
);
264
);
260
$dbh->do(
265
Koha::CirculationRules->set_rules(
261
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
266
    {
262
      VALUES (?, ?, ?, ?, ?)},
267
        categorycode => '*',
263
    {},
268
        branchcode   => '*',
264
    '*', '*', 'CANNOT', 0, 99
269
        itemtype     => 'CANNOT',
270
        rules        => {
271
            reservesallowed  => 0,
272
            holds_per_record => 99,
273
        }
274
    }
265
);
275
);
266
276
267
# make sure some basic sysprefs are set
277
# make sure some basic sysprefs are set
Lines 270-277 t::lib::Mocks::mock_preference('item-level_itypes', 1); Link Here
270
280
271
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
281
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
272
t::lib::Mocks::mock_preference('IndependentBranches', 0);
282
t::lib::Mocks::mock_preference('IndependentBranches', 0);
273
ok(
283
is(
274
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber) eq 'OK',
284
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber), 'OK',
275
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
285
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
276
);
286
);
277
287
Lines 401-413 ok( Link Here
401
411
402
# Test branch item rules
412
# Test branch item rules
403
413
404
$dbh->do('DELETE FROM issuingrules');
405
$dbh->do('DELETE FROM circulation_rules');
414
$dbh->do('DELETE FROM circulation_rules');
406
$dbh->do(
415
Koha::CirculationRules->set_rules(
407
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
416
    {
408
      VALUES (?, ?, ?, ?)},
417
        categorycode => '*',
409
    {},
418
        branchcode   => '*',
410
    '*', '*', '*', 25
419
        itemtype     => '*',
420
        rules        => {
421
            reservesallowed  => 25,
422
            holds_per_record => 99,
423
        }
424
    }
411
);
425
);
412
Koha::CirculationRules->set_rules(
426
Koha::CirculationRules->set_rules(
413
    {
427
    {
Lines 461-471 $dbh->do('DELETE FROM biblio'); Link Here
461
( $item_bibnum, $item_bibitemnum, $itemnumber )
475
( $item_bibnum, $item_bibitemnum, $itemnumber )
462
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $bibnum );
476
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $bibnum );
463
477
464
$dbh->do(
478
Koha::CirculationRules->set_rules(
465
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
479
    {
466
      VALUES (?, ?, ?, ?, ?)},
480
        categorycode => '*',
467
    {},
481
        branchcode   => '*',
468
    '*', '*', 'ONLY1', 1, 99
482
        itemtype     => 'ONLY1',
483
        rules        => {
484
            reservesallowed  => 1,
485
            holds_per_record => 99,
486
        }
487
    }
469
);
488
);
470
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber ),
489
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber ),
471
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
490
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
Lines 479-498 subtest 'Test max_holds per library/patron category' => sub { Link Here
479
    plan tests => 6;
498
    plan tests => 6;
480
499
481
    $dbh->do('DELETE FROM reserves');
500
    $dbh->do('DELETE FROM reserves');
482
    $dbh->do('DELETE FROM issuingrules');
483
    $dbh->do('DELETE FROM circulation_rules');
501
    $dbh->do('DELETE FROM circulation_rules');
484
502
485
    ( $bibnum, $title, $bibitemnum ) = create_helper_biblio('TEST');
503
    ( $bibnum, $title, $bibitemnum ) = create_helper_biblio('TEST');
486
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
504
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
487
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
505
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
488
        $bibnum );
506
        $bibnum );
489
    $dbh->do(
507
    Koha::CirculationRules->set_rules(
490
        q{
508
        {
491
            INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
509
            categorycode => '*',
492
            VALUES (?, ?, ?, ?, ?)
510
            branchcode   => '*',
493
        },
511
            itemtype     => 'TEST',
494
        {},
512
            rules        => {
495
        '*', '*', 'TEST', 99, 99
513
                reservesallowed  => 99,
514
                holds_per_record => 99,
515
            }
516
        }
496
    );
517
    );
497
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
518
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
498
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
519
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
(-)a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t (-8 / +9 lines)
Lines 5-11 use Modern::Perl; Link Here
5
use C4::Context;
5
use C4::Context;
6
use C4::Items;
6
use C4::Items;
7
use C4::Circulation;
7
use C4::Circulation;
8
use Koha::IssuingRule;
8
use Koha::CirculationRules;
9
9
10
use Test::More tests => 4;
10
use Test::More tests => 4;
11
11
Lines 86-104 my $itemnumber2 = Link Here
86
86
87
my $item2 = GetItem( $itemnumber2 );
87
my $item2 = GetItem( $itemnumber2 );
88
88
89
$dbh->do("DELETE FROM issuingrules");
89
$dbh->do("DELETE FROM circulation_rules");
90
my $rule = Koha::IssuingRule->new(
90
Koha::CirculationRules->set_rules(
91
    {
91
    {
92
        categorycode => '*',
92
        categorycode => '*',
93
        itemtype     => '*',
93
        itemtype     => '*',
94
        branchcode   => '*',
94
        branchcode   => '*',
95
        issuelength  => 7,
95
        rules        => {
96
        lengthunit   => 8,
96
            issuelength     => 7,
97
        reservesallowed => 99,
97
            lengthunit      => 8,
98
        onshelfholds => 2,
98
            reservesallowed => 99,
99
            onshelfholds    => 2,
100
        }
99
    }
101
    }
100
);
102
);
101
$rule->store();
102
103
103
my $is = IsAvailableForItemLevelRequest( $item1, $borrower1);
104
my $is = IsAvailableForItemLevelRequest( $item1, $borrower1);
104
is( $is, 0, "Item cannot be held, 2 items available" );
105
is( $is, 0, "Item cannot be held, 2 items available" );
(-)a/t/db_dependent/Koha/IssuingRules.t (-32 / +56 lines)
Lines 23-29 use Test::More tests => 1; Link Here
23
23
24
use Benchmark;
24
use Benchmark;
25
25
26
use Koha::IssuingRules;
26
use Koha::CirculationRules;
27
27
28
use t::lib::TestBuilder;
28
use t::lib::TestBuilder;
29
29
Lines 46-71 subtest 'get_effective_issuing_rule' => sub { Link Here
46
        plan tests => 4;
46
        plan tests => 4;
47
47
48
        my $rule;
48
        my $rule;
49
        Koha::IssuingRules->delete;
49
        Koha::CirculationRules->delete;
50
50
51
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
51
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
52
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
52
        $rule = Koha::CirculationRules->get_effective_rule({
53
            branchcode   => undef,
53
            branchcode   => undef,
54
            categorycode => undef,
54
            categorycode => undef,
55
            itemtype     => undef,
55
            itemtype     => undef,
56
            rule_name    => 'fine',
56
        });
57
        });
57
        is($rule, undef, 'When I attempt to get effective issuing rule by'
58
        is($rule, undef, 'When I attempt to get effective issuing rule by'
58
           .' providing undefined values, then undef is returned.');
59
           .' providing undefined values, then undef is returned.');
59
        ok(Koha::IssuingRule->new({
60
        ok(Koha::CirculationRule->new({
60
            branchcode => '*',
61
            branchcode => '*',
61
            categorycode => '*',
62
            categorycode => '*',
62
            itemtype => '*',
63
            itemtype => '*',
64
            rule_name => 'fine',
63
        })->store, 'Given I added an issuing rule branchcode => *,'
65
        })->store, 'Given I added an issuing rule branchcode => *,'
64
           .' categorycode => *, itemtype => *,');
66
           .' categorycode => *, itemtype => *,');
65
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
67
        $rule = Koha::CirculationRules->get_effective_rule({
66
            branchcode   => undef,
68
            branchcode   => '*',
67
            categorycode => undef,
69
            categorycode => '*',
68
            itemtype     => undef,
70
            itemtype     => '*',
71
            rule_name    => 'fine',
69
        });
72
        });
70
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
73
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
71
           .' issuing rule by providing undefined values, then the above one is'
74
           .' issuing rule by providing undefined values, then the above one is'
Lines 76-191 subtest 'get_effective_issuing_rule' => sub { Link Here
76
        plan tests => 18;
79
        plan tests => 18;
77
80
78
        my $rule;
81
        my $rule;
79
        Koha::IssuingRules->delete;
82
        Koha::CirculationRules->delete;
80
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
83
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
81
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
84
        $rule = Koha::CirculationRules->get_effective_rule({
82
            branchcode   => $branchcode,
85
            branchcode   => $branchcode,
83
            categorycode => $categorycode,
86
            categorycode => $categorycode,
84
            itemtype     => $itemtype,
87
            itemtype     => $itemtype,
88
            rule_name    => 'fine',
85
        });
89
        });
86
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
90
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
87
                        .' is returned.');
91
                        .' is returned.');
88
92
89
        ok(Koha::IssuingRule->new({
93
        ok(Koha::CirculationRule->new({
90
            branchcode => '*',
94
            branchcode => '*',
91
            categorycode => '*',
95
            categorycode => '*',
92
            itemtype => '*',
96
            itemtype => '*',
97
            rule_name => 'fine',
93
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
98
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
94
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
99
        $rule = Koha::CirculationRules->get_effective_rule({
95
            branchcode   => $branchcode,
100
            branchcode   => $branchcode,
96
            categorycode => $categorycode,
101
            categorycode => $categorycode,
97
            itemtype     => $itemtype,
102
            itemtype     => $itemtype,
103
            rule_name    => 'fine',
98
        });
104
        });
99
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
105
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
100
           .' then the above one is returned.');
106
           .' then the above one is returned.');
101
107
102
        ok(Koha::IssuingRule->new({
108
        ok(Koha::CirculationRule->new({
103
            branchcode => '*',
109
            branchcode => '*',
104
            categorycode => '*',
110
            categorycode => '*',
105
            itemtype => $itemtype,
111
            itemtype => $itemtype,
112
            rule_name => 'fine',
106
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
113
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
107
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
114
        $rule = Koha::CirculationRules->get_effective_rule({
108
            branchcode   => $branchcode,
115
            branchcode   => $branchcode,
109
            categorycode => $categorycode,
116
            categorycode => $categorycode,
110
            itemtype     => $itemtype,
117
            itemtype     => $itemtype,
118
            rule_name    => 'fine',
111
        });
119
        });
112
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
120
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
113
           .' then the above one is returned.');
121
           .' then the above one is returned.');
114
122
115
        ok(Koha::IssuingRule->new({
123
        ok(Koha::CirculationRule->new({
116
            branchcode => '*',
124
            branchcode => '*',
117
            categorycode => $categorycode,
125
            categorycode => $categorycode,
118
            itemtype => '*',
126
            itemtype => '*',
127
            rule_name => 'fine',
119
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
128
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
120
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
129
        $rule = Koha::CirculationRules->get_effective_rule({
121
            branchcode   => $branchcode,
130
            branchcode   => $branchcode,
122
            categorycode => $categorycode,
131
            categorycode => $categorycode,
123
            itemtype     => $itemtype,
132
            itemtype     => $itemtype,
133
            rule_name    => 'fine',
124
        });
134
        });
125
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
135
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
126
           .' then the above one is returned.');
136
           .' then the above one is returned.');
127
137
128
        ok(Koha::IssuingRule->new({
138
        ok(Koha::CirculationRule->new({
129
            branchcode => '*',
139
            branchcode => '*',
130
            categorycode => $categorycode,
140
            categorycode => $categorycode,
131
            itemtype => $itemtype,
141
            itemtype => $itemtype,
142
            rule_name => 'fine',
132
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
143
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
133
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
144
        $rule = Koha::CirculationRules->get_effective_rule({
134
            branchcode   => $branchcode,
145
            branchcode   => $branchcode,
135
            categorycode => $categorycode,
146
            categorycode => $categorycode,
136
            itemtype     => $itemtype,
147
            itemtype     => $itemtype,
148
            rule_name    => 'fine',
137
        });
149
        });
138
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
150
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
139
           .' then the above one is returned.');
151
           .' then the above one is returned.');
140
152
141
        ok(Koha::IssuingRule->new({
153
        ok(Koha::CirculationRule->new({
142
            branchcode => $branchcode,
154
            branchcode => $branchcode,
143
            categorycode => '*',
155
            categorycode => '*',
144
            itemtype => '*',
156
            itemtype => '*',
157
            rule_name => 'fine',
145
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
158
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
146
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
159
        $rule = Koha::CirculationRules->get_effective_rule({
147
            branchcode   => $branchcode,
160
            branchcode   => $branchcode,
148
            categorycode => $categorycode,
161
            categorycode => $categorycode,
149
            itemtype     => $itemtype,
162
            itemtype     => $itemtype,
163
            rule_name    => 'fine',
150
        });
164
        });
151
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
165
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
152
           .' then the above one is returned.');
166
           .' then the above one is returned.');
153
167
154
        ok(Koha::IssuingRule->new({
168
        ok(Koha::CirculationRule->new({
155
            branchcode => $branchcode,
169
            branchcode => $branchcode,
156
            categorycode => '*',
170
            categorycode => '*',
157
            itemtype => $itemtype,
171
            itemtype => $itemtype,
172
            rule_name => 'fine',
158
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
173
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
159
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
174
        $rule = Koha::CirculationRules->get_effective_rule({
160
            branchcode   => $branchcode,
175
            branchcode   => $branchcode,
161
            categorycode => $categorycode,
176
            categorycode => $categorycode,
162
            itemtype     => $itemtype,
177
            itemtype     => $itemtype,
178
            rule_name    => 'fine',
163
        });
179
        });
164
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
180
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
165
           .' then the above one is returned.');
181
           .' then the above one is returned.');
166
182
167
        ok(Koha::IssuingRule->new({
183
        ok(Koha::CirculationRule->new({
168
            branchcode => $branchcode,
184
            branchcode => $branchcode,
169
            categorycode => $categorycode,
185
            categorycode => $categorycode,
170
            itemtype => '*',
186
            itemtype => '*',
187
            rule_name => 'fine',
171
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
188
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
172
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
189
        $rule = Koha::CirculationRules->get_effective_rule({
173
            branchcode   => $branchcode,
190
            branchcode   => $branchcode,
174
            categorycode => $categorycode,
191
            categorycode => $categorycode,
175
            itemtype     => $itemtype,
192
            itemtype     => $itemtype,
193
            rule_name    => 'fine',
176
        });
194
        });
177
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
195
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
178
           .' then the above one is returned.');
196
           .' then the above one is returned.');
179
197
180
        ok(Koha::IssuingRule->new({
198
        ok(Koha::CirculationRule->new({
181
            branchcode => $branchcode,
199
            branchcode => $branchcode,
182
            categorycode => $categorycode,
200
            categorycode => $categorycode,
183
            itemtype => $itemtype,
201
            itemtype => $itemtype,
202
            rule_name => 'fine',
184
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
203
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
185
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
204
        $rule = Koha::CirculationRules->get_effective_rule({
186
            branchcode   => $branchcode,
205
            branchcode   => $branchcode,
187
            categorycode => $categorycode,
206
            categorycode => $categorycode,
188
            itemtype     => $itemtype,
207
            itemtype     => $itemtype,
208
            rule_name    => 'fine',
189
        });
209
        });
190
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
210
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
191
           .' then the above one is returned.');
211
           .' then the above one is returned.');
Lines 195-228 subtest 'get_effective_issuing_rule' => sub { Link Here
195
        plan tests => 4;
215
        plan tests => 4;
196
216
197
        my $worst_case = timethis(500,
217
        my $worst_case = timethis(500,
198
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
218
                    sub { Koha::CirculationRules->get_effective_rule({
199
                            branchcode   => 'nonexistent',
219
                            branchcode   => 'nonexistent',
200
                            categorycode => 'nonexistent',
220
                            categorycode => 'nonexistent',
201
                            itemtype     => 'nonexistent',
221
                            itemtype     => 'nonexistent',
222
                            rule_name    => 'nonexistent',
202
                        });
223
                        });
203
                    }
224
                    }
204
                );
225
                );
205
        my $mid_case = timethis(500,
226
        my $mid_case = timethis(500,
206
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
227
                    sub { Koha::CirculationRules->get_effective_rule({
207
                            branchcode   => $branchcode,
228
                            branchcode   => $branchcode,
208
                            categorycode => 'nonexistent',
229
                            categorycode => 'nonexistent',
209
                            itemtype     => 'nonexistent',
230
                            itemtype     => 'nonexistent',
231
                            rule_name    => 'nonexistent',
210
                        });
232
                        });
211
                    }
233
                    }
212
                );
234
                );
213
        my $sec_best_case = timethis(500,
235
        my $sec_best_case = timethis(500,
214
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
236
                    sub { Koha::CirculationRules->get_effective_rule({
215
                            branchcode   => $branchcode,
237
                            branchcode   => $branchcode,
216
                            categorycode => $categorycode,
238
                            categorycode => $categorycode,
217
                            itemtype     => 'nonexistent',
239
                            itemtype     => 'nonexistent',
240
                            rule_name    => 'nonexistent',
218
                        });
241
                        });
219
                    }
242
                    }
220
                );
243
                );
221
        my $best_case = timethis(500,
244
        my $best_case = timethis(500,
222
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
245
                    sub { Koha::CirculationRules->get_effective_rule({
223
                            branchcode   => $branchcode,
246
                            branchcode   => $branchcode,
224
                            categorycode => $categorycode,
247
                            categorycode => $categorycode,
225
                            itemtype     => $itemtype,
248
                            itemtype     => $itemtype,
249
                            rule_name    => 'nonexistent',
226
                        });
250
                        });
227
                    }
251
                    }
228
                );
252
                );
(-)a/t/db_dependent/Koha/Objects.t (-8 / +1 lines)
Lines 24-30 use Test::Warn; Link Here
24
24
25
use Koha::Authority::Types;
25
use Koha::Authority::Types;
26
use Koha::Cities;
26
use Koha::Cities;
27
use Koha::IssuingRules;
28
use Koha::Patron::Category;
27
use Koha::Patron::Category;
29
use Koha::Patron::Categories;
28
use Koha::Patron::Categories;
30
use Koha::Patrons;
29
use Koha::Patrons;
Lines 116-122 subtest 'new' => sub { Link Here
116
};
115
};
117
116
118
subtest 'find' => sub {
117
subtest 'find' => sub {
119
    plan tests => 5;
118
    plan tests => 4;
120
119
121
    # check find on a single PK
120
    # check find on a single PK
122
    my $patron = $builder->build({ source => 'Borrower' });
121
    my $patron = $builder->build({ source => 'Borrower' });
Lines 134-145 subtest 'find' => sub { Link Here
134
        { where => { surname => { '!=', $patron->{surname} }}},
133
        { where => { surname => { '!=', $patron->{surname} }}},
135
    ), undef, 'Additional where clause in find call' );
134
    ), undef, 'Additional where clause in find call' );
136
135
137
    # check find with a composite FK
138
    my $rule = $builder->build({ source => 'Issuingrule' });
139
    my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
140
    is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
141
        'Find returned a Koha object for composite primary key' );
142
143
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
136
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
144
};
137
};
145
138
(-)a/t/db_dependent/Reserves.t (-17 / +25 lines)
Lines 199-210 $requesters{$branch_3} = AddMember( Link Here
199
# to request its items, while $branch_2 will allow its items
199
# to request its items, while $branch_2 will allow its items
200
# to fill holds from anywhere.
200
# to fill holds from anywhere.
201
201
202
$dbh->do('DELETE FROM issuingrules');
202
$dbh->do('DELETE FROM circulation_rules');
203
$dbh->do(
203
Koha::CirculationRules->set_rules(
204
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
204
    {
205
      VALUES (?, ?, ?, ?)},
205
        branchcode   => '*',
206
    {},
206
        categorycode => '*',
207
    '*', '*', '*', 25
207
        itemtype     => '*',
208
        rules        => {
209
            reservesallowed => 25,
210
            holds_per_record => 1,
211
        }
212
    }
208
);
213
);
209
214
210
# CPL allows only its own patrons to request its items
215
# CPL allows only its own patrons to request its items
Lines 565-588 ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $borrower), "Reserving a Link Here
565
my $itype = C4::Reserves::_get_itype($item);
570
my $itype = C4::Reserves::_get_itype($item);
566
my $categorycode = $borrower->{categorycode};
571
my $categorycode = $borrower->{categorycode};
567
my $holdingbranch = $item->{holdingbranch};
572
my $holdingbranch = $item->{holdingbranch};
568
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
573
Koha::CirculationRules->set_rules(
569
    {
574
    {
570
        categorycode => $categorycode,
575
        categorycode => $categorycode,
571
        itemtype     => $itype,
576
        itemtype     => $itype,
572
        branchcode   => $holdingbranch
577
        branchcode   => $holdingbranch,
578
        rules => {
579
            onshelfholds => 1,
580
        }
573
    }
581
    }
574
);
582
);
575
583
576
$dbh->do(
577
    "UPDATE issuingrules SET onshelfholds = 1 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
578
    undef,
579
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
580
);
581
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
584
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
582
$dbh->do(
585
Koha::CirculationRules->set_rules(
583
    "UPDATE issuingrules SET onshelfholds = 0 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
586
    {
584
    undef,
587
        categorycode => $categorycode,
585
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
588
        itemtype     => $itype,
589
        branchcode   => $holdingbranch,
590
        rules => {
591
            onshelfholds => 0,
592
        }
593
    }
586
);
594
);
587
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
595
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
588
596
(-)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, 'OK', 'Hold can be placed with 0 holds' );
287
is( $can, 'OK', 'Hold can be placed with 0 holds' );
(-)a/t/db_dependent/TestBuilder.t (-2 / +2 lines)
Lines 354-360 subtest 'build_object() tests' => sub { Link Here
354
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
354
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
355
355
356
    my $issuing_rule = $builder->build_object(
356
    my $issuing_rule = $builder->build_object(
357
        {   class => 'Koha::IssuingRules',
357
        {   class => 'Koha::CirculationRules',
358
            value => {
358
            value => {
359
                categorycode => $categorycode,
359
                categorycode => $categorycode,
360
                itemtype     => $itemtype
360
                itemtype     => $itemtype
Lines 362-368 subtest 'build_object() tests' => sub { Link Here
362
        }
362
        }
363
    );
363
    );
364
364
365
    is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
365
    is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
366
    is( $issuing_rule->categorycode,
366
    is( $issuing_rule->categorycode,
367
        $categorycode, 'Category code correctly set' );
367
        $categorycode, 'Category code correctly set' );
368
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
368
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
(-)a/t/db_dependent/api/v1/holds.t (-6 / +12 lines)
Lines 32-37 use Koha::Biblios; Link Here
32
use Koha::Biblioitems;
32
use Koha::Biblioitems;
33
use Koha::Items;
33
use Koha::Items;
34
use Koha::Patrons;
34
use Koha::Patrons;
35
use Koha::CirculationRules;
35
36
36
my $schema  = Koha::Database->new->schema;
37
my $schema  = Koha::Database->new->schema;
37
my $builder = t::lib::TestBuilder->new();
38
my $builder = t::lib::TestBuilder->new();
Lines 120-130 my $itemnumber2 = create_item($biblionumber2, 'TEST000002'); Link Here
120
121
121
my $dbh = C4::Context->dbh;
122
my $dbh = C4::Context->dbh;
122
$dbh->do('DELETE FROM reserves');
123
$dbh->do('DELETE FROM reserves');
123
$dbh->do('DELETE FROM issuingrules');
124
$dbh->do('DELETE FROM circulation_rules');
124
    $dbh->do(q{
125
Koha::CirculationRules->set_rules(
125
        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
126
    {
126
        VALUES (?, ?, ?, ?)
127
        categorycode => '*',
127
    }, {}, '*', '*', '*', 1);
128
        branchcode   => '*',
129
        itemtype     => '*',
130
        rules        => {
131
            reservesallowed => 1
132
        }
133
    }
134
);
128
135
129
my $reserve_id = C4::Reserves::AddReserve($branchcode, $borrowernumber,
136
my $reserve_id = C4::Reserves::AddReserve($branchcode, $borrowernumber,
130
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
137
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
131
- 

Return to bug 18936