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 421-438 sub TooMany { Link Here
421
            # specific rule
420
            # specific rule
422
            if (C4::Context->preference('item-level_itypes')) {
421
            if (C4::Context->preference('item-level_itypes')) {
423
                $count_query .= " WHERE items.itype NOT IN (
422
                $count_query .= " WHERE items.itype NOT IN (
424
                                    SELECT itemtype FROM issuingrules
423
                                    SELECT itemtype FROM circulation_rules
425
                                    WHERE branchcode = ?
424
                                    WHERE branchcode = ?
426
                                    AND   (categorycode = ? OR categorycode = ?)
425
                                    AND   (categorycode = ? OR categorycode = ?)
427
                                    AND   itemtype <> '*'
426
                                    AND   itemtype <> '*'
427
                                    AND   rule_name = 'maxissueqty'
428
                                  ) ";
428
                                  ) ";
429
            } else { 
429
            } else {
430
                $count_query .= " JOIN  biblioitems USING (biblionumber) 
430
                $count_query .= " JOIN  biblioitems USING (biblionumber)
431
                                  WHERE biblioitems.itemtype NOT IN (
431
                                  WHERE biblioitems.itemtype NOT IN (
432
                                    SELECT itemtype FROM issuingrules
432
                                    SELECT itemtype FROM circulation_rules
433
                                    WHERE branchcode = ?
433
                                    WHERE branchcode = ?
434
                                    AND   (categorycode = ? OR categorycode = ?)
434
                                    AND   (categorycode = ? OR categorycode = ?)
435
                                    AND   itemtype <> '*'
435
                                    AND   itemtype <> '*'
436
                                    AND   rule_name = 'maxissueqty'
436
                                  ) ";
437
                                  ) ";
437
            }
438
            }
438
            push @bind_params, $maxissueqty_rule->branchcode;
439
            push @bind_params, $maxissueqty_rule->branchcode;
Lines 1343-1356 sub AddIssue { Link Here
1343
1344
1344
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1345
            # If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
1345
            unless ($auto_renew) {
1346
            unless ($auto_renew) {
1346
                my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1347
                my $rule = Koha::CirculationRules->get_effective_rule(
1347
                    {   categorycode => $borrower->{categorycode},
1348
                    {
1349
                        categorycode => $borrower->{categorycode},
1348
                        itemtype     => $item->{itype},
1350
                        itemtype     => $item->{itype},
1349
                        branchcode   => $branch
1351
                        branchcode   => $branch,
1352
                        rule_name    => 'auto_renew'
1350
                    }
1353
                    }
1351
                );
1354
                );
1352
1355
1353
                $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
1356
                $auto_renew = $rule->rule_value if $rule;
1354
            }
1357
            }
1355
1358
1356
            # Record in the database the fact that the book was issued.
1359
            # Record in the database the fact that the book was issued.
Lines 1471-1537 Get loan length for an itemtype, a borrower type and a branch Link Here
1471
=cut
1474
=cut
1472
1475
1473
sub GetLoanLength {
1476
sub GetLoanLength {
1474
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1477
    my ( $categorycode, $itemtype, $branchcode ) = @_;
1475
    my $dbh = C4::Context->dbh;
1476
    my $sth = $dbh->prepare(qq{
1477
        SELECT issuelength, lengthunit, renewalperiod
1478
        FROM issuingrules
1479
        WHERE   categorycode=?
1480
            AND itemtype=?
1481
            AND branchcode=?
1482
            AND issuelength IS NOT NULL
1483
    });
1484
1478
1485
    # try to find issuelength & return the 1st available.
1479
    # Set search precedences
1486
    # check with borrowertype, itemtype and branchcode, then without one of those parameters
1480
    my @params = (
1487
    $sth->execute( $borrowertype, $itemtype, $branchcode );
1481
        {
1488
    my $loanlength = $sth->fetchrow_hashref;
1482
            categorycode => $categorycode,
1489
1483
            itemtype     => $itemtype,
1490
    return $loanlength
1484
            branchcode   => $branchcode,
1491
      if defined($loanlength) && defined $loanlength->{issuelength};
1485
        },
1492
1486
        {
1493
    $sth->execute( $borrowertype, '*', $branchcode );
1487
            categorycode => $categorycode,
1494
    $loanlength = $sth->fetchrow_hashref;
1488
            itemtype     => '*',
1495
    return $loanlength
1489
            branchcode   => $branchcode,
1496
      if defined($loanlength) && defined $loanlength->{issuelength};
1490
        },
1497
1491
        {
1498
    $sth->execute( '*', $itemtype, $branchcode );
1492
            categorycode => '*',
1499
    $loanlength = $sth->fetchrow_hashref;
1493
            itemtype     => $itemtype,
1500
    return $loanlength
1494
            branchcode   => $branchcode,
1501
      if defined($loanlength) && defined $loanlength->{issuelength};
1495
        },
1502
1496
        {
1503
    $sth->execute( '*', '*', $branchcode );
1497
            categorycode => '*',
1504
    $loanlength = $sth->fetchrow_hashref;
1498
            itemtype     => '*',
1505
    return $loanlength
1499
            branchcode   => $branchcode,
1506
      if defined($loanlength) && defined $loanlength->{issuelength};
1500
        },
1507
1501
        {
1508
    $sth->execute( $borrowertype, $itemtype, '*' );
1502
            categorycode => $categorycode,
1509
    $loanlength = $sth->fetchrow_hashref;
1503
            itemtype     => $itemtype,
1510
    return $loanlength
1504
            branchcode   => '*',
1511
      if defined($loanlength) && defined $loanlength->{issuelength};
1505
        },
1512
1506
        {
1513
    $sth->execute( $borrowertype, '*', '*' );
1507
            categorycode => $categorycode,
1514
    $loanlength = $sth->fetchrow_hashref;
1508
            itemtype     => '*',
1515
    return $loanlength
1509
            branchcode   => '*',
1516
      if defined($loanlength) && defined $loanlength->{issuelength};
1510
        },
1517
1511
        {
1518
    $sth->execute( '*', $itemtype, '*' );
1512
            categorycode => '*',
1519
    $loanlength = $sth->fetchrow_hashref;
1513
            itemtype     => $itemtype,
1520
    return $loanlength
1514
            branchcode   => '*',
1521
      if defined($loanlength) && defined $loanlength->{issuelength};
1515
        },
1522
1516
        {
1523
    $sth->execute( '*', '*', '*' );
1517
            categorycode => '*',
1524
    $loanlength = $sth->fetchrow_hashref;
1518
            itemtype     => '*',
1525
    return $loanlength
1519
            branchcode   => '*',
1526
      if defined($loanlength) && defined $loanlength->{issuelength};
1520
        },
1527
1521
    );
1528
    # if no rule is set => 0 day (hardcoded)
1522
1529
    return {
1523
    # Initialize default values
1530
        issuelength => 0,
1524
    my $rules = {
1525
        issuelength   => 0,
1531
        renewalperiod => 0,
1526
        renewalperiod => 0,
1532
        lengthunit => 'days',
1527
        lengthunit    => 'days',
1533
    };
1528
    };
1534
1529
1530
    # Search for rules!
1531
    foreach my $rule_name (qw( issuelength renewalperiod lengthunit )) {
1532
        foreach my $params (@params) {
1533
            my $rule = Koha::CirculationRules->search(
1534
                {
1535
                    rule_name => $rule_name,
1536
                    %$params,
1537
                }
1538
            )->next();
1539
1540
            if ($rule) {
1541
                $rules->{$rule_name} = $rule->rule_value;
1542
                last;
1543
            }
1544
        }
1545
    }
1546
1547
    return $rules;
1535
}
1548
}
1536
1549
1537
1550
Lines 1546-1564 Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a Link Here
1546
sub GetHardDueDate {
1559
sub GetHardDueDate {
1547
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1560
    my ( $borrowertype, $itemtype, $branchcode ) = @_;
1548
1561
1549
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
1562
    my $rules = Koha::CirculationRules->get_effective_rules(
1550
        {   categorycode => $borrowertype,
1563
        {
1564
            categorycode => $borrowertype,
1551
            itemtype     => $itemtype,
1565
            itemtype     => $itemtype,
1552
            branchcode   => $branchcode
1566
            branchcode   => $branchcode,
1567
            rules        => [ 'hardduedate', 'hardduedatecompare' ],
1553
        }
1568
        }
1554
    );
1569
    );
1555
1570
1556
1571
    if ( defined( $rules->{hardduedate} ) ) {
1557
    if ( defined( $issuing_rule ) ) {
1572
        if ( $rules->{hardduedate} ) {
1558
        if ( $issuing_rule->hardduedate ) {
1573
            return ( dt_from_string( $rules->{hardduedate}, 'iso' ), $rules->{hardduedatecompare} );
1559
            return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
1574
        }
1560
        } else {
1575
        else {
1561
            return (undef, undef);
1576
            return ( undef, undef );
1562
        }
1577
        }
1563
    }
1578
    }
1564
}
1579
}
Lines 2229-2242 sub _debar_user_on_return { Link Here
2229
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2244
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2230
2245
2231
    my $circcontrol = C4::Context->preference('CircControl');
2246
    my $circcontrol = C4::Context->preference('CircControl');
2232
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2247
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2233
        {   categorycode => $borrower->{categorycode},
2248
        {   categorycode => $borrower->{categorycode},
2234
            itemtype     => $item->{itype},
2249
            itemtype     => $item->{itype},
2235
            branchcode   => $branchcode
2250
            branchcode   => $branchcode,
2251
            rules => [
2252
                'finedays',
2253
                'lengthunit',
2254
                'firstremind',
2255
                'maxsuspensiondays',
2256
            ]
2236
        }
2257
        }
2237
    );
