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

(-)a/C4/Circulation.pm (-158 / +196 lines)
Lines 45-51 use Koha::Biblioitems; Link Here
45
use Koha::DateUtils;
45
use Koha::DateUtils;
46
use Koha::Calendar;
46
use Koha::Calendar;
47
use Koha::Checkouts;
47
use Koha::Checkouts;
48
use Koha::IssuingRules;
49
use Koha::Items;
48
use Koha::Items;
50
use Koha::Patrons;
49
use Koha::Patrons;
51
use Koha::Patron::Debarments;
50
use Koha::Patron::Debarments;
Lines 434-451 sub TooMany { Link Here
434
            # specific rule
433
            # specific rule
435
            if (C4::Context->preference('item-level_itypes')) {
434
            if (C4::Context->preference('item-level_itypes')) {
436
                $count_query .= " WHERE items.itype NOT IN (
435
                $count_query .= " WHERE items.itype NOT IN (
437
                                    SELECT itemtype FROM issuingrules
436
                                    SELECT itemtype FROM circulation_rules
438
                                    WHERE branchcode = ?
437
                                    WHERE branchcode = ?
439
                                    AND   (categorycode = ? OR categorycode = ?)
438
                                    AND   (categorycode = ? OR categorycode = ?)
440
                                    AND   itemtype <> '*'
439
                                    AND   itemtype <> '*'
440
                                    AND   rule_name = 'maxissueqty'
441
                                  ) ";
441
                                  ) ";
442
            } else { 
442
            } else {
443
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
443
                $count_query .= " JOIN  biblioitems USING (biblionumber)
444
                                  WHERE biblioitems.itemtype NOT IN (
444
                                  WHERE biblioitems.itemtype NOT IN (
445
                                    SELECT itemtype FROM issuingrules
445
                                    SELECT itemtype FROM circulation_rules
446
                                    WHERE branchcode = ?
446
                                    WHERE branchcode = ?
447
                                    AND   (categorycode = ? OR categorycode = ?)
447
                                    AND   (categorycode = ? OR categorycode = ?)
448
                                    AND   itemtype <> '*'
448
                                    AND   itemtype <> '*'
449
                                    AND   rule_name = 'maxissueqty'
449
                                  ) ";
450
                                  ) ";
450
            }
451
            }
451
            push @bind_params, $maxissueqty_rule->branchcode;
452
            push @bind_params, $maxissueqty_rule->branchcode;
Lines 1362-1375 sub AddIssue { Link Here
1362
1363
1363
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1364
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1364
            unless ($auto_renew) {
1365
            unless ($auto_renew) {
1365
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1366
                my $rule = Koha::CirculationRules->get_effective_rule(
1366
                    {   categorycode => $borrower->{categorycode},
1367
                    {
1368
                        categorycode => $borrower->{categorycode},
1367
                        itemtype     => $item->{itype},
1369
                        itemtype     => $item->{itype},
1368
                        branchcode   => $branch
1370
                        branchcode   => $branch,
1371
                        rule_name    => 'auto_renew'
1369
                    }
1372
                    }
1370
                );
1373
                );
1371
1374
1372
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1375
                $auto_renew = $rule->rule_value if $rule;
1373
            }
1376
            }
1374
1377
1375
            # Record in the database the fact that the book was issued.
1378
            # Record in the database the fact that the book was issued.
Lines 1490-1556 Get loan length for an itemtype, a borrower type and a branch Link Here
1490
=cut
1493
=cut
1491
1494
1492
sub GetLoanLength {
1495
sub GetLoanLength {
1493
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1496
    my ( $categorycode, $itemtype, $branchcode ) = @_;
1494
    my $dbh = C4::Context->dbh;
1495
    my $sth = $dbh->prepare(qq{
1496
        SELECT issuelength, lengthunit, renewalperiod
1497
        FROM issuingrules
1498
        WHERE   categorycode=?
1499
            AND itemtype=?
1500
            AND branchcode=?
1501
            AND issuelength IS NOT NULL
1502
    });
1503
1497
1504
    # try to find issuelength & return the 1st available.
1498
    # Set search precedences
1505
    # check with borrowertype, itemtype and branchcode, then without one of those parameters
1499
    my @params = (
1506
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1500
        {
1507
    my $loanlength = $sth->fetchrow_hashref;
1501
            categorycode => $categorycode,
1508
1502
            itemtype     => $itemtype,
1509
    return $loanlength
1503
            branchcode   => $branchcode,
1510
      if defined($loanlength) && defined $loanlength->{issuelength};
1504
        },
1511
1505
        {
1512
    $sth->execute( $borrowertype, '*', $branchcode );
1506
            categorycode => $categorycode,
1513
    $loanlength = $sth->fetchrow_hashref;
1507
            itemtype     => '*',
1514
    return $loanlength
1508
            branchcode   => $branchcode,
1515
      if defined($loanlength) && defined $loanlength->{issuelength};
1509
        },
1516
1510
        {
1517
    $sth->execute( '*', $itemtype, $branchcode );
1511
            categorycode => '*',
1518
    $loanlength = $sth->fetchrow_hashref;
1512
            itemtype     => $itemtype,
1519
    return $loanlength
1513
            branchcode   => $branchcode,
1520
      if defined($loanlength) && defined $loanlength->{issuelength};
1514
        },
1521
1515
        {
1522
    $sth->execute( '*', '*', $branchcode );
1516
            categorycode => '*',
1523
    $loanlength = $sth->fetchrow_hashref;
1517
            itemtype     => '*',
1524
    return $loanlength
1518
            branchcode   => $branchcode,
1525
      if defined($loanlength) && defined $loanlength->{issuelength};
1519
        },
1526
1520
        {
1527
    $sth->execute( $borrowertype, $itemtype, '*' );
1521
            categorycode => $categorycode,
1528
    $loanlength = $sth->fetchrow_hashref;
1522
            itemtype     => $itemtype,
1529
    return $loanlength
1523
            branchcode   => '*',
1530
      if defined($loanlength) && defined $loanlength->{issuelength};
1524
        },
1531
1525
        {
1532
    $sth->execute( $borrowertype, '*', '*' );
1526
            categorycode => $categorycode,
1533
    $loanlength = $sth->fetchrow_hashref;
1527
            itemtype     => '*',
1534
    return $loanlength
1528
            branchcode   => '*',
1535
      if defined($loanlength) && defined $loanlength->{issuelength};
1529
        },
1536
1530
        {
1537
    $sth->execute( '*', $itemtype, '*' );
1531
            categorycode => '*',
1538
    $loanlength = $sth->fetchrow_hashref;
1532
            itemtype     => $itemtype,
1539
    return $loanlength
1533
            branchcode   => '*',
1540
      if defined($loanlength) && defined $loanlength->{issuelength};
1534
        },
1541
1535
        {
1542
    $sth->execute( '*', '*', '*' );
1536
            categorycode => '*',
1543
    $loanlength = $sth->fetchrow_hashref;
1537
            itemtype     => '*',
1544
    return $loanlength
1538
            branchcode   => '*',
1545
      if defined($loanlength) && defined $loanlength->{issuelength};
1539
        },
1546
1540
    );
1547
    # if no rule is set => 0 day (hardcoded)
1541
1548
    return {
1542
    # Initialize default values
1549
        issuelength => 0,
1543
    my $rules = {
1544
        issuelength   => 0,
1550
        renewalperiod => 0,
1545
        renewalperiod => 0,
1551
        lengthunit => 'days',
1546
        lengthunit    => 'days',
1552
    };
1547
    };
1553
1548
1549
    # Search for rules!
1550
    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
1551
        foreach my $params (@params) {
1552
            my $rule = Koha::CirculationRules->search(
1553
                {
1554
                    rule_name => $rule_name,
1555
                    %$params,
1556
                }
1557
            )->next();
1558
1559
            if ($rule) {
1560
                $rules->{$rule_name} = $rule->rule_value;
1561
                last;
1562
            }
1563
        }
1564
    }
1565
1566
    return $rules;
1554
}
1567
}
1555
1568
1556
1569
Lines 1565-1583 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1565
sub GetHardDueDate {
1578
sub GetHardDueDate {
1566
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1579
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1567
1580
1568
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1581
    my $rules = Koha::CirculationRules->get_effective_rules(
1569
        {   categorycode => $borrowertype,
1582
        {
1583
            categorycode => $borrowertype,
1570
            itemtype     => $itemtype,
1584
            itemtype     => $itemtype,
1571
            branchcode   => $branchcode
1585
            branchcode   => $branchcode,
1586
            rules        => [ 'hardduedate', 'hardduedatecompare' ],
1572
        }
1587
        }
1573
    );
1588
    );
1574
1589
1575
1590
    if ( defined( $rules->{hardduedate} ) ) {
1576
    if ( defined( $issuing_rule ) ) {
1591
        if ( $rules->{hardduedate} ) {
1577
        if ( $issuing_rule->hardduedate ) {
1592
            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
1578
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1593
        }
1579
        } else {
1594
        else {
1580
            return (undef, undef);
1595
            return ( undef, undef );
1581
        }
1596
        }
1582
    }
1597
    }
1583
}
1598
}
Lines 2264-2277 sub _debar_user_on_return { Link Here
2264
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2279
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2265
2280
2266
    my $circcontrol = C4::Context->preference('CircControl');
2281
    my $circcontrol = C4::Context->preference('CircControl');
2267
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2282
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2268
        {   categorycode => $borrower->{categorycode},
2283
        {   categorycode => $borrower->{categorycode},
2269
            itemtype     => $item->{itype},
2284
            itemtype     => $item->{itype},
2270
            branchcode   => $branchcode
2285
            branchcode   => $branchcode,
2286
            rules => [
2287
                'finedays',
2288
                'lengthunit',
2289
                'firstremind',
2290
                'maxsuspensiondays',
2291
            ]
2271
        }
2292
        }
2272
    );
2293
    );
2273
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2294
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2274
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2295
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2275
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2296
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2276
2297
2277
    if ($finedays) {
2298
    if ($finedays) {
Lines 2282-2288 sub _debar_user_on_return { Link Here
2282
2303
2283
        # grace period is measured in the same units as the loan
2304
        # grace period is measured in the same units as the loan
2284
        my $grace =
2305
        my $grace =
2285
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2306
          DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
2286
2307
2287
        my $deltadays = DateTime::Duration->new(
2308
        my $deltadays = DateTime::Duration->new(
2288
            days => $chargeable_units
2309
            days => $chargeable_units
Lines 2292-2298 sub _debar_user_on_return { Link Here
2292
2313
2293
            # If the max suspension days is < than the suspension days
2314
            # If the max suspension days is < than the suspension days
2294
            # the suspension days is limited to this maximum period.
2315
            # the suspension days is limited to this maximum period.
2295
            my $max_sd = $issuing_rule->maxsuspensiondays;
2316
            my $max_sd = $issuing_rule->{maxsuspensiondays};
2296
            if ( defined $max_sd ) {
2317
            if ( defined $max_sd ) {
2297
                $max_sd = DateTime::Duration->new( days => $max_sd );
2318
                $max_sd = DateTime::Duration->new( days => $max_sd );
2298
                $suspension_days = $max_sd
2319
                $suspension_days = $max_sd
Lines 2712-2726 sub CanBookBeRenewed { Link Here
2712
    return ( 1, undef ) if $override_limit;
2733
    return ( 1, undef ) if $override_limit;
2713
2734
2714
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2735
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2715
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2736
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2716
        {   categorycode => $patron->categorycode,
2737
        {
2738
            categorycode => $patron->categorycode,
2717
            itemtype     => $item->{itype},
2739
            itemtype     => $item->{itype},
2718
            branchcode   => $branchcode
2740
            branchcode   => $branchcode,
2741
            rules => [
2742
                'renewalsallowed',
2743
                'no_auto_renewal_after',
2744
                'no_auto_renewal_after_hard_limit',
2745
                'lengthunit',
2746
                'norenewalbefore',
2747
            ]
2719
        }
2748
        }
2720
    );
2749
    );
2721
2750
2722
    return ( 0, "too_many" )
2751
    return ( 0, "too_many" )
2723
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2752
      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
2724
2753
2725
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2754
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2726
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2755
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2740-2762 sub CanBookBeRenewed { Link Here
2740
            return ( 0, 'auto_account_expired' );
2769
            return ( 0, 'auto_account_expired' );
2741
        }
2770
        }
2742
2771
2743
        if ( defined $issuing_rule->no_auto_renewal_after
2772
        if ( defined $issuing_rule->{no_auto_renewal_after}
2744
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2773
                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
2745
            # Get issue_date and add no_auto_renewal_after
2774
            # Get issue_date and add no_auto_renewal_after
2746
            # If this is greater than today, it's too late for renewal.
2775
            # If this is greater than today, it's too late for renewal.
2747
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2776
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2748
            $maximum_renewal_date->add(
2777
            $maximum_renewal_date->add(
2749
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2778
                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
2750
            );
2779
            );
2751
            my $now = dt_from_string;
2780
            my $now = dt_from_string;
2752
            if ( $now >= $maximum_renewal_date ) {
2781
            if ( $now >= $maximum_renewal_date ) {
2753
                return ( 0, "auto_too_late" );
2782
                return ( 0, "auto_too_late" );
2754
            }
2783
            }
2755
        }
2784
        }
2756
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2785
        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
2757
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2786
                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
2758
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2787
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2759
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2788
            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
2760
                return ( 0, "auto_too_late" );
2789
                return ( 0, "auto_too_late" );
2761
            }
2790
            }
2762
        }
2791
        }
Lines 2770-2786 sub CanBookBeRenewed { Link Here
2770
        }
2799
        }
2771
    }
