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 1926-1953 wildcards. Link Here
1926
1923
1927
sub GetBranchBorrowerCircRule {
1924
sub GetBranchBorrowerCircRule {
1928
    my ( $branchcode, $categorycode ) = @_;
1925
    my ( $branchcode, $categorycode ) = @_;
1929
1926
    return Koha::CirculationRules->get_effective_rules(
1930
    # Initialize default values
1927
        {
1931
    my $rules = {
1928
            categorycode => $categorycode,
1932
        patron_maxissueqty       => undef,
1929
            itemtype     => undef,
1933
        patron_maxonsiteissueqty => undef,
1930
            branchcode   => $branchcode,
1934
    };
1931
            rules => ['patron_maxissueqty', 'patron_maxonsiteissueqty']
1935
1932
        }
1936
    # Search for rules!
1933
    );
1937
    foreach my $rule_name (qw( patron_maxissueqty patron_maxonsiteissueqty )) {
1938
        my $rule = Koha::CirculationRules->get_effective_rule(
1939
            {
1940
                categorycode => $categorycode,
1941
                itemtype     => undef,
1942
                branchcode   => $branchcode,
1943
                rule_name    => $rule_name,
1944
            }
1945
        );
1946
1947
        $rules->{$rule_name} = $rule->rule_value if defined $rule;
1948
    }
1949
1950
    return $rules;
1951
}
1934
}
1952
1935
1953
=head2 GetBranchItemRule
1936
=head2 GetBranchItemRule
(-)a/C4/Reserves.pm (-54 / +42 lines)
Lines 333-339 See CanItemBeReserved() for possible return values. Link Here
333
333
334
=cut
334
=cut
335
335
336
sub CanBookBeReserved{
336
sub CanBookBeReserved {
337
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
337
    my ($borrowernumber, $biblionumber, $pickup_branchcode, $params) = @_;
338
338
339
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
339
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
Lines 346-361 sub CanBookBeReserved{ Link Here
346
346
347
        # biblio-level, item type-contrained
347
        # biblio-level, item type-contrained
348
        my $patron          = Koha::Patrons->find($borrowernumber);
348
        my $patron          = Koha::Patrons->find($borrowernumber);
349
        my $reservesallowed = Koha::CirculationRules->get_effective_rule(
349
        my $reservesallowed = Koha::CirculationRules->get_effective_rule_value(
350
            {
350
            {
351
                itemtype     => $params->{itemtype},
351
                itemtype     => $params->{itemtype},
352
                categorycode => $patron->categorycode,
352
                categorycode => $patron->categorycode,
353
                branchcode   => $pickup_branchcode,
353
                branchcode   => $pickup_branchcode,
354
                rule_name    => 'reservesallowed',
354
                rule_name    => 'reservesallowed',
355
            }
355
            }
356
        )->rule_value;
356
        );
357
357
358
        $reservesallowed = ( $reservesallowed eq '' ) ? undef : $reservesallowed;
358
        $reservesallowed = $reservesallowed eq '' ? undef : $reservesallowed;
359
359
360
        my $count = $patron->holds->search(
360
        my $count = $patron->holds->search(
361
            {
361
            {
Lines 439-445 sub CanItemBeReserved { Link Here
439
    }
439
    }
440
440
441
    my $dbh = C4::Context->dbh;
441
    my $dbh = C4::Context->dbh;
442
    my $ruleitemtype;    # itemtype of the matching issuing rule
442
    my $effective_itemtype = $item->effective_itemtype;
443
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
443
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
444
444
445
    # We check item branch if IndependentBranches is ON
445
    # We check item branch if IndependentBranches is ON
Lines 480-487 sub CanItemBeReserved { Link Here
480
    }
480
    }
481
481
482
    # check if a recall exists on this item from this borrower
482
    # check if a recall exists on this item from this borrower
483
    return _cache { status => 'recall' }
483
    if (
484
      if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count;
484
        C4::Context->preference('UseRecalls') &&
485
        $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count
486
    ) {
487
        return _cache { status => 'recall' };
488
    }
485
489
486
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
490
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
487
491
Lines 498-528 sub CanItemBeReserved { Link Here
498
    }
502
    }
499
503
500
    # we retrieve rights
504
    # we retrieve rights
501
    if (
505
    #undefined is 0, blank is unlimited
502
        my $reservesallowed = Koha::CirculationRules->get_effective_rule({
506
    $allowedreserves = Koha::CirculationRules->get_effective_rule_value({
503
                itemtype     => $item->effective_itemtype,
507
        itemtype     => $effective_itemtype,
504
                categorycode => $borrower->{categorycode},
508
        categorycode => $borrower->{categorycode},
505
                branchcode   => $reserves_control_branch,
509
        branchcode   => $reserves_control_branch,
506
                rule_name    => 'reservesallowed',
510
        rule_name    => 'reservesallowed'
507
        })
511
    }) // 0;
508
    ) {
509
        $ruleitemtype     = $reservesallowed->itemtype;
510
        $allowedreserves  = $reservesallowed->rule_value // 0; #undefined is 0, blank is unlimited
511
    }
512
    else {
513
        $ruleitemtype = undef;
514
    }
515
512
516
    my $rights = Koha::CirculationRules->get_effective_rules({
513
    my $rights = Koha::CirculationRules->get_effective_rules({
517
        categorycode => $borrower->{'categorycode'},
514
        categorycode => $borrower->{'categorycode'},
518
        itemtype     => $item->effective_itemtype,
515
        itemtype     => $effective_itemtype,
519
        branchcode   => $reserves_control_branch,
516
        branchcode   => $reserves_control_branch,
520
        rules        => ['holds_per_record','holds_per_day']
517
        rules        => ['holds_per_record', 'holds_per_day']
521
    });
518
    });
522
    my $holds_per_record = $rights->{holds_per_record} // 1;
519
    my $holds_per_record = $rights->{holds_per_record} // 1;
523
    my $holds_per_day    = $rights->{holds_per_day};
520
    my $holds_per_day    = $rights->{holds_per_day};
524
521
525
    if (   defined $holds_per_record && $holds_per_record ne '' ){
522
    if ( defined $holds_per_record && $holds_per_record ne '' ){
526
        if ( $holds_per_record == 0 ) {
523
        if ( $holds_per_record == 0 ) {
527
            return _cache { status => "noReservesAllowed" };
524
            return _cache { status => "noReservesAllowed" };
528
        }
525
        }
Lines 546-553 sub CanItemBeReserved { Link Here
546
    }
543
    }
547
544
548
    # we check if it's ok or not
545
    # we check if it's ok or not
549
    if ( defined $allowedreserves && $allowedreserves ne '' ){
546
    if ( $allowedreserves ne '' ) {
550
        if( $allowedreserves == 0 ){
547
        if( $allowedreserves == 0 ) {
551
            return _cache { status => 'noReservesAllowed' };
548
            return _cache { status => 'noReservesAllowed' };
552
        }
549
        }
553
        if ( !$params->{ignore_hold_counts} ) {
550
        if ( !$params->{ignore_hold_counts} ) {
Lines 564-594 sub CanItemBeReserved { Link Here
564
561
565
            # If using item-level itypes, fall back to the record
562
            # If using item-level itypes, fall back to the record
566
            # level itemtype if the hold has no associated item
563
            # level itemtype if the hold has no associated item
567
            if ( defined $ruleitemtype ) {
564
            if ( C4::Context->preference('item-level_itypes') ) {
568
                if ( C4::Context->preference('item-level_itypes') ) {
565
                $querycount .= q{
569
                    $querycount .= q{
566
                    AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
570
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
567
                    OR reserves.itemtype = ? )
571
                           OR reserves.itemtype = ? )
568
                };
572
                    };
573
                }
574
                else {
575
                    $querycount .= q{
576
                        AND ( biblioitems.itemtype = ?
577
                           OR reserves.itemtype = ? )
578
                    };
579
                }
580
            }
581
582
            my $sthcount = $dbh->prepare($querycount);
583
584
            if ( defined $ruleitemtype ) {
585
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $ruleitemtype, $ruleitemtype );
586
            }
569
            }
587
            else {
570
            else {
588
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
571
                $querycount .= q{
572
                    AND ( biblioitems.itemtype = ?
573
                    OR reserves.itemtype = ? )
574
                };
589
            }
575
            }
590
576
591
            my $reservecount = "0";
577
            my $sthcount = $dbh->prepare($querycount);
578
            $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $effective_itemtype, $effective_itemtype );
579
580
            my $reservecount = 0;
592
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
581
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
593
                $reservecount = $rowcount->{count};
582
                $reservecount = $rowcount->{count};
594
            }
583
            }
Lines 598-622 sub CanItemBeReserved { Link Here
598
    }
587
    }
599
588
600
    # Now we need to check hold limits by patron category
589
    # Now we need to check hold limits by patron category
601
    my $rule = Koha::CirculationRules->get_effective_rule(
590
    my $max_holds = Koha::CirculationRules->get_effective_rule_value(
602
        {
591
        {
603
            categorycode => $patron->categorycode,
592
            categorycode => $patron->categorycode,
604
            branchcode   => $reserves_control_branch,
593
            branchcode   => $reserves_control_branch,
605
            rule_name    => 'max_holds',
594
            rule_name    => 'max_holds',
606
        }
595
        }
607
    );
596
    );
608
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
597
    if (!$params->{ignore_hold_counts} && defined $max_holds && $max_holds ne '' ) {
609
        my $total_holds_count = Koha::Holds->search(
598
        my $total_holds_count = Koha::Holds->search(
610
            {
599
            {
611
                borrowernumber => $patron->borrowernumber
600
                borrowernumber => $patron->borrowernumber
612
            }
601
            }
613
        )->count();
602
        )->count();
614
603
615
        return _cache { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value;
604
        return _cache { status => 'tooManyReserves', limit => $max_holds } if $total_holds_count >= $max_holds;
616
    }
605
    }
617
606
618
    my $branchitemrule =
607
    my $branchitemrule =
619
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype );
608
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $effective_itemtype );
620
609
621
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
610
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
622
        return _cache { status => 'notReservable' };
611
        return _cache { status => 'notReservable' };
Lines 2347-2359 sub GetMaxPatronHoldsForRecord { Link Here
2347
2336
2348
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2337
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2349
2338
2350
        my $rule = Koha::CirculationRules->get_effective_rule({
2339
        my $holds_per_record = Koha::CirculationRules->get_effective_rule_value({
2351
            categorycode => $categorycode,
2340
            categorycode => $categorycode,
2352
            itemtype     => $itemtype,
2341
            itemtype     => $itemtype,
2353
            branchcode   => $branchcode,
2342
            branchcode   => $branchcode,
2354
            rule_name    => 'holds_per_record'
2343
            rule_name    => 'holds_per_record'
2355
        });
2344
        }) // 0;
2356
        my $holds_per_record = $rule ? $rule->rule_value : 0;
2357
        $max = $holds_per_record if $holds_per_record > $max;
2345
        $max = $holds_per_record if $holds_per_record > $max;
2358
    }
2346
    }