2258
    );
2238
    my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
2259
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2239
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2260
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2240
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2261
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2241
2262
2242
    if ($finedays) {
2263
    if ($finedays) {
Lines 2247-2253 sub _debar_user_on_return { Link Here
2247
2268
2248
        # grace period is measured in the same units as the loan
2269
        # grace period is measured in the same units as the loan
2249
        my $grace =
2270
        my $grace =
2250
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2271
          DateTime::Duration->new( $unit => $issuing_rule->{firstremind} );
2251
2272
2252
        my $deltadays = DateTime::Duration->new(
2273
        my $deltadays = DateTime::Duration->new(
2253
            days => $chargeable_units
2274
            days => $chargeable_units
Lines 2257-2263 sub _debar_user_on_return { Link Here
2257
2278
2258
            # If the max suspension days is < than the suspension days
2279
            # If the max suspension days is < than the suspension days
2259
            # the suspension days is limited to this maximum period.
2280
            # the suspension days is limited to this maximum period.
2260
            my $max_sd = $issuing_rule->maxsuspensiondays;
2281
            my $max_sd = $issuing_rule->{maxsuspensiondays};
2261
            if ( defined $max_sd ) {
2282
            if ( defined $max_sd ) {
2262
                $max_sd = DateTime::Duration->new( days => $max_sd );
2283
                $max_sd = DateTime::Duration->new( days => $max_sd );
2263
                $suspension_days = $max_sd
2284
                $suspension_days = $max_sd
Lines 2680-2694 sub CanBookBeRenewed { Link Here
2680
    return ( 1, undef ) if $override_limit;
2701
    return ( 1, undef ) if $override_limit;
2681
2702
2682
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2703
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
2683
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2704
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2684
        {   categorycode => $patron->categorycode,
2705
        {
2706
            categorycode => $patron->categorycode,
2685
            itemtype     => $item->{itype},
2707
            itemtype     => $item->{itype},
2686
            branchcode   => $branchcode
2708
            branchcode   => $branchcode,
2709
            rules => [
2710
                'renewalsallowed',
2711
                'no_auto_renewal_after',
2712
                'no_auto_renewal_after_hard_limit',
2713
                'lengthunit',
2714
                'norenewalbefore',
2715
            ]
2687
        }
2716
        }
2688
    );
2717
    );
2689
2718
2690
    return ( 0, "too_many" )
2719
    return ( 0, "too_many" )
2691
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2720
      if not $issuing_rule->{renewalsallowed} or $issuing_rule->{renewalsallowed} <= $issue->renewals;
2692
2721
2693
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2722
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2694
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2723
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
Lines 2708-2730 sub CanBookBeRenewed { Link Here
2708
            return ( 0, 'auto_account_expired' );
2737
            return ( 0, 'auto_account_expired' );
2709
        }
2738
        }
2710
2739
2711
        if ( defined $issuing_rule->no_auto_renewal_after
2740
        if ( defined $issuing_rule->{no_auto_renewal_after}
2712
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2741
                and $issuing_rule->{no_auto_renewal_after} ne "" ) {
2713
            # Get issue_date and add no_auto_renewal_after
2742
            # Get issue_date and add no_auto_renewal_after
2714
            # If this is greater than today, it's too late for renewal.
2743
            # If this is greater than today, it's too late for renewal.
2715
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2744
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2716
            $maximum_renewal_date->add(
2745
            $maximum_renewal_date->add(
2717
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2746
                $issuing_rule->{lengthunit} => $issuing_rule->{no_auto_renewal_after}
2718
            );
2747
            );
2719
            my $now = dt_from_string;
2748
            my $now = dt_from_string;
2720
            if ( $now >= $maximum_renewal_date ) {
2749
            if ( $now >= $maximum_renewal_date ) {
2721
                return ( 0, "auto_too_late" );
2750
                return ( 0, "auto_too_late" );
2722
            }
2751
            }
2723
        }
2752
        }
2724
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2753
        if ( defined $issuing_rule->{no_auto_renewal_after_hard_limit}
2725
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2754
                      and $issuing_rule->{no_auto_renewal_after_hard_limit} ne "" ) {
2726
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2755
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2727
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2756
            if ( dt_from_string >= dt_from_string( $issuing_rule->{no_auto_renewal_after_hard_limit} ) ) {
2728
                return ( 0, "auto_too_late" );
2757
                return ( 0, "auto_too_late" );
2729
            }
2758
            }
2730
        }
2759
        }
Lines 2738-2754 sub CanBookBeRenewed { Link Here
2738
        }
2767
        }
2739
    }
2768
    }
2740
2769
2741
    if ( defined $issuing_rule->norenewalbefore
2770
    if ( defined $issuing_rule->{norenewalbefore}
2742
        and $issuing_rule->norenewalbefore ne "" )
2771
        and $issuing_rule->{norenewalbefore} ne "" )
2743
    {
2772
    {
2744
2773
2745
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2774
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2746
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2775
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2747
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2776
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
2748
2777
2749
        # Depending on syspref reset the exact time, only check the date
2778
        # Depending on syspref reset the exact time, only check the date
2750
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2779
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2751
            and $issuing_rule->lengthunit eq 'days' )
2780
            and $issuing_rule->{lengthunit} eq 'days' )
2752
        {
2781
        {
2753
            $soonestrenewal->truncate( to => 'day' );
2782
            $soonestrenewal->truncate( to => 'day' );
2754
        }
2783
        }
Lines 2956-2969 sub GetRenewCount { Link Here
2956
    # $item and $borrower should be calculated
2985
    # $item and $borrower should be calculated
2957
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
2986
    my $branchcode = _GetCircControlBranch($item, $patron->unblessed);
2958
2987
2959
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2988
    my $rule = Koha::CirculationRules->get_effective_rule(
2960
        {   categorycode => $patron->categorycode,
2989
        {
2990
            categorycode => $patron->categorycode,
2961
            itemtype     => $item->{itype},
2991
            itemtype     => $item->{itype},
2962
            branchcode   => $branchcode
2992
            branchcode   => $branchcode,
2993
            rule_name    => 'renewalsallowed',
2963
        }
2994
        }
2964
    );
2995
    );
2965
2996
2966
    $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : 0;
2997
    $renewsallowed = $rule ? $rule->rule_value : 0;
2967
    $renewsleft    = $renewsallowed - $renewcount;
2998
    $renewsleft    = $renewsallowed - $renewcount;
2968
    if($renewsleft < 0){ $renewsleft = 0; }
2999
    if($renewsleft < 0){ $renewsleft = 0; }
2969
    return ( $renewcount, $renewsallowed, $renewsleft );
3000
    return ( $renewcount, $renewsallowed, $renewsleft );
Lines 3001-3025 sub GetSoonestRenewDate { Link Here
3001
      or return;
3032
      or return;
3002
3033
3003
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3034
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3004
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3035
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3005
        {   categorycode => $patron->categorycode,
3036
        {   categorycode => $patron->categorycode,
3006
            itemtype     => $item->{itype},
3037
            itemtype     => $item->{itype},
3007
            branchcode   => $branchcode
3038
            branchcode   => $branchcode,
3039
            rules => [
3040
                'norenewalbefore',
3041
                'lengthunit',
3042
            ]
3008
        }
3043
        }
3009
    );
3044
    );