2800
    }
2772
2801
2773
    if ( defined $issuing_rule->norenewalbefore
2802
    if ( defined $issuing_rule->{norenewalbefore}
2774
        and $issuing_rule->norenewalbefore ne "" )
2803
        and $issuing_rule->{norenewalbefore} ne "" )
2775
    {
2804
    {
2776
2805
2777
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2806
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2778
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2807
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2779
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2808
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
2780
2809
2781
        # Depending on syspref reset the exact time, only check the date
2810
        # Depending on syspref reset the exact time, only check the date
2782
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2811
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2783
            and $issuing_rule->lengthunit eq 'days' )
2812
            and $issuing_rule->{lengthunit} eq 'days' )
2784
        {
2813
        {
2785
            $soonestrenewal->truncate( to => 'day' );
2814
            $soonestrenewal->truncate( to => 'day' );
2786
        }
2815
        }
Lines 2988-3001 sub GetRenewCount { Link Here
2988
    # $item and $borrower should be calculated
3017
    # $item and $borrower should be calculated
2989
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
3018
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
2990
3019
2991
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3020
    my $rule = Koha::CirculationRules->get_effective_rule(
2992
        {   categorycode => $patron->categorycode,
3021
        {
3022
            categorycode => $patron->categorycode,
2993
            itemtype     => $item->{itype},
3023
            itemtype     => $item->{itype},
2994
            branchcode   => $branchcode
3024
            branchcode   => $branchcode,
3025
            rule_name    => 'renewalsallowed',
2995
        }
3026
        }
2996
    );
3027
    );
2997
3028
2998
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
3029
    $renewsallowed = $rule ? $rule->rule_value : 0;
2999
    $renewsleft    = $renewsallowed - $renewcount;
3030
    $renewsleft    = $renewsallowed - $renewcount;
3000
    if($renewsleft < 0){ $renewsleft = 0; }
3031
    if($renewsleft < 0){ $renewsleft = 0; }
3001
    return ( $renewcount, $renewsallowed, $renewsleft );
3032
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3033-3057 sub GetSoonestRenewDate { Link Here
3033
      or return;
3064
      or return;
3034
3065
3035
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3066
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3036
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3067
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3037
        {   categorycode => $patron->categorycode,
3068
        {   categorycode => $patron->categorycode,
3038
            itemtype     => $item->{itype},
3069
            itemtype     => $item->{itype},
3039
            branchcode   => $branchcode
3070
            branchcode   => $branchcode,
3071
            rules => [
3072
                'norenewalbefore',
3073
                'lengthunit',
3074
            ]
3040
        }
3075
        }
3041
    );
3076
    );
3042
3077
3043
    my $now = dt_from_string;
3078
    my $now = dt_from_string;
3044
    return $now unless $issuing_rule;
3079
    return $now unless $issuing_rule;
3045
3080
3046
    if ( defined $issuing_rule->norenewalbefore
3081
    if ( defined $issuing_rule->{norenewalbefore}
3047
        and $issuing_rule->norenewalbefore ne "" )
3082
        and $issuing_rule->{norenewalbefore} ne "" )
3048
    {
3083
    {
3049
        my $soonestrenewal =
3084
        my $soonestrenewal =
3050
          dt_from_string( $itemissue->date_due )->subtract(
3085
          dt_from_string( $itemissue->date_due )->subtract(
3051
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3086
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3052
3087
3053
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3088
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3054
            and $issuing_rule->lengthunit eq 'days' )
3089
            and $issuing_rule->{lengthunit} eq 'days' )
3055
        {
3090
        {
3056
            $soonestrenewal->truncate( to => 'day' );
3091
            $soonestrenewal->truncate( to => 'day' );
3057
        }
3092
        }
Lines 3092-3121 sub GetLatestAutoRenewDate { Link Here
3092
      or return;
3127
      or return;
3093
3128
3094
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3129
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3095
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3130
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3096
        {   categorycode => $patron->categorycode,
3131
        {
3132
            categorycode => $patron->categorycode,
3097
            itemtype     => $item->{itype},
3133
            itemtype     => $item->{itype},
3098
            branchcode   => $branchcode
3134
            branchcode   => $branchcode,
3135
            rules => [
3136
                'no_auto_renewal_after',
3137
                'no_auto_renewal_after_hard_limit',
3138
                'lengthunit',
3139
            ]
3099
        }
3140
        }
3100
    );
3141
    );
3101
3142
3102
    return unless $issuing_rule;
3143
    return unless $circulation_rules;
3103
    return
3144
    return
3104
      if ( not $issuing_rule->no_auto_renewal_after
3145
      if ( not $circulation_rules->{no_auto_renewal_after}
3105
            or $issuing_rule->no_auto_renewal_after eq '' )
3146
            or $circulation_rules->{no_auto_renewal_after} eq '' )
3106
      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
3147
      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
3107
             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
3148
             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
3108
3149
3109
    my $maximum_renewal_date;
3150
    my $maximum_renewal_date;
3110
    if ( $issuing_rule->no_auto_renewal_after ) {
3151
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3111
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3152
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3112
        $maximum_renewal_date->add(
3153
        $maximum_renewal_date->add(
3113
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3154
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3114
        );
3155
        );
3115
    }
3156
    }
3116
3157
3117
    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
3158
    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
3118
        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
3159
        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
3119
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3160
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3120
    }
3161
    }
3121
    return $maximum_renewal_date;
3162
    return $maximum_renewal_date;
Lines 3162-3180 sub GetIssuingCharges { Link Here
3162
        $item_type = $item_data->{itemtype};
3203
        $item_type = $item_data->{itemtype};
3163
        $charge    = $item_data->{rentalcharge};
3204
        $charge    = $item_data->{rentalcharge};
3164
        my $branch = C4::Context::mybranch();
3205
        my $branch = C4::Context::mybranch();
3165
        my $discount_query = q|SELECT rentaldiscount,
3206
        my $patron = Koha::Patrons->find( $borrowernumber );
3166
            issuingrules.itemtype, issuingrules.branchcode
3207
        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
3167
            FROM borrowers
3208
        if ($discount) {
3168
            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
3169
            WHERE borrowers.borrowernumber = ?
3170
            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
3171
            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
3172
        my $discount_sth = $dbh->prepare($discount_query);
3173
        $discount_sth->execute( $borrowernumber, $item_type, $branch );
3174
        my $discount_rules = $discount_sth->fetchall_arrayref({});
3175
        if (@{$discount_rules}) {
3176
            # We may have multiple rules so get the most specific
3209
            # We may have multiple rules so get the most specific
3177
            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
3178
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3210
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3179
        }
3211
        }
3180
        if ($charge) {
3212
        if ($charge) {
Lines 3187-3223 sub GetIssuingCharges { Link Here
3187
3219
3188
# Select most appropriate discount rule from those returned
3220
# Select most appropriate discount rule from those returned
3189
sub _get_discount_from_rule {
3221
sub _get_discount_from_rule {
3190
    my ($rules_ref, $branch, $itemtype) = @_;
3222
    my ($categorycode, $branchcode, $itemtype) = @_;
3191
    my $discount;
3192
3223
3193
    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
3224
    # Set search precedences
3194
        $discount = $rules_ref->[0]->{rentaldiscount};
3225
    my @params = (
3195
        return (defined $discount) ? $discount : 0;
3226
        {
3196
    }
3227
            branchcode   => $branchcode,
3197
    # could have up to 4 does one match $branch and $itemtype
3228
            itemtype     => $itemtype,
3198
    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
3229
            categorycode => $categorycode,
3199
    if (@d) {
3230
        },
3200
        $discount = $d[0]->{rentaldiscount};
3231
        {
3201
        return (defined $discount) ? $discount : 0;
3232
            branchcode   => '*',
3202
    }
3233
            categorycode => $categorycode,
3203
    # do we have item type + all branches
3234
            itemtype     => $itemtype,
3204
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
3235
        },
3205
    if (@d) {
3236
        {
3206
        $discount = $d[0]->{rentaldiscount};
3237
            branchcode   => $branchcode,
3207
        return (defined $discount) ? $discount : 0;
3238
            categorycode => $categorycode,
3208
    }
3239
            itemtype     => '*',
3209
    # do we all item types + this branch
3240
        },
3210
    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
3241
        {
3211
    if (@d) {
3242
            branchcode   => '*',
3212
        $discount = $d[0]->{rentaldiscount};
3243
            categorycode => $categorycode,
3213
        return (defined $discount) ? $discount : 0;
3244
            itemtype     => '*',
3214
    }
3245
        },
3215
    # so all and all (surely we wont get here)
3246
    );
3216
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
3247
3217
    if (@d) {
3248
    foreach my $params (@params) {
3218
        $discount = $d[0]->{rentaldiscount};
3249
        my $rule = Koha::CirculationRules->search(
3219
        return (defined $discount) ? $discount : 0;
3250
            {
3251
                rule_name => 'rentaldiscount',
3252
                %$params,
3253
            }
3254
        )->next();
3255
3256
        return $rule->rule_value if $rule;
3220
    }
3257
    }
3258
3221
    # none of the above
3259
    # none of the above
3222
    return 0;
3260
    return 0;
3223
}
3261
}
(-)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::Lines;
37
use Koha::Account::Lines;
38
use Koha::Account::Offsets;
38
use Koha::Account::Offsets;
39
use Koha::IssuingRules;
40
use Koha::Libraries;
39
use Koha::Libraries;
41
40
42
use vars qw(@ISA @EXPORT);
41
use vars qw(@ISA @EXPORT);
Lines 243-270 sub CalcFine { Link Here
243
    my $start_date = $due_dt->clone();
242
    my $start_date = $due_dt->clone();
244
    # get issuingrules (fines part will be used)
243
    # get issuingrules (fines part will be used)
245
    my $itemtype = $item->{itemtype} || $item->{itype};
244
    my $itemtype = $item->{itemtype} || $item->{itype};
246
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
245
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
246
        {
247
            categorycode => $bortype,
248
            itemtype     => $itemtype,
249
            branchcode   => $branchcode,
250
            rules => [
251
                'lengthunit',
252
                'firstremind',
253
                'chargeperiod',
254
                'chargeperiod_charge_at',
255
                'fine',
256
                'overduefinescap',
257
                'cap_fine_to_replacement_price',
258
                'chargename',
259
            ]
260
        }
261
    );
247
262
248
    return unless $issuing_rule; # If not rule exist, there is no fine
263
    return unless $issuing_rule; # If not rule exist, there is no fine
249
264
250
    my $fine_unit = $issuing_rule->lengthunit || 'days';
265
    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
251
266
252
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
267
    my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
253
    my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
268
    my $units_minus_grace = $chargeable_units - $issuing_rule->{firstremind};
254
    my $amount = 0;
269
    my $amount = 0;
255
    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
270
    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
256
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
271
        my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
257
        my $charge_periods = $units / $issuing_rule->chargeperiod;
272
        my $charge_periods = $units / $issuing_rule->{chargeperiod};
258
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
273
        # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
259
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
274
        # if chargeperiod_charge_at = 0, we charge at the end of each charge period
260
        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
275
        $charge_periods = $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
261
        $amount = $charge_periods * $issuing_rule->fine;
276
        $amount = $charge_periods * $issuing_rule->{fine};
262
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
277
    } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
263
278
264
    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
279
    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
265
    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
280
    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
266
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
281
    $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
267
    return ($amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
282
    return ($amount, $issuing_rule->{chargename}, $units_minus_grace, $chargeable_units);
268
    # FIXME: chargename is NEVER populated anywhere.
283
    # FIXME: chargename is NEVER populated anywhere.
269
}
284
}
270
285
(-)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 1217-1226 sub _get_itype { Link Here
1217
}
1216
}
1218
1217
1219
sub _OnShelfHoldsAllowed {
1218
sub _OnShelfHoldsAllowed {
1220
    my ($itype,$borrowercategory,$branchcode) = @_;
1219
    my ( $itype, $borrowercategory, $branchcode ) = @_;
1221
1220
1222
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowercategory, itemtype => $itype, branchcode => $branchcode });
1221
    my $rule = Koha::CirculationRules->get_effective_rule(
1223
    return $issuing_rule ? $issuing_rule->onshelfholds : undef;
1222
        {
1223
            categorycode => $borrowercategory,
1224
            itemtype     => $itype,
1225
            branchcode   => $branchcode,
1226
            rule_name    => 'onshelfholds',
1227
        }
1228
    );
