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

(-)a/C4/Circulation.pm (-48 / +31 lines)
Lines 423-438 sub TooMany { Link Here
423
    my $branch = _GetCircControlBranch($item, $patron);
423
    my $branch = _GetCircControlBranch($item, $patron);
424
    my $type = $item->effective_itemtype;
424
    my $type = $item->effective_itemtype;
425
425
426
    my ($type_object, $parent_type, $parent_maxissueqty_rule);
426
    my $type_object = Koha::ItemTypes->find( $type );
427
    $type_object = Koha::ItemTypes->find( $type );
427
    my $parent_type = $type_object->parent_type if $type_object;
428
    $parent_type = $type_object->parent_type if $type_object;
429
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
428
    my $child_types = Koha::ItemTypes->search({ parent_type => $type });
430
    # Find any children if we are a parent_type;
429
    # Find any children if we are a parent_type;
431
430
432
    # given branch, patron category, and item type, determine
431
    # given branch, patron category, and item type, determine
433
    # applicable issuing rule
432
    # applicable issuing rule
434
433
435
    $parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
434
    # If the parent rule is for default type we discount it
435
    my $parent_maxissueqty;
436
    $parent_maxissueqty = Koha::CirculationRules->get_effective_rule_value(
436
        {
437
        {
437
            categorycode => $cat_borrower,
438
            categorycode => $cat_borrower,
438
            itemtype     => $parent_type,
439
            itemtype     => $parent_type,
Lines 440-449 sub TooMany { Link Here
440
            rule_name    => 'maxissueqty',
441
            rule_name    => 'maxissueqty',
441
        }
442
        }
442
    ) if $parent_type;
443
    ) if $parent_type;
443
    # If the parent rule is for default type we discount it
444
    $parent_maxissueqty_rule = undef if $parent_maxissueqty_rule && !defined $parent_maxissueqty_rule->itemtype;
445
444
446
    my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule(
445
    my $maxissueqty = Koha::CirculationRules->get_effective_rule_value(
447
        {
446
        {
448
            categorycode => $cat_borrower,
447
            categorycode => $cat_borrower,
449
            itemtype     => $type,
448
            itemtype     => $type,
Lines 452-458 sub TooMany { Link Here
452
        }
451
        }
453
    );
452
    );
454
453
455
    my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule(
454
    my $maxonsiteissueqty = Koha::CirculationRules->get_effective_rule_value(
456
        {
455
        {
457
            categorycode => $cat_borrower,
456
            categorycode => $cat_borrower,
458
            itemtype     => $type,
457
            itemtype     => $type,
Lines 464-482 sub TooMany { Link Here
464
    # if a rule is found and has a loan limit set, count
463
    # if a rule is found and has a loan limit set, count
465
    # how many loans the patron already has that meet that
464
    # how many loans the patron already has that meet that
466
    # rule
465
    # rule
467
    if (defined($maxissueqty_rule) and $maxissueqty_rule->rule_value ne "") {
466
    if (defined $maxissueqty and $maxissueqty ne "") {
468
467
469
        my $checkouts;
468
        my $checkouts;
470
        if ( $maxissueqty_rule->branchcode ) {
469
        if ( $branch ) {
471
            if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
470
            if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) {
472
                $checkouts = $patron->checkouts->search(
471
                $checkouts = $patron->checkouts->search(
473
                    { 'me.branchcode' => $maxissueqty_rule->branchcode } );
472
                    { 'me.branchcode' => $branch } );
474
            } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') {
473
            } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') {
475
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
474
                $checkouts = $patron->checkouts; # if branch is the patron's home branch, then count all loans by patron
476
            } else {
475
            } else {
477
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
476
                my $branch_type = C4::Context->preference('HomeOrHoldingBranch') || 'homebranch';
478
                $checkouts = $patron->checkouts->search(
477
                $checkouts = $patron->checkouts->search( { "item.$branch_type" => $branch } );
479
                    { "item.$branch_type" => $maxissueqty_rule->branchcode } );
480
            }
478
            }
481
        } else {
479
        } else {
482
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
480
            $checkouts = $patron->checkouts; # if rule is not branch specific then count all loans by patron
Lines 484-506 sub TooMany { Link Here
484
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
482
        $checkouts = $checkouts->search(undef, { prefetch => 'item' });
485
483
486
        my $sum_checkouts;
484
        my $sum_checkouts;
487
        my $rule_itemtype = $maxissueqty_rule->itemtype;
488
485
489
        my @types;
486
        my @types;
490
        unless ( $rule_itemtype ) {
487
        unless ( $type ) {
491
            # matching rule has the default item type, so count only
488
            # matching rule has the default item type, so count only
492
            # those existing loans that don't fall under a more
489
            # those existing loans that don't fall under a more
493
            # specific rule
490
            # specific rule
494
            @types = Koha::CirculationRules->search(
491
            @types = Koha::CirculationRules->search(
495
                {
492
                {
496
                    branchcode => $maxissueqty_rule->branchcode,
493
                    branchcode => $branch,
497
                    categorycode => [ $maxissueqty_rule->categorycode, $cat_borrower ],
494
                    categorycode => $cat_borrower,
498
                    itemtype  => { '!=' => undef },
495
                    itemtype  => { '!=' => undef },
499
                    rule_name => 'maxissueqty'
496
                    rule_name => 'maxissueqty'
500
                }
497
                }
501
            )->get_column('itemtype');
498
            )->get_column('itemtype');
502
        } else {
499
        } else {
503
            if ( $parent_maxissueqty_rule ) {
500
            if ( $parent_maxissueqty ) {
504
                # if we have a parent item type then we count loans of the
501
                # if we have a parent item type then we count loans of the
505
                # specific item type or its siblings or parent
502
                # specific item type or its siblings or parent
506
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
503
                my $children = Koha::ItemTypes->search({ parent_type => $parent_type });
Lines 519-525 sub TooMany { Link Here
519
        while ( my $c = $checkouts->next ) {
516
        while ( my $c = $checkouts->next ) {
520
            my $itemtype = $c->item->effective_itemtype;
517
            my $itemtype = $c->item->effective_itemtype;
521
518
522
            unless ( $rule_itemtype ) {
519
            unless ( $type ) {
523
                next if grep {$_ eq $itemtype} @types;
520
                next if grep {$_ eq $itemtype} @types;
524
            } else {
521
            } else {
525
                next unless grep {$_ eq $itemtype} @types;
522
                next unless grep {$_ eq $itemtype} @types;
Lines 538-557 sub TooMany { Link Here
538
            checkout_count               => $checkout_count,
535
            checkout_count               => $checkout_count,
539
            onsite_checkout_count        => $onsite_checkout_count,
536
            onsite_checkout_count        => $onsite_checkout_count,
540
            onsite_checkout              => $onsite_checkout,
537
            onsite_checkout              => $onsite_checkout,
541
            max_checkouts_allowed        => $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef,
538
            max_checkouts_allowed        => $maxissueqty,,
542
            max_onsite_checkouts_allowed => $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef,
539
            max_onsite_checkouts_allowed => $maxonsiteissueqty,
543
            switch_onsite_checkout       => $switch_onsite_checkout,
540
            switch_onsite_checkout       => $switch_onsite_checkout,
544
        };
541
        };
545
        # If parent rules exists
542
        # If parent rules exists
546
        if ( defined($parent_maxissueqty_rule) and defined($parent_maxissueqty_rule->rule_value) ){
543
        if ( defined $parent_maxissueqty ){
547
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty_rule ? $parent_maxissueqty_rule->rule_value : undef;
544
            $checkout_rules->{max_checkouts_allowed} = $parent_maxissueqty;
548
            my $qty_over = _check_max_qty($checkout_rules);
545
            my $qty_over = _check_max_qty($checkout_rules);
549
            return $qty_over if defined $qty_over;
546
            return $qty_over if defined $qty_over;
550
547
551
            # If the parent rule is less than or equal to the child, we only need check the parent
548
            # If the parent rule is less than or equal to the child, we only need check the parent
552
            if( $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value && defined($maxissueqty_rule->itemtype) ) {
549
            if( $maxissueqty < $parent_maxissueqty && defined($type) ) {
553
                $checkout_rules->{checkout_count} = $checkout_count_type;
550
                $checkout_rules->{checkout_count} = $checkout_count_type;
554
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef;
551
                $checkout_rules->{max_checkouts_allowed} = $maxissueqty;
555
                my $qty_over = _check_max_qty($checkout_rules);
552
                my $qty_over = _check_max_qty($checkout_rules);
556
                return $qty_over if defined $qty_over;
553
                return $qty_over if defined $qty_over;
557
            }
554
            }
Lines 595-601 sub TooMany { Link Here
595
        return $qty_over if defined $qty_over;
592
        return $qty_over if defined $qty_over;
596
    }
593
    }
597
594
598
    if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) {
595
    unless ( defined $maxissueqty || defined $branch_borrower_circ_rule->{patron_maxissueqty} ) {
599
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
596
        return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
600
    }
597
    }
601
598
Lines 1922-1949 wildcards. Link Here
1922
1919
1923
sub GetBranchBorrowerCircRule {
1920
sub GetBranchBorrowerCircRule {
1924
    my ( $branchcode, $categorycode ) = @_;
1921
    my ( $branchcode, $categorycode ) = @_;
1925
1922
    return Koha::CirculationRules->get_effective_rules(
1926
    # Initialize default values
1923
        {
1927
    my $rules = {
1924
            categorycode => $categorycode,
1928
        patron_maxissueqty       => undef,
1925
            itemtype     => undef,
1929
        patron_maxonsiteissueqty => undef,
1926
            branchcode   => $branchcode,
1930
    };
1927
            rules => ['patron_maxissueqty', 'patron_maxonsiteissueqty']
1931
1928
        }
1932
    # Search for rules!
1929
    );
1933
    foreach my $rule_name (qw( patron_maxissueqty patron_maxonsiteissueqty )) {
1934
        my $rule = Koha::CirculationRules->get_effective_rule(
1935
            {
1936
                categorycode => $categorycode,
1937
                itemtype     => undef,
1938
                branchcode   => $branchcode,
1939
                rule_name    => $rule_name,
1940
            }
1941
        );
1942
1943
        $rules->{$rule_name} = $rule->rule_value if defined $rule;
1944
    }
1945
1946
    return $rules;
1947
}
1930
}
1948
1931
1949
=head2 GetBranchItemRule
1932
=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 438-444 sub CanItemBeReserved { Link Here
438
    }
438
    }
439
439
440
    my $dbh = C4::Context->dbh;
440
    my $dbh = C4::Context->dbh;
441
    my $ruleitemtype;    # itemtype of the matching issuing rule
441
    my $effective_itemtype = $item->effective_itemtype;
442
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
442
    my $allowedreserves  = 0; # Total number of holds allowed across all records, default to none
443
443
444
    # We check item branch if IndependentBranches is ON
444
    # We check item branch if IndependentBranches is ON
Lines 479-486 sub CanItemBeReserved { Link Here
479
    }
479
    }
480
480
481
    # check if a recall exists on this item from this borrower
481
    # check if a recall exists on this item from this borrower
482
    return _cache { status => 'recall' }
482
    if (
483
      if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count;
483
        C4::Context->preference('UseRecalls') &&
484
        $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count
485
    ) {
486
        return _cache { status => 'recall' };
487
    }
484
488
485
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
489
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
486
490
Lines 497-527 sub CanItemBeReserved { Link Here
497
    }
501
    }
498
502
499
    # we retrieve rights
503
    # we retrieve rights
500
    if (
504
    #undefined is 0, blank is unlimited
501
        my $reservesallowed = Koha::CirculationRules->get_effective_rule({
505
    $allowedreserves = Koha::CirculationRules->get_effective_rule_value({
502
                itemtype     => $item->effective_itemtype,
506
        itemtype     => $effective_itemtype,
503
                categorycode => $borrower->{categorycode},
507
        categorycode => $borrower->{categorycode},
504
                branchcode   => $reserves_control_branch,
508
        branchcode   => $reserves_control_branch,
505
                rule_name    => 'reservesallowed',
509
        rule_name    => 'reservesallowed'
506
        })
510
    }) // 0;
507
    ) {
508
        $ruleitemtype     = $reservesallowed->itemtype;
509
        $allowedreserves  = $reservesallowed->rule_value // 0; #undefined is 0, blank is unlimited
510
    }
511
    else {
512
        $ruleitemtype = undef;
513
    }
514
511
515
    my $rights = Koha::CirculationRules->get_effective_rules({
512
    my $rights = Koha::CirculationRules->get_effective_rules({
516
        categorycode => $borrower->{'categorycode'},
513
        categorycode => $borrower->{'categorycode'},
517
        itemtype     => $item->effective_itemtype,
514
        itemtype     => $effective_itemtype,
518
        branchcode   => $reserves_control_branch,
515
        branchcode   => $reserves_control_branch,
519
        rules        => ['holds_per_record','holds_per_day']
516
        rules        => ['holds_per_record', 'holds_per_day']
520
    });
517
    });
521
    my $holds_per_record = $rights->{holds_per_record} // 1;
518
    my $holds_per_record = $rights->{holds_per_record} // 1;
522
    my $holds_per_day    = $rights->{holds_per_day};
519
    my $holds_per_day    = $rights->{holds_per_day};
523
520
524
    if (   defined $holds_per_record && $holds_per_record ne '' ){
521
    if ( defined $holds_per_record && $holds_per_record ne '' ){
525
        if ( $holds_per_record == 0 ) {
522
        if ( $holds_per_record == 0 ) {
526
            return _cache { status => "noReservesAllowed" };
523
            return _cache { status => "noReservesAllowed" };
527
        }
524
        }
Lines 545-552 sub CanItemBeReserved { Link Here
545
    }
542
    }
546
543
547
    # we check if it's ok or not
544
    # we check if it's ok or not
548
    if ( defined $allowedreserves && $allowedreserves ne '' ){
545
    if ( $allowedreserves ne '' ) {
549
        if( $allowedreserves == 0 ){
546
        if( $allowedreserves == 0 ) {
550
            return _cache { status => 'noReservesAllowed' };
547
            return _cache { status => 'noReservesAllowed' };
551
        }
548
        }
552
        if ( !$params->{ignore_hold_counts} ) {
549
        if ( !$params->{ignore_hold_counts} ) {
Lines 563-593 sub CanItemBeReserved { Link Here
563
560
564
            # If using item-level itypes, fall back to the record
561
            # If using item-level itypes, fall back to the record
565
            # level itemtype if the hold has no associated item
562
            # level itemtype if the hold has no associated item
566
            if ( defined $ruleitemtype ) {
563
            if ( C4::Context->preference('item-level_itypes') ) {
567
                if ( C4::Context->preference('item-level_itypes') ) {
564
                $querycount .= q{
568
                    $querycount .= q{
565
                    AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
569
                        AND ( COALESCE( items.itype, biblioitems.itemtype ) = ?
566
                    OR reserves.itemtype = ? )
570
                           OR reserves.itemtype = ? )
567
                };
571
                    };
572
                }
573
                else {
574
                    $querycount .= q{
575
                        AND ( biblioitems.itemtype = ?
576
                           OR reserves.itemtype = ? )
577
                    };
578
                }
579
            }
580
581
            my $sthcount = $dbh->prepare($querycount);
582
583
            if ( defined $ruleitemtype ) {
584
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $ruleitemtype, $ruleitemtype );
585
            }
568
            }
586
            else {
569
            else {
587
                $sthcount->execute( $patron->borrowernumber, $reserves_control_branch );
570
                $querycount .= q{
571
                    AND ( biblioitems.itemtype = ?
572
                    OR reserves.itemtype = ? )
573
                };
588
            }
574
            }
589
575
590
            my $reservecount = "0";
576
            my $sthcount = $dbh->prepare($querycount);
577
            $sthcount->execute( $patron->borrowernumber, $reserves_control_branch, $effective_itemtype, $effective_itemtype );
578
579
            my $reservecount = 0;
591
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
580
            if ( my $rowcount = $sthcount->fetchrow_hashref() ) {
592
                $reservecount = $rowcount->{count};
581
                $reservecount = $rowcount->{count};
593
            }
582
            }
Lines 597-621 sub CanItemBeReserved { Link Here
597
    }
586
    }
598
587
599
    # Now we need to check hold limits by patron category
588
    # Now we need to check hold limits by patron category
600
    my $rule = Koha::CirculationRules->get_effective_rule(
589
    my $max_holds = Koha::CirculationRules->get_effective_rule_value(
601
        {
590
        {
602
            categorycode => $patron->categorycode,
591
            categorycode => $patron->categorycode,
603
            branchcode   => $reserves_control_branch,
592
            branchcode   => $reserves_control_branch,
604
            rule_name    => 'max_holds',
593
            rule_name    => 'max_holds',
605
        }
594
        }
606
    );
595
    );
607
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
596
    if (!$params->{ignore_hold_counts} && defined $max_holds && $max_holds ne '' ) {
608
        my $total_holds_count = Koha::Holds->search(
597
        my $total_holds_count = Koha::Holds->search(
609
            {
598
            {
610
                borrowernumber => $patron->borrowernumber
599
                borrowernumber => $patron->borrowernumber
611
            }
600
            }
612
        )->count();
601
        )->count();
613
602
614
        return _cache { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value;
603
        return _cache { status => 'tooManyReserves', limit => $max_holds } if $total_holds_count >= $max_holds;
615
    }
604
    }
616
605
617
    my $branchitemrule =
606
    my $branchitemrule =
618
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype );
607
      C4::Circulation::GetBranchItemRule( $reserves_control_branch, $effective_itemtype );
619
608
620
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
609
    if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) {
621
        return _cache { status => 'notReservable' };
610
        return _cache { status => 'notReservable' };
Lines 2281-2293 sub GetMaxPatronHoldsForRecord { Link Here
2281
2270
2282
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2271
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2283
2272
2284
        my $rule = Koha::CirculationRules->get_effective_rule({
2273
        my $holds_per_record = Koha::CirculationRules->get_effective_rule_value({
2285
            categorycode => $categorycode,
2274
            categorycode => $categorycode,
2286
            itemtype     => $itemtype,
2275
            itemtype     => $itemtype,
2287
            branchcode   => $branchcode,
2276
            branchcode   => $branchcode,
2288
            rule_name    => 'holds_per_record'
2277
            rule_name    => 'holds_per_record'
2289
        });
2278
        }) // 0;
2290
        my $holds_per_record = $rule ? $rule->rule_value : 0;
2291
        $max = $holds_per_record if $holds_per_record > $max;
2279
        $max = $holds_per_record if $holds_per_record > $max;
2292
    }
2280
    }
2293
2281
(-)a/Koha/Biblio.pm (-12 / +6 lines)
Lines 369-384 $borrower must be a Koha::Patron object Link Here
369
sub article_request_type {
369
sub article_request_type {
370
    my ( $self, $borrower ) = @_;
370
    my ( $self, $borrower ) = @_;
371
371
372
    return q{} unless $borrower;
372
    return unless $borrower;
373
373
374
    my $rule = $self->article_request_type_for_items( $borrower );
374
    my $type = $self->article_request_type_for_items( $borrower );
375
    return $rule if $rule;
375
    return $type if $type;
376
376
377
    # If the record has no items that are requestable, go by the record itemtype
377
    # If the record has no items that are requestable, go by the record itemtype
378
    $rule = $self->article_request_type_for_bib($borrower);
378
    return $self->article_request_type_for_bib($borrower);
379
    return $rule if $rule;
380
381
    return q{};
382
}
379
}
383
380
384
=head3 article_request_type_for_bib
381
=head3 article_request_type_for_bib
Lines 392-412 Returns the article request type 'yes', 'no', 'item_only', 'bib_only', for the g Link Here
392
sub article_request_type_for_bib {
389
sub article_request_type_for_bib {
393
    my ( $self, $borrower ) = @_;
390
    my ( $self, $borrower ) = @_;
394
391
395
    return q{} unless $borrower;
392
    return unless $borrower;
396
393
397
    my $borrowertype = $borrower->categorycode;
394
    my $borrowertype = $borrower->categorycode;
398
    my $itemtype     = $self->itemtype();
395
    my $itemtype     = $self->itemtype();
399
396
400
    my $rule = Koha::CirculationRules->get_effective_rule(
397
    return Koha::CirculationRules->get_effective_rule_value(
401
        {
398
        {
402
            rule_name    => 'article_requests',
399
            rule_name    => 'article_requests',
403
            categorycode => $borrowertype,
400
            categorycode => $borrowertype,
404
            itemtype     => $itemtype,
401
            itemtype     => $itemtype,
405
        }
402
        }
406
    );
403
    );
407
408
    return q{} unless $rule;
409
    return $rule->rule_value || q{}
410
}
404
}
411
405
412
=head3 article_request_type_for_items
406
=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 307-319 sub get_effective_rule_value { Link Here
307
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
307
    my $cache_key = sprintf "CircRules:%s:%s:%s:%s", $rule_name // q{},
308
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
308
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
309
309
310
    my $cached       = $memory_cache->get_from_cache($cache_key);
310
    my $value = $memory_cache->get_from_cache($cache_key);
311
    return $cached if $cached;
311
    unless (defined $value) {
312
312
        my $rule = $self->get_effective_rule($params);
313
    my $rule = $self->get_effective_rule($params);
313
        if ($rule) {
314
314
            $value = $rule->rule_value;
315
    my $value= $rule ? $rule->rule_value : undef;
315
        }
316
    $memory_cache->set_in_cache( $cache_key, $value );
316
        $value //= 'undef';
317
        $memory_cache->set_in_cache( $cache_key, $value );
318
    }
319
    return if $value eq 'undef';
317
    return $value;
320
    return $value;
318
}
321
}
319
322
Lines 551-557 sub get_opacitemholds_policy { Link Here
551
554
552
    return unless $item or $patron;
555
    return unless $item or $patron;
553
556
554
    my $rule = Koha::CirculationRules->get_effective_rule(
557
    return Koha::CirculationRules->get_effective_rule_value(
555
        {
558
        {
556
            categorycode => $patron->categorycode,
559
            categorycode => $patron->categorycode,
557
            itemtype     => $item->effective_itemtype,
560
            itemtype     => $item->effective_itemtype,
Lines 559-566 sub get_opacitemholds_policy { Link Here
559
            rule_name    => 'opacitemholds',
562
            rule_name    => 'opacitemholds',
560
        }
563
        }
561
    );
564
    );
562
563
    return $rule ? $rule->rule_value : undef;
564
}
565
}
565
566
566
=head3 get_onshelfholds_policy
567
=head3 get_onshelfholds_policy
Lines 574-588 sub get_onshelfholds_policy { Link Here
574
    my $item = $params->{item};
575
    my $item = $params->{item};
575
    my $itemtype = $item->effective_itemtype;
576
    my $itemtype = $item->effective_itemtype;
576
    my $patron = $params->{patron};
577
    my $patron = $params->{patron};
577
    my $rule = Koha::CirculationRules->get_effective_rule(
578
    return Koha::CirculationRules->get_effective_rule_value(
578
        {
579
        {
579
            categorycode => ( $patron ? $patron->categorycode : undef ),
580
            categorycode => ( $patron ? $patron->categorycode : undef ),
580
            itemtype     => $itemtype,
581
            itemtype     => $itemtype,
581
            branchcode   => $item->holdingbranch,
582
            branchcode   => $item->holdingbranch,
582
            rule_name    => 'onshelfholds',
583
            rule_name    => 'onshelfholds',
583
        }
584
        }
584
    );
585
    ) // 0;
585
    return $rule ? $rule->rule_value : 0;
586
}
586
}
587
587
588
=head3 get_lostreturn_policy
588
=head3 get_lostreturn_policy
Lines 637-643 sub get_lostreturn_policy { Link Here
637
    my $rules = Koha::CirculationRules->get_effective_rules(
637
    my $rules = Koha::CirculationRules->get_effective_rules(
638
        {
638
        {
639
            branchcode => $branch,
639
            branchcode => $branch,
640
            rules  => ['lostreturn','processingreturn']
640
            rules  => ['lostreturn', 'processingreturn']
641
        }
641
        }
642
    );
642
    );
643
643
Lines 724-730 sub get_effective_daysmode { Link Here
724
    my $itemtype         = $params->{itemtype};
724
    my $itemtype         = $params->{itemtype};
725
    my $branchcode       = $params->{branchcode};
725
    my $branchcode       = $params->{branchcode};
726
726
727
    my $daysmode_rule = $class->get_effective_rule(
727
    my $daysmode = $class->get_effective_rule_value(
728
        {
728
        {
729
            categorycode => $categorycode,
729
            categorycode => $categorycode,
730
            itemtype     => $itemtype,
730
            itemtype     => $itemtype,
Lines 732-743 sub get_effective_daysmode { Link Here
732
            rule_name    => 'daysmode',
732
            rule_name    => 'daysmode',
733
        }
733
        }
734
    );
734
    );
735
735
    return $daysmode || C4::Context->preference('useDaysMode');
736
    return ( defined($daysmode_rule)
737
          and $daysmode_rule->rule_value ne '' )
738
      ? $daysmode_rule->rule_value
739
      : C4::Context->preference('useDaysMode');
740
741
}
736
}
742
737
743
738
(-)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 1217-1223 sub can_request_article { Link Here
1217
1217
1218
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1218
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1219
1219
1220
    my $rule = Koha::CirculationRules->get_effective_rule(
1220
    my $limit = Koha::CirculationRules->get_effective_rule_value(
1221
        {
1221
        {
1222
            branchcode   => $library_id,
1222
            branchcode   => $library_id,
1223
            categorycode => $self->categorycode,
1223
            categorycode => $self->categorycode,
Lines 1225-1232 sub can_request_article { Link Here
1225
        }
1225
        }
1226
    );
1226
    );
1227
1227
1228
    my $limit = ($rule) ? $rule->rule_value : undef;
1229
1230
    return 1 unless defined $limit;
1228
    return 1 unless defined $limit;
1231
1229
1232
    my $count = Koha::ArticleRequests->search(
1230
    my $count = Koha::ArticleRequests->search(
Lines 1258-1272 sub article_request_fee { Link Here
1258
1256
1259
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1257
    $library_id //= C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
1260
1258
1261
    my $rule = Koha::CirculationRules->get_effective_rule(
1259
    my $fee = Koha::CirculationRules->get_effective_rule_value(
1262
        {
1260
        {
1263
            branchcode   => $library_id,
1261
            branchcode   => $library_id,
1264
            categorycode => $self->categorycode,
1262
            categorycode => $self->categorycode,
1265
            rule_name    => 'article_request_fee'
1263
            rule_name    => 'article_request_fee'
1266
        }
1264
        }
1267
    );
1265
    ) + 0;
1268
1269
    my $fee = ($rule) ? $rule->rule_value + 0 : 0;
1270
1266
1271
    return $fee;
1267
    return $fee;
1272
}
1268
}
(-)a/Koha/REST/V1/Checkouts.pm (-3 / +3 lines)
Lines 396-414 sub allows_renewal { Link Here
396
        my $renewable = Mojo::JSON->false;
396
        my $renewable = Mojo::JSON->false;
397
        $renewable = Mojo::JSON->true if $can_renew;
397
        $renewable = Mojo::JSON->true if $can_renew;
398
398
399
        my $rule = Koha::CirculationRules->get_effective_rule(
399
        my $renewalsallowed = Koha::CirculationRules->get_effective_rule_value(
400
            {
400
            {
401
                categorycode => $checkout->patron->categorycode,
401
                categorycode => $checkout->patron->categorycode,
402
                itemtype     => $checkout->item->effective_itemtype,
402
                itemtype     => $checkout->item->effective_itemtype,
403
                branchcode   => $checkout->branchcode,
403
                branchcode   => $checkout->branchcode,
404
                rule_name    => 'renewalsallowed',
404
                rule_name    => 'renewalsallowed'
405
            }
405
            }
406
        );
406
        );
407
        return $c->render(
407
        return $c->render(
408
            status => 200,
408
            status => 200,
409
            openapi => {
409
            openapi => {
410
                allows_renewal => $renewable,
410
                allows_renewal => $renewable,
411
                max_renewals => $rule->rule_value,
411
                max_renewals => $renewalsallowed,
412
                current_renewals => $checkout->renewals_count,
412
                current_renewals => $checkout->renewals_count,
413
                unseen_renewals => $checkout->unseen_renewals,
413
                unseen_renewals => $checkout->unseen_renewals,
414
                error => $error
414
                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 (-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 $checkout_timestamp = dt_from_string( $checkout->date_due );
144
        my $checkout_timestamp = dt_from_string( $checkout->date_due );
146
        my $due_date = $timestamp->set(
145
        my $due_date = $timestamp->set(
(-)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