3010
3045
3011
    my $now = dt_from_string;
3046
    my $now = dt_from_string;
3012
    return $now unless $issuing_rule;
3047
    return $now unless $issuing_rule;
3013
3048
3014
    if ( defined $issuing_rule->norenewalbefore
3049
    if ( defined $issuing_rule->{norenewalbefore}
3015
        and $issuing_rule->norenewalbefore ne "" )
3050
        and $issuing_rule->{norenewalbefore} ne "" )
3016
    {
3051
    {
3017
        my $soonestrenewal =
3052
        my $soonestrenewal =
3018
          dt_from_string( $itemissue->date_due )->subtract(
3053
          dt_from_string( $itemissue->date_due )->subtract(
3019
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
3054
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3020
3055
3021
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3056
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3022
            and $issuing_rule->lengthunit eq 'days' )
3057
            and $issuing_rule->{lengthunit} eq 'days' )
3023
        {
3058
        {
3024
            $soonestrenewal->truncate( to => 'day' );
3059
            $soonestrenewal->truncate( to => 'day' );
3025
        }
3060
        }
Lines 3060-3089 sub GetLatestAutoRenewDate { Link Here
3060
      or return;
3095
      or return;
3061
3096
3062
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3097
    my $branchcode = _GetCircControlBranch( $item, $patron->unblessed );
3063
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
3098
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3064
        {   categorycode => $patron->categorycode,
3099
        {
3100
            categorycode => $patron->categorycode,
3065
            itemtype     => $item->{itype},
3101
            itemtype     => $item->{itype},
3066
            branchcode   => $branchcode
3102
            branchcode   => $branchcode,
3103
            rules => [
3104
                'no_auto_renewal_after',
3105
                'no_auto_renewal_after_hard_limit',
3106
                'lengthunit',
3107
            ]
3067
        }
3108
        }
3068
    );
3109
    );
3069
3110
3070
    return unless $issuing_rule;
3111
    return unless $circulation_rules;
3071
    return
3112
    return
3072
      if ( not $issuing_rule->no_auto_renewal_after
3113
      if ( not $circulation_rules->{no_auto_renewal_after}
3073
            or $issuing_rule->no_auto_renewal_after eq '' )
3114
            or $circulation_rules->{no_auto_renewal_after} eq '' )
3074
      and ( not $issuing_rule->no_auto_renewal_after_hard_limit
3115
      and ( not $circulation_rules->{no_auto_renewal_after_hard_limit}
3075
             or $issuing_rule->no_auto_renewal_after_hard_limit eq '' );
3116
             or $circulation_rules->{no_auto_renewal_after_hard_limit} eq '' );
3076
3117
3077
    my $maximum_renewal_date;
3118
    my $maximum_renewal_date;
3078
    if ( $issuing_rule->no_auto_renewal_after ) {
3119
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3079
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3120
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3080
        $maximum_renewal_date->add(
3121
        $maximum_renewal_date->add(
3081
            $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
3122
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3082
        );
3123
        );
3083
    }
3124
    }
3084
3125
3085
    if ( $issuing_rule->no_auto_renewal_after_hard_limit ) {
3126
    if ( $circulation_rules->{no_auto_renewal_after_hard_limit} ) {
3086
        my $dt = dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit );
3127
        my $dt = dt_from_string( $circulation_rules->{no_auto_renewal_after_hard_limit} );
3087
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3128
        $maximum_renewal_date = $dt if not $maximum_renewal_date or $maximum_renewal_date > $dt;
3088
    }
3129
    }
3089
    return $maximum_renewal_date;
3130
    return $maximum_renewal_date;