1229
    return $rule ? $rule->rule_value : undef;
1224
}
1230
}
1225
1231
1226
=head2 AlterPriority
1232
=head2 AlterPriority
Lines 2092-2115 patron category, itemtype, and library. Link Here
2092
sub GetHoldRule {
2098
sub GetHoldRule {
2093
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2099
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2094
2100
2095
    my $dbh = C4::Context->dbh;
2101
    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
2096
2102
        {
2097
    my $sth = $dbh->prepare(
2103
            itemtype     => $itemtype,
2098
        q{
2104
            categorycode => $categorycode,
2099
         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record
2105
            branchcode   => $branchcode,
2100
           FROM issuingrules
2106
            rule_name    => 'reservesallowed',
2101
          WHERE (categorycode in (?,'*') )
2107
            order_by     => {
2102
            AND (itemtype IN (?,'*'))
2108
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2103
            AND (branchcode IN (?,'*'))
2109
            }
2104
       ORDER BY categorycode DESC,
2105
                itemtype     DESC,
2106
                branchcode   DESC
2107
        }
2110
        }
2108
    );
2111
    );
2112
    return unless $reservesallowed;;
2113
2114
    my $rules;
2115
    $rules->{reservesallowed} = $reservesallowed->rule_value;
2116
    $rules->{itemtype}        = $reservesallowed->itemtype;
2117
    $rules->{categorycode}    = $reservesallowed->categorycode;
2118
    $rules->{branchcode}      = $reservesallowed->branchcode;
2109
2119
2110
    $sth->execute( $categorycode, $itemtype, $branchcode );
2120
    my $holds_per_record = Koha::CirculationRules->get_effective_rule(
2121
        {
2122
            itemtype     => $itemtype,
2123
            categorycode => $categorycode,
2124
            branchcode   => $branchcode,
2125
            rule_name    => 'holds_per_record',
2126
            order_by     => {
2127
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2128
            }
2129
        }
2130
    );
2131
    $rules->{holds_per_record} = $holds_per_record->rule_value if $holds_per_record;
2111
2132
2112
    return $sth->fetchrow_hashref();
2133
    return $rules;
2113
}
2134
}
2114
2135
2115
=head1 AUTHOR
2136
=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 127-136 sub article_request_type_for_bib { Link Here
127
    my $borrowertype = $borrower->categorycode;
127
    my $borrowertype = $borrower->categorycode;
128
    my $itemtype     = $self->itemtype();
128
    my $itemtype     = $self->itemtype();
129
129
130
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
130
    my $rule = Koha::CirculationRules->get_effective_rule(
131
        {
132
            rule_name    => 'article_requests',
133
            categorycode => $borrowertype,
134
            itemtype     => $itemtype,
135
        }
136
    );
131
137
132
    return q{} unless $issuing_rule;
138
    return q{} unless $rule;
133
    return $issuing_rule->article_requests || q{}
139
    return $rule->rule_value || q{}
134
}
140
}
135
141
136
=head3 article_request_type_for_items
142
=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 (-115 lines)
Lines 1-115 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 get_opacitemholds_policy
75
76
my $can_place_a_hold_at_item_level = Koha::IssuingRules->get_opacitemholds_policy( { patron => $patron, item => $item } );
77
78
Return 'Y' or 'F' if the patron can place a hold on this item according to the issuing rules
79
and the "Item level holds" (opacitemholds).
80
Can be 'N' - Don't allow, 'Y' - Allow, and 'F' - Force
81
82
=cut
83
84
sub get_opacitemholds_policy {
85
    my ( $class, $params ) = @_;
86
87
    my $item   = $params->{item};
88
    my $patron = $params->{patron};
89
90
    return unless $item or $patron;
91
92
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
93
        {
94
            categorycode => $patron->categorycode,
95
            itemtype     => $item->effective_itemtype,
96
            branchcode   => $item->homebranch,
97
        }
98
    );
99
100
    return $issuing_rule ? $issuing_rule->opacitemholds : undef;
