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

(-)a/C4/Circulation.pm (-98 / +104 lines)
Lines 2672-2677 sub CanBookBeRenewed { Link Here
2672
2672
2673
    my $dbh    = C4::Context->dbh;
2673
    my $dbh    = C4::Context->dbh;
2674
    my $renews = 1;
2674
    my $renews = 1;
2675
    my $auto_renew = 0;
2675
2676
2676
    my $item      = Koha::Items->find($itemnumber)      or return ( 0, 'no_item' );
2677
    my $item      = Koha::Items->find($itemnumber)      or return ( 0, 'no_item' );
2677
    my $issue = $item->checkout or return ( 0, 'no_checkout' );
2678
    my $issue = $item->checkout or return ( 0, 'no_checkout' );
Lines 2680-2685 sub CanBookBeRenewed { Link Here
2680
2681
2681
    my $patron = $issue->patron or return;
2682
    my $patron = $issue->patron or return;
2682
2683
2684
    # override_limit will override anything else except on_reserve
2685
    unless ( $override_limit ){
2686
        my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2687
        my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2688
            {
2689
                categorycode => $patron->categorycode,
2690
                itemtype     => $item->effective_itemtype,
2691
                branchcode   => $branchcode,
2692
            }
2693
        );
2694
2695
        return ( 0, "too_many" )
2696
          if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2697
2698
        my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2699
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2700
        $patron         = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful?
2701
        my $restricted  = $patron->is_debarred;
2702
        my $hasoverdues = $patron->has_overdues;
2703
2704
        if ( $restricted and $restrictionblockrenewing ) {
2705
            return ( 0, 'restriction');
2706
        } elsif ( ($hasoverdues and $overduesblockrenewing eq 'block') || ($issue->is_overdue and $overduesblockrenewing eq 'blockitem') ) {
2707
            return ( 0, 'overdue');
2708
        }
2709
2710
        if ( $issue->auto_renew ) {
2711
2712
            if ( $patron->category->effective_BlockExpiredPatronOpacActions and $patron->is_expired ) {
2713
                return ( 0, 'auto_account_expired' );
2714
            }
2715
2716
            if ( defined $issuing_rule->no_auto_renewal_after
2717
                    and $issuing_rule->no_auto_renewal_after ne "" ) {
2718
                # Get issue_date and add no_auto_renewal_after
2719
                # If this is greater than today, it's too late for renewal.
2720
                my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2721
                $maximum_renewal_date->add(
2722
                    $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2723
                );
2724
                my $now = dt_from_string;
2725
                if ( $now >= $maximum_renewal_date ) {
2726
                    return ( 0, "auto_too_late" );
2727
                }
2728
            }
2729
            if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2730
                          and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2731
                # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2732
                if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2733
                    return ( 0, "auto_too_late" );
2734
                }
2735
            }
2736
2737
            if ( C4::Context->preference('OPACFineNoRenewalsBlockAutoRenew') ) {
2738
                my $fine_no_renewals = C4::Context->preference("OPACFineNoRenewals");
2739
                my $amountoutstanding =
2740
                  C4::Context->preference("OPACFineNoRenewalsIncludeCredit")
2741
                  ? $patron->account->balance
2742
                  : $patron->account->outstanding_debits->total_outstanding;
2743
                if ( $amountoutstanding and $amountoutstanding > $fine_no_renewals ) {
2744
                    return ( 0, "auto_too_much_oweing" );
2745
                }
2746
            }
2747
        }
2748
2749
        if ( defined $issuing_rule->norenewalbefore
2750
            and $issuing_rule->norenewalbefore ne "" )
2751
        {
2752
2753
            # Calculate soonest renewal by subtracting 'No renewal before' from due date
2754
            my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2755
                $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2756
2757
            # Depending on syspref reset the exact time, only check the date
2758
            if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2759
                and $issuing_rule->lengthunit eq 'days' )
2760
            {
2761
                $soonestrenewal->truncate( to => 'day' );
2762
            }
2763
2764
            if ( $soonestrenewal > DateTime->now( time_zone => C4::Context->tz() ) )