Lines 3130-3148 sub GetIssuingCharges { Link Here
3130
        $item_type = $item_data->{itemtype};
3171
        $item_type = $item_data->{itemtype};
3131
        $charge    = $item_data->{rentalcharge};
3172
        $charge    = $item_data->{rentalcharge};
3132
        my $branch = C4::Context::mybranch();
3173
        my $branch = C4::Context::mybranch();
3133
        my $discount_query = q|SELECT rentaldiscount,
3174
        my $patron = Koha::Patrons->find( $borrowernumber );
3134
            issuingrules.itemtype, issuingrules.branchcode
3175
        my $discount = _get_discount_from_rule($patron->categorycode, $branch, $item_type);
3135
            FROM borrowers
3176
        if ($discount) {
3136
            LEFT JOIN issuingrules ON borrowers.categorycode = issuingrules.categorycode
3137
            WHERE borrowers.borrowernumber = ?
3138
            AND (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
3139
            AND (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')|;
3140
        my $discount_sth = $dbh->prepare($discount_query);
3141
        $discount_sth->execute( $borrowernumber, $item_type, $branch );
3142
        my $discount_rules = $discount_sth->fetchall_arrayref({});
3143
        if (@{$discount_rules}) {
3144
            # We may have multiple rules so get the most specific
3177
            # We may have multiple rules so get the most specific
3145
            my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
3146
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3178
            $charge = ( $charge * ( 100 - $discount ) ) / 100;
3147
        }
3179
        }
3148
        if ($charge) {
3180
        if ($charge) {
Lines 3155-3191 sub GetIssuingCharges { Link Here
3155
3187
3156
# Select most appropriate discount rule from those returned
3188
# Select most appropriate discount rule from those returned
3157
sub _get_discount_from_rule {
3189
sub _get_discount_from_rule {
3158
    my ($rules_ref, $branch, $itemtype) = @_;
3190
    my ($categorycode, $branchcode, $itemtype) = @_;
3159
    my $discount;
3160
3191
3161
    if (@{$rules_ref} == 1) { # only 1 applicable rule use it
3192
    # Set search precedences
3162
        $discount = $rules_ref->[0]->{rentaldiscount};
3193
    my @params = (
3163
        return (defined $discount) ? $discount : 0;
3194
        {
3164
    }
3195
            branchcode   => $branchcode,
3165
    # could have up to 4 does one match $branch and $itemtype
3196
            itemtype     => $itemtype,
3166
    my @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq $itemtype } @{$rules_ref};
3197
            categorycode => $categorycode,
3167
    if (@d) {
3198
        },
3168
        $discount = $d[0]->{rentaldiscount};
3199
        {
3169
        return (defined $discount) ? $discount : 0;
3200
            branchcode   => '*',
3170
    }
3201
            categorycode => $categorycode,
3171
    # do we have item type + all branches
3202
            itemtype     => $itemtype,
3172
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq $itemtype } @{$rules_ref};
3203
        },
3173
    if (@d) {
3204
        {
3174
        $discount = $d[0]->{rentaldiscount};
3205
            branchcode   => $branchcode,
3175
        return (defined $discount) ? $discount : 0;
3206
            categorycode => $categorycode,
3176
    }
3207
            itemtype     => '*',
3177
    # do we all item types + this branch
3208
        },
3178
    @d = grep { $_->{branchcode} eq $branch && $_->{itemtype} eq q{*} } @{$rules_ref};
3209
        {
3179
    if (@d) {
3210
            branchcode   => '*',
3180
        $discount = $d[0]->{rentaldiscount};
3211
            categorycode => $categorycode,
3181
        return (defined $discount) ? $discount : 0;
3212
            itemtype     => '*',
3182
    }
3213
        },
3183
    # so all and all (surely we wont get here)
3214
    );
3184
    @d = grep { $_->{branchcode} eq q{*} && $_->{itemtype} eq q{*} } @{$rules_ref};
3215
3185
    if (@d) {
3216
    foreach my $params (@params) {
3186
        $discount = $d[0]->{rentaldiscount};
3217
        my $rule = Koha::CirculationRules->search(
3187
        return (defined $discount) ? $discount : 0;
3218
            {
3219
                rule_name => 'rentaldiscount',
3220
                %$params,
3221
            }
3222
        )->next();
3223
3224
        return $rule->rule_value if $rule;
3188
    }
3225
    }
3226
3189
    # none of the above
3227
    # none of the above
3190
    return 0;
3228
    return 0;
3191
}
3229
}
(-)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 (-15 / +29 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 2072-2095 patron category, itemtype, and library. Link Here
2072
sub GetHoldRule {
2071
sub GetHoldRule {
2073
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2072
    my ( $categorycode, $itemtype, $branchcode ) = @_;
2074
2073
2075
    my $dbh = C4::Context->dbh;
2074
    my $reservesallowed = Koha::CirculationRules->get_effective_rule(
2076
2075
        {
2077
    my $sth = $dbh->prepare(
2076
            itemtype     => $itemtype,
2078
        q{
2077
            categorycode => $categorycode,
2079
         SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record
2078
            branchcode   => $branchcode,
2080
           FROM issuingrules
2079
            rule_name    => 'reservesallowed',
2081
          WHERE (categorycode in (?,'*') )
2080
            order_by     => {
2082
            AND (itemtype IN (?,'*'))
2081
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2083
            AND (branchcode IN (?,'*'))
2082
            }
2084
       ORDER BY categorycode DESC,
2085
                itemtype     DESC,
2086
                branchcode   DESC
2087
        }
2083
        }
2088
    );
2084
    );
2085
    return unless $reservesallowed;;
2089
2086
2090
    $sth->execute( $categorycode, $itemtype, $branchcode );
2087
    my $rules;
2088
    $rules->{reservesallowed} = $reservesallowed->rule_value;
2089
    $rules->{itemtype}        = $reservesallowed->itemtype;
2090
    $rules->{categorycode}    = $reservesallowed->categorycode;
2091
    $rules->{branchcode}      = $reservesallowed->branchcode;
2092
2093
    my $holds_per_record = Koha::CirculationRules->get_effective_rule(
2094
        {
2095
            itemtype     => $itemtype,
2096
            categorycode => $categorycode,
2097
            branchcode   => $branchcode,
2098
            rule_name    => 'holds_per_record',
2099
            order_by     => {
2100
                -desc => [ 'categorycode', 'itemtype', 'branchcode' ]
2101
            }
2102
        }
2103
    );
2104
    $rules->{holds_per_record} = $holds_per_record->rule_value if $holds_per_record;
2091
2105
2092
    return $sth->fetchrow_hashref();
2106
    return $rules;
2093
}
2107
}
2094
2108
2095
=head1 AUTHOR
2109
=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 141-150 sub article_request_type_for_bib { Link Here
141
    my $borrowertype = $borrower->categorycode;
141
    my $borrowertype = $borrower->categorycode;
142
    my $itemtype     = $self->itemtype();
142
    my $itemtype     = $self->itemtype();
143
143
144
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowertype, itemtype => $itemtype });
144
    my $rule = Koha::CirculationRules->get_effective_rule(
145
        {
146
            rule_name    => 'article_requests',
147
            categorycode => $borrowertype,
148
            itemtype     => $itemtype,
149
        }
150
    );
145
151
146
    return q{} unless $issuing_rule;
152
    return q{} unless $rule;
147
    return $issuing_rule->article_requests || q{}
153
    return $rule->rule_value || q{}
148
}
154
}
149
155
150
=head3 article_request_type_for_items
156
=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 (-136 lines)
Lines 1-136 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 get_onshelfholds_policy
104
105
    my $on_shelf_holds = Koha::IssuingRules->get_onshelfholds_policy({ item => $item, patron => $patron });
106
107
=cut
108
109
sub get_onshelfholds_policy {
110
    my ( $class, $params ) = @_;
111
    my $item = $params->{item};
112
    my $itemtype = $item->effective_itemtype;
113
    my $patron = $params->{patron};
114
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
115
        {
116
            ( $patron ? ( categorycode => $patron->categorycode ) : () ),
117
            itemtype   => $itemtype,
118
            branchcode => $item->holdingbranch
119
        }
120
    );
121
    return $issuing_rule ? $issuing_rule->onshelfholds : undef;
122
}
123
124
=head3 type
125
126
=cut
127
128
sub _type {
129
    return 'Issuingrule';
130
}
131
132
sub object_class {
133
    return 'Koha::IssuingRule';
134
}
135
136
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 26-33 use C4::Koha; Link Here
26
use C4::Debug;
26
use C4::Debug;
27
use Koha::DateUtils;
27
use Koha::DateUtils;
28
use Koha::Database;
28
use Koha::Database;
29
use Koha::IssuingRule;
30
use Koha::IssuingRules;
31
use Koha::Logger;
29
use Koha::Logger;
32
use Koha::RefundLostItemFeeRules;
30
use Koha::RefundLostItemFeeRules;
33
use Koha::Libraries;
31
use Koha::Libraries;
Lines 69-76 if ($op eq 'delete') { Link Here
69
    my $categorycode = $input->param('categorycode');
67
    my $categorycode = $input->param('categorycode');
70
    $debug and warn "deleting $1 $2 $branch";
68
    $debug and warn "deleting $1 $2 $branch";
71
69
72
    my $sth_Idelete = $dbh->prepare("delete from issuingrules where branchcode=? and categorycode=? and itemtype=?");
70
    Koha::CirculationRules->set_rules(
73
    $sth_Idelete->execute($branch, $categorycode, $itemtype);
71
        {
72
            categorycode => $categorycode,
73
            branchcode   => $branch,
74
            itemtype     => $itemtype,
75
            rules        => {
76
                restrictedtype                   => undef,
77
                rentaldiscount                   => undef,
78
                fine                             => undef,
79
                finedays                         => undef,
80
                maxsuspensiondays                => undef,
81
                firstremind                      => undef,
82
                chargeperiod                     => undef,
83
                chargeperiod_charge_at           => undef,
84
                accountsent                      => undef,
85
                issuelength                      => undef,
86
                lengthunit                       => undef,
87
                hardduedate                      => undef,
88
                hardduedatecompare               => undef,
89
                renewalsallowed                  => undef,
90
                renewalperiod                    => undef,
91
                norenewalbefore                  => undef,
92
                auto_renew                       => undef,
93
                no_auto_renewal_after            => undef,
94
                no_auto_renewal_after_hard_limit => undef,
95
                reservesallowed                  => undef,
96
                holds_per_record                 => undef,
97
                overduefinescap                  => undef,
98
                cap_fine_to_replacement_price    => undef,
99
                onshelfholds                     => undef,
100
                opacitemholds                    => undef,
101
                article_requests                 => undef,
102
            }
103
        }
104
    );
74
}
105
}
75
elsif ($op eq 'delete-branch-cat') {
106
elsif ($op eq 'delete-branch-cat') {
76
    my $categorycode  = $input->param('categorycode');
107
    my $categorycode  = $input->param('categorycode');
Lines 271-283 elsif ($op eq 'add') { Link Here
271
        article_requests              => $article_requests,
302
        article_requests              => $article_requests,
272
    };
303
    };
273
304
274
    my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
275
    if ($issuingrule) {
276
        $issuingrule->set($params)->store();
277
    } else {
278
        Koha::IssuingRule->new()->set($params)->store();
279
    }
280
281
    Koha::CirculationRules->set_rules(
305
    Koha::CirculationRules->set_rules(
282
        {
306
        {
283
            categorycode => $bor,
307
            categorycode => $bor,
Lines 286-291 elsif ($op eq 'add') { Link Here
286
            rules        => {
310
            rules        => {
287
                maxissueqty       => $maxissueqty,
311
                maxissueqty       => $maxissueqty,
288
                maxonsiteissueqty => $maxonsiteissueqty,
312
                maxonsiteissueqty => $maxonsiteissueqty,
313
                %$params,
289
            }
314
            }
290
        }
315
        }
291
    );
316
    );
Lines 522-583 $template->param( Link Here
522
547
523
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
548
my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
524
549
525
my @row_loop;
526
my $itemtypes = Koha::ItemTypes->search_with_localization;
550
my $itemtypes = Koha::ItemTypes->search_with_localization;
527
551
528
my $sth2 = $dbh->prepare("
529
    SELECT  issuingrules.*,
530
            itemtypes.description AS humanitemtype,
531
            categories.description AS humancategorycode,
532
            COALESCE( localization.translation, itemtypes.description ) AS translated_description
533
    FROM issuingrules
534
    LEFT JOIN itemtypes
535
        ON (itemtypes.itemtype = issuingrules.itemtype)
536
    LEFT JOIN categories
537
        ON (categories.categorycode = issuingrules.categorycode)
538
    LEFT JOIN localization ON issuingrules.itemtype = localization.code
539
        AND localization.entity = 'itemtypes'
540
        AND localization.lang = ?
541
    WHERE issuingrules.branchcode = ?
542
");
543
$sth2->execute($language, $branch);
544
545
while (my $row = $sth2->fetchrow_hashref) {
546
    $row->{'current_branch'} ||= $row->{'branchcode'};
547
    $row->{humanitemtype} ||= $row->{itemtype};
548
    $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
549
    $row->{'humancategorycode'} ||= $row->{'categorycode'};
550
    $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
551
    $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
552
    if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
553
       my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
554
       $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
555
       $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
556
       $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
557
       $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
558
    } else {
559
       $row->{'hardduedate'} = 0;
560
    }
561
    if ($row->{no_auto_renewal_after_hard_limit}) {
562
       my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
563
       $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
564
    }
565
566
    push @row_loop, $row;
567
}
568
569
my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
570
571
$template->param(show_branch_cat_rule_form => 1);
552
$template->param(show_branch_cat_rule_form => 1);
572
553
573
$template->param(
554
$template->param(
574
    patron_categories => $patron_categories,
555
    patron_categories => $patron_categories,
575
                        itemtypeloop => $itemtypes,
556
    itemtypeloop      => $itemtypes,
576
                        rules => \@sorted_row_loop,
557
    humanbranch       => ( $branch ne '*' ? $branch : '' ),
577
                        humanbranch => ($branch ne '*' ? $branch : ''),
558
    current_branch    => $branch,
578
                        current_branch => $branch,
559
);
579
                        definedbranch => scalar(@sorted_row_loop)>0
580
                        );
581
output_html_with_http_headers $input, $cookie, $template->output;
560
output_html_with_http_headers $input, $cookie, $template->output;
582
561
583
exit 0;
562
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 104-220 Link Here
104
            </tr>
113
            </tr>
105
            </thead>
114
            </thead>
106
            <tbody>
115
            <tbody>
107
				[% FOREACH rule IN rules %]
116
                [% SET row_count = 0 %]
108
					<tr id="row_[% loop.count %]">
117
                [% FOREACH c IN categorycodes %]
109
							<td>[% IF ( rule.default_humancategorycode ) %]
118
                    [% FOREACH i IN itemtypes %]
110
									<em>All</em>
119
                        [% SET maxissueqty = CirculationRules.Get( branchcode, c, i, 'maxissueqty' ) %]
111
								[% ELSE %]
120
                        [% SET maxonsiteissueqty = CirculationRules.Get( branchcode, c, i, 'maxonsiteissueqty' ) %]
112
									[% rule.humancategorycode %]
121
                        [% SET issuelength = CirculationRules.Get( branchcode, c, i, 'issuelength' ) %]
113
								[% END %]
122
                        [% SET lengthunit = CirculationRules.Get( branchcode, c, i, 'lengthunit' ) %]
114
							</td>
123
                        [% SET hardduedate = CirculationRules.Get( branchcode, c, i, 'hardduedate' ) %]
115
                            <td>[% IF rule.default_translated_description %]
124
                        [% SET hardduedatecompare = CirculationRules.Get( branchcode, c, i, 'hardduedatecompare' ) %]
116
									<em>All</em>
125
                        [% SET fine = CirculationRules.Get( branchcode, c, i, 'fine' ) %]
117
								[% ELSE %]
126
                        [% SET chargeperiod = CirculationRules.Get( branchcode, c, i, 'chargeperiod' ) %]
118
									[% rule.translated_description %]
127
                        [% SET chargeperiod_charge_at = CirculationRules.Get( branchcode, c, i, 'chargeperiod_charge_at' ) %]
119
								[% END %]
128
                        [% SET firstremind = CirculationRules.Get( branchcode, c, i, 'firstremind' ) %]
120
							</td>
129
                        [% SET overduefinescap = CirculationRules.Get( branchcode, c, i, 'overduefinescap' ) %]
121
                                                        <td class="actions">
130
                        [% SET cap_fine_to_replacement_price = CirculationRules.Get( branchcode, c, i, 'cap_fine_to_replacement_price' ) %]
122
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
131
                        [% SET finedays = CirculationRules.Get( branchcode, c, i, 'finedays' ) %]
123
                                                          <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>
132
                        [% SET maxsuspensiondays = CirculationRules.Get( branchcode, c, i, 'maxsuspensiondays' ) %]
124
                                                        </td>
133
                        [% SET renewalsallowed = CirculationRules.Get( branchcode, c, i, 'renewalsallowed' ) %]
125
134
                        [% SET renewalperiod = CirculationRules.Get( branchcode, c, i, 'renewalperiod' ) %]
126
							<td>
135
                        [% SET norenewalbefore = CirculationRules.Get( branchcode, c, i, 'norenewalbefore' ) %]
127
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxissueqty' ) %]
136
                        [% SET auto_renew = CirculationRules.Get( branchcode, c, i, 'auto_renew' ) %]
128
                                [% IF rule_value  %]
137
                        [% SET no_auto_renewal_after = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after' ) %]
129
                                    [% rule_value %]
138
                        [% SET no_auto_renewal_after_hard_limit = CirculationRules.Get( branchcode, c, i, 'no_auto_renewal_after_hard_limit' ) %]
130
                                [% ELSE %]
139
                        [% SET reservesallowed = CirculationRules.Get( branchcode, c, i, 'reservesallowed' ) %]
131
                                    Unlimited
140
                        [% SET holds_per_record = CirculationRules.Get( branchcode, c, i, 'holds_per_record' ) %]
132
                                [% END %]
141
                        [% SET onshelfholds = CirculationRules.Get( branchcode, c, i, 'onshelfholds' ) %]
133
							</td>
142
                        [% SET opacitemholds = CirculationRules.Get( branchcode, c, i, 'opacitemholds' ) %]
134
							<td>
143
                        [% SET article_requests = CirculationRules.Get( branchcode, c, i, 'article_requests' ) %]
135
                                [% SET rule_value = CirculationRules.Get( rule.branchcode, rule.categorycode, rule.itemtype, 'maxonsiteissueqty' ) %]
144
                        [% SET rentaldiscount = CirculationRules.Get( branchcode, c, i, 'rentaldiscount' ) %]
136
                                [% IF rule_value  %]
145
137
                                    [% rule_value %]
146
                        [% SET show_rule = maxissueqty || maxonsiteissueqty || issuelength || lengthunit || hardduedate || hardduedatebefore || hardduedateexact || fine || chargeperiod
138
                                [% ELSE %]
147
                                        || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || renewalsallowed
139
                                    Unlimited
148
                                        || renewalsallowed || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed
140
                                [% END %]
149
                                        || holds_per_record || onshelfholds || opacitemholds || article_requests || article_requests %]
141
							</td>
150
                        [% IF show_rule %]
142
							<td>[% rule.issuelength %]</td>
151
                            [% SET row_count = row_count + 1 %]
143
							<td>
152
                            <tr row_countd="row_[% row_count %]">
144
							    [% rule.lengthunit %]
153
                                    <td>
145
							</td>
154
                                        [% IF c == '*' %]
146
                            <td>
155
                                            <em>All</em>
147
                              [% IF ( rule.hardduedate ) %]
156
                                        [% ELSE %]
148
                                [% IF ( rule.hardduedatebefore ) %]
157
                                            [% Categories.GetName(c) %]
149
                                  before [% rule.hardduedate %]
158
                                        [% END %]
150
                                  <input type="hidden" name="hardduedatecomparebackup" value="-1" />
159
                                    </td>
151
                                [% ELSIF ( rule.hardduedateexact ) %]
160
                                    <td>
152
                                  on [% rule.hardduedate %]
161
                                        [% IF i == '*' %]
153
                                  <input type="hidden" name="hardduedatecomparebackup" value="0" />
162
                                            <em>All</em>
154
                                [% ELSIF ( rule.hardduedateafter ) %]
163
                                        [% ELSE %]
155
                                  after [% rule.hardduedate %]
164
                                            [% ItemTypes.GetDescription(i) %]
156
                                  <input type="hidden" name="hardduedatecomparebackup" value="1" />
165
                                        [% END %]
157
                                [% END %]
166
                                    </td>
158
                              [% ELSE %]
167
                                    <td>
159
                                None defined
168
                                        [% IF maxissueqty  %]
160
                              [% END %]
169
                                            [% maxissueqty %]
161
                            </td>
170
                                        [% ELSE %]
162
							<td>[% rule.fine %]</td>
171
                                            Unlimited
163
							<td>[% rule.chargeperiod %]</td>
172
                                        [% END %]
164
                <td>[% IF rule.chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
173
                                    </td>
165
							<td>[% rule.firstremind %]</td>
174
                                    <td>
166
                            <td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
175
                                        [% IF maxonsiteissueqty  %]
167
                            <td>
176
                                            [% maxonsiteissueqty %]
168
                                [% IF rule.cap_fine_to_replacement_price %]
177
                                        [% ELSE %]
169
                                    <input type="checkbox" checked="checked" disabled="disabled" />
178
                                            Unlimited
170
                                [% ELSE %]
179
                                        [% END %]
171
                                    <input type="checkbox" disabled="disabled" />
180
                                    </td>
172
                                [% END %]
181
                                    <td>[% issuelength %]</td>
173
                            </td>
182
                                    <td>
174
							<td>[% rule.finedays %]</td>
183
                                        [% lengthunit %]
175
                            <td>[% rule.maxsuspensiondays %]</td>
184
                                    </td>
176
							<td>[% rule.renewalsallowed %]</td>
185
                                    <td>
177
                            <td>[% rule.renewalperiod %]</td>
186
                                      [% IF ( hardduedate ) %]
178
                            <td>[% rule.norenewalbefore %]</td>
187
                                        [% IF ( hardduedatecompare == '-1' ) %]
179
                            <td>
188
                                          before [% hardduedate | $KohaDates %]
180
                                [% IF ( rule.auto_renew ) %]
189
                                          <input type="hidden" name="hardduedatecomparebackup" value="-1" />
181
                                Yes
190
                                        [% ELSIF ( hardduedatecompare == '0' ) %]
182
                                [% ELSE %]
191
                                          on [% hardduedate | $KohaDates %]
183
                                No
192
                                          <input type="hidden" name="hardduedatecomparebackup" value="0" />
184
                                [% END %]
193
                                        [% ELSIF ( hardduedatecompare == '1' ) %]
185
                            </td>
194
                                          after [% hardduedate | $KohaDates %]
186
                            <td>[% rule.no_auto_renewal_after %]</td>
195
                                          <input type="hidden" name="hardduedatecomparebackup" value="1" />
187
                            <td>[% rule.no_auto_renewal_after_hard_limit %]</td>
196
                                        [% END %]
188
							<td>[% rule.reservesallowed %]</td>
197
                                      [% ELSE %]
189
                                                        <td>[% rule.holds_per_record %]</td>
198
                                        None defined
190
                                                        <td>
199
                                      [% END %]
191
                                                            [% IF rule.onshelfholds == 1 %]
200
                                    </td>
192
                                                                Yes
201
                                    <td>[% fine %]</td>
193
                                                            [% ELSIF rule.onshelfholds == 2 %]
202
                                    <td>[% chargeperiod %]</td>
194
                                                                If all unavailable
203
                                    <td>[% IF chargeperiod_charge_at %]Start of interval[% ELSE %]End of interval[% END %]</td>
195
                                                            [% ELSE %]
204
                                    <td>[% firstremind %]</td>
196
                                                                If any unavailable
205
                                    <td>[% overduefinescap FILTER format("%.2f") %]</td>
197
                                                            [% END %]</td>
206
                                    <td>
198
                                                        <td>[% IF rule.opacitemholds == 'F'%]Force[% ELSIF rule.opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
207
                                        [% IF cap_fine_to_replacement_price %]
199
                                                        <td>
208
                                            <input type="checkbox" checked="checked" disabled="disabled" />
200
                                                            [% IF rule.article_requests == 'no' %]
209
                                        [% ELSE %]
201
                                                                No
210
                                            <input type="checkbox" disabled="disabled" />
202
                                                            [% ELSIF rule.article_requests == 'yes' %]
211
                                        [% END %]
203
                                                                Yes
212
                                    </td>
204
                                                            [% ELSIF rule.article_requests == 'bib_only' %]
213
                                    <td>[% finedays %]</td>
205
                                                                Record only
214
                                    <td>[% maxsuspensiondays %]</td>
206
                                                            [% ELSIF rule.article_requests == 'item_only' %]
215
                                    <td>[% renewalsallowed %]</td>
207
                                                                Item only
216
                                    <td>[% renewalperiod %]</td>
208
                                                            [% END %]
217
                                    <td>[% norenewalbefore %]</td>
209
                                                        </td>
218
                                    <td>
210
							<td>[% rule.rentaldiscount %]</td>
219
                                        [% IF auto_renew %]
211
                                                        <td class="actions">
220
                                            Yes
212
                                                          <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
221
                                        [% ELSE %]
213
                                                          <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>
222
                                            No
214
                                                        </td>
223
                                        [% END %]
215
224
                                    </td>
216
                	</tr>
225
                                    <td>[% no_auto_renewal_after %]</td>
217
            	[% END %]
226
                                    <td>[% no_auto_renewal_after_hard_limit %]</td>
227
                                    <td>[% reservesallowed %]</td>
228
                                    <td>[% holds_per_record %]</td>
229
                                    <td>
230
                                        [% IF onshelfholds == 1 %]
231
                                            Yes
232
                                        [% ELSIF onshelfholds == 2 %]
233
                                            If all unavailable
234
                                        [% ELSE %]
235
                                            If any unavailable
236
                                        [% END %]
237
                                    </td>
238
                                    <td>[% IF opacitemholds == 'F'%]Force[% ELSIF opacitemholds == 'Y'%]Allow[% ELSE %]Don't allow[% END %]</td>
239
                                    <td>
240
                                        [% IF article_requests == 'no' %]
241
                                            No
242
                                        [% ELSIF article_requests == 'yes' %]
243
                                            Yes
244
                                        [% ELSIF article_requests == 'bib_only' %]
245
                                            Record only
246
                                        [% ELSIF article_requests == 'item_only' %]
247
                                            Item only
248
                                        [% END %]
249
                                    </td>
250
                                    <td>[% rentaldiscount %]</td>
251
                                    <td class="actions">
252
                                      <a href="#" class="editrule btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
253
                                      <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>
254
                                    </td>
255
                            </tr>
256
                        [% END %]
257
                    [% END %]
258
                [% END %]
218
                <tr id="edit_row">
259
                <tr id="edit_row">
219
                    <td>
260
                    <td>
220
                        <select name="categorycode" id="categorycode">
261
                        <select name="categorycode" id="categorycode">
(-)a/t/db_dependent/ArticleRequests.t (-10 / +39 lines)
Lines 27-32 use Koha::Database; Link Here
27
use Koha::Biblio;
27
use Koha::Biblio;
28
use Koha::Notice::Messages;
28
use Koha::Notice::Messages;
29
use Koha::Patron;
29
use Koha::Patron;
30
use Koha::Library;
31
use Koha::CirculationRules;
30
32
31
use t::lib::TestBuilder;
33
use t::lib::TestBuilder;
32
34
Lines 43-49 my $builder = t::lib::TestBuilder->new; Link Here
43
my $dbh = C4::Context->dbh;
45
my $dbh = C4::Context->dbh;
44
$dbh->{RaiseError} = 1;
46
$dbh->{RaiseError} = 1;
45
47
46
$dbh->do("DELETE FROM issuingrules");
48
$dbh->do("DELETE FROM circulation_rules");
47
49
48
my $biblio = Koha::Biblio->new()->store();
50
my $biblio = Koha::Biblio->new()->store();
49
ok( $biblio->id, 'Koha::Biblio created' );
51
ok( $biblio->id, 'Koha::Biblio created' );
Lines 171-203 $article_request->complete(); Link Here
171
$article_request->cancel();
173
$article_request->cancel();
172
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
174
is( $biblio->article_requests_finished()->count(), 1, 'Canceled request not returned for article_requests_finished' );
173
175
174
my $rule;
176
my $rule = Koha::CirculationRules->set_rule(
175
$rule = $schema->resultset('Issuingrule')
177
    {
176
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'yes' } )->insert();
178
        categorycode => '*',
179
        itemtype     => '*',
180
        branchcode   => '*',
181
        rule_name    => 'article_requests',
182
        rule_value   => 'yes',
183
    }
184
);
177
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
185
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type yes' );
178
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
186
is( $biblio->article_request_type($patron), 'yes', 'Biblio article request type is yes' );
179
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
187
ok( $item->can_article_request($patron),   'Item is requestable with rule type yes' );
180
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
188
is( $item->article_request_type($patron), 'yes', 'Item article request type is yes' );
181
$rule->delete();
189
$rule->delete();
182
190
183
$rule = $schema->resultset('Issuingrule')
191
$rule = Koha::CirculationRules->set_rule(
184
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'bib_only' } )->insert();
192
    {
193
        categorycode => '*',
194
        itemtype     => '*',
195
        branchcode   => '*',
196
        rule_name    => 'article_requests',
197
        rule_value   => 'bib_only',
198
    }
199
);
185
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
200
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type bib_only' );
186
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
201
is( $biblio->article_request_type($patron), 'bib_only', 'Biblio article request type is bib_only' );
187
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
202
ok( !$item->can_article_request($patron),  'Item is not requestable with rule type bib_only' );
188
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
203
is( $item->article_request_type($patron), 'bib_only', 'Item article request type is bib_only' );
189
$rule->delete();
204
$rule->delete();
190
205
191
$rule = $schema->resultset('Issuingrule')
206
$rule = Koha::CirculationRules->set_rule(
192
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'item_only' } )->insert();
207
    {
208
        categorycode => '*',
209
        itemtype     => '*',
210
        branchcode   => '*',
211
        rule_name    => 'article_requests',
212
        rule_value   => 'item_only',
213
    }
214
);
193
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
215
ok( $biblio->can_article_request($patron), 'Record is requestable with rule type item_only' );
194
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
216
is( $biblio->article_request_type($patron), 'item_only', 'Biblio article request type is item_only' );
195
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
217
ok( $item->can_article_request($patron),   'Item is not requestable with rule type item_only' );
196
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
218
is( $item->article_request_type($patron), 'item_only', 'Item article request type is item_only' );
197
$rule->delete();
219
$rule->delete();
198
220
199
$rule = $schema->resultset('Issuingrule')
221
$rule = Koha::CirculationRules->set_rule(
200
  ->new( { categorycode => '*', itemtype => '*', branchcode => '*', article_requests => 'no' } )->insert();
222
    {
223
        categorycode => '*',
224
        itemtype     => '*',
225
        branchcode   => '*',
226
        rule_name    => 'article_requests',
227
        rule_value   => 'no',
228
    }
229
);
201
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
230
ok( !$biblio->can_article_request($patron), 'Record is requestable with rule type no' );
202
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
231
is( $biblio->article_request_type($patron), 'no', 'Biblio article request type is no' );
203
ok( !$item->can_article_request($patron),   'Item is not requestable with rule type no' );
232
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 = NULL, 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 = NULL, 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         => undef,
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 => 0,
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    => 0,
156
        auto_renew                    => 0,