101
}
102
103
=head3 type
104
105
=cut
106
107
sub _type {
108
    return 'Issuingrule';
109
}
110
111
sub object_class {
112
    return 'Koha::IssuingRule';
113
}
114
115
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 77-84 if ($op eq 'delete') { Link Here
77
    my $categorycode = $input->param('categorycode');
75
    my $categorycode = $input->param('categorycode');
78
    $debug and warn "deleting $1 $2 $branch";
76
    $debug and warn "deleting $1 $2 $branch";
79
77
80
    my $sth_Idelete = $dbh->prepare("delete from issuingrules where branchcode=? and categorycode=? and itemtype=?");
78
    Koha::CirculationRules->set_rules(
81
    $sth_Idelete->execute($branch, $categorycode, $itemtype);
79
        {
80
            categorycode => $categorycode,
81
            branchcode   => $branch,
82
            itemtype     => $itemtype,
83
            rules        => {
84
                restrictedtype                   => undef,
85
                rentaldiscount                   => undef,
86
                fine                             => undef,
87
                finedays                         => undef,
88
                maxsuspensiondays                => undef,
89
                firstremind                      => undef,
90
                chargeperiod                     => undef,
91
                chargeperiod_charge_at           => undef,
92
                accountsent                      => undef,
93
                issuelength                      => undef,
94
                lengthunit                       => undef,
95
                hardduedate                      => undef,
96
                hardduedatecompare               => undef,
97
                renewalsallowed                  => undef,
98
                renewalperiod                    => undef,
99
                norenewalbefore                  => undef,
100
                auto_renew                       => undef,
101
                no_auto_renewal_after            => undef,
102
                no_auto_renewal_after_hard_limit => undef,
103
                reservesallowed                  => undef,
104
                holds_per_record                 => undef,
105
                overduefinescap                  => undef,
106
                cap_fine_to_replacement_price    => undef,
107
                onshelfholds                     => undef,
108
                opacitemholds                    => undef,
109
                article_requests                 => undef,
110
            }
111
        }
112
    );
82
}
113
}
83
elsif ($op eq 'delete-branch-cat') {
114
elsif ($op eq 'delete-branch-cat') {
84
    my $categorycode  = $input->param('categorycode');
115
    my $categorycode  = $input->param('categorycode');
Lines 279-291 elsif ($op eq 'add') { Link Here
279
        article_requests              => $article_requests,
310
        article_requests              => $article_requests,
280
    };
311
    };
281
312
282
    my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
283
    if ($issuingrule) {
284
        $issuingrule->set($params)->store();
285
    } else {
286
        Koha::IssuingRule->new()->set($params)->store();
287
    }
288
289
    Koha::CirculationRules->set_rules(
313
    Koha::CirculationRules->set_rules(
290
        {
314
        {
291
            categorycode => $bor,
315
            categorycode => $bor,
Lines 294-299 elsif ($op eq 'add') { Link Here
294
            rules        => {
318
            rules        => {
295
                maxissueqty       => $maxissueqty,
319
                maxissueqty       => $maxissueqty,
296
                maxonsiteissueqty => $maxonsiteissueqty,
320
                maxonsiteissueqty => $maxonsiteissueqty,
321
                %$params,
297
            }
322
            }
298
        }
323
        }
299
    );
324
    );
Lines 530-591 $template->param( Link Here
530
555
531
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
556
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
532
557
533
my @row_loop;
534
my $itemtypes = Koha::ItemTypes->search_with_localization;
558
my $itemtypes = Koha::ItemTypes->search_with_localization;
535
559
536
my $sth2 = $dbh->prepare("
537
    SELECT  issuingrules.*,
538
            itemtypes.description AS humanitemtype,
539
            categories.description AS humancategorycode,
540
            COALESCE( localization.translation, itemtypes.description ) AS translated_description
541
    FROM issuingrules
542
    LEFT JOIN itemtypes
543
        ON (itemtypes.itemtype = issuingrules.itemtype)
544
    LEFT JOIN categories
545
        ON (categories.categorycode = issuingrules.categorycode)
546
    LEFT JOIN localization ON issuingrules.itemtype = localization.code
547
        AND localization.entity = 'itemtypes'
548
        AND localization.lang = ?
549
    WHERE issuingrules.branchcode = ?
550
");
551
$sth2->execute($language, $branch);
552
553
while (my $row = $sth2->fetchrow_hashref) {
554
    $row->{'current_branch'} ||= $row->{'branchcode'};
555
    $row->{humanitemtype} ||= $row->{itemtype};
556
    $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
557
    $row->{'humancategorycode'} ||= $row->{'categorycode'};
558
    $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
559
    $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
560
    if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
561
       my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
562
       $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
563
       $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
564
       $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
565
       $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
566
    } else {
567
       $row->{'hardduedate'} = 0;
568
    }
569
    if ($row->{no_auto_renewal_after_hard_limit}) {
570
       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
571
       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
572
    }
573
574
    push @row_loop, $row;
575
}
576
577
my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
578
579
$template->param(show_branch_cat_rule_form => 1);
560
$template->param(show_branch_cat_rule_form => 1);
580
561
581
$template->param(
562
$template->param(
582
    patron_categories => $patron_categories,
563
    patron_categories => $patron_categories,
583
                        itemtypeloop => $itemtypes,
564
    itemtypeloop      => $itemtypes,
584
                        rules => \@sorted_row_loop,
565
    humanbranch       => ( $branch ne '*' ? $branch : '' ),
585
                        humanbranch => ($branch ne '*' ? $branch : ''),
566
    current_branch    => $branch,
586
                        current_branch => $branch,
567
);
587
                        definedbranch => scalar(@sorted_row_loop)>0
588
                        );
589
output_html_with_http_headers $input, $cookie, $template->output;
568
output_html_with_http_headers $input, $cookie, $template->output;
590
569
591
exit 0;
570
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 (-113 / +154 lines)
Lines 1-14 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
[% SET footerjs = 1 %]
6
[% SET footerjs = 1 %]
5
7
6
[% SET branchcode = humanbranch %]
8
[% SET branchcode = humanbranch || '*' %]
7
9
8
[% SET categorycodes = ['*'] %]
10
[% SET categorycodes = [] %]
9
[% FOREACH pc IN patron_categories %]
11
[% FOREACH pc IN patron_categories %]
10
    [% categorycodes.push( pc.id ) %]
12
    [% categorycodes.push( pc.id ) %]
11
[% END %]
13
[% END %]
14
[% categorycodes.push('*') %]
15
16
[% SET itemtypes = [] %]
17
[% FOREACH i IN itemtypeloop %]
18
    [% itemtypes.push( i.itemtype ) %]
19
[% END %]
20
[% itemtypes.push('*') %]
12
21
13
[% INCLUDE 'doc-head-open.inc' %]
22
[% INCLUDE 'doc-head-open.inc' %]
14
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
23
<title>Koha &rsaquo; Administration &rsaquo; Circulation and fine rules</title>
Lines 106-222 Link Here
106
            </tr>
115
            </tr>
107
            </thead>
116
            </thead>
108
            <tbody>
117
            <tbody>
109
				[% FOREACH rule IN rules %]
118
                [% SET row_count = 0 %]
110
					<tr id="row_[% loop.count %]">
119
                [% FOREACH c IN categorycodes %]
111
							<td>[% IF ( rule.default_humancategorycode ) %]
120
                    [% FOREACH i IN itemtypes %]
112
									<em>All</em>
121
                        [% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
113
								[% ELSE %]
122
                        [% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
114
									[% rule.humancategorycode %]
123
                        [% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
115
								[% END %]
124
                        [% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
116
							</td>
125
                        [% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
117
                            <td>[% IF rule.default_translated_description %]
126
                        [% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
118
									<em>All</em>
127
                        [% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
119
								[% ELSE %]
128
                        [% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
120
									[% rule.translated_description %]
129
                        [% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
121
								[% END %]
130
                        [% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
122
							</td>
131
                        [% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
123
                                                        <td class="actions">
132
                        [% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
124
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
133
                        [% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
125
                                                          <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>
134
                        [% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
126
                                                        </td>
135
                        [% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
127
136
                        [% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
128
							<td>
137
                        [% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
129
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
138
                        [% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
130
                                [% IF rule_value  %]
139
                        [% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
131
                                    [% rule_value %]
140
                        [% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
132
                                [% ELSE %]
141
                        [% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
133
                                    Unlimited
142
                        [% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
134
                                [% END %]
143
                        [% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
135
							</td>
144
                        [% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
136
							<td>
145
                        [% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
137
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
146
                        [% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
138
                                [% IF rule_value  %]
147
139
                                    [% rule_value %]
148
                        [% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
140
                                [% ELSE %]
149
                                        || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || renewalsallowed
141
                                    Unlimited
150
                                        || renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
142
                                [% END %]
151
                                        || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
143
							</td>
152
                        [% IF show_rule %]
144
							<td>[% rule.issuelength %]</td>
153
                            [% SET row_count = row_count + 1 %]
145
							<td>
154
                            <tr row_countd="row_[% row_count %]">
146
							    [% rule.lengthunit %]
155
                                    <td>
147
							</td>
156
                                        [% IF c == '*' %]
148
                            <td>
157
                                            <em>All</em>
149
                              [% IF ( rule.hardduedate ) %]
158
                                        [% ELSE %]
150
                                [% IF ( rule.hardduedatebefore ) %]
159
                                            [% Categories.GetName(c) %]
151
                                  before [% rule.hardduedate %]
160
                                        [% END %]
152
                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
161
                                    </td>
153
                                [% ELSIF ( rule.hardduedateexact ) %]
162
                                    <td>
154
                                  on [% rule.hardduedate %]
163
                                        [% IF i == '*' %]
155
                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
164
                                            <em>All</em>
156
                                [% ELSIF ( rule.hardduedateafter ) %]
165
                                        [% ELSE %]
157
                                  after [% rule.hardduedate %]
166
                                            [% ItemTypes.GetDescription(i) %]
158
                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
167
                                        [% END %]
159
                                [% END %]
168
                                    </td>
160
                              [% ELSE %]
169
                                    <td>
161
                                None defined
170
                                        [% IF maxissueqty  %]
162
                              [% END %]
171
                                            [% maxissueqty %]
163
                            </td>
172
                                        [% ELSE %]
164
							<td>[% rule.fine %]</td>
173
                                            Unlimited
165
							<td>[% rule.chargeperiod %]</td>
174
                                        [% END %]
166
                <td>[% IF rule.chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
175
                                    </td>
167
							<td>[% rule.firstremind %]</td>
176
                                    <td>
168
                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
177
                                        [% IF maxonsiteissueqty  %]
169
                            <td>
178
                                            [% maxonsiteissueqty %]
170
                                [% IF rule.cap_fine_to_replacement_price %]
179
                                        [% ELSE %]
171
                                    <input type="checkbox" checked="checked" disabled="disabled" />
180
                                            Unlimited
172
                                [% ELSE %]
181
                                        [% END %]
173
                                    <input type="checkbox" disabled="disabled" />
182
                                    </td>
174
                                [% END %]
183
                                    <td>[% issuelength %]</td>
175
                            </td>
184
                                    <td>
176
							<td>[% rule.finedays %]</td>
185
                                        [% lengthunit %]
177
                            <td>[% rule.maxsuspensiondays %]</td>
186
                                    </td>
178
							<td>[% rule.renewalsallowed %]</td>
187
                                    <td>
179
                            <td>[% rule.renewalperiod %]</td>
188
                                      [% IF ( hardduedate ) %]
180
                            <td>[% rule.norenewalbefore %]</td>
189
                                        [% IF ( hardduedatecompare == '-1' ) %]
181
                            <td>
190
                                          before [% hardduedate | $KohaDates %]
182
                                [% IF ( rule.auto_renew ) %]
191
                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
183
                                Yes
192
                                        [% ELSIF ( hardduedatecompare == '0' ) %]
184
                                [% ELSE %]
193
                                          on [% hardduedate | $KohaDates %]
185
                                No
194
                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
186
                                [% END %]
195
                                        [% ELSIF ( hardduedatecompare == '1' ) %]
187
                            </td>
196
                                          after [% hardduedate | $KohaDates %]
188
                            <td>[% rule.no_auto_renewal_after %]</td>
197
                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
189
                            <td>[% rule.no_auto_renewal_after_hard_limit %]</td>
198
                                        [% END %]
190
							<td>[% rule.reservesallowed %]</td>
199
                                      [% ELSE %]
191
                                                        <td>[% rule.holds_per_record %]</td>
200
                                        None defined
192
                                                        <td>
201
                                      [% END %]
193
                                                            [% IF rule.onshelfholds == 1 %]
202
                                    </td>
194
                                                                Yes
203
                                    <td>[% fine %]</td>
195
                                                            [% ELSIF rule.onshelfholds == 2 %]
204
                                    <td>[% chargeperiod %]</td>
196
                                                                If all unavailable
205
                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
197
                                                            [% ELSE %]
206
                                    <td>[% firstremind %]</td>
198
                                                                If any unavailable
207
                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
199
                                                            [% END %]</td>
208
                                    <td>
200
                                                        <td>[% IF rule.opacitemholds == 'F'%]Force[% ELSIF rule.opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
209
                                        [% IF cap_fine_to_replacement_price %]
201
                                                        <td>
210
                                            <input type="checkbox" checked="checked" disabled="disabled" />
202
                                                            [% IF rule.article_requests == 'no' %]
211
                                        [% ELSE %]
203
                                                                No
212
                                            <input type="checkbox" disabled="disabled" />
204
                                                            [% ELSIF rule.article_requests == 'yes' %]
213
                                        [% END %]
205
                                                                Yes
214
                                    </td>
206
                                                            [% ELSIF rule.article_requests == 'bib_only' %]
215
                                    <td>[% finedays %]</td>
207
                                                                Record only
216
                                    <td>[% maxsuspensiondays %]</td>
208
                                                            [% ELSIF rule.article_requests == 'item_only' %]
217
                                    <td>[% renewalsallowed %]</td>
209
                                                                Item only
218
                                    <td>[% renewalperiod %]</td>
210
                                                            [% END %]
219
                                    <td>[% norenewalbefore %]</td>
211
                                                        </td>
220
                                    <td>
212
							<td>[% rule.rentaldiscount %]</td>
221
                                        [% IF auto_renew %]
213
                                                        <td class="actions">
222
                                            Yes
214
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
223
                                        [% ELSE %]
215
                                                          <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>
224
                                            No
216
                                                        </td>
225
                                        [% END %]
217
226
                                    </td>
218
                	</tr>
227
                                    <td>[% no_auto_renewal_after %]</td>
219
            	[% END %]
228
                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
229
                                    <td>[% reservesallowed %]</td>
230
                                    <td>[% holds_per_record %]</td>
231
                                    <td>
232
                                        [% IF onshelfholds == 1 %]
233
                                            Yes
234
                                        [% ELSIF onshelfholds == 2 %]
235
                                            If all unavailable
236
                                        [% ELSE %]
237
                                            If any unavailable
238
                                        [% END %]
239
                                    </td>
240
                                    <td>[% IF opacitemholds == 'F'%]Force[% ELSIF opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
241
                                    <td>
242
                                        [% IF article_requests == 'no' %]
243
                                            No
244
                                        [% ELSIF article_requests == 'yes' %]
245
                                            Yes
246
                                        [% ELSIF article_requests == 'bib_only' %]
247
                                            Record only
248
                                        [% ELSIF article_requests == 'item_only' %]
249
                                            Item only
250
                                        [% END %]
251
                                    </td>
252
                                    <td>[% rentaldiscount %]</td>
253
                                    <td class="actions">
254
                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
255
                                      <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>
256
                                    </td>
257
                            </tr>
258
                        [% END %]
259
                    [% END %]
260
                [% END %]
220
                <tr id="edit_row">
261
                <tr id="edit_row">
221
                    <td>
262
                    <td>
222
                        <select name="categorycode" id="categorycode">
263
                        <select name="categorycode" id="categorycode">
(-)a/t/db_dependent/ArticleRequests.t (-10 / +38 lines)
Lines 28-33 use Koha::Biblio; Link Here
28
use Koha::Notice::Messages;
28
use Koha::Notice::Messages;
29
use Koha::Patron;
29
use Koha::Patron;
30
use Koha::Library;
30
use Koha::Library;
31
use Koha::CirculationRules;
31
32
32
BEGIN {
33
BEGIN {
33
    use_ok('Koha::ArticleRequest');
34
    use_ok('Koha::ArticleRequest');
Lines 42-48 my $builder = t::lib::TestBuilder->new; Link Here
42
my $dbh = C4::Context->dbh;
43
my $dbh = C4::Context->dbh;
43
$dbh->{RaiseError} = 1;
44
$dbh->{RaiseError} = 1;
44
45
45
$dbh->do("DELETE FROM issuingrules");
46
$dbh->do("DELETE FROM circulation_rules");
46
47
47
my $biblio = Koha::Biblio->new()->store();
48
my $biblio = Koha::Biblio->new()->store();
48
ok( $biblio->id, 'Koha::Biblio created' );
49
ok( $biblio->id, 'Koha::Biblio created' );
Lines 165-197 $article_request->complete(); Link Here
165
$article_request->cancel();
166
$article_request->cancel();
166
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
167
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
167
168
168
my $rule;
169
my $rule = Koha::CirculationRules->set_rule(
169
$rule = $schema->resultset('Issuingrule')
170
    {
170
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
171
        categorycode => '*',
172
        itemtype     => '*',
173
        branchcode   => '*',
174
        rule_name    => 'article_requests',
175
        rule_value   => 'yes',
176
    }
177
);
171
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
178
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
172
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
179
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
173
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
180
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
174
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
181
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
175
$rule->delete();
182
$rule->delete();
176
183
177
$rule = $schema->resultset('Issuingrule')
184
$rule = Koha::CirculationRules->set_rule(
178
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
185
    {
186
        categorycode => '*',
187
        itemtype     => '*',
188
        branchcode   => '*',
189
        rule_name    => 'article_requests',
190
        rule_value   => 'bib_only',
191
    }
192
);
179
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
193
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
180
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
194
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
181
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
195
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
182
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
196
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
183
$rule->delete();
197
$rule->delete();
184
198
185
$rule = $schema->resultset('Issuingrule')
199
$rule = Koha::CirculationRules->set_rule(
186
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
200
    {
201
        categorycode => '*',
202
        itemtype     => '*',
203
        branchcode   => '*',
204
        rule_name    => 'article_requests',
205
        rule_value   => 'item_only',
206
    }
207
);
187
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
208
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
188
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
209
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
189
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
210
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
190
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
211
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
191
$rule->delete();
212
$rule->delete();
192
213
193
$rule = $schema->resultset('Issuingrule')
214
$rule = Koha::CirculationRules->set_rule(
194
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
215
    {
216
        categorycode => '*',
217
        itemtype     => '*',
218
        branchcode   => '*',
219
        rule_name    => 'article_requests',
220
        rule_value   => 'no',
221
    }
222
);
195
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
223
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
196
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
224
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
197
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
225
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
(-)a/t/db_dependent/Circulation.t (-76 / +272 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 180-206 is( Link Here
180
);
179
);
181
180
182
# Set a simple circ policy
181
# Set a simple circ policy
183
$dbh->do('DELETE FROM issuingrules');
182
$dbh->do('DELETE FROM circulation_rules');
184
Koha::CirculationRules->search()->delete();
183
Koha::CirculationRules->set_rules(
185
$dbh->do(
184
    {
186
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed,
185
        categorycode => '*',
187
                                issuelength, lengthunit,
186
        branchcode   => '*',
188
                                renewalsallowed, renewalperiod,
187
        itemtype     => '*',
189
                                norenewalbefore, auto_renew,
188
        rules        => {
190
                                fine, chargeperiod)
189
            reservesallowed => 25,
191
      VALUES (?, ?, ?, ?,
190
            issuelength     => 14,
192
              ?, ?,
191
            lengthunit      => 'days',
193
              ?, ?,
192
            renewalsallowed => 1,
194
              ?, ?,
193
            renewalperiod   => 7,
195
              ?, ?
194
            norenewalbefore => undef,
196
             )
195
            auto_renew      => 0,
197
    },
196
            fine            => .10,
198
    {},
197
            chargeperiod    => 1,
199
    '*', '*', '*', 25,
198
        }
200
    14, 'days',
199
    }
201
    1, 7,
202
    undef, 0,
203
    .10, 1
204
);
200
);
205
201
206
# Test C4::Circulation::ProcessOfflinePayment
202
# Test C4::Circulation::ProcessOfflinePayment
Lines 345-351 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
345
    );
341
    );
346
342
347
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
343
    # Testing of feature to allow the renewal of reserved items if other items on the record can fill all needed holds
348
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
344
    Koha::CirculationRules->set_rule(
345
        {
346
            categorycode => '*',
347
            branchcode   => '*',
348
            itemtype     => '*',
349
            rule_name    => 'onshelfholds',
350
            rule_value   => '1',
351
        }
352
    );
349
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
353
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
350
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
354
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
351
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
355
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
Lines 558-564 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
558
562
559
    # Bug 7413
563
    # Bug 7413
560
    # Test premature manual renewal
564
    # Test premature manual renewal
561
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 7');
565
    Koha::CirculationRules->set_rule(
566
        {
567
            categorycode => '*',
568
            branchcode   => '*',
569
            itemtype     => '*',
570
            rule_name    => 'norenewalbefore',
571
            rule_value   => '7',
572
        }
573
    );
562
574
563
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
575
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
564
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
576
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
Lines 593-599 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
593
605
594
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
606
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
595
    # and test automatic renewal again
607
    # and test automatic renewal again
596
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 0');
608
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
597
    ( $renewokay, $error ) =
609
    ( $renewokay, $error ) =
598
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
610
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
599
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
611
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
Lines 603-609 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
603
615
604
    # Change policy so that loans can be renewed 99 days prior to the due date
616
    # Change policy so that loans can be renewed 99 days prior to the due date
605
    # and test automatic renewal again
617
    # and test automatic renewal again
606
    $dbh->do('UPDATE issuingrules SET norenewalbefore = 99');
618
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
607
    ( $renewokay, $error ) =
619
    ( $renewokay, $error ) =
608
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
620
      CanBookBeRenewed( $renewing_borrowernumber, $itemnumber4 );
609
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
621
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
Lines 627-669 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
627
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
639
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
628
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
640
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
629
641
630
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 9');
642
        Koha::CirculationRules->set_rules(
643
            {
644
                categorycode => '*',
645
                branchcode   => '*',
646
                itemtype     => '*',
647
                rules        => {
648
                    norenewalbefore       => '7',
649
                    no_auto_renewal_after => '9',
650
                }
651
            }
652
        );
631
        ( $renewokay, $error ) =
653
        ( $renewokay, $error ) =
632
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
654
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
633
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
655
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
634
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
656
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
635
657
636
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 10');
658
        Koha::CirculationRules->set_rules(
659
            {
660
                categorycode => '*',
661
                branchcode   => '*',
662
                itemtype     => '*',
663
                rules        => {
664
                    norenewalbefore       => '7',
665
                    no_auto_renewal_after => '10',
666
                }
667
            }
668
        );
637
        ( $renewokay, $error ) =
669
        ( $renewokay, $error ) =
638
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
670
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
639
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
671
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
640
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
672
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
641
673
642
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = 11');
674
        Koha::CirculationRules->set_rules(
675
            {
676
                categorycode => '*',
677
                branchcode   => '*',
678
                itemtype     => '*',
679
                rules        => {
680
                    norenewalbefore       => '7',
681
                    no_auto_renewal_after => '11',
682
                }
683
            }
684
        );
643
        ( $renewokay, $error ) =
685
        ( $renewokay, $error ) =
644
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
686
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
645
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
687
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
646
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
688
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
647
689
648
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
690
        Koha::CirculationRules->set_rules(
691
            {
692
                categorycode => '*',
693
                branchcode   => '*',
694
                itemtype     => '*',
695
                rules        => {
696
                    norenewalbefore       => '10',
697
                    no_auto_renewal_after => '11',
698
                }
699
            }
700
        );
649
        ( $renewokay, $error ) =
701
        ( $renewokay, $error ) =
650
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
702
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
651
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
703
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
652
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
704
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
653
705
654
        $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 ) );
706
        Koha::CirculationRules->set_rules(
707
            {
708
                categorycode => '*',
709
                branchcode   => '*',
710
                itemtype     => '*',
711
                rules        => {
712
                    norenewalbefore       => '10',
713
                    no_auto_renewal_after => undef,
714
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
715
                }
716
            }
717
        );
655
        ( $renewokay, $error ) =
718
        ( $renewokay, $error ) =
656
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
719
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
657
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
720
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
658
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
721
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
659
722
660
        $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 ) );
723
        Koha::CirculationRules->set_rules(
724
            {
725
                categorycode => '*',
726
                branchcode   => '*',
727
                itemtype     => '*',
728
                rules        => {
729
                    norenewalbefore       => '7',
730
                    no_auto_renewal_after => '15',
731
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => -1 ),
732
                }
733
            }
734
        );
661
        ( $renewokay, $error ) =
735
        ( $renewokay, $error ) =
662
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
736
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
663
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
737
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
664
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
738
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
665
739
666
        $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 ) );
740
        Koha::CirculationRules->set_rules(
741
            {
742
                categorycode => '*',
743
                branchcode   => '*',
744
                itemtype     => '*',
745
                rules        => {
746
                    norenewalbefore       => '10',
747
                    no_auto_renewal_after => undef,
748
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 1 ),
749
                }
750
            }
751
        );
667
        ( $renewokay, $error ) =
752
        ( $renewokay, $error ) =
668
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
753
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
669
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
754
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
Lines 685-691 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
685
        my $ten_days_ahead = dt_from_string->add( days => 10 );
770
        my $ten_days_ahead = dt_from_string->add( days => 10 );
686
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
771
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
687
772
688
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 11');
773
        Koha::CirculationRules->set_rules(
774
            {
775
                categorycode => '*',
776
                branchcode   => '*',
777
                itemtype     => '*',
778
                rules        => {
779
                    norenewalbefore       => '10',
780
                    no_auto_renewal_after => '11',
781
                }
782
            }
783
        );
689
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
784
        C4::Context->set_preference('OPACFineNoRenewalsBlockAutoRenew','1');
690
        C4::Context->set_preference('OPACFineNoRenewals','10');
785
        C4::Context->set_preference('OPACFineNoRenewals','10');
691
        my $fines_amount = 5;
786
        my $fines_amount = 5;
Lines 777-807 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
777
        my $ten_days_before = dt_from_string->add( days => -10 );
872
        my $ten_days_before = dt_from_string->add( days => -10 );
778
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
873
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
779
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
874
        AddIssue( $renewing_borrower, $item_to_auto_renew->{barcode}, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
780
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 7, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = NULL');
875
        Koha::CirculationRules->set_rules(
876
            {
877
                categorycode => '*',
878
                branchcode   => '*',
879
                itemtype     => '*',
880
                rules        => {
881
                    norenewalbefore       => '7',
882
                    no_auto_renewal_after => '',
883
                    no_auto_renewal_after_hard_limit => undef,
884
                }
885
            }
886
        );
781
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
887
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
782
        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' );
888
        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' );
783
        my $five_days_before = dt_from_string->add( days => -5 );
889
        my $five_days_before = dt_from_string->add( days => -5 );
784
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 5, no_auto_renewal_after_hard_limit = NULL');
890
        Koha::CirculationRules->set_rules(
891
            {
892
                categorycode => '*',
893
                branchcode   => '*',
894
                itemtype     => '*',
895
                rules        => {
896
                    norenewalbefore       => '10',
897
                    no_auto_renewal_after => '5',
898
                    no_auto_renewal_after_hard_limit => undef,
899
                }
900
            }
901
        );
785
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
902
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
786
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
903
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
787
            $five_days_before->truncate( to => 'minute' ),
904
            $five_days_before->truncate( to => 'minute' ),
788
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
905
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
789
        );
906
        );
790
        my $five_days_ahead = dt_from_string->add( days => 5 );
907
        my $five_days_ahead = dt_from_string->add( days => 5 );
791
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = 15, no_auto_renewal_after_hard_limit = NULL');
908
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '10' WHERE rule_name = 'norenewalbefore'});
909
        $dbh->do(q{UPDATE circulation_rules SET rule_value = '15' WHERE rule_name = 'no_auto_renewal_after'});
910
        $dbh->do(q{UPDATE circulation_rules SET rule_value = NULL WHERE rule_name = 'no_auto_renewal_after_hard_limit'});
911
        Koha::CirculationRules->set_rules(
912
            {
913
                categorycode => '*',
914
                branchcode   => '*',
915
                itemtype     => '*',
916
                rules        => {
917
                    norenewalbefore       => '10',
918
                    no_auto_renewal_after => '15',
919
                    no_auto_renewal_after_hard_limit => undef,
920
                }
921
            }
922
        );
792
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
923
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
793
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
924
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
794
            $five_days_ahead->truncate( to => 'minute' ),
925
            $five_days_ahead->truncate( to => 'minute' ),
795
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
926
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
796
        );
927
        );
797
        my $two_days_ahead = dt_from_string->add( days => 2 );
928
        my $two_days_ahead = dt_from_string->add( days => 2 );
798
        $dbh->do('UPDATE issuingrules SET norenewalbefore = 10, no_auto_renewal_after = "", no_auto_renewal_after_hard_limit = ?', undef, dt_from_string->add( days => 2 ) );
929
        Koha::CirculationRules->set_rules(
930
            {
931
                categorycode => '*',
932
                branchcode   => '*',
933
                itemtype     => '*',
934
                rules        => {
935
                    norenewalbefore       => '10',
936
                    no_auto_renewal_after => '',
937
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
938
                }
939
            }
940
        );
799
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
941
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
800
        is( $latest_auto_renew_date->truncate( to => 'day' ),
942
        is( $latest_auto_renew_date->truncate( to => 'day' ),
801
            $two_days_ahead->truncate( to => 'day' ),
943
            $two_days_ahead->truncate( to => 'day' ),
802
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
944
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
803
        );
945
        );
804
        $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 ) );
946
        Koha::CirculationRules->set_rules(
947
            {
948
                categorycode => '*',
949
                branchcode   => '*',
950
                itemtype     => '*',
951
                rules        => {
952
                    norenewalbefore       => '10',
953
                    no_auto_renewal_after => '15',
954
                    no_auto_renewal_after_hard_limit => dt_from_string->add( days => 2 ),
955
                }
956
            }
957
        );
805
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
958
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->{itemnumber} );
806
        is( $latest_auto_renew_date->truncate( to => 'day' ),
959
        is( $latest_auto_renew_date->truncate( to => 'day' ),
807
            $two_days_ahead->truncate( to => 'day' ),
960
            $two_days_ahead->truncate( to => 'day' ),
Lines 809-819 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
809
        );
962
        );
810
963
811
    };
964
    };
812
813
    # Too many renewals
965
    # Too many renewals
814
966
815
    # set policy to forbid renewals
967
    # set policy to forbid renewals
816
    $dbh->do('UPDATE issuingrules SET norenewalbefore = NULL, renewalsallowed = 0');
968
    Koha::CirculationRules->set_rules(
969
        {
970
            categorycode => '*',
971
            branchcode   => '*',
972
            itemtype     => '*',
973
            rules        => {
974
                norenewalbefore => undef,
975
                renewalsallowed => 0,
976
            }
977
        }
978
    );
817
979
818
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
980
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $itemnumber);
819
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
981
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
Lines 1031-1057 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
1031
{
1193
{
1032
    $dbh->do('DELETE FROM issues');
1194
    $dbh->do('DELETE FROM issues');
1033
    $dbh->do('DELETE FROM items');
1195
    $dbh->do('DELETE FROM items');
1034
    $dbh->do('DELETE FROM issuingrules');
1196
    $dbh->do('DELETE FROM circulation_rules');
1035
    Koha::CirculationRules->search()->delete();
1036
    $dbh->do(
1037
        q{
1038
        INSERT INTO issuingrules ( categorycode, branchcode, itemtype, reservesallowed, issuelength, lengthunit, renewalsallowed, renewalperiod,
1039
                    norenewalbefore, auto_renew, fine, chargeperiod ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
1040
        },
1041
        {},
1042
        '*', '*', '*', 25,
1043
        14,  'days',
1044
        1,   7,
1045
        undef,  0,
1046
        .10, 1
1047
    );
1048
    Koha::CirculationRules->set_rules(
1197
    Koha::CirculationRules->set_rules(
1049
        {
1198
        {
1050
            categorycode => '*',
1199
            categorycode => '*',
1051
            itemtype     => '*',
1200
            itemtype     => '*',
1052
            branchcode   => '*',
1201
            branchcode   => '*',
1053
            rules        => {
1202
            rules        => {
1054
                maxissueqty => 20
1203
                reservesallowed => 25,
1204
                issuelength     => 14,
1205
                lengthunit      => 'days',
1206
                renewalsallowed => 1,
1207
                renewalperiod   => 7,
1208
                norenewalbefore => undef,
1209
                auto_renew      => 0,
1210
                fine            => .10,
1211
                chargeperiod    => 1,
1212
                maxissueqty     => 20
1055
            }
1213
            }
1056
        }
1214
        }
1057
    );
1215
    );
Lines 1105-1126 C4::Context->dbh->do("DELETE FROM accountlines"); Link Here
1105
        undef, undef, undef
1263
        undef, undef, undef
1106
    );
1264
    );
1107
1265
1108
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1266
    Koha::CirculationRules->set_rules(
1267
        {
1268
            categorycode => '*',
1269
            itemtype     => '*',
1270
            branchcode   => '*',
1271
            rules        => {
1272
                onshelfholds => 0,
1273
            }
1274
        }
1275
    );
1109
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1276
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1110
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1277
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1111
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1278
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1112
1279
1113
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1280
    Koha::CirculationRules->set_rules(
1281
        {
1282
            categorycode => '*',
1283
            itemtype     => '*',
1284
            branchcode   => '*',
1285
            rules        => {
1286
                onshelfholds => 0,
1287
            }
1288
        }
1289
    );
1114
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1290
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1115
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1291
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1116
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1292
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1117
1293
1118
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1294
    Koha::CirculationRules->set_rules(
1295
        {
1296
            categorycode => '*',
1297
            itemtype     => '*',
1298
            branchcode   => '*',
1299
            rules        => {
1300
                onshelfholds => 1,
1301
            }
1302
        }
1303
    );
1119
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1304
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1120
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1305
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1121
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1306
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1122
1307
1123
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 1");
1308
    Koha::CirculationRules->set_rules(
1309
        {
1310
            categorycode => '*',
1311
            itemtype     => '*',
1312
            branchcode   => '*',
1313
            rules        => {
1314
                onshelfholds => 1,
1315
            }
1316
        }
1317
    );
1124
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1318
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1125
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1319
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $itemnumber1 );
1126
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1320
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
Lines 1672-1691 subtest 'AddReturn + CumulativeRestrictionPeriods' => sub { Link Here
1672
        }
1866
        }
1673
    );
1867
    );
1674
1868
1675
    # And the issuing rule
1869
    # And the circulation rule
1676
    Koha::IssuingRules->search->delete;
1870
    Koha::CirculationRules->search->delete;
1677
    my $rule = Koha::IssuingRule->new(
1871
    Koha::CirculationRules->set_rules(
1678
        {
1872
        {
1679
            categorycode => '*',
1873
            categorycode => '*',
1680
            itemtype     => '*',
1874
            itemtype     => '*',
1681
            branchcode   => '*',
1875
            branchcode   => '*',
1682
            issuelength  => 1,
1876
            rules        => {
1683
            firstremind  => 1,        # 1 day of grace
1877
                issuelength => 1,
1684
            finedays     => 2,        # 2 days of fine per day of overdue
1878
                firstremind => 1,        # 1 day of grace
1685
            lengthunit   => 'days',
1879
                finedays    => 2,        # 2 days of fine per day of overdue
1880
                lengthunit  => 'days',
1881
            }
1686
        }
1882
        }
1687
    );
1883
    );
1688
    $rule->store();
1689
1884
1690
    # Patron cannot issue item_1, they have overdues
1885
    # Patron cannot issue item_1, they have overdues
1691
    my $five_days_ago = dt_from_string->subtract( days => 5 );
1886
    my $five_days_ago = dt_from_string->subtract( days => 5 );
Lines 1787-1806 subtest 'AddReturn | is_overdue' => sub { Link Here
1787
        }
1982
        }
1788
    );
1983
    );
1789
1984
1790
    Koha::IssuingRules->search->delete;
1985
    Koha::CirculationRules->search->delete;
1791
    my $rule = Koha::IssuingRule->new(
1986
    my $rule = Koha::CirculationRules->set_rules(
1792
        {
1987
        {
1793
            categorycode => '*',
1988
            categorycode => '*',
1794
            itemtype     => '*',
1989
            itemtype     => '*',
1795
            branchcode   => '*',
1990
            branchcode   => '*',
1796
            maxissueqty  => 99,
1991
            rules        => {
1797
            issuelength  => 6,
1992
                maxissueqty  => 99,
1798
            lengthunit   => 'days',
1993
                issuelength  => 6,
1799
            fine         => 1, # Charge 1 every day of overdue
1994
                lengthunit   => 'days',
1800
            chargeperiod => 1,
1995
                fine         => 1,        # Charge 1 every day of overdue
1996
                chargeperiod => 1,
1997
            }
1801
        }
1998
        }
1802
    );
1999
    );
1803
    $rule->store();
1804
2000
1805
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
2001
    my $one_day_ago   = dt_from_string->subtract( days => 1 );
1806
    my $five_days_ago = dt_from_string->subtract( days => 5 );
2002
    my $five_days_ago = dt_from_string->subtract( days => 5 );
(-)a/t/db_dependent/Circulation/CalcDateDue.t (-8 / +15 lines)
Lines 10-15 use t::lib::Mocks; Link Here
10
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
11
use C4::Calendar;
11
use C4::Calendar;
12
12
13
use Koha::CirculationRules;
14
13
use_ok('C4::Circulation');
15
use_ok('C4::Circulation');
14
16
15
my $schema = Koha::Database->new->schema;
17
my $schema = Koha::Database->new->schema;
Lines 23-36 my $issuelength = 10; Link Here
23
my $renewalperiod = 5;
25
my $renewalperiod = 5;
24
my $lengthunit = 'days';
26
my $lengthunit = 'days';
25
27
26
Koha::Database->schema->resultset('Issuingrule')->create({
28
Koha::CirculationRules->search()->delete();
27
  categorycode => $categorycode,
29
Koha::CirculationRules->set_rules(
28
  itemtype => $itemtype,
30
    {
29
  branchcode => $branchcode,
31
        categorycode => $categorycode,
30
  issuelength => $issuelength,
32
        itemtype     => $itemtype,
31
  renewalperiod => $renewalperiod,
33
        branchcode   => $branchcode,
32
  lengthunit => $lengthunit,
34
        rules        => {
33
});
35
            issuelength   => $issuelength,
36
            renewalperiod => $renewalperiod,
37
            lengthunit    => $lengthunit,
38
        }
39
    }
40
);
34
41
35
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
42
#Set syspref ReturnBeforeExpiry = 1 and useDaysMode = 'Days'
36
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
43
t::lib::Mocks::mock_preference('ReturnBeforeExpiry', 1);
(-)a/t/db_dependent/Circulation/CalcFine.t (-21 / +13 lines)
Lines 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 283-289 subtest 'Handle ids duplication' => sub { Link Here
283
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
283
    t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
284
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
284
    t::lib::Mocks::mock_preference( 'CalculateFinesOnReturn', 1 );
285
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
285
    t::lib::Mocks::mock_preference( 'finesMode', 'production' );
286
    Koha::IssuingRules->search->update({ chargeperiod => 1, fine => 1, firstremind => 1, });
286
    Koha::CirculationRules->set_rules(
287
        {
288
            categorycode => '*',
289
            itemtype     => '*',
290
            branchcode   => '*',
291
            rules        => {
292
                chargeperiod => 1,
293
                fine         => 1,
294
                firstremind  => 1,
295
            }
296
        }
297
    );
287
298
288
    my $biblio = $builder->build( { source => 'Biblio' } );
299
    my $biblio = $builder->build( { source => 'Biblio' } );
289
    my $itemtype = $builder->build( { source => 'Itemtype', value => { rentalcharge => 5 } } );
300
    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 79-94 my $item = $builder->build({ Link Here
79
    },
75
    },
80
});
76
});
81
77
82
my $issuingrule = $builder->build({
83
    source => 'Issuingrule',
84
    value => {
85
        branchcode         => $branch->{branchcode},
86
        categorycode       => '*',
87
        itemtype           => '*',
88
        lengthunit         => 'days',
89
        issuelength        => 5,
90
    },
91
});
92
Koha::CirculationRules->search()->delete();
78
Koha::CirculationRules->search()->delete();
93
Koha::CirculationRules->set_rules(
79
Koha::CirculationRules->set_rules(
94
    {
80
    {
Lines 98-103 Koha::CirculationRules->set_rules( Link Here
98
        rules        => {
84
        rules        => {
99
            maxissueqty       => 2,
85
            maxissueqty       => 2,
100
            maxonsiteissueqty => 1,
86
            maxonsiteissueqty => 1,
87
            branchcode        => $branch->{branchcode},
88
            categorycode      => '*',
89
            itemtype          => '*',
90
            lengthunit        => 'days',
91
            issuelength       => 5,
101
        }
92
        }
102
    }
93
    }
103
);
94
);
(-)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 423-428 subtest '1 BranchBorrowerCircRule exist: 1 CO allowed, 1 OSCO allowed' => sub { Link Here
423
    );
418
    );
424
419
425
    teardown();
420
    teardown();
421
    Koha::CirculationRules->set_rules(
422
        {
423
            branchcode   => $branch->{branchcode},
424
            categorycode => $category->{categorycode},
425
            itemtype     => undef,
426
            rules        => {
427
                maxissueqty       => 1,
428
                maxonsiteissueqty => 1,
429
            }
430
        }
431
    );
426
432
427
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
433
    $issue = C4::Circulation::AddIssue( $patron, $item->{barcode}, dt_from_string(), undef, undef, undef, { onsite_checkout => 1 } );
428
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
434
    like( $issue->issue_id, qr|^\d+$|, 'The issue should have been inserted' );
Lines 470-475 $schema->storage->txn_rollback; Link Here
470
476
471
sub teardown {
477
sub teardown {
472
    $dbh->do(q|DELETE FROM issues|);
478
    $dbh->do(q|DELETE FROM issues|);
473
    $dbh->do(q|DELETE FROM issuingrules|);
479
    $dbh->do(q|DELETE FROM circulation_rules|);
474
}
480
}
475
481
(-)a/t/db_dependent/Circulation/issue.t (-8 / +23 lines)
Lines 34-39 use Koha::DateUtils; Link Here
34
use Koha::Holds;
34
use Koha::Holds;
35
use Koha::Library;
35
use Koha::Library;
36
use Koha::Patrons;
36
use Koha::Patrons;
37
use Koha::CirculationRules;
37
38
38
BEGIN {
39
BEGIN {
39
    require_ok('C4::Circulation');
40
    require_ok('C4::Circulation');
Lines 65-71 $dbh->do(q|DELETE FROM items|); Link Here
65
$dbh->do(q|DELETE FROM borrowers|);
66
$dbh->do(q|DELETE FROM borrowers|);
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 25-30 use Koha::Biblio; Link Here
25
use Koha::Item;
25
use Koha::Item;
26
use Koha::Holds;
26
use Koha::Holds;
27
use Koha::Hold;
27
use Koha::Hold;
28
use Koha::CirculationRules;
28
use t::lib::TestBuilder;
29
use t::lib::TestBuilder;
29
use t::lib::Mocks;
30
use t::lib::Mocks;
30
31
Lines 39-45 $dbh->{RaiseError} = 1; Link Here
39
$schema->storage->txn_begin();
40
$schema->storage->txn_begin();
40
41
41
$dbh->do('DELETE FROM issues');
42
$dbh->do('DELETE FROM issues');
42
$dbh->do('DELETE FROM issuingrules');
43
$dbh->do('DELETE FROM circulation_rules');
43
$dbh->do('DELETE FROM borrowers');
44
$dbh->do('DELETE FROM borrowers');
44
$dbh->do('DELETE FROM items');
45
$dbh->do('DELETE FROM items');
45
46
Lines 93-107 for my $i ( 0 .. 5 ) { Link Here
93
    )->store();
94
    )->store();
94
}
95
}
95
96
96
$builder->build(
97
Koha::CirculationRules->set_rules(
97
    {
98
    {
98
        source => 'Issuingrule',
99
        branchcode   => '*',
99
        value => {
100
        categorycode => '*',
100
            branchcode => '*',
101
        itemtype     => '*',
101
            categorycode => '*',
102
        rules        => {
102
            itemtype => '*',
103
            issuelength     => '14',
103
            issuelength => '14',
104
            lengthunit      => 'days',
104
            lengthunit => 'days',
105
            reservesallowed => '99',
105
            reservesallowed => '99',
106
        }
106
        }
107
    }
107
    }
(-)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 242-259 is( $hold->priority, '6', "Test AlterPriority(), move to bottom" ); Link Here
242
my ($foreign_bibnum, $foreign_title, $foreign_bibitemnum) = create_helper_biblio('DUMMY');
242
my ($foreign_bibnum, $foreign_title, $foreign_bibitemnum) = create_helper_biblio('DUMMY');
243
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
243
my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber)
244
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_bibnum);
244
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_bibnum);
245
$dbh->do('DELETE FROM issuingrules');
245
$dbh->do('DELETE FROM circulation_rules');
246
$dbh->do(
246
Koha::CirculationRules->set_rules(
247
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
247
    {
248
      VALUES (?, ?, ?, ?, ?)},
248
        categorycode => '*',
249
    {},
249
        branchcode   => '*',
250
    '*', '*', '*', 25, 99
250
        itemtype     => '*',
251
        rules        => {
252
            reservesallowed  => 25,
253
            holds_per_record => 99,
254
        }
255
    }
251
);
256
);
252
$dbh->do(
257
Koha::CirculationRules->set_rules(
253
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
258
    {
254
      VALUES (?, ?, ?, ?, ?)},
259
        categorycode => '*',
255
    {},
260
        branchcode   => '*',
256
    '*', '*', 'CANNOT', 0, 99
261
        itemtype     => 'CANNOT',
262
        rules        => {
263
            reservesallowed  => 0,
264
            holds_per_record => 99,
265
        }
266
    }
257
);
267
);
258
268
259
# make sure some basic sysprefs are set
269
# make sure some basic sysprefs are set
Lines 262-269 t::lib::Mocks::mock_preference('item-level_itypes', 1); Link Here
262
272
263
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
273
# if IndependentBranches is OFF, a $branch_1 patron can reserve an $branch_2 item
264
t::lib::Mocks::mock_preference('IndependentBranches', 0);
274
t::lib::Mocks::mock_preference('IndependentBranches', 0);
265
ok(
275
is(
266
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber) eq 'OK',
276
    CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber), 'OK',
