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

(-)a/C4/Circulation.pm (-48 / +31 lines)
Lines 425-440 sub TooMany { Link Here
425
    my $branch = _GetCircControlBranch($item_object->unblessed,$borrower);
425
    my $branch = _GetCircControlBranch($item_object->unblessed,$borrower);
426
    my $type = $item_object->effective_itemtype;
426
    my $type = $item_object->effective_itemtype;
427
427
428
    my ($type_object, $parent_type, $parent_maxissueqty_rule);
428
    my $type_object = Koha::ItemTypes->find( $type );
429
    $type_object = Koha::ItemTypes->find( $type );
429
    my $parent_type = $type_object->parent_type if $type_object;
430
    $parent_type = $type_object->parent_type if $type_object;
431
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
430
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
432
    # Find any children if we are a parent_type;
431
    # Find any children if we are a parent_type;
433
432
434
    # given branch, patron category, and item type, determine
433
    # given branch, patron category, and item type, determine
435
    # applicable issuing rule
434
    # applicable issuing rule
436
435
437
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
436
    # If the parent rule is for default type we discount it
437
    my $parent_maxissueqty;
438
    $parent_maxissueqty = Koha::CirculationRules->get_effective_rule_value(
438
        {
439
        {
439
            categorycode => $cat_borrower,
440
            categorycode => $cat_borrower,
440
            itemtype     => $parent_type,
441
            itemtype     => $parent_type,
Lines 442-451 sub TooMany { Link Here
442
            rule_name    => 'maxissueqty',
443
            rule_name    => 'maxissueqty',
443
        }
444
        }
444
    ) if $parent_type;
445
    ) if $parent_type;
445
    # If the parent rule is for default type we discount it
446
    $parent_maxissueqty_rule = undef if $parent_maxissueqty_rule && !defined $parent_maxissueqty_rule->itemtype;
447
446
448
    my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
447
    my $maxissueqty = Koha::CirculationRules->get_effective_rule_value(
449
        {
448
        {
450
            categorycode => $cat_borrower,
449
            categorycode => $cat_borrower,
451
            itemtype     => $type,
450
            itemtype     => $type,
Lines 454-460 sub TooMany { Link Here
454
        }
453
        }
455
    );
454
    );
456
455
457
    my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule(
456
    my $maxonsiteissueqty = Koha::CirculationRules->get_effective_rule_value(
458
        {
457
        {
459
            categorycode => $cat_borrower,
458
            categorycode => $cat_borrower,
460
            itemtype     => $type,
459
            itemtype     => $type,
Lines 468-486 sub TooMany { Link Here
468
    # if a rule is found and has a loan limit set, count
467
    # if a rule is found and has a loan limit set, count
469
    # how many loans the patron already has that meet that
468
    # how many loans the patron already has that meet that
470
    # rule
469
    # rule
471
    if (defined($maxissueqty_rule) and $maxissueqty_rule->rule_value ne "") {
470
    if (defined $maxissueqty and $maxissueqty ne "") {
472
471
473
        my $checkouts;
472
        my $checkouts;
474
        if ( $maxissueqty_rule->branchcode ) {
473
        if ( $branch ) {
475
            if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
474
            if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
476
                $checkouts = $patron->checkouts->search(
475
                $checkouts = $patron->checkouts->search(
477
                    { 'me.branchcode' => $maxissueqty_rule->branchcode } );
476
                    { 'me.branchcode' => $branch } );
478
            } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') {
477
            } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') {
479
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
478
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
480
            } else {
479
            } else {
481
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
480
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
482
                $checkouts = $patron->checkouts->search(
481
                $checkouts = $patron->checkouts->search( { "item.$branch_type" => $branch } );
483
                    { "item.$branch_type" => $maxissueqty_rule->branchcode } );
484
            }
482
            }
485
        } else {
483
        } else {
486
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
484
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
Lines 488-510 sub TooMany { Link Here
488
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
486
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
489
487
490
        my $sum_checkouts;
488
        my $sum_checkouts;
491
        my $rule_itemtype = $maxissueqty_rule->itemtype;
492
489
493
        my @types;
490
        my @types;
494
        unless ( $rule_itemtype ) {
491
        unless ( $type ) {
495
            # matching rule has the default item type, so count only
492
            # matching rule has the default item type, so count only
496
            # those existing loans that don't fall under a more
493
            # those existing loans that don't fall under a more
497
            # specific rule
494
            # specific rule
498
            @types = Koha::CirculationRules->search(
495
            @types = Koha::CirculationRules->search(
499
                {
496
                {
500
                    branchcode => $maxissueqty_rule->branchcode,
497
                    branchcode => $branch,
501
                    categorycode => [ $maxissueqty_rule->categorycode, $cat_borrower ],
498
                    categorycode => $cat_borrower,
502
                    itemtype  => { '!=' => undef },
499
                    itemtype  => { '!=' => undef },
503
                    rule_name => 'maxissueqty'
500
                    rule_name => 'maxissueqty'
504
                }
501
                }
505
            )->get_column('itemtype');
502
            )->get_column('itemtype');
506
        } else {
503
        } else {
507
            if ( $parent_maxissueqty_rule ) {
504
            if ( $parent_maxissueqty ) {
508
                # if we have a parent item type then we count loans of the
505
                # if we have a parent item type then we count loans of the
509
                # specific item type or its siblings or parent
506
                # specific item type or its siblings or parent
510
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
507
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
Lines 523-529 sub TooMany { Link Here
523
        while ( my $c = $checkouts->next ) {
520
        while ( my $c = $checkouts->next ) {
524
            my $itemtype = $c->item->effective_itemtype;
521
            my $itemtype = $c->item->effective_itemtype;
525
522
526
            unless ( $rule_itemtype ) {
523
            unless ( $type ) {
527
                next if grep {$_ eq $itemtype} @types;
524
                next if grep {$_ eq $itemtype} @types;
528
            } else {
525
            } else {
529
                next unless grep {$_ eq $itemtype} @types;
526
                next unless grep {$_ eq $itemtype} @types;
Lines 542-561 sub TooMany { Link Here
542
            checkout_count               => $checkout_count,
539
            checkout_count               => $checkout_count,
543
            onsite_checkout_count        => $onsite_checkout_count,
540
            onsite_checkout_count        => $onsite_checkout_count,
544
            onsite_checkout              => $onsite_checkout,
541
            onsite_checkout              => $onsite_checkout,
545
            max_checkouts_allowed        => $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef,
542
            max_checkouts_allowed        => $maxissueqty,,
546
            max_onsite_checkouts_allowed => $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef,
543
            max_onsite_checkouts_allowed => $maxonsiteissueqty,
547
            switch_onsite_checkout       => $switch_onsite_checkout,
544
            switch_onsite_checkout       => $switch_onsite_checkout,
548
        };
545
        };
549
        # If parent rules exists
546
        # If parent rules exists
550
        if ( defined($parent_maxissueqty_rule) and defined($parent_maxissueqty_rule->rule_value) ){
547
        if ( defined $parent_maxissueqty ){
551
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty_rule ? $parent_maxissueqty_rule->rule_value : undef;
548
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty;
552
            my $qty_over = _check_max_qty($checkout_rules);
549
            my $qty_over = _check_max_qty($checkout_rules);
553
            return $qty_over if defined $qty_over;
550
            return $qty_over if defined $qty_over;
554
551
555
            # If the parent rule is less than or equal to the child, we only need check the parent
552
            # If the parent rule is less than or equal to the child, we only need check the parent
556
            if( $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value && defined($maxissueqty_rule->itemtype) ) {
553
            if( $maxissueqty < $parent_maxissueqty && defined($type) ) {
557
                $checkout_rules->{checkout_count} = $checkout_count_type;
554
                $checkout_rules->{checkout_count} = $checkout_count_type;
558
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef;
555
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty;
559
                my $qty_over = _check_max_qty($checkout_rules);
556
                my $qty_over = _check_max_qty($checkout_rules);
560
                return $qty_over if defined $qty_over;
557
                return $qty_over if defined $qty_over;
561
            }
558
            }
Lines 599-605 sub TooMany { Link Here
599
        return $qty_over if defined $qty_over;
596
        return $qty_over if defined $qty_over;
600
    }
597
    }
601
598
602
    if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) {
599
    unless ( defined $maxissueqty || defined $branch_borrower_circ_rule->{patron_maxissueqty} ) {
603
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
600
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
604
    }
601
    }
605
602
Lines 1903-1930 wildcards. Link Here
1903
1900
1904
sub GetBranchBorrowerCircRule {
1901
sub GetBranchBorrowerCircRule {
1905
    my ( $branchcode, $categorycode ) = @_;
1902
    my ( $branchcode, $categorycode ) = @_;
1906
1903
    return Koha::CirculationRules->get_effective_rules(
1907
    # Initialize default values
1904
        {
1908
    my $rules = {
1905
            categorycode => $categorycode,
1909
        patron_maxissueqty       => undef,
1906
            itemtype     => undef,
1910
        patron_maxonsiteissueqty => undef,
1907
            branchcode   => $branchcode,
1911
    };
1908
            rules => ['patron_maxissueqty', 'patron_maxonsiteissueqty']
1912
1909
        }
1913
    # Search for rules!
1910
    );
1914
    foreach my $rule_name (qw( patron_maxissueqty patron_maxonsiteissueqty )) {
1915
        my $rule = Koha::CirculationRules->get_effective_rule(
1916
            {
1917
                categorycode => $categorycode,
1918
                itemtype     => undef,
1919
                branchcode   => $branchcode,
1920
                rule_name    => $rule_name,
1921
            }
1922
        );
1923
1924
        $rules->{$rule_name} = $rule->rule_value if defined $rule;
1925
    }
1926
1927
    return $rules;
1928
}
1911
}
1929
1912
1930
=head2 GetBranchItemRule
1913
=head2 GetBranchItemRule
(-)a/C4/Reserves.pm (-54 / +42 lines)
Lines 332-338 See CanItemBeReserved() for possible return values. Link Here
332
332
333
=cut
333
=cut
334
334
335
sub CanBookBeReserved{
335
sub CanBookBeReserved {
336
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
336
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
337
337
338
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
338
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
Lines 345-360 sub CanBookBeReserved{ Link Here
345
345
346
        # biblio-level, item type-contrained
346
        # biblio-level, item type-contrained
347
        my $patron          = Koha::Patrons->find($borrowernumber);
347
        my $patron          = Koha::Patrons->find($borrowernumber);
348
        my $reservesallowed = Koha::CirculationRules->get_effective_rule(
348
        my $reservesallowed = Koha::CirculationRules->get_effective_rule_value(
349
            {
349
            {
350
                itemtype     => $params->{itemtype},
350
                itemtype     => $params->{itemtype},
351
                categorycode => $patron->categorycode,
351
                categorycode => $patron->categorycode,
352
                branchcode   => $pickup_branchcode,
352
                branchcode   => $pickup_branchcode,
353
                rule_name    => 'reservesallowed',
353
                rule_name    => 'reservesallowed',
354
            }
354
            }
355
        )->rule_value;
355
        );
356
356
357
        $reservesallowed = ( $reservesallowed eq '' ) ? undef : $reservesallowed;
357
        $reservesallowed = $reservesallowed eq '' ? undef : $reservesallowed;
358
358
359
        my $count = $patron->holds->search(
359
        my $count = $patron->holds->search(
360
            {
360
            {
Lines 423-429 sub CanItemBeReserved { Link Here
423
    my ( $patron, $item, $pickup_branchcode, $params ) = @_;
423
    my ( $patron, $item, $pickup_branchcode, $params ) = @_;
424
424
425
    my $dbh = C4::Context->dbh;
425
    my $dbh = C4::Context->dbh;
426
    my $ruleitemtype;    # itemtype of the matching issuing rule
426
    my $effective_itemtype = $item->effective_itemtype;
427
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
427
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
428
428
429
    # We check item branch if IndependentBranches is ON
429
    # We check item branch if IndependentBranches is ON
Lines 464-471 sub CanItemBeReserved { Link Here
464
    }
464
    }
465
465
466
    # check if a recall exists on this item from this borrower
466
    # check if a recall exists on this item from this borrower
467
    return { status => 'recall' }
467
    if (
468
      if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count;
468
        C4::Context->preference('UseRecalls') &&
469
        $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count
470
    ) {
471
        return { status => 'recall' };
472
    }
469
473
470
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
474
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
471
475
Lines 482-512 sub CanItemBeReserved { Link Here
482
    }
486
    }
483
487
484
    # we retrieve rights
488
    # we retrieve rights
485
    if (
489
    #undefined is 0, blank is unlimited
486
        my $reservesallowed = Koha::CirculationRules->get_effective_rule({
490
    $allowedreserves = Koha::CirculationRules->get_effective_rule_value({
487
                itemtype     => $item->effective_itemtype,
491
        itemtype     => $effective_itemtype,
488
                categorycode => $borrower->{categorycode},
492
        categorycode => $borrower->{categorycode},
489
                branchcode   => $reserves_control_branch,
493
        branchcode   => $reserves_control_branch,
490
                rule_name    => 'reservesallowed',
494
        rule_name    => 'reservesallowed'
491
        })
495
    }) // 0;
492
    ) {
493
        $ruleitemtype     = $reservesallowed->itemtype;
494
        $allowedreserves  = $reservesallowed->rule_value // 0; #undefined is 0, blank is unlimited
495
    }
496
    else {
497
        $ruleitemtype = undef;
498
    }
499
496
500
    my $rights = Koha::CirculationRules->get_effective_rules({
497
    my $rights = Koha::CirculationRules->get_effective_rules({
501
        categorycode => $borrower->{'categorycode'},
498
        categorycode => $borrower->{'categorycode'},
502
        itemtype     => $item->effective_itemtype,
499
        itemtype     => $effective_itemtype,
503
        branchcode   => $reserves_control_branch,
500
        branchcode   => $reserves_control_branch,
504
        rules        => ['holds_per_record','holds_per_day']
501
        rules        => ['holds_per_record', 'holds_per_day']
505
    });
502
    });
506
    my $holds_per_record = $rights->{holds_per_record} // 1;
503
    my $holds_per_record = $rights->{holds_per_record} // 1;
507
    my $holds_per_day    = $rights->{holds_per_day};
504
    my $holds_per_day    = $rights->{holds_per_day};
508
505
509
    if (   defined $holds_per_record && $holds_per_record ne '' ){
506
    if ( defined $holds_per_record && $holds_per_record ne '' ){
510
        if ( $holds_per_record == 0 ) {
507
        if ( $holds_per_record == 0 ) {
511
            return { status => "noReservesAllowed" };
508
            return { status => "noReservesAllowed" };
512
        }
509
        }
Lines 530-537 sub CanItemBeReserved { Link Here
530
    }
527
    }
531
528
532
    # we check if it's ok or not
529
    # we check if it's ok or not
533
    if ( defined $allowedreserves && $allowedreserves ne '' ){
530
    if ( $allowedreserves ne '' ) {
534
        if( $allowedreserves == 0 ){
531
        if( $allowedreserves == 0 ) {
535
            return { status => 'noReservesAllowed' };
532
            return { status => 'noReservesAllowed' };
536
        }
533
        }
537
        if ( !$params->{ignore_hold_counts} ) {
534
        if ( !$params->{ignore_hold_counts} ) {
Lines 548-578 sub CanItemBeReserved { Link Here
548
545
549
            # If using item-level itypes, fall back to the record
546
            # If using item-level itypes, fall back to the record
550
            # level itemtype if the hold has no associated item
547
            # level itemtype if the hold has no associated item
551
            if ( defined $ruleitemtype ) {
548
            if ( C4::Context->preference('item-level_itypes') ) {
552
                if ( C4::Context->preference('item-level_itypes') ) {
549
                $querycount .= q{
553
                    $querycount .= q{
550
                    AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
554
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
551
                    OR reserves.itemtype = ? )
555
                           OR reserves.itemtype = ? )
552
                };
556
                    };
557
                }
558
                else {
559
                    $querycount .= q{
560
                        AND ( biblioitems.itemtype = ?
561
                           OR reserves.itemtype = ? )
562
                    };
563
                }
564
            }
565
566
            my $sthcount = $dbh->prepare($querycount);
567
568
            if ( defined $ruleitemtype ) {
569
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $ruleitemtype, $ruleitemtype );
570
            }
553
            }
571
            else {
554
            else {
572
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
555
                $querycount .= q{
556
                    AND ( biblioitems.itemtype = ?
557
                    OR reserves.itemtype = ? )
558
                };
573
            }
559
            }
574
560
575
            my $reservecount = "0";
561
            my $sthcount = $dbh->prepare($querycount);
562
            $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $effective_itemtype, $effective_itemtype );
563
564
            my $reservecount = 0;
576
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
565
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
577
                $reservecount = $rowcount->{count};
566
                $reservecount = $rowcount->{count};
578
            }
567
            }
Lines 582-606 sub CanItemBeReserved { Link Here
582
    }
571
    }
583
572
584
    # Now we need to check hold limits by patron category
573
    # Now we need to check hold limits by patron category
585
    my $rule = Koha::CirculationRules->get_effective_rule(
574
    my $max_holds = Koha::CirculationRules->get_effective_rule_value(
586
        {
575
        {
587
            categorycode => $patron->categorycode,
576
            categorycode => $patron->categorycode,
588
            branchcode   => $reserves_control_branch,
577
            branchcode   => $reserves_control_branch,
589
            rule_name    => 'max_holds',
578
            rule_name    => 'max_holds',
590
        }
579
        }
591
    );
580
    );
592
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
581
    if (!$params->{ignore_hold_counts} && defined $max_holds && $max_holds ne '' ) {
593
        my $total_holds_count = Koha::Holds->search(
582
        my $total_holds_count = Koha::Holds->search(
594
            {
583
            {
595
                borrowernumber => $patron->borrowernumber
584
                borrowernumber => $patron->borrowernumber
596
            }
585
            }
597
        )->count();
586
        )->count();
598
587
599
        return { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value;
588
        return { status => 'tooManyReserves', limit => $max_holds } if $total_holds_count >= $max_holds;
600
    }
589
    }
601
590
602
    my $branchitemrule =
591
    my $branchitemrule =
603
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype );
592
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $effective_itemtype );
604
593
605
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
594
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
606
        return { status => 'notReservable' };
595
        return { status => 'notReservable' };
Lines 2366-2378 sub GetMaxPatronHoldsForRecord { Link Here
2366
2355
2367
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2356
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2368
2357
2369
        my $rule = Koha::CirculationRules->get_effective_rule({
2358
        my $holds_per_record = Koha::CirculationRules->get_effective_rule_value({
2370
            categorycode => $categorycode,
2359
            categorycode => $categorycode,
2371
            itemtype     => $itemtype,
2360
            itemtype     => $itemtype,
2372
            branchcode   => $branchcode,
2361
            branchcode   => $branchcode,
2373
            rule_name    => 'holds_per_record'
2362
            rule_name    => 'holds_per_record'
2374
        });
2363
        }) // 0;
2375
        my $holds_per_record = $rule ? $rule->rule_value : 0;
2376
        $max = $holds_per_record if $holds_per_record > $max;
2364
        $max = $holds_per_record if $holds_per_record > $max;
2377
    }
2365
    }
2378
2366
(-)a/Koha/Biblio.pm (-12 / +6 lines)
Lines 295-310 $borrower must be a Koha::Patron object Link Here
295
sub article_request_type {
295
sub article_request_type {
296
    my ( $self, $borrower ) = @_;
296
    my ( $self, $borrower ) = @_;
297
297
298
    return q{} unless $borrower;
298
    return unless $borrower;
299
299
300
    my $rule = $self->article_request_type_for_items( $borrower );
300
    my $type = $self->article_request_type_for_items( $borrower );
301
    return $rule if $rule;
301
    return $type if $type;
302
302
303
    # If the record has no items that are requestable, go by the record itemtype
303
    # If the record has no items that are requestable, go by the record itemtype
304
    $rule = $self->article_request_type_for_bib($borrower);
304
    return $self->article_request_type_for_bib($borrower);
305
    return $rule if $rule;
306
307
    return q{};
308
}
305
}
309
306
310
=head3 article_request_type_for_bib
307
=head3 article_request_type_for_bib
Lines 318-338 Returns the article request type 'yes', 'no', 'item_only', 'bib_only', for the g Link Here
318
sub article_request_type_for_bib {
315
sub article_request_type_for_bib {
319
    my ( $self, $borrower ) = @_;
316
    my ( $self, $borrower ) = @_;
320
317
321
    return q{} unless $borrower;
318
    return unless $borrower;
322
319
323
    my $borrowertype = $borrower->categorycode;
320
    my $borrowertype = $borrower->categorycode;
324
    my $itemtype     = $self->itemtype();
321
    my $itemtype     = $self->itemtype();
325
322
326
    my $rule = Koha::CirculationRules->get_effective_rule(
323
    return Koha::CirculationRules->get_effective_rule_value(
327
        {
324
        {
328
            rule_name    => 'article_requests',
325
            rule_name    => 'article_requests',
329
            categorycode => $borrowertype,
326
            categorycode => $borrowertype,
330
            itemtype     => $itemtype,
327
            itemtype     => $itemtype,
331
        }
328
        }
332
    );
329
    );
333
334
    return q{} unless $rule;
335
    return $rule->rule_value || q{}
336
}
330
}
337
331
338
=head3 article_request_type_for_items
332
=head3 article_request_type_for_items
(-)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 / +16 lines)
Lines 300-312 sub get_effective_rule_value { Link Here
300
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
300
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
301
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
301
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
302
302
303
    my $cached       = $memory_cache->get_from_cache($cache_key);
303
    my $value = $memory_cache->get_from_cache($cache_key);
304
    return $cached if $cached;
304
    unless (defined $value) {
305
305
        my $rule = $self->get_effective_rule($params);
306
    my $rule = $self->get_effective_rule($params);
306
        if ($rule) {
307
307
            $value = $rule->rule_value;
308
    my $value= $rule ? $rule->rule_value : undef;
308
        }
309
    $memory_cache->set_in_cache( $cache_key, $value );
309
        $value //= 'undef';
310
        $memory_cache->set_in_cache( $cache_key, $value );
311
    }
312
    return if $value eq 'undef';
310
    return $value;
313
    return $value;
311
}
314
}
312
315
Lines 541-547 sub get_opacitemholds_policy { Link Here
541
544
542
    return unless $item or $patron;
545
    return unless $item or $patron;
543
546
544
    my $rule = Koha::CirculationRules->get_effective_rule(
547
    return Koha::CirculationRules->get_effective_rule_value(
545
        {
548
        {
546
            categorycode => $patron->categorycode,
549
            categorycode => $patron->categorycode,
547
            itemtype     => $item->effective_itemtype,
550
            itemtype     => $item->effective_itemtype,
Lines 549-556 sub get_opacitemholds_policy { Link Here
549
            rule_name    => 'opacitemholds',
552
            rule_name    => 'opacitemholds',
550
        }
553
        }
551
    );
554
    );
552
553
    return $rule ? $rule->rule_value : undef;
554
}
555
}
555
556
556
=head3 get_onshelfholds_policy
557
=head3 get_onshelfholds_policy
Lines 564-578 sub get_onshelfholds_policy { Link Here
564
    my $item = $params->{item};
565
    my $item = $params->{item};
565
    my $itemtype = $item->effective_itemtype;
566
    my $itemtype = $item->effective_itemtype;
566
    my $patron = $params->{patron};
567
    my $patron = $params->{patron};
567
    my $rule = Koha::CirculationRules->get_effective_rule(
568
    return Koha::CirculationRules->get_effective_rule_value(
568
        {
569
        {
569
            categorycode => ( $patron ? $patron->categorycode : undef ),
570
            categorycode => ( $patron ? $patron->categorycode : undef ),
570
            itemtype     => $itemtype,
571
            itemtype     => $itemtype,
571
            branchcode   => $item->holdingbranch,
572
            branchcode   => $item->holdingbranch,
572
            rule_name    => 'onshelfholds',
573
            rule_name    => 'onshelfholds',
573
        }
574
        }
574
    );
575
    ) // 0;
575
    return $rule ? $rule->rule_value : 0;
576
}
576
}
577
577
578
=head3 get_lostreturn_policy
578
=head3 get_lostreturn_policy
Lines 627-633 sub get_lostreturn_policy { Link Here
627
    my $rules = Koha::CirculationRules->get_effective_rules(
627
    my $rules = Koha::CirculationRules->get_effective_rules(
628
        {
628
        {
629
            branchcode => $branch,
629
            branchcode => $branch,
630
            rules  => ['lostreturn','processingreturn']
630
            rules  => ['lostreturn', 'processingreturn']
631
        }
631
        }
632
    );
632
    );
633
633
Lines 714-720 sub get_effective_daysmode { Link Here
714
    my $itemtype         = $params->{itemtype};
714
    my $itemtype         = $params->{itemtype};
715
    my $branchcode       = $params->{branchcode};
715
    my $branchcode       = $params->{branchcode};
716
716
717
    my $daysmode_rule = $class->get_effective_rule(
717
    my $daysmode = $class->get_effective_rule_value(
718
        {
718
        {
719
            categorycode => $categorycode,
719
            categorycode => $categorycode,
720
            itemtype     => $itemtype,
720
            itemtype     => $itemtype,
Lines 722-733 sub get_effective_daysmode { Link Here
722
            rule_name    => 'daysmode',
722
            rule_name    => 'daysmode',
723
        }
723
        }
724
    );
724
    );
725
725
    return $daysmode || C4::Context->preference('useDaysMode');
726
    return ( defined($daysmode_rule)
727
          and $daysmode_rule->rule_value ne '' )
728
      ? $daysmode_rule->rule_value
729
      : C4::Context->preference('useDaysMode');
730
731
}
726
}
732
727
733
728
(-)a/Koha/Item.pm (-4 / +1 lines)
Lines 829-835 sub article_request_type { Link Here
829
      :                                      undef;
829
      :                                      undef;
830
    my $borrowertype = $borrower->categorycode;
830
    my $borrowertype = $borrower->categorycode;
831
    my $itemtype = $self->effective_itemtype();
831
    my $itemtype = $self->effective_itemtype();
832
    my $rule = Koha::CirculationRules->get_effective_rule(
832
    return Koha::CirculationRules->get_effective_rule_value(
833
        {
833
        {
834
            rule_name    => 'article_requests',
834
            rule_name    => 'article_requests',
835
            categorycode => $borrowertype,
835
            categorycode => $borrowertype,
Lines 837-845 sub article_request_type { Link Here
837
            branchcode   => $branchcode
837
            branchcode   => $branchcode
838
        }
838
        }
839
    );
839
    );
840
841
    return q{} unless $rule;
842
    return $rule->rule_value || q{}
843
}
840
}
844
841
845
=head3 current_holds
842
=head3 current_holds
(-)a/Koha/Patron.pm (-7 / +3 lines)
Lines 1035-1041 sub can_request_article { Link Here
1035
1035
1036
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1036
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1037
1037
1038
    my $rule = Koha::CirculationRules->get_effective_rule(
1038
    my $limit = Koha::CirculationRules->get_effective_rule_value(
1039
        {
1039
        {
1040
            branchcode   => $library_id,
1040
            branchcode   => $library_id,
1041
            categorycode => $self->categorycode,
1041
            categorycode => $self->categorycode,
Lines 1043-1050 sub can_request_article { Link Here
1043
        }
1043
        }
1044
    );
1044
    );
1045
1045
1046
    my $limit = ($rule) ? $rule->rule_value : undef;
1047
1048
    return 1 unless defined $limit;
1046
    return 1 unless defined $limit;
1049
1047
1050
    my $count = Koha::ArticleRequests->search(
1048
    my $count = Koha::ArticleRequests->search(
Lines 1076-1090 sub article_request_fee { Link Here
1076
1074
1077
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1075
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1078
1076
1079
    my $rule = Koha::CirculationRules->get_effective_rule(
1077
    my $fee = Koha::CirculationRules->get_effective_rule_value(
1080
        {
1078
        {
1081
            branchcode   => $library_id,
1079
            branchcode   => $library_id,
1082
            categorycode => $self->categorycode,
1080
            categorycode => $self->categorycode,
1083
            rule_name    => 'article_request_fee'
1081
            rule_name    => 'article_request_fee'
1084
        }
1082
        }
1085
    );
1083
    ) + 0;
1086
1087
    my $fee = ($rule) ? $rule->rule_value + 0 : 0;
1088
1084
1089
    return $fee;
1085
    return $fee;
1090
}
1086
}
(-)a/Koha/REST/V1/Checkouts.pm (-3 / +3 lines)
Lines 216-234 sub allows_renewal { Link Here
216
        my $renewable = Mojo::JSON->false;
216
        my $renewable = Mojo::JSON->false;
217
        $renewable = Mojo::JSON->true if $can_renew;
217
        $renewable = Mojo::JSON->true if $can_renew;
218
218
219
        my $rule = Koha::CirculationRules->get_effective_rule(
219
        my $renewalsallowed = Koha::CirculationRules->get_effective_rule_value(
220
            {
220
            {
221
                categorycode => $checkout->patron->categorycode,
221
                categorycode => $checkout->patron->categorycode,
222
                itemtype     => $checkout->item->effective_itemtype,
222
                itemtype     => $checkout->item->effective_itemtype,
223
                branchcode   => $checkout->branchcode,
223
                branchcode   => $checkout->branchcode,
224
                rule_name    => 'renewalsallowed',
224
                rule_name    => 'renewalsallowed'
225
            }
225
            }
226
        );
226
        );
227
        return $c->render(
227
        return $c->render(
228
            status => 200,
228
            status => 200,
229
            openapi => {
229
            openapi => {
230
                allows_renewal => $renewable,
230
                allows_renewal => $renewable,
231
                max_renewals => $rule->rule_value,
231
                max_renewals => $renewalsallowed,
232
                current_renewals => $checkout->renewals_count,
232
                current_renewals => $checkout->renewals_count,
233
                unseen_renewals => $checkout->unseen_renewals,
233
                unseen_renewals => $checkout->unseen_renewals,
234
                error => $error
234
                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->unblessed, $self->patron->unblessed );
261
        $branchcode = C4::Circulation::_GetCircControlBranch( $item->unblessed, $self->patron->unblessed );
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 (-3 / +2 lines)
Lines 134-146 sub add_recall { Link Here
134
134
135
        # get checkout and adjust due date based on circulation rules
135
        # get checkout and adjust due date based on circulation rules
136
        my $checkout = $recall->checkout;
136
        my $checkout = $recall->checkout;
137
        my $recall_due_date_interval = Koha::CirculationRules->get_effective_rule({
137
        my $due_interval = Koha::CirculationRules->get_effective_rule_value({
138
            categorycode => $checkout->patron->categorycode,
138
            categorycode => $checkout->patron->categorycode,
139
            itemtype => $checkout->item->effective_itemtype,
139
            itemtype => $checkout->item->effective_itemtype,
140
            branchcode => $branchcode,
140
            branchcode => $branchcode,
141
            rule_name => 'recall_due_date_interval',
141
            rule_name => 'recall_due_date_interval',
142
        });
142
        }) // 5;
143
        my $due_interval = defined $recall_due_date_interval ? $recall_due_date_interval->rule_value : 5;
144
        my $timestamp = dt_from_string( $recall->timestamp );
143
        my $timestamp = dt_from_string( $recall->timestamp );
145
        my $due_date = $timestamp->add( days => $due_interval );
144
        my $due_date = $timestamp->add( days => $due_interval );
146
        $checkout->update({ date_due => $due_date });
145
        $checkout->update({ date_due => $due_date });
(-)a/Koha/Template/Plugin/CirculationRules.pm (-4 / +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
62
- 

Return to bug 32092