157
    issuelength        => 2,
157
        reservesallowed               => 'Null',
158
    lengthunit         => 'days',
158
        issuelength                   => 2,
159
    hardduedate        => undef,
159
        lengthunit                    => 'days',
160
    hardduedatecompare => 0,
160
        hardduedate                   => 2,
161
    fine               => undef,
161
        hardduedatecompare            => 'Null',
162
    finedays           => undef,
162
        fine                          => 'Null',
163
    firstremind        => undef,
163
        finedays                      => 'Null',
164
    chargeperiod       => undef,
164
        firstremind                   => 'Null',
165
    chargeperiod_charge_at => 0,
165
        chargeperiod                  => 'Null',
166
    rentaldiscount     => 2.00,
166
        chargeperiod_charge_at        => 0,
167
    overduefinescap    => undef,
167
        rentaldiscount                => 2.00,
168
    accountsent        => undef,
168
        overduefinescap               => 'Null',
169
    reservecharge      => undef,
169
        accountsent                   => 'Null',
170
    chargename         => undef,
170
        reservecharge                 => 'Null',
171
    restrictedtype     => undef,
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    => 0,
189
        auto_renew                    => 0,
188
    issuelength        => 3,
190
        reservesallowed               => 'Null',
189
    lengthunit         => 'days',