267
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
277
    '$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)'
268
);
278
);
269
279
Lines 350-362 ok( Link Here
350
360
351
# Test branch item rules
361
# Test branch item rules
352
362
353
$dbh->do('DELETE FROM issuingrules');
354
$dbh->do('DELETE FROM circulation_rules');
363
$dbh->do('DELETE FROM circulation_rules');
355
$dbh->do(
364
Koha::CirculationRules->set_rules(
356
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
365
    {
357
      VALUES (?, ?, ?, ?)},
366
        categorycode => '*',
358
    {},
367
        branchcode   => '*',
359
    '*', '*', '*', 25
368
        itemtype     => '*',
369
        rules        => {
370
            reservesallowed  => 25,
371
            holds_per_record => 99,
372
        }
373
    }
360
);
374
);
361
Koha::CirculationRules->set_rules(
375
Koha::CirculationRules->set_rules(
362
    {
376
    {
Lines 410-420 $dbh->do('DELETE FROM biblio'); Link Here
410
( $item_bibnum, $item_bibitemnum, $itemnumber )
424
( $item_bibnum, $item_bibitemnum, $itemnumber )
411
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $bibnum );
425
    = AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 }, $bibnum );
412
426
413
$dbh->do(
427
Koha::CirculationRules->set_rules(
414
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
428
    {
415
      VALUES (?, ?, ?, ?, ?)},
429
        categorycode => '*',
416
    {},
430
        branchcode   => '*',
417
    '*', '*', 'ONLY1', 1, 99
431
        itemtype     => 'ONLY1',
432
        rules        => {
433
            reservesallowed  => 1,
434
            holds_per_record => 99,
435
        }
436
    }
418
);
437
);
419
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber ),
438
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber ),
420
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
439
    'OK', 'Patron can reserve item with hold limit of 1, no holds placed' );