2765
            {
2766
                return ( 0, "auto_too_soon" ) if $issue->auto_renew;
2767
                return ( 0, "too_soon" );
2768
            }
2769
            elsif ( $issue->auto_renew ) {
2770
                $auto_renew = 1;
2771
            }
2772
        }
2773
2774
        # Fallback for automatic renewals:
2775
        # If norenewalbefore is undef, don't renew before due date.
2776
        if ( $issue->auto_renew && !$auto_renew ) {
2777
            my $now = dt_from_string;
2778
            if ( $now >= dt_from_string( $issue->date_due, 'sql' ) ){
2779
                $auto_renew = 1;
2780
            } else {
2781
                return ( 0, "auto_too_soon" );
2782
            }
2783
        }
2784
    }
2785
2683
    my ( $resfound, $resrec, undef ) = C4::Reserves::CheckReserves($itemnumber);
2786
    my ( $resfound, $resrec, undef ) = C4::Reserves::CheckReserves($itemnumber);
2684
2787
2685
    # This item can fill one or more unfilled reserve, can those unfilled reserves
2788
    # This item can fill one or more unfilled reserve, can those unfilled reserves
Lines 2746-2849 sub CanBookBeRenewed { Link Here
2746
        }
2849
        }
2747
    }
2850
    }
2748
    return ( 0, "on_reserve" ) if $resfound;    # '' when no hold was found
2851
    return ( 0, "on_reserve" ) if $resfound;    # '' when no hold was found
2749
2852
    return ( 0, "auto_renew" ) if $auto_renew && !$override_limit; # 0 if auto-renewal should not succeed
2750
    return ( 1, undef ) if $override_limit;
2751
2752
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2753
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2754
        {   categorycode => $patron->categorycode,
2755
            itemtype     => $item->effective_itemtype,
2756
            branchcode   => $branchcode
2757
        }
2758
    );
2759
2760
    return ( 0, "too_many" )
2761
      if not $issuing_rule or $issuing_rule->renewalsallowed <= $issue->renewals;
2762
2763
    my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2764
    my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2765
    $patron         = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful?
2766
    my $restricted  = $patron->is_debarred;
2767
    my $hasoverdues = $patron->has_overdues;
2768
2769
    if ( $restricted and $restrictionblockrenewing ) {
2770
        return ( 0, 'restriction');
2771
    } elsif ( ($hasoverdues and $overduesblockrenewing eq 'block') || ($issue->is_overdue and $overduesblockrenewing eq 'blockitem') ) {
2772
        return ( 0, 'overdue');
2773
    }
2774
2775
    if ( $issue->auto_renew ) {
2776
2777
        if ( $patron->category->effective_BlockExpiredPatronOpacActions and $patron->is_expired ) {
2778
            return ( 0, 'auto_account_expired' );
2779
        }
2780
2781
        if ( defined $issuing_rule->no_auto_renewal_after
2782
                and $issuing_rule->no_auto_renewal_after ne "" ) {
2783
            # Get issue_date and add no_auto_renewal_after
2784
            # If this is greater than today, it's too late for renewal.
2785
            my $maximum_renewal_date = dt_from_string($issue->issuedate, 'sql');
2786
            $maximum_renewal_date->add(
2787
                $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
2788
            );
2789
            my $now = dt_from_string;
2790
            if ( $now >= $maximum_renewal_date ) {
2791
                return ( 0, "auto_too_late" );
2792
            }
2793
        }
2794
        if ( defined $issuing_rule->no_auto_renewal_after_hard_limit
2795
                      and $issuing_rule->no_auto_renewal_after_hard_limit ne "" ) {
2796
            # If no_auto_renewal_after_hard_limit is >= today, it's also too late for renewal
2797
            if ( dt_from_string >= dt_from_string( $issuing_rule->no_auto_renewal_after_hard_limit ) ) {
2798
                return ( 0, "auto_too_late" );
2799
            }
2800
        }
2801
2802
        if ( C4::Context->preference('OPACFineNoRenewalsBlockAutoRenew') ) {
2803
            my $fine_no_renewals = C4::Context->preference("OPACFineNoRenewals");
2804
            my $amountoutstanding =
2805
              C4::Context->preference("OPACFineNoRenewalsIncludeCredit")
2806
              ? $patron->account->balance
2807
              : $patron->account->outstanding_debits->total_outstanding;
2808
            if ( $amountoutstanding and $amountoutstanding > $fine_no_renewals ) {
2809
                return ( 0, "auto_too_much_oweing" );
2810
            }
2811
        }
2812
    }
