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

(-)a/C4/Circulation.pm (-51 / +35 lines)
Lines 438-446 sub TooMany { Link Here
438
    my $branch = _GetCircControlBranch( $item, $patron );
438
    my $branch = _GetCircControlBranch( $item, $patron );
439
    my $type   = $item->effective_itemtype;
439
    my $type   = $item->effective_itemtype;
440
440
441
    my ( $type_object, $parent_type, $parent_maxissueqty_rule );
441
    my $type_object = Koha::ItemTypes->find($type);
442
    $type_object = Koha::ItemTypes->find($type);
442
    my $parent_type = $type_object->parent_type if $type_object;
443
    $parent_type = $type_object->parent_type if $type_object;
444
    my $child_types = Koha::ItemTypes->search( { parent_type => $type } );
443
    my $child_types = Koha::ItemTypes->search( { parent_type => $type } );
445
444
446
    # Find any children if we are a parent_type;
445
    # Find any children if we are a parent_type;
Lines 448-453 sub TooMany { Link Here
448
    # given branch, patron category, and item type, determine
447
    # given branch, patron category, and item type, determine
449
    # applicable issuing rule
448
    # applicable issuing rule
450
449
450
    my $parent_maxissueqty_rule;
451
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
451
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
452
        {
452
        {
453
            categorycode => $cat_borrower,
453
            categorycode => $cat_borrower,
Lines 499-508 sub TooMany { Link Here
499
        $checkouts = $checkouts->search( undef, { prefetch => 'item' } );
499
        $checkouts = $checkouts->search( undef, { prefetch => 'item' } );
500
500
501
        my $sum_checkouts;
501
        my $sum_checkouts;
502
        my $rule_itemtype = $maxissueqty_rule->itemtype;
503
502
504
        my @types;
503
        my @types;
505
        unless ( $rule_itemtype || $parent_maxissueqty_rule ) {
504
        unless ( $maxissueqty_rule->itemtype || $parent_maxissueqty_rule ) {
506
505
507
            # matching rule has the default item type, so count only
506
            # matching rule has the default item type, so count only
508
            # those existing loans that don't fall under a more
507
            # those existing loans that don't fall under a more
Lines 516-522 sub TooMany { Link Here
516
                }
515
                }
517
            )->get_column('itemtype');
516
            )->get_column('itemtype');
518
        } else {
517
        } else {
519
            if ($parent_maxissueqty_rule) {
518
            if ( defined $parent_maxissueqty_rule ) {
520
519
521
                # if we have a parent item type then we count loans of the
520
                # if we have a parent item type then we count loans of the
522
                # specific item type or its siblings or parent
521
                # specific item type or its siblings or parent
Lines 538-544 sub TooMany { Link Here
538
        while ( my $c = $checkouts->next ) {
537
        while ( my $c = $checkouts->next ) {
539
            my $itemtype = $c->item->effective_itemtype;
538
            my $itemtype = $c->item->effective_itemtype;
540
539
541
            unless ( $rule_itemtype || $parent_maxissueqty_rule ) {
540
            unless ( $maxissueqty_rule->itemtype || $parent_maxissueqty_rule ) {
542
                next if grep { $_ eq $itemtype } @types;
541
                next if grep { $_ eq $itemtype } @types;
543
            } else {
542
            } else {
544
                next unless grep { $_ eq $itemtype } @types;
543
                next unless grep { $_ eq $itemtype } @types;
Lines 565-573 sub TooMany { Link Here
565
        };
564
        };
566
565
567
        # If parent rules exists
566
        # If parent rules exists
568
        if ( defined($parent_maxissueqty_rule) and defined( $parent_maxissueqty_rule->rule_value ) ) {
567
        if ( defined $parent_maxissueqty_rule ) {
569
            $checkout_rules->{max_checkouts_allowed} =
568
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty_rule->rule_value;
570
                $parent_maxissueqty_rule ? $parent_maxissueqty_rule->rule_value : undef;
571
            my $qty_over = _check_max_qty($checkout_rules);
569
            my $qty_over = _check_max_qty($checkout_rules);
572
            return $qty_over if defined $qty_over;
570
            return $qty_over if defined $qty_over;
573
571
Lines 576-582 sub TooMany { Link Here
576
                && defined( $maxissueqty_rule->itemtype ) )
574
                && defined( $maxissueqty_rule->itemtype ) )
577
            {
575
            {
578
                $checkout_rules->{checkout_count}        = $checkout_count_type;
576
                $checkout_rules->{checkout_count}        = $checkout_count_type;
579
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef;
577
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule->rule_value;
580
                my $qty_over = _check_max_qty($checkout_rules);
578
                my $qty_over = _check_max_qty($checkout_rules);
581
                return $qty_over if defined $qty_over;
579
                return $qty_over if defined $qty_over;
582
            }
580
            }
Lines 623-629 sub TooMany { Link Here
623
        return $qty_over if defined $qty_over;
621
        return $qty_over if defined $qty_over;
624
    }
622
    }
625
623
626
    if ( not defined($maxissueqty_rule) and not defined( $branch_borrower_circ_rule->{patron_maxissueqty} ) ) {
624
    unless ( defined $maxissueqty_rule || defined $branch_borrower_circ_rule->{patron_maxissueqty} ) {
627
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
625
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
628
    }
626
    }
629
627
Lines 643-649 sub _check_max_qty { Link Here
643
    my $onsite_circulation_rule      = $params->{onsite_circulation_rule};
641
    my $onsite_circulation_rule      = $params->{onsite_circulation_rule};
644
642
645
    if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) {
643
    if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) {
646
        if ( $max_onsite_checkouts_allowed eq '' ) { return; }
644
        return if $max_onsite_checkouts_allowed eq '';
647
        if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) {
645
        if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) {
648
            return {
646
            return {
649
                reason           => 'TOO_MANY_ONSITE_CHECKOUTS',
647
                reason           => 'TOO_MANY_ONSITE_CHECKOUTS',
Lines 654-660 sub _check_max_qty { Link Here
654
        }
652
        }
655
    }
653
    }
656
    if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) {
654
    if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) {
657
        if ( $max_checkouts_allowed eq '' ) { return; }
655
        return if $max_checkouts_allowed eq '';
658
        my $delta = $switch_onsite_checkout ? 1 : 0;
656
        my $delta = $switch_onsite_checkout ? 1 : 0;
659
        if ( $checkout_count >= $max_checkouts_allowed + $delta ) {
657
        if ( $checkout_count >= $max_checkouts_allowed + $delta ) {
660
            return {
658
            return {
Lines 665-671 sub _check_max_qty { Link Here
665
            };
663
            };
666
        }
664
        }
667
    } elsif ( not $onsite_checkout ) {
665
    } elsif ( not $onsite_checkout ) {
668
        if ( $max_checkouts_allowed eq '' ) { return; }
666
        return if $max_checkouts_allowed eq '';
669
        if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) {
667
        if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) {
670
            return {
668
            return {
671
                reason           => 'TOO_MANY_CHECKOUTS',
669
                reason           => 'TOO_MANY_CHECKOUTS',
Lines 1520-1542 sub checkHighHolds { Link Here
1520
1518
1521
        my $orig_due = C4::Circulation::CalcDateDue( $issuedate, $itype, $branchcode, $patron );
1519
        my $orig_due = C4::Circulation::CalcDateDue( $issuedate, $itype, $branchcode, $patron );
1522
1520
1523
        my $rule = Koha::CirculationRules->get_effective_rule_value(
1521
        # overrides decreaseLoanHighHoldsDuration syspref
1522
        my $duration = Koha::CirculationRules->get_effective_rule_value(
1524
            {
1523
            {
1525
                categorycode => $patron->categorycode,
1524
                categorycode => $patron->categorycode,
1526
                itemtype     => $item->effective_itemtype,
1525
                itemtype     => $item->effective_itemtype,
1527
                branchcode   => $branchcode,
1526
                branchcode   => $branchcode,
1528
                rule_name    => 'decreaseloanholds',
1527
                rule_name    => 'decreaseloanholds',
1529
            }
1528
            }
1530
        );
1529
        ) || C4::Context->preference('decreaseLoanHighHoldsDuration');
1531
1532
        my $duration;
1533
        if ( defined($rule) && $rule ne '' ) {
1534
1530
1535
            # overrides decreaseLoanHighHoldsDuration syspref
1536
            $duration = $rule;
1537
        } else {
1538
            $duration = C4::Context->preference('decreaseLoanHighHoldsDuration') || 0;
1539
        }
1540
        my $reduced_datedue = $calendar->addDuration( $issuedate, $duration );
1531
        my $reduced_datedue = $calendar->addDuration( $issuedate, $duration );
1541
        $reduced_datedue->set_hour( $orig_due->hour );
1532
        $reduced_datedue->set_hour( $orig_due->hour );
1542
        $reduced_datedue->set_minute( $orig_due->minute );
1533
        $reduced_datedue->set_minute( $orig_due->minute );
Lines 2097-2123 wildcards. Link Here
2097
sub GetBranchBorrowerCircRule {
2088
sub GetBranchBorrowerCircRule {
2098
    my ( $branchcode, $categorycode ) = @_;
2089
    my ( $branchcode, $categorycode ) = @_;
2099
2090
2100
    # Initialize default values
2091
    my $rules = Koha::CirculationRules->get_effective_rules(
2101
    my $rules = {
2092
        {
2093
            categorycode => $categorycode,
2094
            itemtype     => undef,
2095
            branchcode   => $branchcode,
2096
            rules        => [ 'patron_maxissueqty', 'patron_maxonsiteissueqty' ]
2097
        }
2098
    ) // {};
2099
2100
    # Initialize default values and return
2101
    return {
2102
        patron_maxissueqty       => undef,
2102
        patron_maxissueqty       => undef,
2103
        patron_maxonsiteissueqty => undef,
2103
        patron_maxonsiteissueqty => undef,
2104
        %{$rules}
2104
    };
2105
    };
2105
2106
    # Search for rules!
2107
    foreach my $rule_name (qw( patron_maxissueqty patron_maxonsiteissueqty )) {
2108
        my $rule = Koha::CirculationRules->get_effective_rule(
2109
            {
2110
                categorycode => $categorycode,
2111
                itemtype     => undef,
2112
                branchcode   => $branchcode,
2113
                rule_name    => $rule_name,
2114
            }
2115
        );
2116
2117
        $rules->{$rule_name} = $rule->rule_value if defined $rule;
2118
    }
2119
2120
    return $rules;
2121
}
2106
}
2122
2107
2123
=head2 GetBranchItemRule
2108
=head2 GetBranchItemRule
Lines 2909-2920 sub _calculate_new_debar_dt { Link Here
2909
            ]
2894
            ]
2910
        }
2895
        }
2911
    );
2896
    );
2912
    my $finedays         = $issuing_rule ? $issuing_rule->{finedays}   : undef;
2897
    return unless $issuing_rule->{finedays};
2913
    my $unit             = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2898
    my $finedays         = $issuing_rule->{finedays};
2899
    my $unit             = $issuing_rule->{lengthunit};
2914
    my $chargeable_units = C4::Overdues::get_chargeable_units( $unit, $dt_due, $return_date, $branchcode );
2900
    my $chargeable_units = C4::Overdues::get_chargeable_units( $unit, $dt_due, $return_date, $branchcode );
2915
2901
2916
    return unless $finedays;
2917
2918
    # finedays is in days, so hourly loans must multiply by 24
2902
    # finedays is in days, so hourly loans must multiply by 24
2919
    # thus 1 hour late equals 1 day suspension * finedays rate
2903
    # thus 1 hour late equals 1 day suspension * finedays rate
2920
    $finedays = $finedays * 24 if ( $unit eq 'hours' );
2904
    $finedays = $finedays * 24 if ( $unit eq 'hours' );
Lines 3493-3499 sub AddRenewal { Link Here
3493
            # a maximum value has been set in the circ rules
3477
            # a maximum value has been set in the circ rules
3494
            my $unseen_renewals = $issue->unseen_renewals;
3478
            my $unseen_renewals = $issue->unseen_renewals;
3495
            if ( C4::Context->preference('UnseenRenewals') ) {
3479
            if ( C4::Context->preference('UnseenRenewals') ) {
3496
                my $rule = Koha::CirculationRules->get_effective_rule(
3480
                my $unseen_renewals_allowed = Koha::CirculationRules->get_effective_rule_value(
3497
                    {
3481
                    {
3498
                        categorycode => $patron->categorycode,
3482
                        categorycode => $patron->categorycode,
3499
                        itemtype     => $item_object->effective_itemtype,
3483
                        itemtype     => $item_object->effective_itemtype,
Lines 3501-3507 sub AddRenewal { Link Here
3501
                        rule_name    => 'unseen_renewals_allowed'
3485
                        rule_name    => 'unseen_renewals_allowed'
3502
                    }
3486
                    }
3503
                );
3487
                );
3504
                if ( !$seen && $rule && looks_like_number( $rule->rule_value ) ) {
3488
                if ( !$seen && $unseen_renewals_allowed && looks_like_number($unseen_renewals_allowed) ) {
3505
                    $unseen_renewals++;
3489
                    $unseen_renewals++;
3506
                    push @{$confirmations}, 'UNSEEN';
3490
                    push @{$confirmations}, 'UNSEEN';
3507
                } else {
3491
                } else {
Lines 3907-3913 sub GetIssuingCharges { Link Here
3907
            # FIXME This should follow CircControl
3891
            # FIXME This should follow CircControl
3908
            my $branch = C4::Context::mybranch();
3892
            my $branch = C4::Context::mybranch();
3909
            $patron //= Koha::Patrons->find($borrowernumber);
3893
            $patron //= Koha::Patrons->find($borrowernumber);
3910
            my $discount = Koha::CirculationRules->get_effective_rule(
3894
            my $discount = Koha::CirculationRules->get_effective_rule_value(
3911
                {
3895
                {
3912
                    categorycode => $patron->categorycode,
3896
                    categorycode => $patron->categorycode,
3913
                    branchcode   => $branch,
3897
                    branchcode   => $branch,
Lines 3916-3922 sub GetIssuingCharges { Link Here
3916
                }
3900
                }
3917
            );
3901
            );
3918
            if ($discount) {
3902
            if ($discount) {
3919
                $charge = ( $charge * ( 100 - $discount->rule_value ) ) / 100;
3903
                $charge = ( $charge * ( 100 - $discount ) ) / 100;
3920
            }
3904
            }
3921
            $charge = sprintf '%.2f', $charge;    # ensure no fractions of a penny returned
3905
            $charge = sprintf '%.2f', $charge;    # ensure no fractions of a penny returned
3922
        }
3906
        }
(-)a/C4/Reserves.pm (-40 / +36 lines)
Lines 397-412 sub CanBookBeReserved { Link Here
397
397
398
        # biblio-level, item type-contrained
398
        # biblio-level, item type-contrained
399
        my $patron          = Koha::Patrons->find($borrowernumber);
399
        my $patron          = Koha::Patrons->find($borrowernumber);
400
        my $reservesallowed = Koha::CirculationRules->get_effective_rule(
400
        my $reservesallowed = Koha::CirculationRules->get_effective_rule_value(
401
            {
401
            {
402
                itemtype     => $params->{itemtype},
402
                itemtype     => $params->{itemtype},
403
                categorycode => $patron->categorycode,
403
                categorycode => $patron->categorycode,
404
                branchcode   => $pickup_branchcode,
404
                branchcode   => $pickup_branchcode,
405
                rule_name    => 'reservesallowed',
405
                rule_name    => 'reservesallowed',
406
            }
406
            }
407
        )->rule_value;
407
        );
408
408
409
        $reservesallowed = ( $reservesallowed eq '' ) ? undef : $reservesallowed;
409
        $reservesallowed = $reservesallowed eq '' ? undef : $reservesallowed;
410
410
411
        my $count = $patron->holds->count_holds(
411
        my $count = $patron->holds->count_holds(
412
            {
412
            {
Lines 492-500 sub CanItemBeReserved { Link Here
492
        return $cached if $cached;
492
        return $cached if $cached;
493
    }
493
    }
494
494
495
    my $dbh = C4::Context->dbh;
495
    my $dbh                = C4::Context->dbh;
496
    my $ruleitemtype;           # itemtype of the matching issuing rule
496
    my $effective_itemtype = $item->effective_itemtype;
497
    my $allowedreserves = 0;    # Total number of holds allowed across all records, default to none
497
    my $allowedreserves    = 0;    # Total number of holds allowed across all records, default to none
498
498
499
    # We check item branch if IndependentBranches is ON
499
    # We check item branch if IndependentBranches is ON
500
    # and canreservefromotherbranches is OFF
500
    # and canreservefromotherbranches is OFF
Lines 534-541 sub CanItemBeReserved { Link Here
534
    }
534
    }
535
535
536
    # check if a recall exists on this item from this borrower
536
    # check if a recall exists on this item from this borrower
537
    return _cache { status => 'recall' }
537
    if ( C4::Context->preference('UseRecalls')
538
        if $patron->recalls->filter_by_current->search( { item_id => $item->itemnumber } )->count;
538
        && $patron->recalls->filter_by_current->search( { item_id => $item->itemnumber } )->count )
539
    {
540
        return _cache { status => 'recall' };
541
    }
539
542
540
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
543
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
541
544
Lines 550-577 sub CanItemBeReserved { Link Here
550
        $reserves_control_branch = $patron->branchcode;
553
        $reserves_control_branch = $patron->branchcode;
551
    }
554
    }
552
555
553
    # we retrieve rights
556
    #undefined is 0, blank is unlimited
554
    if (
557
    $allowedreserves = Koha::CirculationRules->get_effective_rule_value(
555
        my $reservesallowed = Koha::CirculationRules->get_effective_rule(
558
        {
556
            {
559
            itemtype     => $effective_itemtype,
557
                itemtype     => $item->effective_itemtype,
560
            categorycode => $patron->categorycode,
558
                categorycode => $patron->categorycode,
561
            branchcode   => $reserves_control_branch,
559
                branchcode   => $reserves_control_branch,
562
            rule_name    => 'reservesallowed'
560
                rule_name    => 'reservesallowed',
563
        }
561
            }
564
    ) // 0;
562
        )
563
        )
564
    {
565
        $ruleitemtype    = $reservesallowed->itemtype;
566
        $allowedreserves = $reservesallowed->rule_value // 0;    #undefined is 0, blank is unlimited
567
    } else {
568
        $ruleitemtype = undef;
569
    }
570
565
571
    my $rights = Koha::CirculationRules->get_effective_rules(
566
    my $rights = Koha::CirculationRules->get_effective_rules(
572
        {
567
        {
573
            categorycode => $patron->categorycode,
568
            categorycode => $patron->categorycode,
574
            itemtype     => $item->effective_itemtype,
569
            itemtype     => $effective_itemtype,
575
            branchcode   => $reserves_control_branch,
570
            branchcode   => $reserves_control_branch,
576
            rules        => [ 'holds_per_record', 'holds_per_day' ]
571
            rules        => [ 'holds_per_record', 'holds_per_day' ]
577
        }
572
        }
Lines 606-612 sub CanItemBeReserved { Link Here
606
    }
601
    }
607
602
608
    # we check if it's ok or not
603
    # we check if it's ok or not
609
    if ( defined $allowedreserves && $allowedreserves ne '' ) {
604
    if ( $allowedreserves ne '' ) {
610
        if ( $allowedreserves == 0 ) {
605
        if ( $allowedreserves == 0 ) {
611
            return _cache { status => 'noReservesAllowed' };
606
            return _cache { status => 'noReservesAllowed' };
612
        }
607
        }
Lines 625-631 sub CanItemBeReserved { Link Here
625
620
626
            # If using item-level itypes, fall back to the record
621
            # If using item-level itypes, fall back to the record
627
            # level itemtype if the hold has no associated item
622
            # level itemtype if the hold has no associated item
628
            if ( defined $ruleitemtype ) {
623
            if ( defined $effective_itemtype ) {
629
                if ( C4::Context->preference('item-level_itypes') ) {
624
                if ( C4::Context->preference('item-level_itypes') ) {
630
                    $querycount .= q{
625
                    $querycount .= q{
631
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
626
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
Lines 640-653 sub CanItemBeReserved { Link Here
640
            }
635
            }
641
636
642
            my $sthcount = $dbh->prepare($querycount);
637
            my $sthcount = $dbh->prepare($querycount);
643
638
            if ( defined $effective_itemtype ) {
644
            if ( defined $ruleitemtype ) {
639
                $sthcount->execute(
645
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $ruleitemtype, $ruleitemtype );
640
                    $patron->borrowernumber, $reserves_control_branch, $effective_itemtype,
641
                    $effective_itemtype
642
                );
646
            } else {
643
            } else {
647
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
644
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
648
            }
645
            }
649
646
650
            my $reservecount = "0";
647
            my $reservecount = 0;
651
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
648
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
652
                $reservecount = $rowcount->{count};
649
                $reservecount = $rowcount->{count};
653
            }
650
            }
Lines 658-678 sub CanItemBeReserved { Link Here
658
    }
655
    }
659
656
660
    # Now we need to check hold limits by patron category
657
    # Now we need to check hold limits by patron category
661
    my $rule = Koha::CirculationRules->get_effective_rule(
658
    my $max_holds = Koha::CirculationRules->get_effective_rule_value(
662
        {
659
        {
663
            categorycode => $patron->categorycode,
660
            categorycode => $patron->categorycode,
664
            branchcode   => $reserves_control_branch,
661
            branchcode   => $reserves_control_branch,
665
            rule_name    => 'max_holds',
662
            rule_name    => 'max_holds',
666
        }
663
        }
667
    );
664
    );
668
    if ( !$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
665
    if ( !$params->{ignore_hold_counts} && defined $max_holds && $max_holds ne '' ) {
669
        my $total_holds_count = Koha::Holds->search( { borrowernumber => $patron->borrowernumber } )->count();
666
        my $total_holds_count = Koha::Holds->search( { borrowernumber => $patron->borrowernumber } )->count();
670
667
671
        return _cache { status => 'tooManyReserves', limit => $rule->rule_value }
668
        return _cache { status => 'tooManyReserves', limit => $max_holds }
672
            if $total_holds_count >= $rule->rule_value;
669
            if $total_holds_count >= $max_holds;
673
    }
670
    }
674
671
675
    my $branchitemrule = C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype );
672
    my $branchitemrule = C4::Circulation::GetBranchItemRule( $reserves_control_branch, $effective_itemtype );
676
673
677
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
674
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
678
        return _cache { status => 'notReservable' };
675
        return _cache { status => 'notReservable' };
Lines 2409-2423 sub GetMaxPatronHoldsForRecord { Link Here
2409
2406
2410
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2407
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2411
2408
2412
        my $rule = Koha::CirculationRules->get_effective_rule(
2409
        my $holds_per_record = Koha::CirculationRules->get_effective_rule_value(
2413
            {
2410
            {
2414
                categorycode => $categorycode,
2411
                categorycode => $categorycode,
2415
                itemtype     => $itemtype,
2412
                itemtype     => $itemtype,
2416
                branchcode   => $branchcode,
2413
                branchcode   => $branchcode,
2417
                rule_name    => 'holds_per_record'
2414
                rule_name    => 'holds_per_record'
2418
            }
2415
            }
2419
        );
2416
        ) // 0;
2420
        my $holds_per_record = $rule ? $rule->rule_value : 0;
2421
        $max = $holds_per_record if $holds_per_record > $max;
2417
        $max = $holds_per_record if $holds_per_record > $max;
2422
    }
2418
    }
2423
2419
(-)a/Koha/Biblio.pm (-17 / +11 lines)
Lines 566-581 $borrower must be a Koha::Patron object Link Here
566
sub article_request_type {
566
sub article_request_type {
567
    my ( $self, $borrower ) = @_;
567
    my ( $self, $borrower ) = @_;
568
568
569
    return q{} unless $borrower;
569
    return unless $borrower;
570
570
571
    my $rule = $self->article_request_type_for_items($borrower);
571
    my $type = $self->article_request_type_for_items( $borrower );
572
    return $rule if $rule;
572
    return $type if $type;
573
573
574
    # If the record has no items that are requestable, go by the record itemtype
574
    # If the record has no items that are requestable, go by the record itemtype
575
    $rule = $self->article_request_type_for_bib($borrower);
575
    return $self->article_request_type_for_bib($borrower);
576
    return $rule if $rule;
577
578
    return q{};
579
}
576
}
580
577
581
=head3 article_request_type_for_bib
578
=head3 article_request_type_for_bib
Lines 589-609 Returns the article request type 'yes', 'no', 'item_only', 'bib_only', for the g Link Here
589
sub article_request_type_for_bib {
586
sub article_request_type_for_bib {
590
    my ( $self, $borrower ) = @_;
587
    my ( $self, $borrower ) = @_;
591
588
592
    return q{} unless $borrower;
589
    return unless $borrower;
593
590
594
    my $borrowertype = $borrower->categorycode;
591
    my $borrowertype = $borrower->categorycode;
595
    my $itemtype     = $self->itemtype();
592
    my $itemtype     = $self->itemtype();
596
593
597
    my $rule = Koha::CirculationRules->get_effective_rule(
594
    return Koha::CirculationRules->get_effective_rule_value(
598
        {
595
        {
599
            rule_name    => 'article_requests',
596
            rule_name    => 'article_requests',
600
            categorycode => $borrowertype,
597
            categorycode => $borrowertype,
601
            itemtype     => $itemtype,
598
            itemtype     => $itemtype,
602
        }
599
        }
603
    );
600
    );
604
605
    return q{} unless $rule;
606
    return $rule->rule_value || q{};
607
}
601
}
608
602
609
=head3 article_request_type_for_items
603
=head3 article_request_type_for_items
Lines 2207-2215 sub can_be_recalled { Link Here
2207
                ],
2201
                ],
2208
            }
2202
            }
2209
        );
2203
        );
2210
        push( @recalls_allowed,    $rule->{recalls_allowed} )    if $rule;
2204
        push( @recalls_allowed,    $rule->{recalls_allowed} )    if $rule->{recalls_allowed};
2211
        push( @recalls_per_record, $rule->{recalls_per_record} ) if $rule;
2205
        push( @recalls_per_record, $rule->{recalls_per_record} ) if $rule->{recalls_per_record};
2212
        push( @on_shelf_recalls,   $rule->{on_shelf_recalls} )   if $rule;
2206
        push( @on_shelf_recalls,   $rule->{on_shelf_recalls} )   if $rule->{on_shelf_recalls};
2213
    }
2207
    }
2214
    my $recalls_allowed        = ( sort { $b <=> $a } @recalls_allowed )[0];       # take highest
2208
    my $recalls_allowed        = ( sort { $b <=> $a } @recalls_allowed )[0];       # take highest
2215
    my $recalls_per_record     = ( sort { $b <=> $a } @recalls_per_record )[0];    # take highest
2209
    my $recalls_per_record     = ( sort { $b <=> $a } @recalls_per_record )[0];    # take highest
Lines 2220-2227 sub can_be_recalled { Link Here
2220
    my $on_shelf_recalls = ( sort { $on_shelf_recalls_count{$b} <=> $on_shelf_recalls_count{$a} } @on_shelf_recalls )[0]
2214
    my $on_shelf_recalls = ( sort { $on_shelf_recalls_count{$b} <=> $on_shelf_recalls_count{$a} } @on_shelf_recalls )[0]
2221
        ;                                                                          # take most common
2215
        ;                                                                          # take most common
2222
2216
2223
    # check recalls allowed has been set and is not zero
2217
    # check if recalls are not allowed
2224
    return 0 if ( !defined($recalls_allowed) || $recalls_allowed == 0 );
2218
    return 0 if !$recalls_allowed;
2225
2219
2226
    if ($patron) {
2220
    if ($patron) {
2227
2221
(-)a/Koha/Charges/Fees.pm (-4 / +3 lines)
Lines 88-95 sub new { Link Here
88
sub accumulate_rentalcharge {
88
sub accumulate_rentalcharge {
89
    my ($self) = @_;
89
    my ($self) = @_;
90
90
91
    my $itemtype        = Koha::ItemTypes->find( $self->item->effective_itemtype );
91
    my $itemtype = Koha::ItemTypes->find( $self->item->effective_itemtype );
92
    my $lengthunit_rule = Koha::CirculationRules->get_effective_rule(
92
    my $units = Koha::CirculationRules->get_effective_rule_value(
93
        {
93
        {
94
            categorycode => $self->patron->categorycode,
94
            categorycode => $self->patron->categorycode,
95
            itemtype     => $itemtype->id,
95
            itemtype     => $itemtype->id,
Lines 97-105 sub accumulate_rentalcharge { Link Here
97
            rule_name    => 'lengthunit',
97
            rule_name    => 'lengthunit',
98
        }
98
        }
99
    );
99
    );
100
    return 0 unless $lengthunit_rule;
100
    return 0 unless $units;
101
101
102
    my $units = $lengthunit_rule->rule_value;
103
    my $rentalcharge_increment =
102
    my $rentalcharge_increment =
104
        ( $units eq 'days' )
103
        ( $units eq 'days' )
105
        ? $itemtype->rentalcharge_daily
104
        ? $itemtype->rentalcharge_daily
(-)a/Koha/CirculationRules.pm (-19 / +17 lines)
Lines 323-335 sub get_effective_rule_value { Link Here
323
    my $cache_key    = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
323
    my $cache_key    = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
324
        $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
324
        $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
325
325
326
    my $cached = $memory_cache->get_from_cache($cache_key);
326
    my $value = $memory_cache->get_from_cache($cache_key);
327
    return $cached if $cached;
327
    unless (defined $value) {
328
328
        my $rule = $self->get_effective_rule($params);
329
    my $rule = $self->get_effective_rule($params);
329
        if ($rule) {
330
330
            $value = $rule->rule_value;
331
    my $value = $rule ? $rule->rule_value : undef;
331
        }
332
    $memory_cache->set_in_cache( $cache_key, $value );
332
        else {
333
            $value = 'undef';
334
        }
335
        $memory_cache->set_in_cache( $cache_key, $value );
336
    }
337
    return if $value eq 'undef';
333
    return $value;
338
    return $value;
334
}
339
}
335
340
Lines 567-573 sub get_opacitemholds_policy { Link Here
567
572
568
    return unless $item or $patron;
573
    return unless $item or $patron;
569
574
570
    my $rule = Koha::CirculationRules->get_effective_rule(
575
    return Koha::CirculationRules->get_effective_rule_value(
571
        {
576
        {
572
            categorycode => $patron->categorycode,
577
            categorycode => $patron->categorycode,
573
            itemtype     => $item->effective_itemtype,
578
            itemtype     => $item->effective_itemtype,
Lines 575-582 sub get_opacitemholds_policy { Link Here
575
            rule_name    => 'opacitemholds',
580
            rule_name    => 'opacitemholds',
576
        }
581
        }
577
    );
582
    );
578
579
    return $rule ? $rule->rule_value : undef;
580
}
583
}
581
584
582
=head3 get_onshelfholds_policy
585
=head3 get_onshelfholds_policy
Lines 590-604 sub get_onshelfholds_policy { Link Here
590
    my $item     = $params->{item};
593
    my $item     = $params->{item};
591
    my $itemtype = $item->effective_itemtype;
594
    my $itemtype = $item->effective_itemtype;
592
    my $patron   = $params->{patron};
595
    my $patron   = $params->{patron};
593
    my $rule     = Koha::CirculationRules->get_effective_rule(
596
    return Koha::CirculationRules->get_effective_rule_value(
594
        {
597
        {
595
            categorycode => ( $patron ? $patron->categorycode : undef ),
598
            categorycode => ( $patron ? $patron->categorycode : undef ),
596
            itemtype     => $itemtype,
599
            itemtype     => $itemtype,
597
            branchcode   => $item->holdingbranch,
600
            branchcode   => $item->holdingbranch,
598
            rule_name    => 'onshelfholds',
601
            rule_name    => 'onshelfholds',
599
        }
602
        }
600
    );
603
    ) // 0;
601
    return $rule ? $rule->rule_value : 0;
602
}
604
}
603
605
604
=head3 get_lostreturn_policy
606
=head3 get_lostreturn_policy
Lines 744-750 sub get_effective_daysmode { Link Here
744
    my $itemtype     = $params->{itemtype};
746
    my $itemtype     = $params->{itemtype};
745
    my $branchcode   = $params->{branchcode};
747
    my $branchcode   = $params->{branchcode};
746
748
747
    my $daysmode_rule = $class->get_effective_rule(
749
    my $daysmode = $class->get_effective_rule_value(
748
        {
750
        {
749
            categorycode => $categorycode,
751
            categorycode => $categorycode,
750
            itemtype     => $itemtype,
752
            itemtype     => $itemtype,
Lines 752-762 sub get_effective_daysmode { Link Here
752
            rule_name    => 'daysmode',
754
            rule_name    => 'daysmode',
753
        }
755
        }
754
    );
756
    );
755
757
    return $daysmode || C4::Context->preference('useDaysMode');
756
    return ( defined($daysmode_rule) and $daysmode_rule->rule_value ne '' )
757
        ? $daysmode_rule->rule_value
758
        : C4::Context->preference('useDaysMode');
759
760
}
758
}
761
759
762
=head3 get_effective_expire_reserves_charge
760
=head3 get_effective_expire_reserves_charge
(-)a/Koha/Item.pm (-11 / +6 lines)
Lines 1163-1169 sub article_request_type { Link Here
1163
        :                                      undef;
1163
        :                                      undef;
1164
    my $borrowertype = $borrower->categorycode;
1164
    my $borrowertype = $borrower->categorycode;
1165
    my $itemtype     = $self->effective_itemtype();
1165
    my $itemtype     = $self->effective_itemtype();
1166
    my $rule         = Koha::CirculationRules->get_effective_rule(
1166
    return Koha::CirculationRules->get_effective_rule_value(
1167
        {
1167
        {
1168
            rule_name    => 'article_requests',
1168
            rule_name    => 'article_requests',
1169
            categorycode => $borrowertype,
1169
            categorycode => $borrowertype,
Lines 1171-1179 sub article_request_type { Link Here
1171
            branchcode   => $branchcode
1171
            branchcode   => $branchcode
1172
        }
1172
        }
1173
    );
1173
    );
1174
1175
    return q{} unless $rule;
1176
    return $rule->rule_value || q{};
1177
}
1174
}
1178
1175
1179
=head3 current_holds
1176
=head3 current_holds
Lines 2502-2515 sub can_be_recalled { Link Here
2502
        }
2499
        }
2503
    );
2500
    );
2504
2501
2505
    # check recalls allowed has been set and is not zero
2502
    # check if recalls are not allowed
2506
    return 0 if ( !defined( $rule->{recalls_allowed} ) || $rule->{recalls_allowed} == 0 );
2503
    return 0 if !$rule->{recalls_allowed};
2507
2504
2508
    if ($patron) {
2505
    if ($patron) {
2509
2506
2510
        # check borrower has not reached open recalls allowed limit
2507
        # check borrower has not reached open recalls allowed limit
2511
        return 0 if ( $patron->recalls->filter_by_current->count >= $rule->{recalls_allowed} );
2508
        return 0 if ( $patron->recalls->filter_by_current->count >= $rule->{recalls_allowed} );
2512
2509
2510
        $rule->{recalls_per_record} //= 0;
2513
        # check borrower has not reach open recalls allowed per record limit
2511
        # check borrower has not reach open recalls allowed per record limit
2514
        return 0
2512
        return 0
2515
            if ( $patron->recalls->filter_by_current->search( { biblio_id => $self->biblionumber } )->count >=
2513
            if ( $patron->recalls->filter_by_current->search( { biblio_id => $self->biblionumber } )->count >=
Lines 2595-2608 sub can_be_waiting_recall { Link Here
2595
            branchcode   => $branchcode,
2593
            branchcode   => $branchcode,
2596
            categorycode => $most_relevant_recall ? $most_relevant_recall->patron->categorycode : undef,
2594
            categorycode => $most_relevant_recall ? $most_relevant_recall->patron->categorycode : undef,
2597
            itemtype     => $self->effective_itemtype,
2595
            itemtype     => $self->effective_itemtype,
2598
            rules        => [ 'recalls_allowed', ],
2596
            rules        => [ 'recalls_allowed' ],
2599
        }
2597
        }
2600
    );
2598
    );
2601
2599
2602
    # check recalls allowed has been set and is not zero
2600
    return 0 if !$rule->{recalls_allowed};
2603
    return 0 if ( !defined( $rule->{recalls_allowed} ) || $rule->{recalls_allowed} == 0 );
2604
2605
    # can recall
2606
    return 1;
2601
    return 1;
2607
}
2602
}
2608
2603
(-)a/Koha/Patron.pm (-7 / +3 lines)
Lines 1545-1551 sub can_request_article { Link Here
1545
1545
1546
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1546
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1547
1547
1548
    my $rule = Koha::CirculationRules->get_effective_rule(
1548
    my $limit = Koha::CirculationRules->get_effective_rule_value(
1549
        {
1549
        {
1550
            branchcode   => $library_id,
1550
            branchcode   => $library_id,
1551
            categorycode => $self->categorycode,
1551
            categorycode => $self->categorycode,
Lines 1553-1560 sub can_request_article { Link Here
1553
        }
1553
        }
1554
    );
1554
    );
1555
1555
1556
    my $limit = ($rule) ? $rule->rule_value : undef;
1557
1558
    return 1 unless defined $limit;
1556
    return 1 unless defined $limit;
1559
1557
1560
    my $count = Koha::ArticleRequests->search(
1558
    my $count = Koha::ArticleRequests->search(
Lines 1590-1596 sub article_request_fee { Link Here
1590
1588
1591
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1589
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1592
1590
1593
    my $rule = Koha::CirculationRules->get_effective_rule(
1591
    my $value = Koha::CirculationRules->get_effective_rule_value(
1594
        {
1592
        {
1595
            branchcode   => $library_id,
1593
            branchcode   => $library_id,
1596
            categorycode => $self->categorycode,
1594
            categorycode => $self->categorycode,
Lines 1598-1606 sub article_request_fee { Link Here
1598
        }
1596
        }
1599
    );
1597
    );
1600
1598
1601
    my $fee = ($rule) ? $rule->rule_value + 0 : 0;
1599
    return $value ? $value + 0 : 0;
1602
1603
    return $fee;
1604
}
1600
}
1605
1601
1606
=head3 add_article_request_fee_if_needed
1602
=head3 add_article_request_fee_if_needed
(-)a/Koha/REST/V1/Checkouts.pm (-3 / +3 lines)
Lines 423-441 sub allows_renewal { Link Here
423
        my $renewable = Mojo::JSON->false;
423
        my $renewable = Mojo::JSON->false;
424
        $renewable = Mojo::JSON->true if $can_renew;
424
        $renewable = Mojo::JSON->true if $can_renew;
425
425
426
        my $rule = Koha::CirculationRules->get_effective_rule(
426
        my $renewalsallowed = Koha::CirculationRules->get_effective_rule_value(
427
            {
427
            {
428
                categorycode => $checkout->patron->categorycode,
428
                categorycode => $checkout->patron->categorycode,
429
                itemtype     => $checkout->item->effective_itemtype,
429
                itemtype     => $checkout->item->effective_itemtype,
430
                branchcode   => $checkout->branchcode,
430
                branchcode   => $checkout->branchcode,
431
                rule_name    => 'renewalsallowed',
431
                rule_name    => 'renewalsallowed'
432
            }
432
            }
433
        );
433
        );
434
        return $c->render(
434
        return $c->render(
435
            status  => 200,
435
            status  => 200,
436
            openapi => {
436
            openapi => {
437
                allows_renewal   => $renewable,
437
                allows_renewal   => $renewable,
438
                max_renewals     => $rule->rule_value,
438
                max_renewals     => $renewalsallowed,
439
                current_renewals => $checkout->renewals_count,
439
                current_renewals => $checkout->renewals_count,
440
                unseen_renewals  => $checkout->unseen_renewals,
440
                unseen_renewals  => $checkout->unseen_renewals,
441
                error            => $error
441
                error            => $error
(-)a/Koha/Recall.pm (-6 / +4 lines)
Lines 116-122 sub checkout { Link Here
116
        my @items = Koha::Items->search( { biblionumber => $self->biblio_id } )->as_list;
116
        my @items = Koha::Items->search( { biblionumber => $self->biblio_id } )->as_list;
117
        my @itemnumbers;
117
        my @itemnumbers;
118
        foreach (@items) {
118
        foreach (@items) {
119
            my $recalls_allowed = Koha::CirculationRules->get_effective_rule(
119
            my $recalls_allowed = Koha::CirculationRules->get_effective_rule_value(
120
                {
120
                {
121
                    branchcode   => C4::Context->userenv->{'branch'},
121
                    branchcode   => C4::Context->userenv->{'branch'},
122
                    categorycode => $self->patron->categorycode,
122
                    categorycode => $self->patron->categorycode,
Lines 124-130 sub checkout { Link Here
124
                    rule_name    => 'recalls_allowed',
124
                    rule_name    => 'recalls_allowed',
125
                }
125
                }
126
            );
126
            );
127
            if ( defined $recalls_allowed and $recalls_allowed->rule_value > 0 ) {
127
            if ( defined $recalls_allowed and $recalls_allowed > 0 ) {
128
                push( @itemnumbers, $_->itemnumber );
128
                push( @itemnumbers, $_->itemnumber );
129
            }
129
            }
130
        }
130
        }
Lines 265-280 sub calc_expirationdate { Link Here
265
        $branchcode = C4::Circulation::_GetCircControlBranch( $item, $self->patron );
265
        $branchcode = C4::Circulation::_GetCircControlBranch( $item, $self->patron );
266
    }
266
    }
267
267
268
    my $rule = Koha::CirculationRules->get_effective_rule(
268
    my $shelf_time = Koha::CirculationRules->get_effective_rule_value(
269
        {
269
        {
270
            categorycode => $self->patron->categorycode,
270
            categorycode => $self->patron->categorycode,
271
            branchcode   => $branchcode,
271
            branchcode   => $branchcode,
272
            itemtype     => $item ? $item->effective_itemtype : undef,
272
            itemtype     => $item ? $item->effective_itemtype : undef,
273
            rule_name    => 'recall_shelf_time'
273
            rule_name    => 'recall_shelf_time'
274
        }
274
        }
275
    );
275
    ) // C4::Context->preference('RecallsMaxPickUpDelay');
276
277
    my $shelf_time = defined $rule ? $rule->rule_value : C4::Context->preference('RecallsMaxPickUpDelay');
278
276
279
    my $expirationdate = dt_from_string->add( days => $shelf_time );
277
    my $expirationdate = dt_from_string->add( days => $shelf_time );
280
    return $expirationdate;
278
    return $expirationdate;
(-)a/Koha/Recalls.pm (-6 / +3 lines)
Lines 138-157 sub add_recall { Link Here
138
138
139
        # get checkout and adjust due date based on circulation rules
139
        # get checkout and adjust due date based on circulation rules
140
        my $checkout                 = $recall->checkout;
140
        my $checkout                 = $recall->checkout;
141
        my $recall_due_date_interval = Koha::CirculationRules->get_effective_rule(
141
        my $due_interval = Koha::CirculationRules->get_effective_rule_value(
142
            {
142
            {
143
                categorycode => $checkout->patron->categorycode,
143
                categorycode => $checkout->patron->categorycode,
144
                itemtype     => $checkout->item->effective_itemtype,
144
                itemtype     => $checkout->item->effective_itemtype,
145
                branchcode   => $branchcode,
145
                branchcode   => $branchcode,
146
                rule_name    => 'recall_due_date_interval',
146
                rule_name    => 'recall_due_date_interval',
147
            }
147
            }
148
        );
148
        ) // 5;
149
        my $due_interval = 5;
150
        $due_interval = $recall_due_date_interval->rule_value
151
            if defined $recall_due_date_interval && $recall_due_date_interval->rule_value;
152
        my $timestamp         = dt_from_string( $recall->timestamp );
149
        my $timestamp         = dt_from_string( $recall->timestamp );
153
        my $checkout_due_date = dt_from_string( $checkout->date_due );
150
        my $checkout_due_date = dt_from_string( $checkout->date_due );
154
        my $recall_due_date   = $timestamp->set(
151
        my $recall_due_date = $timestamp->set(
155
            {
152
            {
156
                hour   => $checkout_due_date->hour, minute => $checkout_due_date->minute,
153
                hour   => $checkout_due_date->hour, minute => $checkout_due_date->minute,
157
                second => $checkout_due_date->second
154
                second => $checkout_due_date->second
(-)a/Koha/Template/Plugin/CirculationRules.pm (-3 / +1 lines)
Lines 46-52 sub Get { Link Here
46
    $categorycode = undef if $categorycode eq q{} or $categorycode eq q{*};
46
    $categorycode = undef if $categorycode eq q{} or $categorycode eq q{*};
47
    $itemtype     = undef if $itemtype eq q{}     or $itemtype eq q{*};
47
    $itemtype     = undef if $itemtype eq q{}     or $itemtype eq q{*};
48
48
49
    my $rule = Koha::CirculationRules->get_effective_rule(
49
    return Koha::CirculationRules->get_effective_rule_value(
50
        {
50
        {
51
            branchcode   => $branchcode,
51
            branchcode   => $branchcode,
52
            categorycode => $categorycode,
52
            categorycode => $categorycode,
Lines 54-61 sub Get { Link Here
54
            rule_name    => $rule_name,
54
            rule_name    => $rule_name,
55
        }
55
        }
56
    );
56
    );
57
58
    return $rule->rule_value if $rule;
59
}
57
}
60
58
61
=head3 Search
59
=head3 Search
(-)a/misc/cronjobs/recalls/expire_recalls.pl (-3 / +3 lines)
Lines 51-57 while ( my $recall = $recalls->next ) { Link Here
51
        }
51
        }
52
    }
52
    }
53
    if ( $recall->waiting ) {
53
    if ( $recall->waiting ) {
54
        my $recall_shelf_time = Koha::CirculationRules->get_effective_rule(
54
        my $recall_shelf_time = Koha::CirculationRules->get_effective_rule_value(
55
            {
55
            {
56
                categorycode => $recall->patron->categorycode,
56
                categorycode => $recall->patron->categorycode,
57
                itemtype     => $recall->item->effective_itemtype,
57
                itemtype     => $recall->item->effective_itemtype,
Lines 61-68 while ( my $recall = $recalls->next ) { Link Here
61
        );
61
        );
62
        my $waitingdate  = dt_from_string( $recall->waiting_date )->truncate( to => 'day' );
62
        my $waitingdate  = dt_from_string( $recall->waiting_date )->truncate( to => 'day' );
63
        my $days_waiting = $today->subtract_datetime($waitingdate);
63
        my $days_waiting = $today->subtract_datetime($waitingdate);
64
        if ( defined $recall_shelf_time and $recall_shelf_time->rule_value >= 0 ) {
64
        if ( defined $recall_shelf_time and $recall_shelf_time >= 0 ) {
65
            if ( $days_waiting->days > $recall_shelf_time->rule_value ) {
65
            if ( $days_waiting->days > $recall_shelf_time ) {
66
66
67
                # recall has been awaiting pickup for longer than the circ rules allow
67
                # recall has been awaiting pickup for longer than the circ rules allow
68
                $recall->set_expired( { interface => 'COMMANDLINE' } );
68
                $recall->set_expired( { interface => 'COMMANDLINE' } );
(-)a/opac/opac-recall.pl (-5 / +2 lines)
Lines 48-54 if ( C4::Context->preference('UseRecalls') ) { Link Here
48
    # check if already recalled
48
    # check if already recalled
49
    my $recalled = $biblio->recalls->filter_by_current->search( { patron_id => $borrowernumber } )->count;
49
    my $recalled = $biblio->recalls->filter_by_current->search( { patron_id => $borrowernumber } )->count;
50
    if ( defined $recalled and $recalled > 0 ) {
50
    if ( defined $recalled and $recalled > 0 ) {
51
        my $recalls_per_record = Koha::CirculationRules->get_effective_rule(
51
        my $recalls_per_record = Koha::CirculationRules->get_effective_rule_value(
52
            {
52
            {
53
                categorycode => $patron->categorycode,
53
                categorycode => $patron->categorycode,
54
                branchcode   => undef,
54
                branchcode   => undef,
Lines 56-65 if ( C4::Context->preference('UseRecalls') ) { Link Here
56
                rule_name    => 'recalls_per_record'
56
                rule_name    => 'recalls_per_record'
57
            }
57
            }
58
        );
58
        );
59
        if (    defined $recalls_per_record
59
        if ( $recalls_per_record and $recalled >= $recalls_per_record ) {
60
            and $recalls_per_record->rule_value
61
            and $recalled >= $recalls_per_record->rule_value )
62
        {
63
            $error = 'duplicate';
60
            $error = 'duplicate';
64
        }
61
        }
65
    }
62
    }
(-)a/t/db_dependent/Koha/CirculationRules.t (-1 / +6 lines)
Lines 758-763 subtest 'get_onshelfholds_policy() tests' => sub { Link Here
758
        }
758
        }
759
    );
759
    );
760
760
761
    my $memory_cache = Koha::Cache::Memory::Lite->get_instance;
762
    $memory_cache->flush();
763
761
    is(
764
    is(
762
        $circ_rules->get_onshelfholds_policy( { item => $item } ), 1,
765
        $circ_rules->get_onshelfholds_policy( { item => $item } ), 1,
763
        'If rule_value is set on a matching rule, return it'
766
        'If rule_value is set on a matching rule, return it'
Lines 765-770 subtest 'get_onshelfholds_policy() tests' => sub { Link Here
765
768
766
    # Delete the rule (i.e. get_effective_rule returns undef)
769
    # Delete the rule (i.e. get_effective_rule returns undef)
767
    $circ_rules->delete;
770
    $circ_rules->delete;
771
    $memory_cache->flush();
768
    is( $circ_rules->get_onshelfholds_policy( { item => $item } ), 0, 'If no matching rule, fallback to 0' );
772
    is( $circ_rules->get_onshelfholds_policy( { item => $item } ), 0, 'If no matching rule, fallback to 0' );
769
773
770
    $schema->storage->txn_rollback;
774
    $schema->storage->txn_rollback;
Lines 1132-1137 subtest 'get_lostreturn_policy() tests' => sub { Link Here
1132
            rule_name    => 'processingreturn'
1136
            rule_name    => 'processingreturn'
1133
        }
1137
        }
1134
    )->next->delete;
1138
    )->next->delete;
1139
    $memory_cache->flush();
1140
1135
    is_deeply(
1141
    is_deeply(
1136
        Koha::CirculationRules->get_lostreturn_policy($params),
1142
        Koha::CirculationRules->get_lostreturn_policy($params),
1137
        { lostreturn => 'refund', processingreturn => 'refund' },
1143
        { lostreturn => 'refund', processingreturn => 'refund' },
1138
- 

Return to bug 32092