Lines 428-447 subtest 'Test max_holds per library/patron category' => sub { Link Here
428
    plan tests => 6;
447
    plan tests => 6;
429
448
430
    $dbh->do('DELETE FROM reserves');
449
    $dbh->do('DELETE FROM reserves');
431
    $dbh->do('DELETE FROM issuingrules');
432
    $dbh->do('DELETE FROM circulation_rules');
450
    $dbh->do('DELETE FROM circulation_rules');
433
451
434
    ( $bibnum, $title, $bibitemnum ) = create_helper_biblio('TEST');
452
    ( $bibnum, $title, $bibitemnum ) = create_helper_biblio('TEST');
435
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
453
    ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
436
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
454
      AddItem( { homebranch => $branch_1, holdingbranch => $branch_1 },
437
        $bibnum );
455
        $bibnum );
438
    $dbh->do(
456
    Koha::CirculationRules->set_rules(
439
        q{
457
        {
440
            INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
458
            categorycode => '*',
441
            VALUES (?, ?, ?, ?, ?)
459
            branchcode   => '*',
442
        },
460
            itemtype     => 'TEST',
443
        {},
461
            rules        => {
444
        '*', '*', 'TEST', 99, 99
462
                reservesallowed  => 99,
463
                holds_per_record => 99,
464
            }
465
        }
445
    );
466
    );