2813
2814
    if ( defined $issuing_rule->norenewalbefore
2815
        and $issuing_rule->norenewalbefore ne "" )
2816
    {
2817
2818
        # Calculate soonest renewal by subtracting 'No renewal before' from due date
2819
        my $soonestrenewal = dt_from_string( $issue->date_due, 'sql' )->subtract(
2820
            $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
2821
2822
        # Depending on syspref reset the exact time, only check the date
2823
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
2824
            and $issuing_rule->lengthunit eq 'days' )
2825
        {
2826
            $soonestrenewal->truncate( to => 'day' );
2827
        }
2828
2829
        if ( $soonestrenewal > DateTime->now( time_zone => C4::Context->tz() ) )
2830
        {
2831
            return ( 0, "auto_too_soon" ) if $issue->auto_renew;
2832
            return ( 0, "too_soon" );
2833
        }
2834
        elsif ( $issue->auto_renew ) {
2835
            return ( 0, "auto_renew" );
2836
        }
2837
    }
2838
2839
    # Fallback for automatic renewals:
2840
    # If norenewalbefore is undef, don't renew before due date.
2841
    if ( $issue->auto_renew ) {
2842
        my $now = dt_from_string;
2843
        return ( 0, "auto_renew" )
2844
          if $now >= dt_from_string( $issue->date_due, 'sql' );
2845
        return ( 0, "auto_too_soon" );
2846
    }
2847
2853
2848
    return ( 1, undef );
2854
    return ( 1, undef );
2849
}
2855
}
(-)a/t/db_dependent/Circulation.t (-2 / +19 lines)
Lines 277-283 $dbh->do( Link Here
277
277
278
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
278
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
279
subtest "CanBookBeRenewed tests" => sub {
279
subtest "CanBookBeRenewed tests" => sub {
280
    plan tests => 71;
280
    plan tests => 77;
281
281
282
    C4::Context->set_preference('ItemsDeniedRenewal','');
282
    C4::Context->set_preference('ItemsDeniedRenewal','');
283
    # Generate test biblio
283
    # Generate test biblio
Lines 606-611 subtest "CanBookBeRenewed tests" => sub { Link Here
606
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
606
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
607
    is( $error, 'auto_too_soon',
607
    is( $error, 'auto_too_soon',
608
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = undef (returned code is auto_too_soon)' );
608
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = undef (returned code is auto_too_soon)' );
609
    AddReserve(
610
        $branch, $reserving_borrowernumber, $biblio->biblionumber,
611
        $bibitems,  $priority, $resdate, $expdate, $notes,
612
        'a title', $item_4->itemnumber, $found
613
    );
614
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
615
    is( $renewokay, 0, 'Still should not be able to renew' );
616
    is( $error, 'auto_too_soon', 'returned code is auto_too_soon, reserve not checked' );
617
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, 1 );
618
    is( $renewokay, 0, 'Still should not be able to renew' );
619
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_too_soon limit is overridden' );
620
    $dbh->do('UPDATE circulation_rules SET rule_value = 0 where rule_name = "norenewalbefore"');
621
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, 1 );
622
    is( $renewokay, 0, 'Still should not be able to renew' );
623
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_renew only happens if not on reserve' );
624
    ModReserveCancelAll($item_4->itemnumber, $reserving_borrowernumber);
625
626
609
627
610
    # Bug 7413
628
    # Bug 7413
611
    # Test premature manual renewal
629
    # Test premature manual renewal
612
- 

Return to bug 19014