191
        issuelength                   => 3,
190
    hardduedate        => undef,
192
        lengthunit                    => 'days',
191
    hardduedatecompare => 0,
193
        hardduedate                   => 3,
192
    fine               => undef,
194
        hardduedatecompare            => 'Null',
193
    finedays           => undef,
195
        fine                          => 'Null',
194
    firstremind        => undef,
196
        finedays                      => 'Null',
195
    chargeperiod       => undef,
197
        firstremind                   => 'Null',
196
    chargeperiod_charge_at => 0,
198
        chargeperiod                  => 'Null',
197
    rentaldiscount     => 3.00,
199
        chargeperiod_charge_at        => 0,
198
    overduefinescap    => undef,
200
        rentaldiscount                => 3.00,
199
    accountsent        => undef,
201
        overduefinescap               => 'Null',
200
    reservecharge      => undef,
202
        accountsent                   => 'Null',
201
    chargename         => undef,
203
        reservecharge                 => 'Null',
202
    restrictedtype     => undef,
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 (-8 / +9 lines)
Lines 5-11 use Modern::Perl; Link Here
5
use C4::Context;
5
use C4::Context;
6
use C4::Items;
6
use C4::Items;
7
use C4::Circulation;
7
use C4::Circulation;
8
use Koha::IssuingRule;
8
use Koha::CirculationRules;
9
9
10
use Test::More tests => 6;
10
use Test::More tests => 6;
11
11
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 => 3; 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 (-6 / +38 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 546-551 $item = GetItem($itemnumber); Link Here
546
551
547
ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $borrower), "Reserving a book on item level" );
552
ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $borrower), "Reserving a book on item level" );
548
553
554
my $itype = C4::Reserves::_get_itype($item);
555
my $categorycode = $borrower->{categorycode};
556
my $holdingbranch = $item->{holdingbranch};
557
Koha::CirculationRules->set_rules(
558
    {
559
        categorycode => $categorycode,
560
        itemtype     => $itype,
561
        branchcode   => $holdingbranch,
562
        rules => {
563
            onshelfholds => 1,
564
        }
565
    }
566
);
567
568
ok( C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() allowed" );
569
Koha::CirculationRules->set_rules(
570
    {
571
        categorycode => $categorycode,
572
        itemtype     => $itype,
573
        branchcode   => $holdingbranch,
574
        rules => {
575
            onshelfholds => 0,
576
        }
577
    }
578
);
579
ok( !C4::Reserves::OnShelfHoldsAllowed($item, $borrower), "OnShelfHoldsAllowed() disallowed" );
580
549
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
581
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
550
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
582
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
551
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
583
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
(-)a/t/db_dependent/Reserves/MultiplePerRecord.t (-49 / +56 lines)
Lines 115-133 my $item3 = $builder->build( Link Here
115
    }
115
    }