446
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
467
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
447
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
468
    AddReserve( $branch_1, $borrowernumbers[0], $bibnum, '', 1, );
(-)a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t (-9 / +10 lines)
Lines 5-13 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 => 5;
10
use Test::More tests => 4;
11
11
12
use t::lib::TestBuilder;
12
use t::lib::TestBuilder;
13
use t::lib::Mocks;
13
use t::lib::Mocks;
Lines 92-110 my $itemnumber2 = Link Here
92
92
93
my $item2 = GetItem( $itemnumber2 );
93
my $item2 = GetItem( $itemnumber2 );
94
94
95
$dbh->do("DELETE FROM issuingrules");
95
$dbh->do("DELETE FROM circulation_rules");
96
my $rule = Koha::IssuingRule->new(
96
Koha::CirculationRules->set_rules(
97
    {
97
    {
98
        categorycode => '*',
98
        categorycode => '*',
99
        itemtype     => '*',
99
        itemtype     => '*',
100
        branchcode   => '*',
100
        branchcode   => '*',
101
        issuelength  => 7,
101
        rules        => {
102
        lengthunit   => 8,
102
            issuelength     => 7,
103
        reservesallowed => 99,
103
            lengthunit      => 8,
104
        onshelfholds => 2,
104
            reservesallowed => 99,
105
            onshelfholds    => 2,
106
        }
105
    }
107
    }
106
);
108
);
107
$rule->store();
108
109
109
my $is = IsAvailableForItemLevelRequest( $item1, $borrower1);
110
my $is = IsAvailableForItemLevelRequest( $item1, $borrower1);
110
is( $is, 0, "Item cannot be held, 2 items available" );
111
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 => 2; 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
use t::lib::Mocks;
29
use t::lib::Mocks;
Lines 47-72 subtest 'get_effective_issuing_rule' => sub { Link Here
47
        plan tests => 4;
47
        plan tests => 4;
48
48
49
        my $rule;
49
        my $rule;
50
        Koha::IssuingRules->delete;
50
        Koha::CirculationRules->delete;
51
51
52
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
52
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
53
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
53
        $rule = Koha::CirculationRules->get_effective_rule({
54
            branchcode   => undef,
54
            branchcode   => undef,
55
            categorycode => undef,
55
            categorycode => undef,
56
            itemtype     => undef,
56
            itemtype     => undef,
57
            rule_name    => 'fine',
57
        });
58
        });
58
        is($rule, undef, 'When I attempt to get effective issuing rule by'
59
        is($rule, undef, 'When I attempt to get effective issuing rule by'
59
           .' providing undefined values, then undef is returned.');
60
           .' providing undefined values, then undef is returned.');
60
        ok(Koha::IssuingRule->new({
61
        ok(Koha::CirculationRule->new({
61
            branchcode => '*',
62
            branchcode => '*',
62
            categorycode => '*',
63
            categorycode => '*',
63
            itemtype => '*',
64
            itemtype => '*',
65
            rule_name => 'fine',
64
        })->store, 'Given I added an issuing rule branchcode => *,'
66
        })->store, 'Given I added an issuing rule branchcode => *,'
65
           .' categorycode => *, itemtype => *,');
67
           .' categorycode => *, itemtype => *,');
66
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
68
        $rule = Koha::CirculationRules->get_effective_rule({
67
            branchcode   => undef,
69
            branchcode   => '*',
68
            categorycode => undef,
70
            categorycode => '*',
69
            itemtype     => undef,
71
            itemtype     => '*',
72
            rule_name    => 'fine',
70
        });
73
        });
71
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
74
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective'
72
           .' issuing rule by providing undefined values, then the above one is'
75
           .' issuing rule by providing undefined values, then the above one is'
Lines 77-192 subtest 'get_effective_issuing_rule' => sub { Link Here
77
        plan tests => 18;
80
        plan tests => 18;
78
81
79
        my $rule;
82
        my $rule;
80
        Koha::IssuingRules->delete;
83
        Koha::CirculationRules->delete;
81
        is(Koha::IssuingRules->search->count, 0, 'There are no issuing rules.');
84
        is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
82
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
85
        $rule = Koha::CirculationRules->get_effective_rule({
83
            branchcode   => $branchcode,
86
            branchcode   => $branchcode,
84
            categorycode => $categorycode,
87
            categorycode => $categorycode,
85
            itemtype     => $itemtype,
88
            itemtype     => $itemtype,
89
            rule_name    => 'fine',
86
        });
90
        });
87
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
91
        is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
88
                        .' is returned.');
92
                        .' is returned.');
89
93
90
        ok(Koha::IssuingRule->new({
94
        ok(Koha::CirculationRule->new({
91
            branchcode => '*',
95
            branchcode => '*',
92
            categorycode => '*',
96
            categorycode => '*',
93
            itemtype => '*',
97
            itemtype => '*',
98
            rule_name => 'fine',
94
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
99
        })->store, 'Given I added an issuing rule branchcode => *, categorycode => *, itemtype => *,');
95
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
100
        $rule = Koha::CirculationRules->get_effective_rule({
96
            branchcode   => $branchcode,
101
            branchcode   => $branchcode,
97
            categorycode => $categorycode,
102
            categorycode => $categorycode,
98
            itemtype     => $itemtype,
103
            itemtype     => $itemtype,
104
            rule_name    => 'fine',
99
        });
105
        });
100
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
106
        ok(_row_match($rule, '*', '*', '*'), 'When I attempt to get effective issuing rule,'
101
           .' then the above one is returned.');
107
           .' then the above one is returned.');
102
108
103
        ok(Koha::IssuingRule->new({
109
        ok(Koha::CirculationRule->new({
104
            branchcode => '*',
110
            branchcode => '*',
105
            categorycode => '*',
111
            categorycode => '*',
106
            itemtype => $itemtype,
112
            itemtype => $itemtype,
113
            rule_name => 'fine',
107
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
114
        })->store, "Given I added an issuing rule branchcode => *, categorycode => *, itemtype => $itemtype,");
108
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
115
        $rule = Koha::CirculationRules->get_effective_rule({
109
            branchcode   => $branchcode,
116
            branchcode   => $branchcode,
110
            categorycode => $categorycode,
117
            categorycode => $categorycode,
111
            itemtype     => $itemtype,
118
            itemtype     => $itemtype,
119
            rule_name    => 'fine',
112
        });
120
        });
113
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
121
        ok(_row_match($rule, '*', '*', $itemtype), 'When I attempt to get effective issuing rule,'
114
           .' then the above one is returned.');
122
           .' then the above one is returned.');
