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

(-)a/C4/Circulation.pm (-58 / +44 lines)
Lines 422-436 sub TooMany { Link Here
422
    my $branch = _GetCircControlBranch($item, $patron);
422
    my $branch = _GetCircControlBranch($item, $patron);
423
    my $type = $item->effective_itemtype;
423
    my $type = $item->effective_itemtype;
424
424
425
    my ($type_object, $parent_type, $parent_maxissueqty_rule);
425
    my $type_object = Koha::ItemTypes->find( $type );
426
    $type_object = Koha::ItemTypes->find( $type );
426
    my $parent_type = $type_object->parent_type if $type_object;
427
    $parent_type = $type_object->parent_type if $type_object;
428
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
427
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
429
    # Find any children if we are a parent_type;
428
    # Find any children if we are a parent_type;
430
429
431
    # given branch, patron category, and item type, determine
430
    # given branch, patron category, and item type, determine
432
    # applicable issuing rule
431
    # applicable issuing rule
433
432
433
    # If the parent rule is for default type we discount it
434
    my $parent_maxissueqty_rule;
434
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
435
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
435
        {
436
        {
436
            categorycode => $cat_borrower,
437
            categorycode => $cat_borrower,
Lines 463-469 sub TooMany { Link Here
463
    # if a rule is found and has a loan limit set, count
464
    # if a rule is found and has a loan limit set, count
464
    # how many loans the patron already has that meet that
465
    # how many loans the patron already has that meet that
465
    # rule
466
    # rule
466
    if (defined($maxissueqty_rule) and $maxissueqty_rule->rule_value ne "") {
467
    if (defined $maxissueqty_rule and $maxissueqty_rule->rule_value ne "") {
467
468
468
        my $checkouts;
469
        my $checkouts;
469
        if ( $maxissueqty_rule->branchcode ) {
470
        if ( $maxissueqty_rule->branchcode ) {
Lines 474-481 sub TooMany { Link Here
474
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
475
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
475
            } else {
476
            } else {
476
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
477
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
477
                $checkouts = $patron->checkouts->search(
478
                $checkouts = $patron->checkouts->search( { "item.$branch_type" => $maxissueqty_rule->branchcode } );
478
                    { "item.$branch_type" => $maxissueqty_rule->branchcode } );
479
            }
479
            }
480
        } else {
480
        } else {
481
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
481
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
Lines 483-492 sub TooMany { Link Here
483
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
483
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
484
484
485
        my $sum_checkouts;
485
        my $sum_checkouts;
486
        my $rule_itemtype = $maxissueqty_rule->itemtype;
487
486
488
        my @types;
487
        my @types;
489
        unless ( $rule_itemtype || $parent_maxissueqty_rule ) {
488
        unless ( $maxissueqty_rule->itemtype || $parent_maxissueqty_rule ) {
490
            # matching rule has the default item type, so count only
489
            # matching rule has the default item type, so count only
491
            # those existing loans that don't fall under a more
490
            # those existing loans that don't fall under a more
492
            # specific rule
491
            # specific rule
Lines 499-505 sub TooMany { Link Here
499
                }
498
                }
500
            )->get_column('itemtype');
499
            )->get_column('itemtype');
501
        } else {
500
        } else {
502
            if ( $parent_maxissueqty_rule ) {
501
            if ( defined $parent_maxissueqty_rule ) {
503
                # if we have a parent item type then we count loans of the
502
                # if we have a parent item type then we count loans of the
504
                # specific item type or its siblings or parent
503
                # specific item type or its siblings or parent
505
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
504
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
Lines 518-524 sub TooMany { Link Here
518
        while ( my $c = $checkouts->next ) {
517
        while ( my $c = $checkouts->next ) {
519
            my $itemtype = $c->item->effective_itemtype;
518
            my $itemtype = $c->item->effective_itemtype;
520
519
521
            unless ( $rule_itemtype || $parent_maxissueqty_rule ) {
520
            unless ( $maxissueqty_rule->itemtype || $parent_maxissueqty_rule ) {
522
                next if grep {$_ eq $itemtype} @types;
521
                next if grep {$_ eq $itemtype} @types;
523
            } else {
522
            } else {
524
                next unless grep {$_ eq $itemtype} @types;
523
                next unless grep {$_ eq $itemtype} @types;
Lines 544-558 sub TooMany { Link Here
544
            onsite_circulation_rule      => $maxonsiteissueqty_rule,
543
            onsite_circulation_rule      => $maxonsiteissueqty_rule,
545
        };
544
        };
546
        # If parent rules exists
545
        # If parent rules exists
547
        if ( defined($parent_maxissueqty_rule) and defined($parent_maxissueqty_rule->rule_value) ){
546
        if ( defined $parent_maxissueqty_rule ) {
548
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty_rule ? $parent_maxissueqty_rule->rule_value : undef;
547
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty_rule->rule_value;
549
            my $qty_over = _check_max_qty($checkout_rules);
548
            my $qty_over = _check_max_qty($checkout_rules);
550
            return $qty_over if defined $qty_over;
549
            return $qty_over if defined $qty_over;
551
550
552
            # If the parent rule is less than or equal to the child, we only need check the parent
551
            # If the parent rule is less than or equal to the child, we only need check the parent
553
            if( $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value && defined($maxissueqty_rule->itemtype) ) {
552
            if(
553
                $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value
554
                && defined($maxissueqty_rule->itemtype)
555
            ) {
554
                $checkout_rules->{checkout_count} = $checkout_count_type;
556
                $checkout_rules->{checkout_count} = $checkout_count_type;
555
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef;
557
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule->rule_value;
556
                my $qty_over = _check_max_qty($checkout_rules);
558
                my $qty_over = _check_max_qty($checkout_rules);
557
                return $qty_over if defined $qty_over;
559
                return $qty_over if defined $qty_over;
558
            }
560
            }
Lines 564-570 sub TooMany { Link Here
564
566
565
    # Now count total loans against the limit for the branch
567
    # Now count total loans against the limit for the branch
566
    my $branch_borrower_circ_rule = GetBranchBorrowerCircRule($branch, $cat_borrower);
568
    my $branch_borrower_circ_rule = GetBranchBorrowerCircRule($branch, $cat_borrower);
567
    if (defined($branch_borrower_circ_rule->{patron_maxissueqty}) and $branch_borrower_circ_rule->{patron_maxissueqty} ne '') {
569
    if (
570
        defined($branch_borrower_circ_rule->{patron_maxissueqty})
571
        and $branch_borrower_circ_rule->{patron_maxissueqty} ne ''
572
    ) {
568
        my $checkouts;
573
        my $checkouts;
569
        if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
574
        if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
570
            $checkouts = $patron->checkouts->search(
575
            $checkouts = $patron->checkouts->search(
Lines 597-603 sub TooMany { Link Here
597
        return $qty_over if defined $qty_over;
602
        return $qty_over if defined $qty_over;
598
    }
603
    }
599
604
600
    if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) {
605
    unless ( defined $maxissueqty_rule || defined $branch_borrower_circ_rule->{patron_maxissueqty} ) {
601
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
606
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
602
    }
607
    }
603
608
Lines 617-623 sub _check_max_qty { Link Here
617
    my $onsite_circulation_rule      = $params->{onsite_circulation_rule};
622
    my $onsite_circulation_rule      = $params->{onsite_circulation_rule};
618
623
619
    if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) {
624
    if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) {
620
        if ( $max_onsite_checkouts_allowed eq '' ) { return; }
625
        return if $max_onsite_checkouts_allowed eq '';
621
        if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) {
626
        if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) {
622
            return {
627
            return {
623
                reason           => 'TOO_MANY_ONSITE_CHECKOUTS',
628
                reason           => 'TOO_MANY_ONSITE_CHECKOUTS',
Lines 628-634 sub _check_max_qty { Link Here
628
        }
633
        }
629
    }
634
    }
630
    if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) {
635
    if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) {
631
        if ( $max_checkouts_allowed eq '' ) { return; }
636
        return if $max_checkouts_allowed eq '';
632
        my $delta = $switch_onsite_checkout ? 1 : 0;
637
        my $delta = $switch_onsite_checkout ? 1 : 0;
633
        if ( $checkout_count >= $max_checkouts_allowed + $delta ) {
638
        if ( $checkout_count >= $max_checkouts_allowed + $delta ) {
634
            return {
639
            return {
Lines 640-649 sub _check_max_qty { Link Here
640
        }
645
        }
641
    }
646
    }
642
    elsif ( not $onsite_checkout ) {
647
    elsif ( not $onsite_checkout ) {
643
        if ( $max_checkouts_allowed eq '' ) { return; }
648
        return if $max_checkouts_allowed eq '';
644
        if (
649
        if (
645
            $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed )
650
            $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed
646
        {
651
        ) {
647
            return {
652
            return {
648
                reason           => 'TOO_MANY_CHECKOUTS',
653
                reason           => 'TOO_MANY_CHECKOUTS',
649
                count            => $checkout_count - $onsite_checkout_count,
654
                count            => $checkout_count - $onsite_checkout_count,
Lines 1470-1491 sub checkHighHolds { Link Here
1470
1475
1471
        my $orig_due = C4::Circulation::CalcDateDue( $issuedate, $itype, $branchcode, $patron );
1476
        my $orig_due = C4::Circulation::CalcDateDue( $issuedate, $itype, $branchcode, $patron );
1472
1477
1473
        my $rule = Koha::CirculationRules->get_effective_rule_value(
1478
        # overrides decreaseLoanHighHoldsDuration syspref
1479
        my $duration = Koha::CirculationRules->get_effective_rule_value(
1474
            {
1480
            {
1475
                categorycode => $patron->categorycode,
1481
                categorycode => $patron->categorycode,
1476
                itemtype     => $item->effective_itemtype,
1482
                itemtype     => $item->effective_itemtype,
1477
                branchcode   => $branchcode,
1483
                branchcode   => $branchcode,
1478
                rule_name    => 'decreaseloanholds',
1484
                rule_name    => 'decreaseloanholds',
1479
            }
1485
            }
1480
        );
1486
        ) || C4::Context->preference('decreaseLoanHighHoldsDuration');
1481
1487
1482
        my $duration;
1483
        if ( defined($rule) && $rule ne '' ){
1484
            # overrides decreaseLoanHighHoldsDuration syspref
1485
            $duration = $rule;
1486
        } else {
1487
            $duration = C4::Context->preference('decreaseLoanHighHoldsDuration');
1488
        }
1489
        my $reduced_datedue = $calendar->addDuration( $issuedate, $duration );
1488
        my $reduced_datedue = $calendar->addDuration( $issuedate, $duration );
1490
        $reduced_datedue->set_hour($orig_due->hour);
1489
        $reduced_datedue->set_hour($orig_due->hour);
1491
        $reduced_datedue->set_minute($orig_due->minute);
1490
        $reduced_datedue->set_minute($orig_due->minute);
Lines 1974-2000 wildcards. Link Here
1974
sub GetBranchBorrowerCircRule {
1973
sub GetBranchBorrowerCircRule {
1975
    my ( $branchcode, $categorycode ) = @_;
1974
    my ( $branchcode, $categorycode ) = @_;
1976
1975
1977
    # Initialize default values
1976
    return Koha::CirculationRules->get_effective_rules(
1978
    my $rules = {
1977
        {
1979
        patron_maxissueqty       => undef,
1978
            categorycode => $categorycode,
1980
        patron_maxonsiteissueqty => undef,
1979
            itemtype     => undef,
1981
    };
1980
            branchcode   => $branchcode,
1982
1981
            rules => ['patron_maxissueqty', 'patron_maxonsiteissueqty']
1983
    # Search for rules!
1982
        }
1984
    foreach my $rule_name (qw( patron_maxissueqty patron_maxonsiteissueqty )) {
1983
    );
1985
        my $rule = Koha::CirculationRules->get_effective_rule(
1986
            {
1987
                categorycode => $categorycode,
1988
                itemtype     => undef,
1989
                branchcode   => $branchcode,
1990
                rule_name    => $rule_name,
1991
            }
1992
        );
1993
1994
        $rules->{$rule_name} = $rule->rule_value if defined $rule;
1995
    }
1996
1997
    return $rules;
1998
}
1984
}
1999
1985
2000
=head2 GetBranchItemRule
1986
=head2 GetBranchItemRule
Lines 2731-2741 sub _calculate_new_debar_dt { Link Here
2731
            ]
2717
            ]
2732
        }
2718
        }
2733
    );
2719
    );
2734
    my $finedays = $issuing_rule ? $issuing_rule->{finedays} : undef;
2720
    return unless $issuing_rule->{finedays};
2735
    my $unit     = $issuing_rule ? $issuing_rule->{lengthunit} : undef;
2721
    my $finedays = $issuing_rule->{finedays};
2722
    my $unit     = $issuing_rule->{lengthunit};
2736
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2723
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2737
2724
2738
    return unless $finedays;
2739
2725
2740
    # finedays is in days, so hourly loans must multiply by 24
2726
    # finedays is in days, so hourly loans must multiply by 24
2741
    # thus 1 hour late equals 1 day suspension * finedays rate
2727
    # thus 1 hour late equals 1 day suspension * finedays rate
Lines 3293-3306 sub AddRenewal { Link Here
3293
        # a maximum value has been set in the circ rules
3279
        # a maximum value has been set in the circ rules
3294
        my $unseen_renewals = $issue->unseen_renewals;
3280
        my $unseen_renewals = $issue->unseen_renewals;
3295
        if (C4::Context->preference('UnseenRenewals')) {
3281
        if (C4::Context->preference('UnseenRenewals')) {
3296
            my $rule = Koha::CirculationRules->get_effective_rule(
3282
            my $unseen_renewals_allowed = Koha::CirculationRules->get_effective_rule_value(
3297
                {   categorycode => $patron->categorycode,
3283
                {   categorycode => $patron->categorycode,
3298
                    itemtype     => $item_object->effective_itemtype,
3284
                    itemtype     => $item_object->effective_itemtype,
3299
                    branchcode   => $circ_library->branchcode,
3285
                    branchcode   => $circ_library->branchcode,
3300
                    rule_name    => 'unseen_renewals_allowed'
3286
                    rule_name    => 'unseen_renewals_allowed'
3301
                }
3287
                }
3302
            );
3288
            );
3303
            if (!$seen && $rule && looks_like_number($rule->rule_value)) {
3289
            if (!$seen && $unseen_renewals_allowed && looks_like_number($unseen_renewals_allowed)) {
3304
                $unseen_renewals++;
3290
                $unseen_renewals++;
3305
            } else {
3291
            } else {
3306
                # If the renewal is seen, unseen should revert to 0
3292
                # If the renewal is seen, unseen should revert to 0
Lines 3665-3678 sub GetIssuingCharges { Link Here
3665
            # FIXME This should follow CircControl
3651
            # FIXME This should follow CircControl
3666
            my $branch = C4::Context::mybranch();
3652
            my $branch = C4::Context::mybranch();
3667
            $patron //= Koha::Patrons->find( $borrowernumber );
3653
            $patron //= Koha::Patrons->find( $borrowernumber );
3668
            my $discount = Koha::CirculationRules->get_effective_rule({
3654
            my $discount = Koha::CirculationRules->get_effective_rule_value({
3669
                categorycode => $patron->categorycode,
3655
                categorycode => $patron->categorycode,
3670
                branchcode   => $branch,
3656
                branchcode   => $branch,
3671
                itemtype     => $item_type,
3657
                itemtype     => $item_type,
3672
                rule_name    => 'rentaldiscount'
3658
                rule_name    => 'rentaldiscount'
3673
            });
3659
            });
3674
            if ($discount) {
3660
            if ($discount) {
3675
                $charge = ( $charge * ( 100 - $discount->rule_value ) ) / 100;
3661
                $charge = ( $charge * ( 100 - $discount ) ) / 100;
3676
            }
3662
            }
3677
            $charge = sprintf '%.2f', $charge; # ensure no fractions of a penny returned
3663
            $charge = sprintf '%.2f', $charge; # ensure no fractions of a penny returned
3678
        }
3664
        }
(-)a/C4/Reserves.pm (-55 / +42 lines)
Lines 361-367 See CanItemBeReserved() for possible return values. Link Here
361
361
362
=cut
362
=cut
363
363
364
sub CanBookBeReserved{
364
sub CanBookBeReserved {
365
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
365
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
366
366
367
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
367
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
Lines 374-389 sub CanBookBeReserved{ Link Here
374
374
375
        # biblio-level, item type-contrained
375
        # biblio-level, item type-contrained
376
        my $patron          = Koha::Patrons->find($borrowernumber);
376
        my $patron          = Koha::Patrons->find($borrowernumber);
377
        my $reservesallowed = Koha::CirculationRules->get_effective_rule(
377
        my $reservesallowed = Koha::CirculationRules->get_effective_rule_value(
378
            {
378
            {
379
                itemtype     => $params->{itemtype},
379
                itemtype     => $params->{itemtype},
380
                categorycode => $patron->categorycode,
380
                categorycode => $patron->categorycode,
381
                branchcode   => $pickup_branchcode,
381
                branchcode   => $pickup_branchcode,
382
                rule_name    => 'reservesallowed',
382
                rule_name    => 'reservesallowed',
383
            }
383
            }
384
        )->rule_value;
384
        );
385
385
386
        $reservesallowed = ( $reservesallowed eq '' ) ? undef : $reservesallowed;
386
        $reservesallowed = $reservesallowed eq '' ? undef : $reservesallowed;
387
387
388
        my $count = $patron->holds->search(
388
        my $count = $patron->holds->search(
389
            {
389
            {
Lines 467-473 sub CanItemBeReserved { Link Here
467
    }
467
    }
468
468
469
    my $dbh = C4::Context->dbh;
469
    my $dbh = C4::Context->dbh;
470
    my $ruleitemtype;    # itemtype of the matching issuing rule
470
    my $effective_itemtype = $item->effective_itemtype;
471
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
471
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
472
472
473
    # We check item branch if IndependentBranches is ON
473
    # We check item branch if IndependentBranches is ON
Lines 503-510 sub CanItemBeReserved { Link Here
503
    }
503
    }
504
504
505
    # check if a recall exists on this item from this borrower
505
    # check if a recall exists on this item from this borrower
506
    return _cache { status => 'recall' }
506
    if (
507
      if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count;
507
        C4::Context->preference('UseRecalls') &&
508
        $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count
509
    ) {
510
        return _cache { status => 'recall' };
511
    }
508
512
509
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
513
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
510
514
Lines 520-551 sub CanItemBeReserved { Link Here
520
        $reserves_control_branch  = $patron->branchcode;
524
        $reserves_control_branch  = $patron->branchcode;
521
    }
525
    }
522
526
523
    # we retrieve rights
527
    #undefined is 0, blank is unlimited
524
    if (
528
    $allowedreserves = Koha::CirculationRules->get_effective_rule_value({
525
        my $reservesallowed = Koha::CirculationRules->get_effective_rule({
529
        itemtype     => $effective_itemtype,
526
                itemtype     => $item->effective_itemtype,
530
        categorycode => $patron->categorycode,
527
                categorycode => $patron->categorycode,
531
        branchcode   => $reserves_control_branch,
528
                branchcode   => $reserves_control_branch,
532
        rule_name    => 'reservesallowed'
529
                rule_name    => 'reservesallowed',
533
    }) // 0;
530
        })
531
    ) {
532
        $ruleitemtype     = $reservesallowed->itemtype;
533
        $allowedreserves  = $reservesallowed->rule_value // 0; #undefined is 0, blank is unlimited
534
    }
535
    else {
536
        $ruleitemtype = undef;
537
    }
538
534
539
    my $rights = Koha::CirculationRules->get_effective_rules({
535
    my $rights = Koha::CirculationRules->get_effective_rules({
540
        categorycode => $patron->categorycode,
536
        categorycode => $patron->categorycode,
541
        itemtype     => $item->effective_itemtype,
537
        itemtype     => $effective_itemtype,
542
        branchcode   => $reserves_control_branch,
538
        branchcode   => $reserves_control_branch,
543
        rules        => ['holds_per_record','holds_per_day']
539
        rules        => ['holds_per_record', 'holds_per_day']
544
    });
540
    });
545
    my $holds_per_record = $rights->{holds_per_record} // 1;
541
    my $holds_per_record = $rights->{holds_per_record} // 1;
546
    my $holds_per_day    = $rights->{holds_per_day};
542
    my $holds_per_day    = $rights->{holds_per_day};
547
543
548
    if (   defined $holds_per_record && $holds_per_record ne '' ){
544
    if ( defined $holds_per_record && $holds_per_record ne '' ){
549
        if ( $holds_per_record == 0 ) {
545
        if ( $holds_per_record == 0 ) {
550
            return _cache { status => "noReservesAllowed" };
546
            return _cache { status => "noReservesAllowed" };
551
        }
547
        }
Lines 569-576 sub CanItemBeReserved { Link Here
569
    }
565
    }
570
566
571
    # we check if it's ok or not
567
    # we check if it's ok or not
572
    if ( defined $allowedreserves && $allowedreserves ne '' ){
568
    if ( $allowedreserves ne '' ) {
573
        if( $allowedreserves == 0 ){
569
        if( $allowedreserves == 0 ) {
574
            return _cache { status => 'noReservesAllowed' };
570
            return _cache { status => 'noReservesAllowed' };
575
        }
571
        }
576
        if ( !$params->{ignore_hold_counts} ) {
572
        if ( !$params->{ignore_hold_counts} ) {
Lines 587-617 sub CanItemBeReserved { Link Here
587
583
588
            # If using item-level itypes, fall back to the record
584
            # If using item-level itypes, fall back to the record
589
            # level itemtype if the hold has no associated item
585
            # level itemtype if the hold has no associated item
590
            if ( defined $ruleitemtype ) {
586
            if ( C4::Context->preference('item-level_itypes') ) {
591
                if ( C4::Context->preference('item-level_itypes') ) {
587
                $querycount .= q{
592
                    $querycount .= q{
588
                    AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
593
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
589
                    OR reserves.itemtype = ? )
594
                           OR reserves.itemtype = ? )
590
                };
595
                    };
596
                }
597
                else {
598
                    $querycount .= q{
599
                        AND ( biblioitems.itemtype = ?
600
                           OR reserves.itemtype = ? )
601
                    };
602
                }
603
            }
604
605
            my $sthcount = $dbh->prepare($querycount);
606
607
            if ( defined $ruleitemtype ) {
608
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $ruleitemtype, $ruleitemtype );
609
            }
591
            }
610
            else {
592
            else {
611
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
593
                $querycount .= q{
594
                    AND ( biblioitems.itemtype = ?
595
                    OR reserves.itemtype = ? )
596
                };
612
            }
597
            }
613
598
614
            my $reservecount = "0";
599
            my $sthcount = $dbh->prepare($querycount);
600
            $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $effective_itemtype, $effective_itemtype );
601
602
            my $reservecount = 0;
615
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
603
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
616
                $reservecount = $rowcount->{count};
604
                $reservecount = $rowcount->{count};
617
            }
605
            }
Lines 621-645 sub CanItemBeReserved { Link Here
621
    }
609
    }
622
610
623
    # Now we need to check hold limits by patron category
611
    # Now we need to check hold limits by patron category
624
    my $rule = Koha::CirculationRules->get_effective_rule(
612
    my $max_holds = Koha::CirculationRules->get_effective_rule_value(
625
        {
613
        {
626
            categorycode => $patron->categorycode,
614
            categorycode => $patron->categorycode,
627
            branchcode   => $reserves_control_branch,
615
            branchcode   => $reserves_control_branch,
628
            rule_name    => 'max_holds',
616
            rule_name    => 'max_holds',
629
        }
617
        }
630
    );
618
    );
631
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
619
    if (!$params->{ignore_hold_counts} && defined $max_holds && $max_holds ne '' ) {
632
        my $total_holds_count = Koha::Holds->search(
620
        my $total_holds_count = Koha::Holds->search(
633
            {
621
            {
634
                borrowernumber => $patron->borrowernumber
622
                borrowernumber => $patron->borrowernumber
635
            }
623
            }
636
        )->count();
624
        )->count();
637
625
638
        return _cache { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value;
626
        return _cache { status => 'tooManyReserves', limit => $max_holds } if $total_holds_count >= $max_holds;
639
    }
627
    }
640
628
641
    my $branchitemrule =
629
    my $branchitemrule =
642
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype );
630
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $effective_itemtype );
643
631
644
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
632
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
645
        return _cache { status => 'notReservable' };
633
        return _cache { status => 'notReservable' };
Lines 2231-2243 sub GetMaxPatronHoldsForRecord { Link Here
2231
2219
2232
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2220
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2233
2221
2234
        my $rule = Koha::CirculationRules->get_effective_rule({
2222
        my $holds_per_record = Koha::CirculationRules->get_effective_rule_value({
2235
            categorycode => $categorycode,
2223
            categorycode => $categorycode,
2236
            itemtype     => $itemtype,
2224
            itemtype     => $itemtype,
2237
            branchcode   => $branchcode,
2225
            branchcode   => $branchcode,
2238
            rule_name    => 'holds_per_record'
2226
            rule_name    => 'holds_per_record'
2239
        });
2227
        }) // 0;
2240
        my $holds_per_record = $rule ? $rule->rule_value : 0;
2241
        $max = $holds_per_record if $holds_per_record > $max;
2228
        $max = $holds_per_record if $holds_per_record > $max;
2242
    }
2229
    }
2243
2230
(-)a/Koha/Biblio.pm (-15 / +9 lines)
Lines 560-575 $borrower must be a Koha::Patron object Link Here
560
sub article_request_type {
560
sub article_request_type {
561
    my ( $self, $borrower ) = @_;
561
    my ( $self, $borrower ) = @_;
562
562
563
    return q{} unless $borrower;
563
    return unless $borrower;
564
564
565
    my $rule = $self->article_request_type_for_items( $borrower );
565
    my $type = $self->article_request_type_for_items( $borrower );
566
    return $rule if $rule;
566
    return $type if $type;
567
567
568
    # If the record has no items that are requestable, go by the record itemtype
568
    # If the record has no items that are requestable, go by the record itemtype
569
    $rule = $self->article_request_type_for_bib($borrower);
569
    return $self->article_request_type_for_bib($borrower);
570
    return $rule if $rule;
571
572
    return q{};
573
}
570
}
574
571
575
=head3 article_request_type_for_bib
572
=head3 article_request_type_for_bib
Lines 583-603 Returns the article request type 'yes', 'no', 'item_only', 'bib_only', for the g Link Here
583
sub article_request_type_for_bib {
580
sub article_request_type_for_bib {
584
    my ( $self, $borrower ) = @_;
581
    my ( $self, $borrower ) = @_;
585
582
586
    return q{} unless $borrower;
583
    return unless $borrower;
587
584
588
    my $borrowertype = $borrower->categorycode;
585
    my $borrowertype = $borrower->categorycode;
589
    my $itemtype     = $self->itemtype();
586
    my $itemtype     = $self->itemtype();
590
587
591
    my $rule = Koha::CirculationRules->get_effective_rule(
588
    return Koha::CirculationRules->get_effective_rule_value(
592
        {
589
        {
593
            rule_name    => 'article_requests',
590
            rule_name    => 'article_requests',
594
            categorycode => $borrowertype,
591
            categorycode => $borrowertype,
595
            itemtype     => $itemtype,
592
            itemtype     => $itemtype,
596
        }
593
        }
597
    );
594
    );
598
599
    return q{} unless $rule;
600
    return $rule->rule_value || q{}
601
}
595
}
602
596
603
=head3 article_request_type_for_items
597
=head3 article_request_type_for_items
Lines 2122-2130 sub can_be_recalled { Link Here
2122
                'on_shelf_recalls',
2116
                'on_shelf_recalls',
2123
            ],
2117
            ],
2124
        });
2118
        });
2125
        push( @recalls_allowed, $rule->{recalls_allowed} ) if $rule;
2119
        push( @recalls_allowed, $rule->{recalls_allowed} ) if $rule->{recalls_allowed};
2126
        push( @recalls_per_record, $rule->{recalls_per_record} ) if $rule;
2120
        push( @recalls_per_record, $rule->{recalls_per_record} ) if $rule->{recalls_per_record};
2127
        push( @on_shelf_recalls, $rule->{on_shelf_recalls} ) if $rule;
2121
        push( @on_shelf_recalls, $rule->{on_shelf_recalls} ) if $rule->{on_shelf_recalls};
2128
    }
2122
    }
2129
    my $recalls_allowed = (sort {$b <=> $a} @recalls_allowed)[0]; # take highest
2123
    my $recalls_allowed = (sort {$b <=> $a} @recalls_allowed)[0]; # take highest
2130
    my $recalls_per_record = (sort {$b <=> $a} @recalls_per_record)[0]; # take highest
2124
    my $recalls_per_record = (sort {$b <=> $a} @recalls_per_record)[0]; # take highest
(-)a/Koha/Charges/Fees.pm (-4 / +3 lines)
Lines 89-96 sub new { Link Here
89
sub accumulate_rentalcharge {
89
sub accumulate_rentalcharge {
90
    my ($self) = @_;
90
    my ($self) = @_;
91
91
92
    my $itemtype        = Koha::ItemTypes->find( $self->item->effective_itemtype );
92
    my $itemtype = Koha::ItemTypes->find( $self->item->effective_itemtype );
93
    my $lengthunit_rule = Koha::CirculationRules->get_effective_rule(
93
    my $units = Koha::CirculationRules->get_effective_rule_value(
94
        {
94
        {
95
            categorycode => $self->patron->categorycode,
95
            categorycode => $self->patron->categorycode,
96
            itemtype     => $itemtype->id,
96
            itemtype     => $itemtype->id,
Lines 98-106 sub accumulate_rentalcharge { Link Here
98
            rule_name    => 'lengthunit',
98
            rule_name    => 'lengthunit',
99
        }
99
        }
100
    );
100
    );
101
    return 0 unless $lengthunit_rule;
101
    return 0 unless $units;
102
102
103
    my $units = $lengthunit_rule->rule_value;
104
    my $rentalcharge_increment =
103
    my $rentalcharge_increment =
105
      ( $units eq 'days' )
104
      ( $units eq 'days' )
106
      ? $itemtype->rentalcharge_daily
105
      ? $itemtype->rentalcharge_daily
(-)a/Koha/CirculationRules.pm (-21 / +18 lines)
Lines 319-331 sub get_effective_rule_value { Link Here
319
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
319
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
320
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
320
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
321
321
322
    my $cached       = $memory_cache->get_from_cache($cache_key);
322
    my $value = $memory_cache->get_from_cache($cache_key);
323
    return $cached if $cached;
323
    unless (defined $value) {
324
324
        my $rule = $self->get_effective_rule($params);
325
    my $rule = $self->get_effective_rule($params);
325
        if ($rule) {
326
326
            $value = $rule->rule_value;
327
    my $value= $rule ? $rule->rule_value : undef;
327
        }
328
    $memory_cache->set_in_cache( $cache_key, $value );
328
        else {
329
            $value = 'undef';
330
        }
331
        $memory_cache->set_in_cache( $cache_key, $value );
332
    }
333
    return if $value eq 'undef';
329
    return $value;
334
    return $value;
330
}
335
}
331
336
Lines 563-569 sub get_opacitemholds_policy { Link Here
563
568
564
    return unless $item or $patron;
569
    return unless $item or $patron;
565
570
566
    my $rule = Koha::CirculationRules->get_effective_rule(
571
    return Koha::CirculationRules->get_effective_rule_value(
567
        {
572
        {
568
            categorycode => $patron->categorycode,
573
            categorycode => $patron->categorycode,
569
            itemtype     => $item->effective_itemtype,
574
            itemtype     => $item->effective_itemtype,
Lines 571-578 sub get_opacitemholds_policy { Link Here
571
            rule_name    => 'opacitemholds',
576
            rule_name    => 'opacitemholds',
572
        }
577
        }
573
    );
578
    );
574
575
    return $rule ? $rule->rule_value : undef;
576
}
579
}
577
580
578
=head3 get_onshelfholds_policy
581
=head3 get_onshelfholds_policy
Lines 586-600 sub get_onshelfholds_policy { Link Here
586
    my $item = $params->{item};
589
    my $item = $params->{item};
587
    my $itemtype = $item->effective_itemtype;
590
    my $itemtype = $item->effective_itemtype;
588
    my $patron = $params->{patron};
591
    my $patron = $params->{patron};
589
    my $rule = Koha::CirculationRules->get_effective_rule(
592
    return Koha::CirculationRules->get_effective_rule_value(
590
        {
593
        {
591
            categorycode => ( $patron ? $patron->categorycode : undef ),
594
            categorycode => ( $patron ? $patron->categorycode : undef ),
592
            itemtype     => $itemtype,
595
            itemtype     => $itemtype,
593
            branchcode   => $item->holdingbranch,
596
            branchcode   => $item->holdingbranch,
594
            rule_name    => 'onshelfholds',
597
            rule_name    => 'onshelfholds',
595
        }
598
        }
596
    );
599
    ) // 0;
597
    return $rule ? $rule->rule_value : 0;
598
}
600
}
599
601
600
=head3 get_lostreturn_policy
602
=head3 get_lostreturn_policy
Lines 649-655 sub get_lostreturn_policy { Link Here
649
    my $rules = Koha::CirculationRules->get_effective_rules(
651
    my $rules = Koha::CirculationRules->get_effective_rules(
650
        {
652
        {
651
            branchcode => $branch,
653
            branchcode => $branch,
652
            rules  => ['lostreturn','processingreturn']
654
            rules  => ['lostreturn', 'processingreturn']
653
        }
655
        }
654
    );
656
    );
655
657
Lines 736-742 sub get_effective_daysmode { Link Here
736
    my $itemtype         = $params->{itemtype};
738
    my $itemtype         = $params->{itemtype};
737
    my $branchcode       = $params->{branchcode};
739
    my $branchcode       = $params->{branchcode};
738
740
739
    my $daysmode_rule = $class->get_effective_rule(
741
    my $daysmode = $class->get_effective_rule_value(
740
        {
742
        {
741
            categorycode => $categorycode,
743
            categorycode => $categorycode,
742
            itemtype     => $itemtype,
744
            itemtype     => $itemtype,
Lines 744-755 sub get_effective_daysmode { Link Here
744
            rule_name    => 'daysmode',
746
            rule_name    => 'daysmode',
745
        }
747
        }
746
    );
748
    );
747
749
    return $daysmode || C4::Context->preference('useDaysMode');
748
    return ( defined($daysmode_rule)
749
          and $daysmode_rule->rule_value ne '' )
750
      ? $daysmode_rule->rule_value
751
      : C4::Context->preference('useDaysMode');
752
753
}
750
}
754
751
755
752
(-)a/Koha/Item.pm (-7 / +5 lines)
Lines 1122-1128 sub article_request_type { Link Here
1122
      :                                      undef;
1122
      :                                      undef;
1123
    my $borrowertype = $borrower->categorycode;
1123
    my $borrowertype = $borrower->categorycode;
1124
    my $itemtype = $self->effective_itemtype();
1124
    my $itemtype = $self->effective_itemtype();
1125
    my $rule = Koha::CirculationRules->get_effective_rule(
1125
    return Koha::CirculationRules->get_effective_rule_value(
1126
        {
1126
        {
1127
            rule_name    => 'article_requests',
1127
            rule_name    => 'article_requests',
1128
            categorycode => $borrowertype,
1128
            categorycode => $borrowertype,
Lines 1130-1138 sub article_request_type { Link Here
1130
            branchcode   => $branchcode
1130
            branchcode   => $branchcode
1131
        }
1131
        }
1132
    );
1132
    );
1133
1134
    return q{} unless $rule;
1135
    return $rule->rule_value || q{}
1136
}
1133
}
1137
1134
1138
=head3 current_holds
1135
=head3 current_holds
Lines 2359-2370 sub can_be_recalled { Link Here
2359
    });
2356
    });
2360
2357
2361
    # check recalls allowed has been set and is not zero
2358
    # check recalls allowed has been set and is not zero
2362
    return 0 if ( !defined($rule->{recalls_allowed}) || $rule->{recalls_allowed} == 0 );
2359
    return 0 if !$rule->{recalls_allowed};
2363
2360
2364
    if ( $patron ) {
2361
    if ( $patron ) {
2365
        # check borrower has not reached open recalls allowed limit
2362
        # check borrower has not reached open recalls allowed limit
2366
        return 0 if ( $patron->recalls->filter_by_current->count >= $rule->{recalls_allowed} );
2363
        return 0 if ( $patron->recalls->filter_by_current->count >= $rule->{recalls_allowed} );
2367
2364
2365
        $rule->{recalls_per_record} //= 0;
2368
        # check borrower has not reach open recalls allowed per record limit
2366
        # check borrower has not reach open recalls allowed per record limit
2369
        return 0 if ( $patron->recalls->filter_by_current->search({ biblio_id => $self->biblionumber })->count >= $rule->{recalls_per_record} );
2367
        return 0 if ( $patron->recalls->filter_by_current->search({ biblio_id => $self->biblionumber })->count >= $rule->{recalls_per_record} );
2370
2368
Lines 2433-2444 sub can_be_waiting_recall { Link Here
2433
            branchcode   => $branchcode,
2431
            branchcode   => $branchcode,
2434
            categorycode => $most_relevant_recall ? $most_relevant_recall->patron->categorycode : undef,
2432
            categorycode => $most_relevant_recall ? $most_relevant_recall->patron->categorycode : undef,
2435
            itemtype     => $self->effective_itemtype,
2433
            itemtype     => $self->effective_itemtype,
2436
            rules        => [ 'recalls_allowed', ],
2434
            rules        => [ 'recalls_allowed' ],
2437
        }
2435
        }
2438
    );
2436
    );
2439
2437
2440
    # check recalls allowed has been set and is not zero
2438
    # check recalls allowed has been set and is not zero
2441
    return 0 if ( !defined($rule->{recalls_allowed}) || $rule->{recalls_allowed} == 0 );
2439
    return 0 if !$rule->{recalls_allowed};
2442
2440
2443
    # can recall
2441
    # can recall
2444
    return 1;
2442
    return 1;
(-)a/Koha/Patron.pm (-7 / +3 lines)
Lines 1298-1304 sub can_request_article { Link Here
1298
1298
1299
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1299
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1300
1300
1301
    my $rule = Koha::CirculationRules->get_effective_rule(
1301
    my $limit = Koha::CirculationRules->get_effective_rule_value(
1302
        {
1302
        {
1303
            branchcode   => $library_id,
1303
            branchcode   => $library_id,
1304
            categorycode => $self->categorycode,
1304
            categorycode => $self->categorycode,
Lines 1306-1313 sub can_request_article { Link Here
1306
        }
1306
        }
1307
    );
1307
    );
1308
1308
1309
    my $limit = ($rule) ? $rule->rule_value : undef;
1310
1311
    return 1 unless defined $limit;
1309
    return 1 unless defined $limit;
1312
1310
1313
    my $count = Koha::ArticleRequests->search(
1311
    my $count = Koha::ArticleRequests->search(
Lines 1339-1345 sub article_request_fee { Link Here
1339
1337
1340
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1338
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1341
1339
1342
    my $rule = Koha::CirculationRules->get_effective_rule(
1340
    my $value = Koha::CirculationRules->get_effective_rule_value(
1343
        {
1341
        {
1344
            branchcode   => $library_id,
1342
            branchcode   => $library_id,
1345
            categorycode => $self->categorycode,
1343
            categorycode => $self->categorycode,
Lines 1347-1355 sub article_request_fee { Link Here
1347
        }
1345
        }
1348
    );
1346
    );
1349
1347
1350
    my $fee = ($rule) ? $rule->rule_value + 0 : 0;
1348
    return $value ? $value + 0 : 0;
1351
1352
    return $fee;
1353
}
1349
}
1354
1350
1355
=head3 add_article_request_fee_if_needed
1351
=head3 add_article_request_fee_if_needed
(-)a/Koha/REST/V1/Checkouts.pm (-3 / +3 lines)
Lines 415-433 sub allows_renewal { Link Here
415
        my $renewable = Mojo::JSON->false;
415
        my $renewable = Mojo::JSON->false;
416
        $renewable = Mojo::JSON->true if $can_renew;
416
        $renewable = Mojo::JSON->true if $can_renew;
417
417
418
        my $rule = Koha::CirculationRules->get_effective_rule(
418
        my $renewalsallowed = Koha::CirculationRules->get_effective_rule_value(
419
            {
419
            {
420
                categorycode => $checkout->patron->categorycode,
420
                categorycode => $checkout->patron->categorycode,
421
                itemtype     => $checkout->item->effective_itemtype,
421
                itemtype     => $checkout->item->effective_itemtype,
422
                branchcode   => $checkout->branchcode,
422
                branchcode   => $checkout->branchcode,
423
                rule_name    => 'renewalsallowed',
423
                rule_name    => 'renewalsallowed'
424
            }
424
            }
425
        );
425
        );
426
        return $c->render(
426
        return $c->render(
427
            status => 200,
427
            status => 200,
428
            openapi => {
428
            openapi => {
429
                allows_renewal => $renewable,
429
                allows_renewal => $renewable,
430
                max_renewals => $rule->rule_value,
430
                max_renewals => $renewalsallowed,
431
                current_renewals => $checkout->renewals_count,
431
                current_renewals => $checkout->renewals_count,
432
                unseen_renewals => $checkout->unseen_renewals,
432
                unseen_renewals => $checkout->unseen_renewals,
433
                error => $error
433
                error => $error
(-)a/Koha/Recall.pm (-6 / +4 lines)
Lines 115-127 sub checkout { Link Here
115
        my @items = Koha::Items->search({ biblionumber => $self->biblio_id })->as_list;
115
        my @items = Koha::Items->search({ biblionumber => $self->biblio_id })->as_list;
116
        my @itemnumbers;
116
        my @itemnumbers;
117
        foreach (@items) {
117
        foreach (@items) {
118
            my $recalls_allowed = Koha::CirculationRules->get_effective_rule({
118
            my $recalls_allowed = Koha::CirculationRules->get_effective_rule_value({
119
                branchcode => C4::Context->userenv->{'branch'},
119
                branchcode => C4::Context->userenv->{'branch'},
120
                categorycode => $self->patron->categorycode,
120
                categorycode => $self->patron->categorycode,
121
                itemtype => $_->effective_itemtype,
121
                itemtype => $_->effective_itemtype,
122
                rule_name => 'recalls_allowed',
122
                rule_name => 'recalls_allowed',
123
            });
123
            });
124
            if ( defined $recalls_allowed and $recalls_allowed->rule_value > 0 ) {
124
            if ( defined $recalls_allowed and $recalls_allowed > 0 ) {
125
                push ( @itemnumbers, $_->itemnumber );
125
                push ( @itemnumbers, $_->itemnumber );
126
            }
126
            }
127
        }
127
        }
Lines 261-274 sub calc_expirationdate { Link Here
261
        $branchcode = C4::Circulation::_GetCircControlBranch( $item, $self->patron );
261
        $branchcode = C4::Circulation::_GetCircControlBranch( $item, $self->patron );
262
    }
262
    }
263
263
264
    my $rule = Koha::CirculationRules->get_effective_rule({
264
    my $shelf_time = Koha::CirculationRules->get_effective_rule_value({
265
        categorycode => $self->patron->categorycode,
265
        categorycode => $self->patron->categorycode,
266
        branchcode => $branchcode,
266
        branchcode => $branchcode,
267
        itemtype => $item ? $item->effective_itemtype : undef,
267
        itemtype => $item ? $item->effective_itemtype : undef,
268
        rule_name => 'recall_shelf_time'
268
        rule_name => 'recall_shelf_time'
269
    });
269
    }) // C4::Context->preference('RecallsMaxPickUpDelay');
270
271
    my $shelf_time = defined $rule ? $rule->rule_value : C4::Context->preference('RecallsMaxPickUpDelay');
272
270
273
    my $expirationdate = dt_from_string->add( days => $shelf_time );
271
    my $expirationdate = dt_from_string->add( days => $shelf_time );
274
    return $expirationdate;
272
    return $expirationdate;
(-)a/Koha/Recalls.pm (-7 / +4 lines)
Lines 135-152 sub add_recall { Link Here
135
135
136
        # get checkout and adjust due date based on circulation rules
136
        # get checkout and adjust due date based on circulation rules
137
        my $checkout = $recall->checkout;
137
        my $checkout = $recall->checkout;
138
        my $recall_due_date_interval = Koha::CirculationRules->get_effective_rule({
138
        my $due_interval = Koha::CirculationRules->get_effective_rule_value({
139
            categorycode => $checkout->patron->categorycode,
139
            categorycode => $checkout->patron->categorycode,
140
            itemtype => $checkout->item->effective_itemtype,
140
            itemtype => $checkout->item->effective_itemtype,
141
            branchcode => $branchcode,
141
            branchcode => $branchcode,
142
            rule_name => 'recall_due_date_interval',
142
            rule_name => 'recall_due_date_interval',
143
        });
143
        }) // 5;
144
        my $due_interval = 5;
144
        my $timestamp = dt_from_string( $recall->timestamp );
145
        $due_interval = $recall_due_date_interval->rule_value
146
            if defined $recall_due_date_interval && $recall_due_date_interval->rule_value;
147
        my $timestamp         = dt_from_string( $recall->timestamp );
148
        my $checkout_due_date = dt_from_string( $checkout->date_due );
145
        my $checkout_due_date = dt_from_string( $checkout->date_due );
149
        my $recall_due_date   = $timestamp->set(
146
        my $recall_due_date = $timestamp->set(
150
            {
147
            {
151
                hour   => $checkout_due_date->hour, minute => $checkout_due_date->minute,
148
                hour   => $checkout_due_date->hour, minute => $checkout_due_date->minute,
152
                second => $checkout_due_date->second
149
                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 50-56 while( my $recall = $recalls->next ) { Link Here
50
        }
50
        }
51
    }
51
    }
52
    if ( $recall->waiting ) {
52
    if ( $recall->waiting ) {
53
        my $recall_shelf_time = Koha::CirculationRules->get_effective_rule({
53
        my $recall_shelf_time = Koha::CirculationRules->get_effective_rule_value({
54
            categorycode => $recall->patron->categorycode,
54
            categorycode => $recall->patron->categorycode,
55
            itemtype => $recall->item->effective_itemtype,
55
            itemtype => $recall->item->effective_itemtype,
56
            branchcode => $recall->pickup_library_id,
56
            branchcode => $recall->pickup_library_id,
Lines 58-65 while( my $recall = $recalls->next ) { Link Here
58
        });
58
        });
59
        my $waitingdate = dt_from_string( $recall->waiting_date )->truncate( to  => 'day' );
59
        my $waitingdate = dt_from_string( $recall->waiting_date )->truncate( to  => 'day' );
60
        my $days_waiting = $today->subtract_datetime( $waitingdate );
60
        my $days_waiting = $today->subtract_datetime( $waitingdate );
61
        if ( defined $recall_shelf_time and $recall_shelf_time->rule_value >= 0 ) {
61
        if ( defined $recall_shelf_time and $recall_shelf_time >= 0 ) {
62
            if ( $days_waiting->days > $recall_shelf_time->rule_value ) {
62
            if ( $days_waiting->days > $recall_shelf_time ) {
63
                # recall has been awaiting pickup for longer than the circ rules allow
63
                # recall has been awaiting pickup for longer than the circ rules allow
64
                $recall->set_expired({ interface => 'COMMANDLINE' });
64
                $recall->set_expired({ interface => 'COMMANDLINE' });
65
            }
65
            }
(-)a/opac/opac-recall.pl (-2 / +2 lines)
Lines 48-60 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
            categorycode => $patron->categorycode,
52
            categorycode => $patron->categorycode,
53
            branchcode => undef,
53
            branchcode => undef,
54
            itemtype => undef,
54
            itemtype => undef,
55
            rule_name => 'recalls_per_record'
55
            rule_name => 'recalls_per_record'
56
        });
56
        });
57
        if ( defined $recalls_per_record and $recalls_per_record->rule_value and $recalled >= $recalls_per_record->rule_value ){
57
        if ( defined $recalls_per_record and $recalls_per_record and $recalled >= $recalls_per_record ) {
58
            $error = 'duplicate';
58
            $error = 'duplicate';
59
        }
59
        }
60
    }
60
    }
(-)a/t/db_dependent/Circulation/Branch.t (-2 / +2 lines)
Lines 143-150 my $borrower_id1 = Koha::Patron->new({ Link Here
143
143
144
is_deeply(
144
is_deeply(
145
    GetBranchBorrowerCircRule(),
145
    GetBranchBorrowerCircRule(),
146
    { patron_maxissueqty => undef, patron_maxonsiteissueqty => undef },
146
    undef,
147
"Without parameter, GetBranchBorrower returns undef (unilimited) for patron_maxissueqty and patron_maxonsiteissueqty if no rules defined"
147
    "Without parameter, GetBranchBorrower returns undef (unilimited) for patron_maxissueqty and patron_maxonsiteissueqty if no rules defined"
148
);
148
);
149
149
150
Koha::CirculationRules->set_rules(
150
Koha::CirculationRules->set_rules(
(-)a/t/db_dependent/Koha/CirculationRules.t (-1 / +5 lines)
Lines 628-636 subtest 'get_onshelfholds_policy() tests' => sub { Link Here
628
        }
628
        }
629
    );
629
    );
630
630
631
    my $memory_cache = Koha::Cache::Memory::Lite->get_instance;
632
    $memory_cache->flush();
633
631
    is( $circ_rules->get_onshelfholds_policy({ item => $item }), 1, 'If rule_value is set on a matching rule, return it' );
634
    is( $circ_rules->get_onshelfholds_policy({ item => $item }), 1, 'If rule_value is set on a matching rule, return it' );
632
    # Delete the rule (i.e. get_effective_rule returns undef)
635
    # Delete the rule (i.e. get_effective_rule returns undef)
633
    $circ_rules->delete;
636
    $circ_rules->delete;
637
    $memory_cache->flush();
634
    is( $circ_rules->get_onshelfholds_policy({ item => $item }), 0, 'If no matching rule, fallback to 0' );
638
    is( $circ_rules->get_onshelfholds_policy({ item => $item }), 0, 'If no matching rule, fallback to 0' );
635
639
636
    $schema->storage->txn_rollback;
640
    $schema->storage->txn_rollback;
Lines 901-906 subtest 'get_lostreturn_policy() tests' => sub { Link Here
901
          )
905
          )
902
        ->next
906
        ->next
903
        ->delete;
907
        ->delete;
908
    $memory_cache->flush();
904
    is_deeply( Koha::CirculationRules->get_lostreturn_policy( $params ),
909
    is_deeply( Koha::CirculationRules->get_lostreturn_policy( $params ),
905
         { lostreturn => 'refund', processingreturn => 'refund' },'No rule for branch, no default rule, fallback default (refund)');
910
         { lostreturn => 'refund', processingreturn => 'refund' },'No rule for branch, no default rule, fallback default (refund)');
906
911
907
- 

Return to bug 32092