116
);
116
);
117
117
118
my $rules_rs = Koha::Database->new()->schema()->resultset('Issuingrule');
118
Koha::CirculationRules->delete();
119
$rules_rs->delete();
120
119
121
# Test GetMaxPatronHoldsForRecord and GetHoldRule
120
# Test GetMaxPatronHoldsForRecord and GetHoldRule
122
my $rule1 = $rules_rs->new(
121
Koha::CirculationRules->set_rules(
123
    {
122
    {
124
        categorycode     => '*',
123
        categorycode => '*',
125
        itemtype         => '*',
124
        itemtype     => '*',
126
        branchcode       => '*',
125
        branchcode   => '*',
127
        reservesallowed  => 1,
126
        rules        => {
128
        holds_per_record => 1,
127
            reservesallowed  => 1,
128
            holds_per_record => 1,
129
        }
129
    }
130
    }
130
)->insert();
131
);
131
132
132
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
133
t::lib::Mocks::mock_preference('item-level_itypes', 1); # Assuming the item type is defined at item level
133
134
Lines 144-158 is( $rule->{branchcode}, '*', 'Got rule with universal branchcode' ); Link Here
144
is( $rule->{reservesallowed},  1,   'Got reservesallowed of 1' );
145
is( $rule->{reservesallowed},  1,   'Got reservesallowed of 1' );
145
is( $rule->{holds_per_record}, 1,   'Got holds_per_record of 1' );
146
is( $rule->{holds_per_record}, 1,   'Got holds_per_record of 1' );
146
147
147
my $rule2 = $rules_rs->new(
148
Koha::CirculationRules->set_rules(
148
    {
149
    {
149
        categorycode     => $category->{categorycode},
150
        categorycode => $category->{categorycode},
150
        itemtype         => '*',
151
        itemtype     => '*',
151
        branchcode       => '*',
152
        branchcode   => '*',
152
        reservesallowed  => 2,
153
        rules        => {
153
        holds_per_record => 2,
154
            reservesallowed  => 2,
155
            holds_per_record => 2,
156
        }
154
    }
157
    }
155
)->insert();
158
);
156
159
157
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
160
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
158
is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
161
is( $max, 2, 'GetMaxPatronHoldsForRecord returns max of 2' );
Lines 167-181 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
167
is( $rule->{reservesallowed},  2,                         'Got reservesallowed of 2' );
170
is( $rule->{reservesallowed},  2,                         'Got reservesallowed of 2' );
168
is( $rule->{holds_per_record}, 2,                         'Got holds_per_record of 2' );
171
is( $rule->{holds_per_record}, 2,                         'Got holds_per_record of 2' );
169
172
170
my $rule3 = $rules_rs->new(
173
Koha::CirculationRules->set_rules(
171
    {
174
    {
172
        categorycode     => $category->{categorycode},
175
        categorycode => $category->{categorycode},
173
        itemtype         => $itemtype1->{itemtype},
176
        itemtype     => $itemtype1->{itemtype},
174
        branchcode       => '*',
177
        branchcode   => '*',
175
        reservesallowed  => 3,
178
        rules        => {
176
        holds_per_record => 3,
179
            reservesallowed  => 3,
180
            holds_per_record => 3,
181
        }
177
    }
182
    }
178
)->insert();
183
);
179
184
180
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
185
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
181
is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
186
is( $max, 3, 'GetMaxPatronHoldsForRecord returns max of 3' );
Lines 190-204 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
190
is( $rule->{reservesallowed},  3,                         'Got reservesallowed of 3' );
195
is( $rule->{reservesallowed},  3,                         'Got reservesallowed of 3' );
191
is( $rule->{holds_per_record}, 3,                         'Got holds_per_record of 3' );
196
is( $rule->{holds_per_record}, 3,                         'Got holds_per_record of 3' );
192
197
193
my $rule4 = $rules_rs->new(
198
Koha::CirculationRules->set_rules(
194
    {
199
    {
195
        categorycode     => $category->{categorycode},
200
        categorycode => $category->{categorycode},
196
        itemtype         => $itemtype2->{itemtype},
201
        itemtype     => $itemtype2->{itemtype},
197
        branchcode       => '*',
202
        branchcode   => '*',
198
        reservesallowed  => 4,
203
        rules        => {
199
        holds_per_record => 4,
204
            reservesallowed  => 4,
205
            holds_per_record => 4,
206
        }
200
    }
207
    }
201
)->insert();
208
);
202
209
203
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
210
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
204
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
211
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
Lines 213-227 is( $rule->{branchcode}, '*', 'Got rule with univers Link Here
213
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
220
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
214
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
221
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
215
222
216
my $rule5 = $rules_rs->new(
223
Koha::CirculationRules->set_rules(
217
    {
224
    {
218
        categorycode     => $category->{categorycode},
225
        categorycode => $category->{categorycode},
219
        itemtype         => $itemtype2->{itemtype},
226
        itemtype     => $itemtype2->{itemtype},
220
        branchcode       => $library->{branchcode},
227
        branchcode   => $library->{branchcode},
221
        reservesallowed  => 5,
228
        rules        => {
222
        holds_per_record => 5,
229
            reservesallowed  => 5,
230
            holds_per_record => 5,
231
        }
223
    }
232
    }
224
)->insert();
233
);
225
234
226
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
235
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
227
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
236
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
Lines 236-246 is( $rule->{branchcode}, $library->{branchcode}, 'Got rule with specifi Link Here
236
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
245
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
237
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
246
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
238
247
239
$rule1->delete();
248
Koha::CirculationRules->delete();
240
$rule2->delete();
241
$rule3->delete();
242
$rule4->delete();
243
$rule5->delete();
244
249
245
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
250
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
246
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
251
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
Lines 266-280 is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds" Link Here
266
$hold->delete();
271
$hold->delete();
267
272
268
# Test multi-hold via AddReserve
273
# Test multi-hold via AddReserve
269
$rule = $rules_rs->new(
274
Koha::CirculationRules->set_rules(
270
    {
275
    {
271
        categorycode     => '*',
276
        categorycode => '*',
272
        itemtype         => '*',
277
        itemtype     => '*',
273
        branchcode       => '*',
278
        branchcode   => '*',
274
        reservesallowed  => 2,
279
        rules        => {
275
        holds_per_record => 2,
280
            reservesallowed  => 2,
281
            holds_per_record => 2,
282
        }
276
    }
283
    }
277
)->insert();
284
);
278
285
279
my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
286
my $can = CanBookBeReserved($patron->{borrowernumber}, $biblio->{biblionumber});
280
is( $can, '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 34-39 use Koha::Biblios; Link Here
34
use Koha::Biblioitems;
34
use Koha::Biblioitems;
35
use Koha::Items;
35
use Koha::Items;
36
use Koha::Patrons;
36
use Koha::Patrons;
37
use Koha::CirculationRules;
37
38
38
my $schema  = Koha::Database->new->schema;
39
my $schema  = Koha::Database->new->schema;
39
my $builder = t::lib::TestBuilder->new();
40
my $builder = t::lib::TestBuilder->new();
Lines 136-146 my $itemnumber2 = $item2->{itemnumber}; Link Here
136
137
137
my $dbh = C4::Context->dbh;
138
my $dbh = C4::Context->dbh;
138
$dbh->do('DELETE FROM reserves');
139
$dbh->do('DELETE FROM reserves');
139
$dbh->do('DELETE FROM issuingrules');
140
$dbh->do('DELETE FROM circulation_rules');
140
    $dbh->do(q{
141
Koha::CirculationRules->set_rules(
141
        INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
142
    {
142
        VALUES (?, ?, ?, ?)
143
        categorycode => '*',
143
    }, {}, '*', '*', '*', 1);
144
        branchcode   => '*',
145
        itemtype     => '*',
146
        rules        => {
147
            reservesallowed => 1
148
        }
149
    }
150
);
144
151
145
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
152
my $reserve_id = C4::Reserves::AddReserve($branchcode, $patron_1->borrowernumber,
146
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
153
    $biblionumber, undef, 1, undef, undef, undef, '', $itemnumber);
147
- 

Return to bug 18936