115
123
116
        ok(Koha::IssuingRule->new({
124
        ok(Koha::CirculationRule->new({
117
            branchcode => '*',
125
            branchcode => '*',
118
            categorycode => $categorycode,
126
            categorycode => $categorycode,
119
            itemtype => '*',
127
            itemtype => '*',
128
            rule_name => 'fine',
120
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
129
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => *,");
121
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
130
        $rule = Koha::CirculationRules->get_effective_rule({
122
            branchcode   => $branchcode,
131
            branchcode   => $branchcode,
123
            categorycode => $categorycode,
132
            categorycode => $categorycode,
124
            itemtype     => $itemtype,
133
            itemtype     => $itemtype,
134
            rule_name    => 'fine',
125
        });
135
        });
126
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
136
        ok(_row_match($rule, '*', $categorycode, '*'), 'When I attempt to get effective issuing rule,'
127
           .' then the above one is returned.');
137
           .' then the above one is returned.');
128
138
129
        ok(Koha::IssuingRule->new({
139
        ok(Koha::CirculationRule->new({
130
            branchcode => '*',
140
            branchcode => '*',
131
            categorycode => $categorycode,
141
            categorycode => $categorycode,
132
            itemtype => $itemtype,
142
            itemtype => $itemtype,
143
            rule_name => 'fine',
133
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
144
        })->store, "Given I added an issuing rule branchcode => *, categorycode => $categorycode, itemtype => $itemtype,");
134
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
145
        $rule = Koha::CirculationRules->get_effective_rule({
135
            branchcode   => $branchcode,
146
            branchcode   => $branchcode,
136
            categorycode => $categorycode,
147
            categorycode => $categorycode,
137
            itemtype     => $itemtype,
148
            itemtype     => $itemtype,
149
            rule_name    => 'fine',
138
        });
150
        });
139
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
151
        ok(_row_match($rule, '*', $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
140
           .' then the above one is returned.');
152
           .' then the above one is returned.');
141
153
142
        ok(Koha::IssuingRule->new({
154
        ok(Koha::CirculationRule->new({
143
            branchcode => $branchcode,
155
            branchcode => $branchcode,
144
            categorycode => '*',
156
            categorycode => '*',
145
            itemtype => '*',
157
            itemtype => '*',
158
            rule_name => 'fine',
146
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
159
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => '*',");
147
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
160
        $rule = Koha::CirculationRules->get_effective_rule({
148
            branchcode   => $branchcode,
161
            branchcode   => $branchcode,
149
            categorycode => $categorycode,
162
            categorycode => $categorycode,
150
            itemtype     => $itemtype,
163
            itemtype     => $itemtype,
164
            rule_name    => 'fine',
151
        });
165
        });
152
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
166
        ok(_row_match($rule, $branchcode, '*', '*'), 'When I attempt to get effective issuing rule,'
153
           .' then the above one is returned.');
167
           .' then the above one is returned.');
154
168
155
        ok(Koha::IssuingRule->new({
169
        ok(Koha::CirculationRule->new({
156
            branchcode => $branchcode,
170
            branchcode => $branchcode,
157
            categorycode => '*',
171
            categorycode => '*',
158
            itemtype => $itemtype,
172
            itemtype => $itemtype,
173
            rule_name => 'fine',
159
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
174
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => '*', itemtype => $itemtype,");
160
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
175
        $rule = Koha::CirculationRules->get_effective_rule({
161
            branchcode   => $branchcode,
176
            branchcode   => $branchcode,
162
            categorycode => $categorycode,
177
            categorycode => $categorycode,
163
            itemtype     => $itemtype,
178
            itemtype     => $itemtype,
179
            rule_name    => 'fine',
164
        });
180
        });
165
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
181
        ok(_row_match($rule, $branchcode, '*', $itemtype), 'When I attempt to get effective issuing rule,'
166
           .' then the above one is returned.');
182
           .' then the above one is returned.');
167
183
168
        ok(Koha::IssuingRule->new({
184
        ok(Koha::CirculationRule->new({
169
            branchcode => $branchcode,
185
            branchcode => $branchcode,
170
            categorycode => $categorycode,
186
            categorycode => $categorycode,
171
            itemtype => '*',
187
            itemtype => '*',
188
            rule_name => 'fine',
172
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
189
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => '*',");
173
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
190
        $rule = Koha::CirculationRules->get_effective_rule({
174
            branchcode   => $branchcode,
191
            branchcode   => $branchcode,
175
            categorycode => $categorycode,
192
            categorycode => $categorycode,
176
            itemtype     => $itemtype,
193
            itemtype     => $itemtype,
194
            rule_name    => 'fine',
177
        });
195
        });
178
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
196
        ok(_row_match($rule, $branchcode, $categorycode, '*'), 'When I attempt to get effective issuing rule,'
179
           .' then the above one is returned.');
197
           .' then the above one is returned.');
180
198
181
        ok(Koha::IssuingRule->new({
199
        ok(Koha::CirculationRule->new({
182
            branchcode => $branchcode,
200
            branchcode => $branchcode,
183
            categorycode => $categorycode,
201
            categorycode => $categorycode,
184
            itemtype => $itemtype,
202
            itemtype => $itemtype,
203
            rule_name => 'fine',
185
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
204
        })->store, "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,");
186
        $rule = Koha::IssuingRules->get_effective_issuing_rule({
205
        $rule = Koha::CirculationRules->get_effective_rule({
187
            branchcode   => $branchcode,
206
            branchcode   => $branchcode,
188
            categorycode => $categorycode,
207
            categorycode => $categorycode,
189
            itemtype     => $itemtype,
208
            itemtype     => $itemtype,
209
            rule_name    => 'fine',
190
        });
210
        });
191
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
211
        ok(_row_match($rule, $branchcode, $categorycode, $itemtype), 'When I attempt to get effective issuing rule,'
192
           .' then the above one is returned.');
212
           .' then the above one is returned.');
Lines 196-229 subtest 'get_effective_issuing_rule' => sub { Link Here
196
        plan tests => 4;
216
        plan tests => 4;
197
217
198
        my $worst_case = timethis(500,
218
        my $worst_case = timethis(500,
199
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
219
                    sub { Koha::CirculationRules->get_effective_rule({
200
                            branchcode   => 'nonexistent',
220
                            branchcode   => 'nonexistent',
201
                            categorycode => 'nonexistent',
221
                            categorycode => 'nonexistent',
202
                            itemtype     => 'nonexistent',
222
                            itemtype     => 'nonexistent',
223
                            rule_name    => 'nonexistent',
203
                        });
224
                        });
204
                    }
225
                    }
205
                );
226
                );
206
        my $mid_case = timethis(500,
227
        my $mid_case = timethis(500,
207
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
228
                    sub { Koha::CirculationRules->get_effective_rule({
208
                            branchcode   => $branchcode,
229
                            branchcode   => $branchcode,
209
                            categorycode => 'nonexistent',
230
                            categorycode => 'nonexistent',
210
                            itemtype     => 'nonexistent',
231
                            itemtype     => 'nonexistent',
232
                            rule_name    => 'nonexistent',
211
                        });
233
                        });
212
                    }
234
                    }
213
                );
235
                );
214
        my $sec_best_case = timethis(500,
236
        my $sec_best_case = timethis(500,
215
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
237
                    sub { Koha::CirculationRules->get_effective_rule({
216
                            branchcode   => $branchcode,
238
                            branchcode   => $branchcode,
217
                            categorycode => $categorycode,
239
                            categorycode => $categorycode,
218
                            itemtype     => 'nonexistent',
240
                            itemtype     => 'nonexistent',
241
                            rule_name    => 'nonexistent',
219
                        });
242
                        });
220
                    }
243
                    }
221
                );
244
                );
222
        my $best_case = timethis(500,
245
        my $best_case = timethis(500,
223
                    sub { Koha::IssuingRules->get_effective_issuing_rule({
246
                    sub { Koha::CirculationRules->get_effective_rule({
224
                            branchcode   => $branchcode,
247
                            branchcode   => $branchcode,
225
                            categorycode => $categorycode,
248
                            categorycode => $categorycode,
226
                            itemtype     => $itemtype,
249
                            itemtype     => $itemtype,
250
                            rule_name    => 'nonexistent',
227
                        });
251
                        });
228
                    }
252
                    }
229
                );
253
                );
(-)a/t/db_dependent/Koha/Objects.t (-8 / +1 lines)
Lines 25-31 use Test::Warn; Link Here
25
25
26
use Koha::Authority::Types;
26
use Koha::Authority::Types;
27
use Koha::Cities;
27
use Koha::Cities;
28
use Koha::IssuingRules;
29
use Koha::Patron::Category;
28
use Koha::Patron::Category;
30
use Koha::Patron::Categories;
29
use Koha::Patron::Categories;
31
use Koha::Patrons;
30
use Koha::Patrons;
Lines 111-117 subtest 'new' => sub { Link Here
111
};
110
};
112
111
113
subtest 'find' => sub {
112
subtest 'find' => sub {
114
    plan tests => 5;
113
    plan tests => 4;
115
114
116
    # check find on a single PK
115
    # check find on a single PK
117
    my $patron = $builder->build({ source => 'Borrower' });
116
    my $patron = $builder->build({ source => 'Borrower' });
Lines 129-140 subtest 'find' => sub { Link Here
129
        { where => { surname => { '!=', $patron->{surname} }}},
128
        { where => { surname => { '!=', $patron->{surname} }}},
130
    ), undef, 'Additional where clause in find call' );
129
    ), undef, 'Additional where clause in find call' );
131
130
132
    # check find with a composite FK
133
    my $rule = $builder->build({ source => 'Issuingrule' });
134
    my @pk = ( $rule->{branchcode}, $rule->{categorycode}, $rule->{itemtype} );
135
    is( ref(Koha::IssuingRules->find(@pk)), "Koha::IssuingRule",
136
        'Find returned a Koha object for composite primary key' );
137
138
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
131
    is( Koha::Patrons->find(), undef, 'Find returns undef if no params passed' );
139
};
132
};
140
133
(-)a/t/db_dependent/Reserves.t (-17 / +25 lines)
Lines 198-209 $requesters{$branch_3} = AddMember( Link Here
198
# to request its items, while $branch_2 will allow its items
198
# to request its items, while $branch_2 will allow its items
199
# to fill holds from anywhere.
199
# to fill holds from anywhere.
200
200
201
$dbh->do('DELETE FROM issuingrules');
201
$dbh->do('DELETE FROM circulation_rules');
202
$dbh->do(
202
Koha::CirculationRules->set_rules(
203
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
203
    {
204
      VALUES (?, ?, ?, ?)},
204
        branchcode   => '*',
205
    {},
205
        categorycode => '*',
206
    '*', '*', '*', 25
206
        itemtype     => '*',
207
        rules        => {
208
            reservesallowed => 25,
209
            holds_per_record => 1,
210
        }
211
    }
207
);
212
);
208
213
209
# CPL allows only its own patrons to request its items
214
# CPL allows only its own patrons to request its items
Lines 549-572 ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $borrower), "Reserving a Link Here
549
my $itype = C4::Reserves::_get_itype($item);
554
my $itype = C4::Reserves::_get_itype($item);
550
my $categorycode = $borrower->{categorycode};
555
my $categorycode = $borrower->{categorycode};
551
my $holdingbranch = $item->{holdingbranch};
556
my $holdingbranch = $item->{holdingbranch};
552
my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
557
Koha::CirculationRules->set_rules(
553
    {
558
    {
554
        categorycode => $categorycode,
559
        categorycode => $categorycode,
555
        itemtype     => $itype,
560
        itemtype     => $itype,
556
        branchcode   => $holdingbranch
561
        branchcode   => $holdingbranch,
562
        rules => {
563
            onshelfholds => 1,
564
        }
557
    }
565
    }
558
);
566
);
559
567
560
$dbh->do(
561
    "UPDATE issuingrules SET onshelfholds = 1 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
562
    undef,
563
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
564
);
565
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
568
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
566
$dbh->do(
569
Koha::CirculationRules->set_rules(
567
    "UPDATE issuingrules SET onshelfholds = 0 WHERE categorycode = ? AND itemtype= ? and branchcode = ?",
570
    {
568
    undef,
571
        categorycode => $categorycode,
569
    $issuing_rule->categorycode, $issuing_rule->itemtype, $issuing_rule->branchcode
572
        itemtype     => $itype,
573
        branchcode   => $holdingbranch,
574
        rules => {
575
            onshelfholds => 0,
576
        }
577
    }
570
);
578
);
571
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
579
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
572
580
(-)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 359-365 subtest 'build_object() tests' => sub { Link Here
359
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
359
    my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
360
360
361
    my $issuing_rule = $builder->build_object(
361
    my $issuing_rule = $builder->build_object(
362
        {   class => 'Koha::IssuingRules',
362
        {   class => 'Koha::CirculationRules',
363
            value => {
363
            value => {
364
                categorycode => $categorycode,
364
                categorycode => $categorycode,
365
                itemtype     => $itemtype
365
                itemtype     => $itemtype
Lines 367-373 subtest 'build_object() tests' => sub { Link Here
367
        }
367
        }
368
    );
368
    );
369
369
370
    is( ref($issuing_rule), 'Koha::IssuingRule', 'Type is correct' );
370
    is( ref($issuing_rule), 'Koha::CirculationRule', 'Type is correct' );
371
    is( $issuing_rule->categorycode,
371
    is( $issuing_rule->categorycode,
372
        $categorycode, 'Category code correctly set' );
372
        $categorycode, 'Category code correctly set' );
373
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
373
    is( $issuing_rule->itemtype, $itemtype, 'Item type correctly set' );
(-)a/t/db_dependent/api/v1/holds.t (-6 / +12 lines)
Lines 33-38 use Koha::Biblios; Link Here
33
use Koha::Biblioitems;
33
use Koha::Biblioitems;
34
use Koha::Items;
34
use Koha::Items;
35
use Koha::Patrons;
35
use Koha::Patrons;
36
use Koha::CirculationRules;
36
37
37
my $schema  = Koha::Database->new->schema;
38
my $schema  = Koha::Database->new->schema;
38
my $builder = t::lib::TestBuilder->new();
39
my $builder = t::lib::TestBuilder->new();
Lines 130-140 my $itemnumber2 = create_item($biblionumber2, 'TEST000002'); Link Here
130
131
131
my $dbh = C4::Context->dbh;
132
my $dbh = C4::Context->dbh;
132
$dbh->do('DELETE FROM reserves');
133
$dbh->do('DELETE FROM reserves');
133
$dbh->do('DELETE FROM issuingrules');
134
$dbh->do('DELETE FROM circulation_rules');
134
    $dbh->do(q{
135
Koha::CirculationRules->set_rules(
135
        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
136
    {
136
        VALUES (?, ?, ?, ?)
137
        categorycode => '*',
137
    }, {}, '*', '*', '*', 1);
138
        branchcode   => '*',
139
        itemtype     => '*',
140
        rules        => {
141
            reservesallowed => 1
142
        }
143
    }
144
);
138
145
139
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
146
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
140
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
147
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
141
- 

Return to bug 18936