2359
2347
(-)a/Koha/Biblio.pm (-12 / +6 lines)
Lines 367-382 $borrower must be a Koha::Patron object Link Here
367
sub article_request_type {
367
sub article_request_type {
368
    my ( $self, $borrower ) = @_;
368
    my ( $self, $borrower ) = @_;
369
369
370
    return q{} unless $borrower;
370
    return unless $borrower;
371
371
372
    my $rule = $self->article_request_type_for_items( $borrower );
372
    my $type = $self->article_request_type_for_items( $borrower );
373
    return $rule if $rule;
373
    return $type if $type;
374
374
375
    # If the record has no items that are requestable, go by the record itemtype
375
    # If the record has no items that are requestable, go by the record itemtype
376
    $rule = $self->article_request_type_for_bib($borrower);
376
    return $self->article_request_type_for_bib($borrower);
377
    return $rule if $rule;
378
379
    return q{};
380
}
377
}
381
378
382
=head3 article_request_type_for_bib
379
=head3 article_request_type_for_bib
Lines 390-410 Returns the article request type 'yes', 'no', 'item_only', 'bib_only', for the g Link Here
390
sub article_request_type_for_bib {
387
sub article_request_type_for_bib {
391
    my ( $self, $borrower ) = @_;
388
    my ( $self, $borrower ) = @_;
392
389
393
    return q{} unless $borrower;
390
    return unless $borrower;
394
391
395
    my $borrowertype = $borrower->categorycode;
392
    my $borrowertype = $borrower->categorycode;
396
    my $itemtype     = $self->itemtype();
393
    my $itemtype     = $self->itemtype();
397
394
398
    my $rule = Koha::CirculationRules->get_effective_rule(
395
    return Koha::CirculationRules->get_effective_rule_value(
399
        {
396
        {
400
            rule_name    => 'article_requests',
397
            rule_name    => 'article_requests',
401
            categorycode => $borrowertype,
398
            categorycode => $borrowertype,
402
            itemtype     => $itemtype,
399
            itemtype     => $itemtype,
403
        }
400
        }
404
    );
401
    );
405
406
    return q{} unless $rule;
407
    return $rule->rule_value || q{}
408
}
402
}
409
403
410
=head3 article_request_type_for_items
404
=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 818-824 sub article_request_type { Link Here
818
      :                                      undef;
818
      :                                      undef;
819
    my $borrowertype = $borrower->categorycode;
819
    my $borrowertype = $borrower->categorycode;
820
    my $itemtype = $self->effective_itemtype();
820
    my $itemtype = $self->effective_itemtype();
821
    my $rule = Koha::CirculationRules->get_effective_rule(
821
    return Koha::CirculationRules->get_effective_rule_value(
822
        {
822
        {
823
            rule_name    => 'article_requests',
823
            rule_name    => 'article_requests',
824
            categorycode => $borrowertype,
824
            categorycode => $borrowertype,
Lines 826-834 sub article_request_type { Link Here
826
            branchcode   => $branchcode
826
            branchcode   => $branchcode
827
        }
827
        }
828
    );
828
    );
829
830
    return q{} unless $rule;
831
    return $rule->rule_value || q{}
832
}
829
}
833
830
834
=head3 current_holds
831
=head3 current_holds
(-)a/Koha/Patron.pm (-7 / +3 lines)
Lines 1049-1055 sub can_request_article { Link Here
1049
1049
1050
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1050
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1051
1051
1052
    my $rule = Koha::CirculationRules->get_effective_rule(
1052
    my $limit = Koha::CirculationRules->get_effective_rule_value(
1053
        {
1053
        {
1054
            branchcode   => $library_id,
1054
            branchcode   => $library_id,
1055
            categorycode => $self->categorycode,
1055
            categorycode => $self->categorycode,
Lines 1057-1064 sub can_request_article { Link Here
1057
        }
1057
        }
1058
    );
1058
    );
1059
1059
1060
    my $limit = ($rule) ? $rule->rule_value : undef;
1061
1062
    return 1 unless defined $limit;
1060
    return 1 unless defined $limit;
1063
1061
1064
    my $count = Koha::ArticleRequests->search(
1062
    my $count = Koha::ArticleRequests->search(
Lines 1090-1104 sub article_request_fee { Link Here
1090
1088
1091
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1089
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1092
1090
1093
    my $rule = Koha::CirculationRules->get_effective_rule(
1091
    my $fee = Koha::CirculationRules->get_effective_rule_value(
1094
        {
1092
        {
1095
            branchcode   => $library_id,
1093
            branchcode   => $library_id,
1096
            categorycode => $self->categorycode,
1094
            categorycode => $self->categorycode,
1097
            rule_name    => 'article_request_fee'
1095
            rule_name    => 'article_request_fee'
1098
        }
1096
        }
1099
    );
1097
    ) + 0;
1100
1101
    my $fee = ($rule) ? $rule->rule_value + 0 : 0;
1102
1098
1103
    return $fee;
1099
    return $fee;
1104
}
1100
}
(-)a/Koha/REST/V1/Checkouts.pm (-3 / +3 lines)
Lines 354-372 sub allows_renewal { Link Here
354
        my $renewable = Mojo::JSON->false;
354
        my $renewable = Mojo::JSON->false;
355
        $renewable = Mojo::JSON->true if $can_renew;
355
        $renewable = Mojo::JSON->true if $can_renew;
356
356
357
        my $rule = Koha::CirculationRules->get_effective_rule(
357
        my $renewalsallowed = Koha::CirculationRules->get_effective_rule_value(
358
            {
358
            {
359
                categorycode => $checkout->patron->categorycode,
359
                categorycode => $checkout->patron->categorycode,
360
                itemtype     => $checkout->item->effective_itemtype,
360
                itemtype     => $checkout->item->effective_itemtype,
361
                branchcode   => $checkout->branchcode,
361
                branchcode   => $checkout->branchcode,
362
                rule_name    => 'renewalsallowed',
362
                rule_name    => 'renewalsallowed'
363
            }
363
            }
364
        );
364
        );
365
        return $c->render(
365
        return $c->render(
366
            status => 200,
366
            status => 200,
367
            openapi => {
367
            openapi => {
368
                allows_renewal => $renewable,
368
                allows_renewal => $renewable,
369
                max_renewals => $rule->rule_value,
369
                max_renewals => $renewalsallowed,
370
                current_renewals => $checkout->renewals_count,
370
                current_renewals => $checkout->renewals_count,
371
                unseen_renewals => $checkout->unseen_renewals,
371
                unseen_renewals => $checkout->unseen_renewals,
372
                error => $error
372
                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