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

(-)a/C4/Circulation.pm (-80 / +74 lines)
Lines 65-71 use Koha::Plugins; Link Here
65
use Koha::Recalls;
65
use Koha::Recalls;
66
use Carp qw( carp );
66
use Carp qw( carp );
67
use List::MoreUtils qw( any );
67
use List::MoreUtils qw( any );
68
use Scalar::Util qw( looks_like_number );
68
use Scalar::Util qw( looks_like_number blessed );
69
use Date::Calc qw( Date_to_Days );
69
use Date::Calc qw( Date_to_Days );
70
our (@ISA, @EXPORT_OK);
70
our (@ISA, @EXPORT_OK);
71
BEGIN {
71
BEGIN {
Lines 369-375 sub transferbook { Link Here
369
    }
369
    }
370
370
371
    # check if it is still issued to someone, return it...
371
    # check if it is still issued to someone, return it...
372
    my $issue = Koha::Checkouts->find({ itemnumber => $itemnumber });
372
    my $issue = $item->checkout;
373
    if ( $issue ) {
373
    if ( $issue ) {
374
        AddReturn( $barcode, $fbr );
374
        AddReturn( $barcode, $fbr );
375
        $messages->{'WasReturned'} = $issue->borrowernumber;
375
        $messages->{'WasReturned'} = $issue->borrowernumber;
Lines 378-384 sub transferbook { Link Here
378
    # find reserves.....
378
    # find reserves.....
379
    # That'll save a database query.
379
    # That'll save a database query.
380
    my ( $resfound, $resrec, undef ) =
380
    my ( $resfound, $resrec, undef ) =
381
      CheckReserves( $itemnumber );
381
      CheckReserves( $item );
382
    if ( $resfound ) {
382
    if ( $resfound ) {
383
        $resrec->{'ResFound'} = $resfound;
383
        $resrec->{'ResFound'} = $resfound;
384
        $messages->{'ResFound'} = $resrec;
384
        $messages->{'ResFound'} = $resrec;
Lines 952-961 sub CanBookBeIssued { Link Here
952
                and C4::Context->preference('SwitchOnSiteCheckouts') ) {
952
                and C4::Context->preference('SwitchOnSiteCheckouts') ) {
953
            $messages{ONSITE_CHECKOUT_WILL_BE_SWITCHED} = 1;
953
            $messages{ONSITE_CHECKOUT_WILL_BE_SWITCHED} = 1;
954
        } else {
954
        } else {
955
            my ($CanBookBeRenewed,$renewerror) = CanBookBeRenewed(
955
            my ($CanBookBeRenewed,$renewerror) = CanBookBeRenewed($patron, $issue);
956
                $patron->borrowernumber,
957
                $item_object->itemnumber,
958
            );
959
            if ( $CanBookBeRenewed == 0 ) {    # no more renewals allowed
956
            if ( $CanBookBeRenewed == 0 ) {    # no more renewals allowed
960
                if ( $renewerror eq 'onsite_checkout' ) {
957
                if ( $renewerror eq 'onsite_checkout' ) {
961
                    $issuingimpossible{NO_RENEWAL_FOR_ONSITE_CHECKOUTS} = 1;
958
                    $issuingimpossible{NO_RENEWAL_FOR_ONSITE_CHECKOUTS} = 1;
Lines 977-994 sub CanBookBeIssued { Link Here
977
974
978
        my ( $can_be_returned, $message ) = CanBookBeReturned( $item_unblessed, C4::Context->userenv->{branch} );
975
        my ( $can_be_returned, $message ) = CanBookBeReturned( $item_unblessed, C4::Context->userenv->{branch} );
979
976
980
        unless ( $can_be_returned ) {
977
        if ( !$can_be_returned ) {
981
            $issuingimpossible{RETURN_IMPOSSIBLE} = 1;
978
            $issuingimpossible{RETURN_IMPOSSIBLE} = 1;
982
            $issuingimpossible{branch_to_return} = $message;
979
            $issuingimpossible{branch_to_return} = $message;
983
        } else {
980
        } else {
984
            if ( C4::Context->preference('AutoReturnCheckedOutItems') ) {
981
            if ( C4::Context->preference('AutoReturnCheckedOutItems') ) {
985
                $alerts{RETURNED_FROM_ANOTHER} = { patron => $patron };
982
                $alerts{RETURNED_FROM_ANOTHER} = { patron => $patron };
986
            } else {
983
            }
987
            $needsconfirmation{ISSUED_TO_ANOTHER} = 1;
984
            else {
988
            $needsconfirmation{issued_firstname} = $patron->firstname;
985
                $needsconfirmation{ISSUED_TO_ANOTHER} = 1;
989
            $needsconfirmation{issued_surname} = $patron->surname;
986
                $needsconfirmation{issued_firstname} = $patron->firstname;
990
            $needsconfirmation{issued_cardnumber} = $patron->cardnumber;
987
                $needsconfirmation{issued_surname} = $patron->surname;
991
            $needsconfirmation{issued_borrowernumber} = $patron->borrowernumber;
988
                $needsconfirmation{issued_cardnumber} = $patron->cardnumber;
989
                $needsconfirmation{issued_borrowernumber} = $patron->borrowernumber;
992
            }
990
            }
993
        }
991
        }
994
    }
992
    }
Lines 1021-1029 sub CanBookBeIssued { Link Here
1021
    # CHECKPREVCHECKOUT: CHECK IF ITEM HAS EVER BEEN LENT TO PATRON
1019
    # CHECKPREVCHECKOUT: CHECK IF ITEM HAS EVER BEEN LENT TO PATRON
1022
    #
1020
    #
1023
    $patron = Koha::Patrons->find( $patron->borrowernumber ); # FIXME Refetch just in case, to avoid regressions. But must not be needed
1021
    $patron = Koha::Patrons->find( $patron->borrowernumber ); # FIXME Refetch just in case, to avoid regressions. But must not be needed
1024
    my $wants_check = $patron->wants_check_for_previous_checkout;
1022
    if ($patron->do_check_for_previous_checkout($item_unblessed) && $patron->wants_check_for_previous_checkout) {
1025
    $needsconfirmation{PREVISSUE} = 1
1023
        $needsconfirmation{PREVISSUE} = 1;
1026
        if ($wants_check and $patron->do_check_for_previous_checkout($item_unblessed));
1024
    }
1027
1025
1028
    #
1026
    #
1029
    # ITEM CHECKING
1027
    # ITEM CHECKING
Lines 1161-1167 sub CanBookBeIssued { Link Here
1161
1159
1162
    unless ( $ignore_reserves and defined $recall ) {
1160
    unless ( $ignore_reserves and defined $recall ) {
1163
        # See if the item is on reserve.
1161
        # See if the item is on reserve.
1164
        my ( $restype, $res ) = C4::Reserves::CheckReserves( $item_object->itemnumber );
1162
        my ( $restype, $res ) = CheckReserves( $item_object );
1165
        if ($restype) {
1163
        if ($restype) {
1166
            my $resbor = $res->{'borrowernumber'};
1164
            my $resbor = $res->{'borrowernumber'};
1167
            if ( $resbor ne $patron->borrowernumber ) {
1165
            if ( $resbor ne $patron->borrowernumber ) {
Lines 2328-2334 sub AddReturn { Link Here
2328
    # launch the Checkreserves routine to find any holds
2326
    # launch the Checkreserves routine to find any holds
2329
    my ($resfound, $resrec);
2327
    my ($resfound, $resrec);
2330
    my $lookahead= C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2328
    my $lookahead= C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2331
    ($resfound, $resrec, undef) = C4::Reserves::CheckReserves( $item->itemnumber, undef, $lookahead ) unless ( $item->withdrawn );
2329
    ($resfound, $resrec, undef) = CheckReserves( $item, $lookahead ) unless ( $item->withdrawn );
2332
    # if a hold is found and is waiting at another branch, change the priority back to 1 and trigger the hold (this will trigger a transfer and update the hold status properly)
2330
    # if a hold is found and is waiting at another branch, change the priority back to 1 and trigger the hold (this will trigger a transfer and update the hold status properly)
2333
    if ( $resfound and $resfound eq "Waiting" and $branch ne $resrec->{branchcode} ) {
2331
    if ( $resfound and $resfound eq "Waiting" and $branch ne $resrec->{branchcode} ) {
2334
        my $hold = C4::Reserves::RevertWaitingStatus( { itemnumber => $item->itemnumber } );
2332
        my $hold = C4::Reserves::RevertWaitingStatus( { itemnumber => $item->itemnumber } );
Lines 2820-2833 sub GetUpcomingDueIssues { Link Here
2820
2818
2821
=head2 CanBookBeRenewed
2819
=head2 CanBookBeRenewed
2822
2820
2823
  ($ok,$error,$info) = &CanBookBeRenewed($borrowernumber, $itemnumber[, $override_limit]);
2821
  ($ok,$error,$info) = &CanBookBeRenewed($patron, $issue, $override_limit);
2824
2822
2825
Find out whether a borrowed item may be renewed.
2823
Find out whether a borrowed item may be renewed.
2826
2824
2827
C<$borrowernumber> is the borrower number of the patron who currently
2825
C<$patron> is the patron who currently has the issue.
2828
has the item on loan.
2829
2826
2830
C<$itemnumber> is the number of the item to renew.
2827
C<$issue> is the checkout to renew.
2831
2828
2832
C<$override_limit>, if supplied with a true value, causes
2829
C<$override_limit>, if supplied with a true value, causes
2833
the limit on the number of times that the loan can be renewed
2830
the limit on the number of times that the loan can be renewed
Lines 2846-2864 already renewed the loan. Link Here
2846
=cut
2843
=cut
2847
2844
2848
sub CanBookBeRenewed {
2845
sub CanBookBeRenewed {
2849
    my ( $borrowernumber, $itemnumber, $override_limit, $cron ) = @_;
2846
    my ( $patron, $issue, $override_limit, $cron ) = @_;
2850
2847
2851
    my $auto_renew = "no";
2848
    my $auto_renew = "no";
2852
    my $soonest;
2849
    my $soonest;
2850
    my $item = $issue->item;
2853
2851
2854
    my $item      = Koha::Items->find($itemnumber)      or return ( 0, 'no_item' );
2852
    return ( 0, 'no_item' ) unless $item;
2855
    my $issue = $item->checkout or return ( 0, 'no_checkout' );
2853
    return ( 0, 'no_checkout' ) unless $issue;
2856
    return ( 0, 'onsite_checkout' ) if $issue->onsite_checkout;
2854
    return ( 0, 'onsite_checkout' ) if $issue->onsite_checkout;
2855
    return ( 0, 'item_issued_to_other_patron') if $issue->borrowernumber != $patron->borrowernumber;
2857
    return ( 0, 'item_denied_renewal') if _item_denied_renewal({ item => $item });
2856
    return ( 0, 'item_denied_renewal') if _item_denied_renewal({ item => $item });
2858
2857
2859
    my $patron = $issue->patron or return;
2858
       # override_limit will override anything else except on_reserve
2860
2861
    # override_limit will override anything else except on_reserve
2862
    unless ( $override_limit ){
2859
    unless ( $override_limit ){
2863
        my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2860
        my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
2864
        my $issuing_rule = Koha::CirculationRules->get_effective_rules(
2861
        my $issuing_rule = Koha::CirculationRules->get_effective_rules(
Lines 2884-2890 sub CanBookBeRenewed { Link Here
2884
2881
2885
        my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2882
        my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
2886
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2883
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2887
        $patron         = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful?
2888
        my $restricted  = $patron->is_debarred;
2884
        my $restricted  = $patron->is_debarred;
2889
        my $hasoverdues = $patron->has_overdues;
2885
        my $hasoverdues = $patron->has_overdues;
2890
2886
Lines 2928-2936 sub CanBookBeRenewed { Link Here
2928
            non_priority => 0,
2924
            non_priority => 0,
2929
            found        => undef,
2925
            found        => undef,
2930
            reservedate  => { '<=' => \'NOW()' },
2926
            reservedate  => { '<=' => \'NOW()' },
2931
            suspend      => 0,
2927
            suspend      => 0
2932
        },
2928
        }
2933
        { prefetch => 'patron' }
2934
    );
2929
    );
2935
    if ( $fillable_holds->count ) {
2930
    if ( $fillable_holds->count ) {
2936
        if ( C4::Context->preference('AllowRenewalIfOtherItemsAvailable') ) {
2931
        if ( C4::Context->preference('AllowRenewalIfOtherItemsAvailable') ) {
Lines 2942-2948 sub CanBookBeRenewed { Link Here
2942
                biblionumber => $item->biblionumber,
2937
                biblionumber => $item->biblionumber,
2943
                onloan       => undef,
2938
                onloan       => undef,
2944
                notforloan   => 0,
2939
                notforloan   => 0,
2945
                -not         => { itemnumber => $itemnumber } })->as_list;
2940
                -not         => { itemnumber => $item->itemnumber } })->as_list;
2946
2941
2947
            return ( 0, "on_reserve" ) if @possible_holds && (scalar @other_items < scalar @possible_holds);
2942
            return ( 0, "on_reserve" ) if @possible_holds && (scalar @other_items < scalar @possible_holds);
2948
2943
Lines 2950-2956 sub CanBookBeRenewed { Link Here
2950
            foreach my $possible_hold (@possible_holds) {
2945
            foreach my $possible_hold (@possible_holds) {
2951
                my $fillable = 0;
2946
                my $fillable = 0;
2952
                my $patron_with_reserve = Koha::Patrons->find($possible_hold->borrowernumber);
2947
                my $patron_with_reserve = Koha::Patrons->find($possible_hold->borrowernumber);
2953
                my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron_with_reserve });
2948
                my $items_any_available = ItemsAnyAvailableAndNotRestricted({
2949
                    biblionumber => $item->biblionumber,
2950
                    patron => $patron_with_reserve
2951
                });
2954
2952
2955
                # FIXME: We are not checking whether the item we are renewing can fill the hold
2953
                # FIXME: We are not checking whether the item we are renewing can fill the hold
2956
2954
Lines 2968-2982 sub CanBookBeRenewed { Link Here
2968
                }
2966
                }
2969
                return ( 0, "on_reserve" ) unless $fillable;
2967
                return ( 0, "on_reserve" ) unless $fillable;
2970
            }
2968
            }
2971
2969
        }
2972
        } else {
2970
        else {
2973
            my ($status, $matched_reserve, $possible_reserves) = CheckReserves($itemnumber);
2971
            my ($status, $matched_reserve, $possible_reserves) = CheckReserves($item);
2974
            return ( 0, "on_reserve" ) if $status;
2972
            return ( 0, "on_reserve" ) if $status;
2975
        }
2973
        }
2976
    }
2974
    }
2977
2975
2978
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
2976
    return ( 0, $auto_renew, { soonest_renew_date => $soonest } ) if $auto_renew =~ 'too_soon';#$auto_renew ne "no" && $auto_renew ne "ok";
2979
    $soonest = GetSoonestRenewDate($borrowernumber, $itemnumber);
2977
    $soonest = GetSoonestRenewDate($patron, $issue);
2980
    if ( $soonest > dt_from_string() ){
2978
    if ( $soonest > dt_from_string() ){
2981
        return (0, "too_soon", { soonest_renew_date => $soonest } ) unless $override_limit;
2979
        return (0, "too_soon", { soonest_renew_date => $soonest } ) unless $override_limit;
2982
    }
2980
    }
Lines 3207-3213 sub AddRenewal { Link Here
3207
3205
3208
sub GetRenewCount {
3206
sub GetRenewCount {
3209
    # check renewal status
3207
    # check renewal status
3210
    my ( $bornum, $itemno ) = @_;
3208
    my ( $borrowernumber_or_patron, $itemnumber_or_item ) = @_;
3209
3211
    my $dbh           = C4::Context->dbh;
3210
    my $dbh           = C4::Context->dbh;
3212
    my $renewcount    = 0;
3211
    my $renewcount    = 0;
3213
    my $unseencount    = 0;
3212
    my $unseencount    = 0;
Lines 3215-3223 sub GetRenewCount { Link Here
3215
    my $unseenallowed = 0;
3214
    my $unseenallowed = 0;
3216
    my $renewsleft    = 0;
3215
    my $renewsleft    = 0;
3217
    my $unseenleft    = 0;
3216
    my $unseenleft    = 0;
3218
3217
    my $patron = blessed $borrowernumber_or_patron ?
3219
    my $patron = Koha::Patrons->find( $bornum );
3218
        $borrowernumber_or_patron : Koha::Patrons->find($borrowernumber_or_patron);
3220
    my $item   = Koha::Items->find($itemno);
3219
    my $item = blessed $itemnumber_or_item ?
3220
        $itemnumber_or_item : Koha::Items->find($itemnumber_or_item);
3221
3221
3222
    return (0, 0, 0, 0, 0, 0) unless $patron or $item; # Wrong call, no renewal allowed
3222
    return (0, 0, 0, 0, 0, 0) unless $patron or $item; # Wrong call, no renewal allowed
3223
3223
Lines 3225-3236 sub GetRenewCount { Link Here
3225
    # and not yet returned.
3225
    # and not yet returned.
3226
3226
3227
    # FIXME - I think this function could be redone to use only one SQL call.
3227
    # FIXME - I think this function could be redone to use only one SQL call.
3228
    my $sth = $dbh->prepare(
3228
    my $sth = $dbh->prepare(q{
3229
        "select * from issues
3229
        SELECT * FROM issues
3230
                                where (borrowernumber = ?)
3230
        WHERE  (borrowernumber = ?) AND (itemnumber = ?)
3231
                                and (itemnumber = ?)"
3231
    });
3232
    );
3232
    $sth->execute( $patron->borrowernumber, $item->itemnumber );
3233
    $sth->execute( $bornum, $itemno );
3234
    my $data = $sth->fetchrow_hashref;
3233
    my $data = $sth->fetchrow_hashref;
3235
    $renewcount = $data->{'renewals_count'} if $data->{'renewals_count'};
3234
    $renewcount = $data->{'renewals_count'} if $data->{'renewals_count'};
3236
    $unseencount = $data->{'unseen_renewals'} if $data->{'unseen_renewals'};
3235
    $unseencount = $data->{'unseen_renewals'} if $data->{'unseen_renewals'};
Lines 3265-3278 sub GetRenewCount { Link Here
3265
3264
3266
=head2 GetSoonestRenewDate
3265
=head2 GetSoonestRenewDate
3267
3266
3268
  $NoRenewalBeforeThisDate = &GetSoonestRenewDate($borrowernumber, $itemnumber);
3267
  $NoRenewalBeforeThisDate = &GetSoonestRenewDate($patron, $issue);
3269
3268
3270
Find out the soonest possible renew date of a borrowed item.
3269
Find out the soonest possible renew date of a borrowed item.
3271
3270
3272
C<$borrowernumber> is the borrower number of the patron who currently
3271
C<$patron> is the patron who currently has the item on loan.
3273
has the item on loan.
3274
3272
3275
C<$itemnumber> is the number of the item to renew.
3273
C<$issue> is the the item issue.
3276
3274
3277
C<$GetSoonestRenewDate> returns the DateTime of the soonest possible
3275
C<$GetSoonestRenewDate> returns the DateTime of the soonest possible
3278
renew date, based on the value "No renewal before" of the applicable
3276
renew date, based on the value "No renewal before" of the applicable
Lines 3283-3298 cannot be found. Link Here
3283
=cut
3281
=cut
3284
3282
3285
sub GetSoonestRenewDate {
3283
sub GetSoonestRenewDate {
3286
    my ( $borrowernumber, $itemnumber ) = @_;
3284
    my ( $patron, $issue ) = @_;
3287
3285
    return unless $issue;
3288
    my $dbh = C4::Context->dbh;
3286
    return unless $patron;
3289
3287
3290
    my $item      = Koha::Items->find($itemnumber)      or return;
3288
    my $item = $issue->item;
3291
    my $itemissue = $item->checkout or return;
3289
    return unless $item;
3292
3290
3293
    $borrowernumber ||= $itemissue->borrowernumber;
3291
    my $dbh = C4::Context->dbh;
3294
    my $patron = Koha::Patrons->find( $borrowernumber )
3295
      or return;
3296
3292
3297
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3293
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3298
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
3294
    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
Lines 3312-3318 sub GetSoonestRenewDate { Link Here
3312
        and $issuing_rule->{norenewalbefore} ne "" )
3308
        and $issuing_rule->{norenewalbefore} ne "" )
3313
    {
3309
    {
3314
        my $soonestrenewal =
3310
        my $soonestrenewal =
3315
          dt_from_string( $itemissue->date_due )->subtract(
3311
          dt_from_string( $issue->date_due )->subtract(
3316
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3312
            $issuing_rule->{lengthunit} => $issuing_rule->{norenewalbefore} );
3317
3313
3318
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3314
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
Lines 3321-3329 sub GetSoonestRenewDate { Link Here
3321
            $soonestrenewal->truncate( to => 'day' );
3317
            $soonestrenewal->truncate( to => 'day' );
3322
        }
3318
        }
3323
        return $soonestrenewal if $now < $soonestrenewal;
3319
        return $soonestrenewal if $now < $soonestrenewal;
3324
    } elsif ( $itemissue->auto_renew && $patron->autorenew_checkouts ) {
3320
    } elsif ( $issue->auto_renew && $patron->autorenew_checkouts ) {
3325
        # Checkouts with auto-renewing fall back to due date
3321
        # Checkouts with auto-renewing fall back to due date
3326
        my $soonestrenewal = dt_from_string( $itemissue->date_due );
3322
        my $soonestrenewal = dt_from_string( $issue->date_due );
3327
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3323
        if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
3328
            and $issuing_rule->{lengthunit} eq 'days' )
3324
            and $issuing_rule->{lengthunit} eq 'days' )
3329
        {
3325
        {
Lines 3336-3349 sub GetSoonestRenewDate { Link Here
3336
3332
3337
=head2 GetLatestAutoRenewDate
3333
=head2 GetLatestAutoRenewDate
3338
3334
3339
  $NoAutoRenewalAfterThisDate = &GetLatestAutoRenewDate($borrowernumber, $itemnumber);
3335
  $NoAutoRenewalAfterThisDate = &GetLatestAutoRenewDate($patron, $issue);
3340
3336
3341
Find out the latest possible auto renew date of a borrowed item.
3337
Find out the latest possible auto renew date of a borrowed item.
3342
3338
3343
C<$borrowernumber> is the borrower number of the patron who currently
3339
C<$patron> is the patron who currently has the item on loan.
3344
has the item on loan.
3345
3340
3346
C<$itemnumber> is the number of the item to renew.
3341
C<$issue> is the item issue.
3347
3342
3348
C<$GetLatestAutoRenewDate> returns the DateTime of the latest possible
3343
C<$GetLatestAutoRenewDate> returns the DateTime of the latest possible
3349
auto renew date, based on the value "No auto renewal after" and the "No auto
3344
auto renew date, based on the value "No auto renewal after" and the "No auto
Lines 3354-3369 or item cannot be found. Link Here
3354
=cut
3349
=cut
3355
3350
3356
sub GetLatestAutoRenewDate {
3351
sub GetLatestAutoRenewDate {
3357
    my ( $borrowernumber, $itemnumber ) = @_;
3352
    my ( $patron, $issue ) = @_;
3358
3353
    return unless $issue;
3359
    my $dbh = C4::Context->dbh;
3354
    return unless $patron;
3360
3355
3361
    my $item      = Koha::Items->find($itemnumber)  or return;
3356
    my $item = $issue->item;
3362
    my $itemissue = $item->checkout                 or return;
3357
    return unless $item;
3363
3358
3364
    $borrowernumber ||= $itemissue->borrowernumber;
3359
    my $dbh = C4::Context->dbh;
3365
    my $patron = Koha::Patrons->find( $borrowernumber )
3366
      or return;
3367
3360
3368
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3361
    my $branchcode = _GetCircControlBranch( $item->unblessed, $patron->unblessed );
3369
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
3362
    my $circulation_rules = Koha::CirculationRules->get_effective_rules(
Lines 3388-3394 sub GetLatestAutoRenewDate { Link Here
3388
3381
3389
    my $maximum_renewal_date;
3382
    my $maximum_renewal_date;
3390
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3383
    if ( $circulation_rules->{no_auto_renewal_after} ) {
3391
        $maximum_renewal_date = dt_from_string($itemissue->issuedate);
3384
        $maximum_renewal_date = dt_from_string($issue->issuedate);
3392
        $maximum_renewal_date->add(
3385
        $maximum_renewal_date->add(
3393
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3386
            $circulation_rules->{lengthunit} => $circulation_rules->{no_auto_renewal_after}
3394
        );
3387
        );
Lines 3438-3450 sub GetIssuingCharges { Link Here
3438
3431
3439
    my $sth = $dbh->prepare($charge_query);
3432
    my $sth = $dbh->prepare($charge_query);
3440
    $sth->execute($itemnumber);
3433
    $sth->execute($itemnumber);
3434
    my $patron;
3441
    if ( my $item_data = $sth->fetchrow_hashref ) {
3435
    if ( my $item_data = $sth->fetchrow_hashref ) {
3442
        $item_type = $item_data->{itemtype};
3436
        $item_type = $item_data->{itemtype};
3443
        $charge    = $item_data->{rentalcharge};
3437
        $charge    = $item_data->{rentalcharge};
3444
        if ($charge) {
3438
        if ($charge) {
3445
            # FIXME This should follow CircControl
3439
            # FIXME This should follow CircControl
3446
            my $branch = C4::Context::mybranch();
3440
            my $branch = C4::Context::mybranch();
3447
            my $patron = Koha::Patrons->find( $borrowernumber );
3441
            $patron //= Koha::Patrons->find( $borrowernumber );
3448
            my $discount = Koha::CirculationRules->get_effective_rule({
3442
            my $discount = Koha::CirculationRules->get_effective_rule({
3449
                categorycode => $patron->categorycode,
3443
                categorycode => $patron->categorycode,
3450
                branchcode   => $branch,
3444
                branchcode   => $branch,
Lines 4380-4386 sub _CanBookBeAutoRenewed { Link Here
4380
        }
4374
        }
4381
    );
4375
    );
4382
4376
4383
    if ( $patron->category->effective_BlockExpiredPatronOpacActions and $patron->is_expired ) {
4377
    if ( $patron->is_expired && $patron->category->effective_BlockExpiredPatronOpacActions ) {
4384
        return 'auto_account_expired';
4378
        return 'auto_account_expired';
4385
    }
4379
    }
4386
4380
Lines 4416-4422 sub _CanBookBeAutoRenewed { Link Here
4416
        }
4410
        }
4417
    }
4411
    }
4418
4412
4419
    my $soonest = GetSoonestRenewDate($patron->id, $item->id);
4413
    my $soonest = GetSoonestRenewDate($patron, $issue);
4420
    if ( $soonest > dt_from_string() )
4414
    if ( $soonest > dt_from_string() )
4421
    {
4415
    {
4422
        return ( "auto_too_soon", $soonest );
4416
        return ( "auto_too_soon", $soonest );
(-)a/C4/ILSDI/Services.pm (-5 / +7 lines)
Lines 637-643 sub GetServices { Link Here
637
    }
637
    }
638
638
639
    # Renewal management
639
    # Renewal management
640
    my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
640
    my @renewal = CanBookBeRenewed( $patron, $item->checkout ); # TODO: Error if issue not found?
641
    if ( $renewal[0] ) {
641
    if ( $renewal[0] ) {
642
        push @availablefor, 'loan renewal';
642
        push @availablefor, 'loan renewal';
643
    }
643
    }
Lines 681-696 sub RenewLoan { Link Here
681
    return { code => 'PatronNotFound' } unless $patron;
681
    return { code => 'PatronNotFound' } unless $patron;
682
682
683
    # Get the item, or return an error code
683
    # Get the item, or return an error code
684
    my $itemnumber = $cgi->param('item_id');
684
    my $itemnumber = $cgi->param('item_id'); # TODO: Refactor and send issue_id instead?
685
    my $item = Koha::Items->find($itemnumber);
685
    my $item = Koha::Items->find($itemnumber);
686
686
    return { code => 'RecordNotFound' } unless $item;
687
    return { code => 'RecordNotFound' } unless $item;
687
688
689
    my $issue = $item->checkout;
690
    return unless $issue; # FIXME should be handled
691
688
    # Add renewal if possible
692
    # Add renewal if possible
689
    my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
693
    my @renewal = CanBookBeRenewed( $patron, $issue );
690
    if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 ); }
694
    if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 ); }
691
695
692
    my $issue = $item->checkout;
693
    return unless $issue; # FIXME should be handled
694
696
695
    # Hashref building
697
    # Hashref building
696
    my $out;
698
    my $out;
(-)a/C4/Reserves.pm (-67 / +33 lines)
Lines 677-685 sub GetOtherReserves { Link Here
677
    my ($itemnumber) = @_;
677
    my ($itemnumber) = @_;
678
    my $messages;
678
    my $messages;
679
    my $nextreservinfo;
679
    my $nextreservinfo;
680
    my ( undef, $checkreserves, undef ) = CheckReserves($itemnumber);
680
    my $item = Koha::Items->find($itemnumber);
681
    my ( undef, $checkreserves, undef ) = CheckReserves($item);
681
    if ($checkreserves) {
682
    if ($checkreserves) {
682
        my $item = Koha::Items->find($itemnumber);
683
        if ( $item->holdingbranch ne $checkreserves->{'branchcode'} ) {
683
        if ( $item->holdingbranch ne $checkreserves->{'branchcode'} ) {
684
            $messages->{'transfert'} = $checkreserves->{'branchcode'};
684
            $messages->{'transfert'} = $checkreserves->{'branchcode'};
685
            #minus priorities of others reservs
685
            #minus priorities of others reservs
Lines 820-832 sub GetReserveStatus { Link Here
820
820
821
=head2 CheckReserves
821
=head2 CheckReserves
822
822
823
  ($status, $matched_reserve, $possible_reserves) = &CheckReserves($itemnumber);
823
  ($status, $matched_reserve, $possible_reserves) = &CheckReserves($item);
824
  ($status, $matched_reserve, $possible_reserves) = &CheckReserves(undef, $barcode);
824
  ($status, $matched_reserve, $possible_reserves) = &CheckReserves($item, $lookahead);
825
  ($status, $matched_reserve, $possible_reserves) = &CheckReserves($itemnumber,undef,$lookahead);
826
825
827
Find a book in the reserves.
826
Find a book in the reserves.
828
827
829
C<$itemnumber> is the book's item number.
828
C<$item> is the book's item.
830
C<$lookahead> is the number of days to look in advance for future reserves.
829
C<$lookahead> is the number of days to look in advance for future reserves.
831
830
832
As I understand it, C<&CheckReserves> looks for the given item in the
831
As I understand it, C<&CheckReserves> looks for the given item in the
Lines 848-912 table in the Koha database. Link Here
848
=cut
847
=cut
849
848
850
sub CheckReserves {
849
sub CheckReserves {
851
    my ( $item, $barcode, $lookahead_days, $ignore_borrowers) = @_;
850
    my ( $item, $lookahead_days, $ignore_borrowers ) = @_;
852
    my $dbh = C4::Context->dbh;
853
    my $sth;
854
    my $select;
855
    if (C4::Context->preference('item-level_itypes')){
856
	$select = "
857
           SELECT items.biblionumber,
858
           items.biblioitemnumber,
859
           itemtypes.notforloan,
860
           items.notforloan AS itemnotforloan,
861
           items.itemnumber,
862
           items.damaged,
863
           items.homebranch,
864
           items.holdingbranch
865
           FROM   items
866
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
867
           LEFT JOIN itemtypes   ON items.itype   = itemtypes.itemtype
868
        ";
869
    }
870
    else {
871
	$select = "
872
           SELECT items.biblionumber,
873
           items.biblioitemnumber,
874
           itemtypes.notforloan,
875
           items.notforloan AS itemnotforloan,
876
           items.itemnumber,
877
           items.damaged,
878
           items.homebranch,
879
           items.holdingbranch
880
           FROM   items
881
           LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
882
           LEFT JOIN itemtypes   ON biblioitems.itemtype   = itemtypes.itemtype
883
        ";
884
    }
885
886
    if ($item) {
887
        $sth = $dbh->prepare("$select WHERE itemnumber = ?");
888
        $sth->execute($item);
889
    }
890
    else {
891
        $sth = $dbh->prepare("$select WHERE barcode = ?");
892
        $sth->execute($barcode);
893
    }
894
    # note: we get the itemnumber because we might have started w/ just the barcode.  Now we know for sure we have it.
851
    # note: we get the itemnumber because we might have started w/ just the barcode.  Now we know for sure we have it.
895
    my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber, $damaged, $item_homebranch, $item_holdingbranch ) = $sth->fetchrow_array;
896
    return if ( $damaged && !C4::Context->preference('AllowHoldsOnDamagedItems') );
897
852
898
    return unless $itemnumber; # bail if we got nothing.
853
    return unless $item; # bail if we got nothing.
854
855
    return if ( $item->damaged && !C4::Context->preference('AllowHoldsOnDamagedItems') );
856
899
    # if item is not for loan it cannot be reserved either.....
857
    # if item is not for loan it cannot be reserved either.....
900
    # except where items.notforloan < 0 :  This indicates the item is holdable.
858
    # except where items.notforloan < 0 :  This indicates the item is holdable.
901
859
902
    my @SkipHoldTrapOnNotForLoanValue = split( '\|', C4::Context->preference('SkipHoldTrapOnNotForLoanValue') );
860
    my @SkipHoldTrapOnNotForLoanValue = split( '\|', C4::Context->preference('SkipHoldTrapOnNotForLoanValue') );
903
    return if grep { $_ eq $notforloan_per_item } @SkipHoldTrapOnNotForLoanValue;
861
    return if grep { $_ eq $item->notforloan } @SkipHoldTrapOnNotForLoanValue;
904
862
905
    my $dont_trap = C4::Context->preference('TrapHoldsOnOrder') ? ($notforloan_per_item > 0) : ($notforloan_per_item && 1 );
863
    # TODO: Double check 'TrapHoldsOnOrder' should not also be performed on itemtype?
906
    return if $dont_trap or $notforloan_per_itemtype;
864
    # or perhaps perform one check depeding on 'item-level_itypes'?
865
    my $dont_trap = C4::Context->preference('TrapHoldsOnOrder') ? $item->notforloan > 0 : $item->notforloan;
866
    if ( !$dont_trap ) {
867
        my $item_type = $item->effective_itemtype();
868
        if ( $item_type ) {
869
            return if Koha::ItemTypes->find( $item_type )->notforloan;
870
        }
871
    }
872
    else {
873
        return;
874
    }
907
875
908
    # Find this item in the reserves
876
    # Find this item in the reserves
909
    my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber, $lookahead_days, $ignore_borrowers);
877
    my @reserves = _Findgroupreserve( $item->biblionumber, $item->itemnumber, $lookahead_days, $ignore_borrowers);
910
878
911
    # $priority and $highest are used to find the most important item
879
    # $priority and $highest are used to find the most important item
912
    # in the list returned by &_Findgroupreserve. (The lower $priority,
880
    # in the list returned by &_Findgroupreserve. (The lower $priority,
Lines 918-925 sub CheckReserves { Link Here
918
        my $LocalHoldsPriority = C4::Context->preference('LocalHoldsPriority');
886
        my $LocalHoldsPriority = C4::Context->preference('LocalHoldsPriority');
919
        my $LocalHoldsPriorityPatronControl = C4::Context->preference('LocalHoldsPriorityPatronControl');
887
        my $LocalHoldsPriorityPatronControl = C4::Context->preference('LocalHoldsPriorityPatronControl');
920
        my $LocalHoldsPriorityItemControl = C4::Context->preference('LocalHoldsPriorityItemControl');
888
        my $LocalHoldsPriorityItemControl = C4::Context->preference('LocalHoldsPriorityItemControl');
921
922
        my $priority = 10000000;
889
        my $priority = 10000000;
890
923
        foreach my $res (@reserves) {
891
        foreach my $res (@reserves) {
924
            if ($res->{'found'} && $res->{'found'} eq 'W') {
892
            if ($res->{'found'} && $res->{'found'} eq 'W') {
925
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
893
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
Lines 929-940 sub CheckReserves { Link Here
929
                return ( "Transferred", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
897
                return ( "Transferred", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
930
            } else {
898
            } else {
931
                my $patron;
899
                my $patron;
932
                my $item;
933
                my $local_hold_match;
900
                my $local_hold_match;
934
901
935
                if ($LocalHoldsPriority) {
902
                if ($LocalHoldsPriority) {
936
                    $patron = Koha::Patrons->find( $res->{borrowernumber} );
903
                    $patron = Koha::Patrons->find( $res->{borrowernumber} );
937
                    $item = Koha::Items->find($itemnumber);
938
904
939
                    unless ($item->exclude_from_local_holds_priority || $patron->category->exclude_from_local_holds_priority) {
905
                    unless ($item->exclude_from_local_holds_priority || $patron->category->exclude_from_local_holds_priority) {
940
                        my $local_holds_priority_item_branchcode =
906
                        my $local_holds_priority_item_branchcode =
Lines 953-961 sub CheckReserves { Link Here
953
919
954
                # See if this item is more important than what we've got so far
920
                # See if this item is more important than what we've got so far
955
                if ( ( $res->{'priority'} && $res->{'priority'} < $priority ) || $local_hold_match ) {
921
                if ( ( $res->{'priority'} && $res->{'priority'} < $priority ) || $local_hold_match ) {
956
                    $item ||= Koha::Items->find($itemnumber);
957
                    next if $res->{itemtype} && $res->{itemtype} ne $item->effective_itemtype;
922
                    next if $res->{itemtype} && $res->{itemtype} ne $item->effective_itemtype;
958
                    $patron ||= Koha::Patrons->find( $res->{borrowernumber} );
923
                    $patron //= Koha::Patrons->find( $res->{borrowernumber} );
959
                    my $branch = GetReservesControlBranch( $item->unblessed, $patron->unblessed );
924
                    my $branch = GetReservesControlBranch( $item->unblessed, $patron->unblessed );
960
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$item->effective_itemtype);
925
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$item->effective_itemtype);
961
                    next if ($branchitemrule->{'holdallowed'} eq 'not_allowed');
926
                    next if ($branchitemrule->{'holdallowed'} eq 'not_allowed');
Lines 978-984 sub CheckReserves { Link Here
978
    # If we get this far, then no exact match was found.
943
    # If we get this far, then no exact match was found.
979
    # We return the most important (i.e. next) reservation.
944
    # We return the most important (i.e. next) reservation.
980
    if ($highest) {
945
    if ($highest) {
981
        $highest->{'itemnumber'} = $item;
946
        $highest->{'itemnumber'} = $item->itemnumber;
982
        return ( "Reserved", $highest, \@reserves );
947
        return ( "Reserved", $highest, \@reserves );
983
    }
948
    }
984
949
Lines 1706-1712 sub _FixPriority { Link Here
1706
1671
1707
=head2 _Findgroupreserve
1672
=head2 _Findgroupreserve
1708
1673
1709
  @results = &_Findgroupreserve($biblioitemnumber, $biblionumber, $itemnumber, $lookahead, $ignore_borrowers);
1674
  @results = &_Findgroupreserve($biblionumber, $itemnumber, $lookahead, $ignore_borrowers);
1710
1675
1711
Looks for a holds-queue based item-specific match first, then for a holds-queue title-level match, returning the
1676
Looks for a holds-queue based item-specific match first, then for a holds-queue title-level match, returning the
1712
first match found.  If neither, then we look for non-holds-queue based holds.
1677
first match found.  If neither, then we look for non-holds-queue based holds.
Lines 1727-1733 All return values will respect any borrowernumbers passed as arrayref in $ignore Link Here
1727
=cut
1692
=cut
1728
1693
1729
sub _Findgroupreserve {
1694
sub _Findgroupreserve {
1730
    my ( $bibitem, $biblio, $itemnumber, $lookahead, $ignore_borrowers) = @_;
1695
    my ( $biblionumber, $itemnumber, $lookahead, $ignore_borrowers) = @_;
1731
    my $dbh   = C4::Context->dbh;
1696
    my $dbh   = C4::Context->dbh;
1732
1697
1733
    # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
1698
    # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
Lines 1826-1832 sub _Findgroupreserve { Link Here
1826
          ORDER BY priority
1791
          ORDER BY priority
1827
    };
1792
    };
1828
    $sth = $dbh->prepare($query);
1793
    $sth = $dbh->prepare($query);
1829
    $sth->execute( $biblio, $itemnumber, $lookahead||0);
1794
    $sth->execute( $biblionumber, $itemnumber, $lookahead||0);
1830
    @results = ();
1795
    @results = ();
1831
    while ( my $data = $sth->fetchrow_hashref ) {
1796
    while ( my $data = $sth->fetchrow_hashref ) {
1832
        push( @results, $data )
1797
        push( @results, $data )
Lines 2042-2048 sub MoveReserve { Link Here
2042
    $cancelreserve //= 0;
2007
    $cancelreserve //= 0;
2043
2008
2044
    my $lookahead = C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2009
    my $lookahead = C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2045
    my ( $restype, $res, undef ) = CheckReserves( $itemnumber, undef, $lookahead );
2010
    my $item = Koha::Items->find($itemnumber);
2011
    my ( $restype, $res, undef ) = CheckReserves( $item, $lookahead );
2046
    return unless $res;
2012
    return unless $res;
2047
2013
2048
    my $biblionumber = $res->{biblionumber};
2014
    my $biblionumber = $res->{biblionumber};
(-)a/C4/RotatingCollections.pm (-1 lines)
Lines 25-31 package C4::RotatingCollections; Link Here
25
use Modern::Perl;
25
use Modern::Perl;
26
26
27
use C4::Context;
27
use C4::Context;
28
use C4::Reserves qw(CheckReserves);
29
use Koha::Database;
28
use Koha::Database;
30
29
31
use Try::Tiny qw( catch try );
30
use Try::Tiny qw( catch try );
(-)a/C4/SIP/ILS/Transaction/Checkin.pm (-1 / +1 lines)
Lines 90-96 sub do_checkin { Link Here
90
90
91
    my $reserved;
91
    my $reserved;
92
    my $lookahead = C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
92
    my $lookahead = C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
93
    my ($resfound) = $item->withdrawn ? q{} : C4::Reserves::CheckReserves( $item->itemnumber, undef, $lookahead );
93
    my ($resfound) = $item->withdrawn ? q{} : CheckReserves( $item, $lookahead );
94
    if ( $resfound eq "Reserved") {
94
    if ( $resfound eq "Reserved") {
95
        $reserved = 1;
95
        $reserved = 1;
96
    }
96
    }
(-)a/C4/SIP/ILS/Transaction/Renew.pm (-3 / +5 lines)
Lines 31-38 sub new { Link Here
31
31
32
sub do_renew_for  {
32
sub do_renew_for  {
33
    my $self = shift;
33
    my $self = shift;
34
    my $borrower = shift;
34
    my $patron = shift;
35
    my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber});
35
    my $checkout = Koha::Checkouts->find({ itemnumber => $self->{item}->{itemnumber} });
36
    my ($renewokay,$renewerror) = CanBookBeRenewed($patron, $checkout);
36
    if ($renewokay) { # ok so far check charges
37
    if ($renewokay) { # ok so far check charges
37
        my ($fee, undef) = GetIssuingCharges($self->{item}->{itemnumber}, $self->{patron}->{borrowernumber});
38
        my ($fee, undef) = GetIssuingCharges($self->{item}->{itemnumber}, $self->{patron}->{borrowernumber});
38
        if ($fee > 0) {
39
        if ($fee > 0) {
Lines 53-58 sub do_renew_for { Link Here
53
        $renewerror=~s/too_many/Item has reached maximum renewals/;
54
        $renewerror=~s/too_many/Item has reached maximum renewals/;
54
        $renewerror=~s/too_unseen/Item has reached maximum consecutive renewals without being seen/;
55
        $renewerror=~s/too_unseen/Item has reached maximum consecutive renewals without being seen/;
55
        $renewerror=~s/item_denied_renewal/Item renewal is not allowed/;
56
        $renewerror=~s/item_denied_renewal/Item renewal is not allowed/;
57
        $renewerror=~s/item_issued_to_other_patron/Item already issued to other borrower/;
56
        $self->screen_msg($renewerror);
58
        $self->screen_msg($renewerror);
57
        $self->renewal_ok(0);
59
        $self->renewal_ok(0);
58
    }
60
    }
Lines 64-70 sub do_renew { Link Here
64
    my $self = shift;
66
    my $self = shift;
65
    my $patron = Koha::Patrons->find( $self->{patron}->borrowernumber );
67
    my $patron = Koha::Patrons->find( $self->{patron}->borrowernumber );
66
    $patron or return; # FIXME we should log that
68
    $patron or return; # FIXME we should log that
67
    return $self->do_renew_for($patron->unblessed);
69
    return $self->do_renew_for($patron);
68
}
70
}
69
71
70
1;
72
1;
(-)a/C4/SIP/Sip/MsgType.pm (-1 / +2 lines)
Lines 1165-1171 sub handle_fee_paid { Link Here
1165
        "on_reserve" => "On hold for another patron",
1165
        "on_reserve" => "On hold for another patron",
1166
        "patron_restricted" => "Patron is currently restricted",
1166
        "patron_restricted" => "Patron is currently restricted",
1167
        "item_denied_renewal" => "Item is not allowed renewal",
1167
        "item_denied_renewal" => "Item is not allowed renewal",
1168
        "onsite_checkout" => "Item is an onsite checkout"
1168
        "onsite_checkout" => "Item is an onsite checkout",
1169
        "item_issued_to_other_patron" => "Item already issued to other borrower"
1169
    };
1170
    };
1170
    my @success = ();
1171
    my @success = ();
1171
    my @fail = ();
1172
    my @fail = ();
(-)a/Koha/Account/Line.pm (-8 / +5 lines)
Lines 21-26 use Data::Dumper qw( Dumper ); Link Here
21
21
22
use C4::Log qw( logaction );
22
use C4::Log qw( logaction );
23
use C4::Overdues qw( UpdateFine );
23
use C4::Overdues qw( UpdateFine );
24
use C4::Circulation qw( CanBookBeRenewed AddRenewal ReturnLostItem );
24
25
25
use Koha::Account::CreditType;
26
use Koha::Account::CreditType;
26
use Koha::Account::DebitType;
27
use Koha::Account::DebitType;
Lines 693-700 sub apply { Link Here
693
                )
694
                )
694
              )
695
              )
695
            {
696
            {
696
                C4::Circulation::ReturnLostItem( $self->borrowernumber,
697
                ReturnLostItem( $self->borrowernumber, $debit->itemnumber );
697
                    $debit->itemnumber );
698
            }
698
            }
699
699
700
            last if $available_credit == 0;
700
            last if $available_credit == 0;
Lines 1023-1035 sub renew_item { Link Here
1023
    }
1023
    }
1024
1024
1025
    my $itemnumber = $self->item->itemnumber;
1025
    my $itemnumber = $self->item->itemnumber;
1026
    my $borrowernumber = $self->patron->borrowernumber;
1026
    my ( $can_renew, $error ) = CanBookBeRenewed( $self->patron, $self->item->checkout );
1027
    my ( $can_renew, $error ) = C4::Circulation::CanBookBeRenewed(
1028
        $borrowernumber,
1029
        $itemnumber
1030
    );
1031
    if ( $can_renew ) {
1027
    if ( $can_renew ) {
1032
        my $due_date = C4::Circulation::AddRenewal(
1028
        my $borrowernumber = $self->patron->borrowernumber;
1029
        my $due_date = AddRenewal(
1033
            $borrowernumber,
1030
            $borrowernumber,
1034
            $itemnumber,
1031
            $itemnumber,
1035
            $self->{branchcode},
1032
            $self->{branchcode},
(-)a/Koha/CirculationRules.pm (-1 / +1 lines)
Lines 299-305 sub get_effective_rule_value { Link Here
299
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
299
      $categorycode // q{}, $branchcode // q{}, $itemtype // q{};
300
300
301
    my $cached       = $memory_cache->get_from_cache($cache_key);
301
    my $cached       = $memory_cache->get_from_cache($cache_key);
302
    return $cached if $cached;
302
    return $cached if defined($cached);
303
303
304
    my $rule = $self->get_effective_rule($params);
304
    my $rule = $self->get_effective_rule($params);
305
305
(-)a/Koha/Hold.pm (-1 / +1 lines)
Lines 724-730 sub cancel { Link Here
724
    );
724
    );
725
725
726
    if ($autofill_next) {
726
    if ($autofill_next) {
727
        my ( undef, $next_hold ) = C4::Reserves::CheckReserves( $self->itemnumber );
727
        my ( undef, $next_hold ) = CheckReserves( $self->item );
728
        if ($next_hold) {
728
        if ($next_hold) {
729
            my $is_transfer = $self->branchcode ne $next_hold->{branchcode};
729
            my $is_transfer = $self->branchcode ne $next_hold->{branchcode};
730
730
(-)a/Koha/REST/V1/Checkouts.pm (-10 / +5 lines)
Lines 22-28 use Mojo::JSON; Link Here
22
22
23
use C4::Auth qw( haspermission );
23
use C4::Auth qw( haspermission );
24
use C4::Context;
24
use C4::Context;
25
use C4::Circulation qw( AddRenewal );
25
use C4::Circulation qw( AddRenewal CanBookBeRenewed );
26
use Koha::Checkouts;
26
use Koha::Checkouts;
27
use Koha::Old::Checkouts;
27
use Koha::Old::Checkouts;
28
28
Lines 156-166 sub renew { Link Here
156
    }
156
    }
157
157
158
    return try {
158
    return try {
159
        my $borrowernumber = $checkout->borrowernumber;
159
        my ($can_renew, $error) = CanBookBeRenewed($checkout->patron, $checkout);
160
        my $itemnumber = $checkout->itemnumber;
161
162
        my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed(
163
            $borrowernumber, $itemnumber);
164
160
165
        if (!$can_renew) {
161
        if (!$can_renew) {
166
            return $c->render(
162
            return $c->render(
Lines 170-177 sub renew { Link Here
170
        }
166
        }
171
167
172
        AddRenewal(
168
        AddRenewal(
173
            $borrowernumber,
169
            $checkout->borrowernumber,
174
            $itemnumber,
170
            $checkout->itemnumber,
175
            $checkout->branchcode,
171
            $checkout->branchcode,
176
            undef,
172
            undef,
177
            undef,
173
            undef,
Lines 210-217 sub allows_renewal { Link Here
210
    }
206
    }
211
207
212
    return try {
208
    return try {
213
        my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed(
209
        my ($can_renew, $error) = CanBookBeRenewed($checkout->patron, $checkout);
214
            $checkout->borrowernumber, $checkout->itemnumber);
215
210
216
        my $renewable = Mojo::JSON->false;
211
        my $renewable = Mojo::JSON->false;
217
        $renewable = Mojo::JSON->true if $can_renew;
212
        $renewable = Mojo::JSON->true if $can_renew;
(-)a/circ/renew.pl (-14 / +13 lines)
Lines 48-75 my $override_limit = $cgi->param('override_limit'); Link Here
48
my $override_holds = $cgi->param('override_holds');
48
my $override_holds = $cgi->param('override_holds');
49
my $hard_due_date  = $cgi->param('hard_due_date');
49
my $hard_due_date  = $cgi->param('hard_due_date');
50
50
51
my ( $item, $issue, $borrower );
51
my ( $item, $checkout, $patron );
52
my $error = q{};
52
my $error = q{};
53
my ( $soonest_renew_date, $latest_auto_renew_date );
53
my ( $soonest_renew_date, $latest_auto_renew_date );
54
54
55
if ($barcode) {
55
if ($barcode) {
56
    $barcode = barcodedecode($barcode) if $barcode;
56
    $barcode = barcodedecode($barcode) if $barcode;
57
    $item = $schema->resultset("Item")->single( { barcode => $barcode } );
57
    $item = Koha::Items->find({ barcode => $barcode });
58
58
59
    if ($item) {
59
    if ($item) {
60
60
61
        $issue = $item->issue();
61
        $checkout = $item->checkout;
62
62
63
        if ($issue) {
63
        if ($checkout) {
64
64
65
            $borrower = $issue->patron();
65
            $patron = $checkout->patron;
66
            
66
67
            if ( ( $borrower->debarred() || q{} ) lt dt_from_string()->ymd() ) {
67
            if ( ( $patron->is_debarred || q{} ) lt dt_from_string()->ymd() ) {
68
                my $can_renew;
68
                my $can_renew;
69
                my $info;
69
                my $info;
70
                ( $can_renew, $error, $info ) =
70
                ( $can_renew, $error, $info ) =
71
                  CanBookBeRenewed( $borrower->borrowernumber(),
71
                  CanBookBeRenewed( $patron, $checkout, $override_limit );
72
                    $item->itemnumber(), $override_limit );
73
72
74
                if ( $error && ($error eq 'on_reserve') ) {
73
                if ( $error && ($error eq 'on_reserve') ) {
75
                    if ($override_holds) {
74
                    if ($override_holds) {
Lines 85-93 if ($barcode) { Link Here
85
                    $soonest_renew_date = $info->{soonest_renew_date};
84
                    $soonest_renew_date = $info->{soonest_renew_date};
86
                }
85
                }
87
                if ( $error && ( $error eq 'auto_too_late' ) ) {
86
                if ( $error && ( $error eq 'auto_too_late' ) ) {
88
                    $latest_auto_renew_date = C4::Circulation::GetLatestAutoRenewDate(
87
                    $latest_auto_renew_date = GetLatestAutoRenewDate(
89
                        $borrower->borrowernumber(),
88
                        $patron,
90
                        $item->itemnumber(),
89
                        $checkout,
91
                    );
90
                    );
92
                }
91
                }
93
                if ($can_renew) {
92
                if ($can_renew) {
Lines 124-131 if ($barcode) { Link Here
124
123
125
    $template->param(
124
    $template->param(
126
        item     => $item,
125
        item     => $item,
127
        issue    => $issue,
126
        issue    => $checkout,
128
        borrower => $borrower,
127
        borrower => $patron,
129
        error    => $error,
128
        error    => $error,
130
        soonestrenewdate => $soonest_renew_date,
129
        soonestrenewdate => $soonest_renew_date,
131
        latestautorenewdate => $latest_auto_renew_date,
130
        latestautorenewdate => $latest_auto_renew_date,
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/renew_strings.inc (+2 lines)
Lines 27-32 Link Here
27
    <span>Item is an onsite checkout</span>
27
    <span>Item is an onsite checkout</span>
28
[% CASE 'has_fine' %]
28
[% CASE 'has_fine' %]
29
    <span>Item has an outstanding fine</span>
29
    <span>Item has an outstanding fine</span>
30
[% CASE 'item_issued_to_other_patron'%]
31
    <span>Item already issued to other borrower</span>
30
[% CASE %]
32
[% CASE %]
31
    <span>Unknown error</span>
33
    <span>Unknown error</span>
32
[% END %]
34
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt (+2 lines)
Lines 108-113 Link Here
108
                                            <li>This item is on hold for another borrower.</li>
108
                                            <li>This item is on hold for another borrower.</li>
109
                                        [% ELSIF error == 'item_denied_renewal' %]
109
                                        [% ELSIF error == 'item_denied_renewal' %]
110
                                            <li>Item renewal is not allowed.</li>
110
                                            <li>Item renewal is not allowed.</li>
111
                                        [% ELSIF error == 'item_issued_to_other_patron'%]
112
                                            <li>Item already issued to other borrower.</li>
111
                                        [% ELSIF error == 'auto_too_soon' %]
113
                                        [% ELSIF error == 'auto_too_soon' %]
112
                                            <li>This item is scheduled for auto renewal.</li>
114
                                            <li>This item is scheduled for auto renewal.</li>
113
                                        [% END %]
115
                                        [% END %]
(-)a/misc/cronjobs/automatic_renewals.pl (-11 / +14 lines)
Lines 169-175 while ( my $auto_renew = $auto_renews->next ) { Link Here
169
    }
169
    }
170
170
171
    # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script
171
    # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script
172
    my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->borrowernumber, $auto_renew->itemnumber, undef, 1 );
172
    my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->patron, $auto_renew, undef, 1 );
173
    my $updated;
173
    my $updated;
174
    if ( $error eq 'auto_renew' ) {
174
    if ( $error eq 'auto_renew' ) {
175
        $updated = 1;
175
        $updated = 1;
Lines 183-198 while ( my $auto_renew = $auto_renews->next ) { Link Here
183
        }
183
        }
184
        push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
184
        push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
185
            if ( $wants_messages ) && !$wants_digest;
185
            if ( $wants_messages ) && !$wants_digest;
186
    } elsif ( $error eq 'too_many'
186
    } elsif (
187
        or $error eq 'on_reserve'
187
        $error eq 'too_many' ||
188
        or $error eq 'restriction'
188
        $error eq 'on_reserve' ||
189
        or $error eq 'overdue'
189
        $error eq 'restriction' ||
190
        or $error eq 'too_unseen'
190
        $error eq 'overdue' ||
191
        or $error eq 'auto_account_expired'
191
        $error eq 'too_unseen' ||
192
        or $error eq 'auto_too_late'
192
        $error eq 'auto_account_expired' ||
193
        or $error eq 'auto_too_much_oweing'
193
        $error eq 'auto_too_late' ||
194
        or $error eq 'auto_too_soon'
194
        $error eq 'auto_too_much_oweing' ||
195
        or $error eq 'item_denied_renewal' ) {
195
        $error eq 'auto_too_soon' ||
196
        $error eq 'item_denied_renewal' ||
197
        $error eq 'item_issued_to_other_patron'
198
    ) {
196
        if ( $verbose ) {
199
        if ( $verbose ) {
197
            say sprintf "Issue id: %s for borrower: %s and item: %s %s not be renewed. (%s)",
200
            say sprintf "Issue id: %s for borrower: %s and item: %s %s not be renewed. (%s)",
198
              $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would', $error;
201
              $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would', $error;
(-)a/opac/opac-renew.pl (-1 / +2 lines)
Lines 56-63 if ( $patron->category->effective_BlockExpiredPatronOpacActions Link Here
56
else {
56
else {
57
    my @renewed;
57
    my @renewed;
58
    for my $itemnumber (@items) {
58
    for my $itemnumber (@items) {
59
        my $item = Koha::Items->find($itemnumber);
59
        my ( $status, $error ) =
60
        my ( $status, $error ) =
60
          CanBookBeRenewed( $borrowernumber, $itemnumber );
61
          CanBookBeRenewed( $patron, $item->checkout ); #TODO: Pass issue numbers instead
61
        if ( $status == 1 && $opacrenew == 1 ) {
62
        if ( $status == 1 && $opacrenew == 1 ) {
62
            AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 );
63
            AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 );
63
            push( @renewed, $itemnumber );
64
            push( @renewed, $itemnumber );
(-)a/opac/opac-user.pl (-3 / +10 lines)
Lines 187-193 my $overdues_count = 0; Link Here
187
my @overdues;
187
my @overdues;
188
my @issuedat;
188
my @issuedat;
189
my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
189
my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
190
my $pending_checkouts = $patron->pending_checkouts->search({}, { order_by => [ { -desc => 'date_due' }, { -asc => 'issue_id' } ] });
190
my $pending_checkouts = $patron->pending_checkouts->search(
191
    {},
192
    {
193
        order_by => [ { -desc => 'date_due' }, { -asc => 'issue_id' } ],
194
        prefetch => 'item'
195
    }
196
);
191
my $are_renewable_items = 0;
197
my $are_renewable_items = 0;
192
if ( $pending_checkouts->count ) { # Useless test
198
if ( $pending_checkouts->count ) { # Useless test
193
    while ( my $c = $pending_checkouts->next ) {
199
    while ( my $c = $pending_checkouts->next ) {
Lines 220-226 if ( $pending_checkouts->count ) { # Useless test Link Here
220
        $issue->{rentalfines} = $rental_fines->total_outstanding;
226
        $issue->{rentalfines} = $rental_fines->total_outstanding;
221
227
222
        # check if item is renewable
228
        # check if item is renewable
223
        my ($status,$renewerror,$info) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} );
229
        my ($status, $renewerror, $info) = CanBookBeRenewed( $patron, $c );
224
        (
230
        (
225
            $issue->{'renewcount'},
231
            $issue->{'renewcount'},
226
            $issue->{'renewsallowed'},
232
            $issue->{'renewsallowed'},
Lines 230-236 if ( $pending_checkouts->count ) { # Useless test Link Here
230
            $issue->{'unseenleft'}
236
            $issue->{'unseenleft'}
231
        ) = GetRenewCount($borrowernumber, $issue->{'itemnumber'});
237
        ) = GetRenewCount($borrowernumber, $issue->{'itemnumber'});
232
        ( $issue->{'renewalfee'}, $issue->{'renewalitemtype'} ) = GetIssuingCharges( $issue->{'itemnumber'}, $borrowernumber );
238
        ( $issue->{'renewalfee'}, $issue->{'renewalitemtype'} ) = GetIssuingCharges( $issue->{'itemnumber'}, $borrowernumber );
233
        $issue->{itemtype_object} = Koha::ItemTypes->find( Koha::Items->find( $issue->{itemnumber} )->effective_itemtype );
239
        $issue->{itemtype_object} = Koha::ItemTypes->find( $c->item->effective_itemtype );
234
        if($status && C4::Context->preference("OpacRenewalAllowed")){
240
        if($status && C4::Context->preference("OpacRenewalAllowed")){
235
            $are_renewable_items = 1;
241
            $are_renewable_items = 1;
236
            $issue->{'status'} = $status;
242
            $issue->{'status'} = $status;
Lines 248-253 if ( $pending_checkouts->count ) { # Useless test Link Here
248
            $issue->{'auto_too_late'}  = 1 if $renewerror eq 'auto_too_late';
254
            $issue->{'auto_too_late'}  = 1 if $renewerror eq 'auto_too_late';
249
            $issue->{'auto_too_much_oweing'}  = 1 if $renewerror eq 'auto_too_much_oweing';
255
            $issue->{'auto_too_much_oweing'}  = 1 if $renewerror eq 'auto_too_much_oweing';
250
            $issue->{'item_denied_renewal'}  = 1 if $renewerror eq 'item_denied_renewal';
256
            $issue->{'item_denied_renewal'}  = 1 if $renewerror eq 'item_denied_renewal';
257
            $issue->{'item_issued_to_other_patron'} = 1 if $renewerror eq 'item_issued_to_other_patron';
251
258
252
            if ( $renewerror eq 'too_soon' ) {
259
            if ( $renewerror eq 'too_soon' ) {
253
                $issue->{'too_soon'}         = 1;
260
                $issue->{'too_soon'}         = 1;
(-)a/opac/sco/sco-main.pl (-5 / +2 lines)
Lines 279-285 if ( $patron && ( $op eq 'renew' ) ) { Link Here
279
    my $item = Koha::Items->find({ barcode => $barcode });
279
    my $item = Koha::Items->find({ barcode => $barcode });
280
280
281
    if ( $patron->checkouts->find( { itemnumber => $item->itemnumber } ) ) {
281
    if ( $patron->checkouts->find( { itemnumber => $item->itemnumber } ) ) {
282
        my ($status,$renewerror) = CanBookBeRenewed( $patron->borrowernumber, $item->itemnumber );
282
        my ($status,$renewerror) = CanBookBeRenewed( $patron, $item->checkout );
283
        if ($status) {
283
        if ($status) {
284
            AddRenewal( $patron->borrowernumber, $item->itemnumber, undef, undef, undef, undef, 1 );
284
            AddRenewal( $patron->borrowernumber, $item->itemnumber, undef, undef, undef, undef, 1 );
285
            push @newissueslist, $barcode;
285
            push @newissueslist, $barcode;
Lines 296-305 if ( $patron) { Link Here
296
    my @checkouts;
296
    my @checkouts;
297
    while ( my $c = $pending_checkouts->next ) {
297
    while ( my $c = $pending_checkouts->next ) {
298
        my $checkout = $c->unblessed_all_relateds;
298
        my $checkout = $c->unblessed_all_relateds;
299
        my ($can_be_renewed, $renew_error) = CanBookBeRenewed(
299
        my ($can_be_renewed, $renew_error) = CanBookBeRenewed( $patron, $c );
300
            $patron->borrowernumber,
301
            $checkout->{itemnumber},
302
        );
303
        $checkout->{can_be_renewed} = $can_be_renewed; # In the future this will be $checkout->can_be_renewed
300
        $checkout->{can_be_renewed} = $can_be_renewed; # In the future this will be $checkout->can_be_renewed
304
        $checkout->{renew_error} = $renew_error;
301
        $checkout->{renew_error} = $renew_error;
305
        $checkout->{overdue} = $c->is_overdue;
302
        $checkout->{overdue} = $c->is_overdue;
(-)a/svc/checkouts (-1 / +3 lines)
Lines 67-72 print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); Link Here
67
my @parameters;
67
my @parameters;
68
my $sql = '
68
my $sql = '
69
    SELECT
69
    SELECT
70
        issues.issue_id,
70
        issues.issuedate,
71
        issues.issuedate,
71
        issues.date_due,
72
        issues.date_due,
72
        issues.date_due < now() as date_due_overdue,
73
        issues.date_due < now() as date_due_overdue,
Lines 154-161 while ( my $c = $sth->fetchrow_hashref() ) { Link Here
154
    my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} );
155
    my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} );
155
    my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} );
156
    my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} );
156
157
158
    my $checkout_obj = Koha::Checkouts->find( $c->{issue_id} );
157
    my ( $can_renew, $can_renew_error, $info ) =
159
    my ( $can_renew, $can_renew_error, $info ) =
158
      CanBookBeRenewed( $c->{borrowernumber}, $c->{itemnumber} );
160
      CanBookBeRenewed( $checkout_obj->patron, $checkout_obj );
159
    my $can_renew_date =
161
    my $can_renew_date =
160
      $can_renew_error && $can_renew_error eq 'too_soon'
162
      $can_renew_error && $can_renew_error eq 'too_soon'
161
      ? output_pref(
163
      ? output_pref(
(-)a/svc/renew (-1 / +4 lines)
Lines 58-65 $data->{itemnumber} = $itemnumber; Link Here
58
$data->{borrowernumber} = $borrowernumber;
58
$data->{borrowernumber} = $borrowernumber;
59
$data->{branchcode} = $branchcode;
59
$data->{branchcode} = $branchcode;
60
60
61
my $patron = Koha::Patrons->find($borrowernumber);
62
my $item = Koha::Items->find($itemnumber);
63
61
( $data->{renew_okay}, $data->{error} ) =
64
( $data->{renew_okay}, $data->{error} ) =
62
  CanBookBeRenewed( $borrowernumber, $itemnumber, $override_limit );
65
    CanBookBeRenewed( $patron, $item->checkout, $override_limit );
63
66
64
# If we're allowing reserved items to be renewed...
67
# If we're allowing reserved items to be renewed...
65
if ( $data->{error} && $data->{error} eq 'on_reserve' && C4::Context->preference('AllowRenewalOnHoldOverride')) {
68
if ( $data->{error} && $data->{error} eq 'on_reserve' && C4::Context->preference('AllowRenewalOnHoldOverride')) {
(-)a/t/db_dependent/Circulation.t (-185 / +178 lines)
Lines 310-316 subtest "CanBookBeRenewed AllowRenewalIfOtherItemsAvailable multiple borrowers a Link Here
310
    );
310
    );
311
311
312
    # Patrons from three different branches
312
    # Patrons from three different branches
313
    my $patron_borrower = $builder->build_object({ class => 'Koha::Patrons' });
313
    my $patron = $builder->build_object({ class => 'Koha::Patrons' });
314
    my $patron_hold_1   = $builder->build_object({ class => 'Koha::Patrons' });
314
    my $patron_hold_1   = $builder->build_object({ class => 'Koha::Patrons' });
315
    my $patron_hold_2   = $builder->build_object({ class => 'Koha::Patrons' });
315
    my $patron_hold_2   = $builder->build_object({ class => 'Koha::Patrons' });
316
    my $biblio = $builder->build_sample_biblio();
316
    my $biblio = $builder->build_sample_biblio();
Lines 318-324 subtest "CanBookBeRenewed AllowRenewalIfOtherItemsAvailable multiple borrowers a Link Here
318
    # Item at each patron branch
318
    # Item at each patron branch
319
    my $item_1 = $builder->build_sample_item({
319
    my $item_1 = $builder->build_sample_item({
320
        biblionumber => $biblio->biblionumber,
320
        biblionumber => $biblio->biblionumber,
321
        homebranch   => $patron_borrower->branchcode
321
        homebranch   => $patron->branchcode
322
    });
322
    });
323
    my $item_2 = $builder->build_sample_item({
323
    my $item_2 = $builder->build_sample_item({
324
        biblionumber => $biblio->biblionumber,
324
        biblionumber => $biblio->biblionumber,
Lines 329-335 subtest "CanBookBeRenewed AllowRenewalIfOtherItemsAvailable multiple borrowers a Link Here
329
        homebranch   => $patron_hold_1->branchcode
329
        homebranch   => $patron_hold_1->branchcode
330
    });
330
    });
331
331
332
    my $issue = AddIssue( $patron_borrower->unblessed, $item_1->barcode);
332
    my $issue = AddIssue( $patron->unblessed, $item_1->barcode);
333
    my $datedue = dt_from_string( $issue->date_due() );
333
    my $datedue = dt_from_string( $issue->date_due() );
334
    is (defined $issue->date_due(), 1, "Item 1 checked out, due date: " . $issue->date_due() );
334
    is (defined $issue->date_due(), 1, "Item 1 checked out, due date: " . $issue->date_due() );
335
335
Lines 360-376 subtest "CanBookBeRenewed AllowRenewalIfOtherItemsAvailable multiple borrowers a Link Here
360
    );
360
    );
361
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 0 );
361
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 0 );
362
362
363
    my ( $renewokay, $error ) = CanBookBeRenewed($patron_borrower->borrowernumber, $item_1->itemnumber);
363
    my ( $renewokay, $error ) = CanBookBeRenewed($patron, $issue);
364
    is( $renewokay, 0, 'Cannot renew, reserved');
364
    is( $renewokay, 0, 'Cannot renew, reserved');
365
    is( $error, 'on_reserve', 'Cannot renew, reserved (returned error is on_reserve)');
365
    is( $error, 'on_reserve', 'Cannot renew, reserved (returned error is on_reserve)');
366
366
367
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
367
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
368
368
369
    ( $renewokay, $error ) = CanBookBeRenewed($patron_borrower->borrowernumber, $item_1->itemnumber);
369
    ( $renewokay, $error ) = CanBookBeRenewed($patron, $issue);
370
    is( $renewokay, 1, 'Can renew, two items available for two holds');
370
    is( $renewokay, 1, 'Can renew, two items available for two holds');
371
    is( $error, undef, 'Can renew, each reserve has an item');
371
    is( $error, undef, 'Can renew, each reserve has an item');
372
372
373
374
};
373
};
375
374
376
subtest "GetIssuingCharges tests" => sub {
375
subtest "GetIssuingCharges tests" => sub {
Lines 463-468 subtest "CanBookBeRenewed tests" => sub { Link Here
463
        surname => 'Renewal',
462
        surname => 'Renewal',
464
        categorycode => $patron_category->{categorycode},
463
        categorycode => $patron_category->{categorycode},
465
        branchcode => $branch,
464
        branchcode => $branch,
465
        autorenew_checkouts => 1,
466
    );
466
    );
467
467
468
    my %reserving_borrower_data = (
468
    my %reserving_borrower_data = (
Lines 493-510 subtest "CanBookBeRenewed tests" => sub { Link Here
493
        categorycode => $patron_category->{categorycode},
493
        categorycode => $patron_category->{categorycode},
494
        branchcode => $branch,
494
        branchcode => $branch,
495
        dateexpiry => dt_from_string->subtract( months => 1 ),
495
        dateexpiry => dt_from_string->subtract( months => 1 ),
496
        autorenew_checkouts => 1,
496
    );
497
    );
497
498
498
    my $renewing_borrowernumber = Koha::Patron->new(\%renewing_borrower_data)->store->borrowernumber;
499
    my $renewing_borrower_obj = Koha::Patron->new(\%renewing_borrower_data)->store;
500
    my $renewing_borrowernumber = $renewing_borrower_obj->borrowernumber;
499
    my $reserving_borrowernumber = Koha::Patron->new(\%reserving_borrower_data)->store->borrowernumber;
501
    my $reserving_borrowernumber = Koha::Patron->new(\%reserving_borrower_data)->store->borrowernumber;
500
    my $hold_waiting_borrowernumber = Koha::Patron->new(\%hold_waiting_borrower_data)->store->borrowernumber;
502
    my $hold_waiting_borrowernumber = Koha::Patron->new(\%hold_waiting_borrower_data)->store->borrowernumber;
501
    my $restricted_borrowernumber = Koha::Patron->new(\%restricted_borrower_data)->store->borrowernumber;
503
    my $restricted_borrower_obj = Koha::Patron->new(\%restricted_borrower_data)->store;
502
    my $expired_borrowernumber = Koha::Patron->new(\%expired_borrower_data)->store->borrowernumber;
503
504
504
    my $renewing_borrower_obj = Koha::Patrons->find( $renewing_borrowernumber );
505
    my $expired_borrower_obj = Koha::Patron->new(\%expired_borrower_data)->store;
505
    my $renewing_borrower = $renewing_borrower_obj->unblessed;
506
    my $restricted_borrower = Koha::Patrons->find( $restricted_borrowernumber )->unblessed;
507
    my $expired_borrower = Koha::Patrons->find( $expired_borrowernumber )->unblessed;
508
506
509
    my $bibitems       = '';
507
    my $bibitems       = '';
510
    my $priority       = '1';
508
    my $priority       = '1';
Lines 514-532 subtest "CanBookBeRenewed tests" => sub { Link Here
514
    my $checkitem      = undef;
512
    my $checkitem      = undef;
515
    my $found          = undef;
513
    my $found          = undef;
516
514
517
    my $issue = AddIssue( $renewing_borrower, $item_1->barcode);
515
    my $issue_1 = AddIssue( $renewing_borrower_obj->unblessed, $item_1->barcode);
518
    my $datedue = dt_from_string( $issue->date_due() );
516
    my $datedue = dt_from_string( $issue_1->date_due() );
519
    is (defined $issue->date_due(), 1, "Item 1 checked out, due date: " . $issue->date_due() );
517
    is (defined $issue_1->date_due(), 1, "Item 1 checked out, due date: " . $issue_1->date_due() );
520
521
    my $issue2 = AddIssue( $renewing_borrower, $item_2->barcode);
522
    $datedue = dt_from_string( $issue->date_due() );
523
    is (defined $issue2, 1, "Item 2 checked out, due date: " . $issue2->date_due());
524
518
519
    my $issue_2 = AddIssue( $renewing_borrower_obj->unblessed, $item_2->barcode);
520
    is (defined $issue_2, 1, "Item 2 checked out, due date: " . $issue_2->date_due());
525
521
526
    my $borrowing_borrowernumber = Koha::Checkouts->find( { itemnumber => $item_1->itemnumber } )->borrowernumber;
522
    my $borrowing_borrowernumber = Koha::Checkouts->find( { itemnumber => $item_1->itemnumber } )->borrowernumber;
527
    is ($borrowing_borrowernumber, $renewing_borrowernumber, "Item checked out to $renewing_borrower->{firstname} $renewing_borrower->{surname}");
523
    is ($borrowing_borrowernumber, $renewing_borrowernumber, "Item checked out to ".$renewing_borrower_obj->firstname." ".$renewing_borrower_obj->surname);
528
524
529
    my ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber, 1);
525
    my ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1, 1);
530
    is( $renewokay, 1, 'Can renew, no holds for this title or item');
526
    is( $renewokay, 1, 'Can renew, no holds for this title or item');
531
527
532
528
Lines 565-573 subtest "CanBookBeRenewed tests" => sub { Link Here
565
        }
561
        }
566
    );
562
    );
567
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
563
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 1 );
568
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
564
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
569
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
565
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
570
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
566
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_2);
571
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
567
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
572
568
573
569
Lines 585-591 subtest "CanBookBeRenewed tests" => sub { Link Here
585
            found            => $found,
581
            found            => $found,
586
        }
582
        }
587
    );
583
    );
588
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
584
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
589
    is( $renewokay, 0, 'Renewal not possible when single patron\'s holds exceed the number of available items');
585
    is( $renewokay, 0, 'Renewal not possible when single patron\'s holds exceed the number of available items');
590
    Koha::Holds->find($reserve_id)->delete;
586
    Koha::Holds->find($reserve_id)->delete;
591
587
Lines 600-606 subtest "CanBookBeRenewed tests" => sub { Link Here
600
            reservedate    => '1999-01-01',
596
            reservedate    => '1999-01-01',
601
        }
597
        }
602
    );
598
    );
603
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
599
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
604
    is( $renewokay, 0, 'Bug 13919 - Renewal possible with item level hold on item');
600
    is( $renewokay, 0, 'Bug 13919 - Renewal possible with item level hold on item');
605
    $hold->delete();
601
    $hold->delete();
606
602
Lines 616-632 subtest "CanBookBeRenewed tests" => sub { Link Here
616
            found          => 'W'
612
            found          => 'W'
617
        }
613
        }
618
    );
614
    );
619
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
615
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
620
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
616
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
621
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
617
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_2);
622
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
618
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
623
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 0 );
619
    t::lib::Mocks::mock_preference('AllowRenewalIfOtherItemsAvailable', 0 );
624
620
625
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
621
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
626
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
622
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
627
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
623
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
628
624
629
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
625
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_2);
630
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
626
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
631
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
627
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
632
628
Lines 655-670 subtest "CanBookBeRenewed tests" => sub { Link Here
655
        }
651
        }
656
    );
652
    );
657
653
658
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber, 1);
654
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1, 1);
659
    is( $renewokay, 0, '(Bug 10663) Cannot renew, item reserved');
655
    is( $renewokay, 0, '(Bug 10663) Cannot renew, item reserved');
660
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, item reserved (returned error is on_reserve)');
656
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, item reserved (returned error is on_reserve)');
661
657
662
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber, 1);
658
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_2, 1);
663
    is( $renewokay, 1, 'Can renew item 2, item-level hold is on item 1');
659
    is( $renewokay, 1, 'Can renew item 2, item-level hold is on item 1');
664
660
665
    # Items can't fill hold for reasons
661
    # Items can't fill hold for reasons
666
    $item_1->notforloan(1)->store;
662
    $issue_1->item->notforloan(1)->store;
667
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber, 1);
663
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1, 1);
668
    is( $renewokay, 1, 'Can renew, item is marked not for loan, hold does not block');
664
    is( $renewokay, 1, 'Can renew, item is marked not for loan, hold does not block');
669
    $item_1->set({notforloan => 0, itype => $itemtype })->store;
665
    $item_1->set({notforloan => 0, itype => $itemtype })->store;
670
666
Lines 679-691 subtest "CanBookBeRenewed tests" => sub { Link Here
679
            itype            => $itemtype,
675
            itype            => $itemtype,
680
        }
676
        }
681
    );
677
    );
682
    my $datedue5 = AddIssue($restricted_borrower, $item_5->barcode);
678
    my $issue_5 = AddIssue($restricted_borrower_obj->unblessed, $item_5->barcode);
683
    is (defined $datedue5, 1, "Item with date due checked out, due date: $datedue5");
679
    is (defined $issue_5, 1, "Item with date due checked out, due date: ". $issue_5->date_due);
684
680
685
    t::lib::Mocks::mock_preference('RestrictionBlockRenewing','1');
681
    t::lib::Mocks::mock_preference('RestrictionBlockRenewing','1');
686
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
682
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_2);
687
    is( $renewokay, 1, '(Bug 8236), Can renew, user is not restricted');
683
    is( $renewokay, 1, '(Bug 8236), Can renew, user is not restricted');
688
    ( $renewokay, $error ) = CanBookBeRenewed($restricted_borrowernumber, $item_5->itemnumber);
684
    ( $renewokay, $error ) = CanBookBeRenewed($restricted_borrower_obj, $issue_5);
689
    is( $renewokay, 0, '(Bug 8236), Cannot renew, user is restricted');
685
    is( $renewokay, 0, '(Bug 8236), Cannot renew, user is restricted');
690
    is( $error, 'restriction', "Correct error returned");
686
    is( $error, 'restriction', "Correct error returned");
691
687
Lines 708-751 subtest "CanBookBeRenewed tests" => sub { Link Here
708
        }
704
        }
709
    );
705
    );
710
706
711
    my $datedue6 = AddIssue( $renewing_borrower, $item_6->barcode);
707
    my $issue_6 = AddIssue( $renewing_borrower_obj->unblessed, $item_6->barcode);
712
    is (defined $datedue6, 1, "Item 2 checked out, due date: ".$datedue6->date_due);
708
    is (defined $issue_6, 1, "Item 2 checked out, due date: ".$issue_6->date_due);
713
709
714
    my $now = dt_from_string();
710
    my $now = dt_from_string();
715
    my $five_weeks = DateTime::Duration->new(weeks => 5);
711
    my $five_weeks = DateTime::Duration->new(weeks => 5);
716
    my $five_weeks_ago = $now - $five_weeks;
712
    my $five_weeks_ago = $now - $five_weeks;
717
    t::lib::Mocks::mock_preference('finesMode', 'production');
713
    t::lib::Mocks::mock_preference('finesMode', 'production');
718
714
719
    my $passeddatedue1 = AddIssue($renewing_borrower, $item_7->barcode, $five_weeks_ago);
715
    my $issue_7 = AddIssue($renewing_borrower_obj->unblessed, $item_7->barcode, $five_weeks_ago);
720
    is (defined $passeddatedue1, 1, "Item with passed date due checked out, due date: " . $passeddatedue1->date_due);
716
    is (defined $issue_7, 1, "Item with passed date due checked out, due date: " . $issue_7->date_due);
721
717
722
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','allow');
718
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','allow');
723
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_6->itemnumber);
719
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_6);
724
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is not overdue');
720
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is not overdue');
725
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_7->itemnumber);
721
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_7);
726
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is overdue but not pref does not block');
722
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is overdue but not pref does not block');
727
723
728
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','block');
724
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','block');
729
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_6->itemnumber);
725
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_6);
730
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is not overdue but patron has overdues');
726
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is not overdue but patron has overdues');
731
    is( $error, 'overdue', "Correct error returned");
727
    is( $error, 'overdue', "Correct error returned");
732
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_7->itemnumber);
728
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_7);
733
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is overdue so patron has overdues');
729
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is overdue so patron has overdues');
734
    is( $error, 'overdue', "Correct error returned");
730
    is( $error, 'overdue', "Correct error returned");
735
731
736
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','blockitem');
732
    t::lib::Mocks::mock_preference('OverduesBlockRenewing','blockitem');
737
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_6->itemnumber);
733
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_6);
738
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is not overdue');
734
    is( $renewokay, 1, '(Bug 8236), Can renew, this item is not overdue');
739
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_7->itemnumber);
735
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_7);
740
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is overdue');
736
    is( $renewokay, 0, '(Bug 8236), Cannot renew, this item is overdue');
741
    is( $error, 'overdue', "Correct error returned");
737
    is( $error, 'overdue', "Correct error returned");
742
738
743
    my ( $fine ) = CalcFine( $item_7->unblessed, $renewing_borrower->{categorycode}, $branch, $five_weeks_ago, $now );
739
    my ( $fine ) = CalcFine( $item_7->unblessed, $renewing_borrower_obj->categorycode, $branch, $five_weeks_ago, $now );
744
    C4::Overdues::UpdateFine(
740
    C4::Overdues::UpdateFine(
745
        {
741
        {
746
            issue_id       => $passeddatedue1->id(),
742
            issue_id       => $issue_7->id(),
747
            itemnumber     => $item_7->itemnumber,
743
            itemnumber     => $item_7->itemnumber,
748
            borrowernumber => $renewing_borrower->{borrowernumber},
744
            borrowernumber => $renewing_borrower_obj->borrowernumber,
749
            amount         => $fine,
745
            amount         => $fine,
750
            due            => Koha::DateUtils::output_pref($five_weeks_ago)
746
            due            => Koha::DateUtils::output_pref($five_weeks_ago)
751
        }
747
        }
Lines 776-782 subtest "CanBookBeRenewed tests" => sub { Link Here
776
    my $old_log_size = Koha::ActionLogs->count( \%params_renewal );
772
    my $old_log_size = Koha::ActionLogs->count( \%params_renewal );
777
    my $dt = dt_from_string();
773
    my $dt = dt_from_string();
778
    Time::Fake->offset( $dt->epoch );
774
    Time::Fake->offset( $dt->epoch );
779
    my $datedue1 = AddRenewal( $renewing_borrower->{borrowernumber}, $item_7->itemnumber, $branch );
775
    my $datedue1 = AddRenewal( $renewing_borrower_obj->borrowernumber, $item_7->itemnumber, $branch );
780
    my $new_log_size = Koha::ActionLogs->count( \%params_renewal );
776
    my $new_log_size = Koha::ActionLogs->count( \%params_renewal );
781
    is ($new_log_size, $old_log_size, 'renew log not added because of the syspref RenewalLog');
777
    is ($new_log_size, $old_log_size, 'renew log not added because of the syspref RenewalLog');
782
    isnt (DateTime->compare($datedue1, $dt), 0, "AddRenewal returned a good duedate");
778
    isnt (DateTime->compare($datedue1, $dt), 0, "AddRenewal returned a good duedate");
Lines 785-802 subtest "CanBookBeRenewed tests" => sub { Link Here
785
    t::lib::Mocks::mock_preference('RenewalLog', 1);
781
    t::lib::Mocks::mock_preference('RenewalLog', 1);
786
    $date = output_pref( { dt => dt_from_string(), dateonly => 1, dateformat => 'iso' } );
782
    $date = output_pref( { dt => dt_from_string(), dateonly => 1, dateformat => 'iso' } );
787
    $old_log_size = Koha::ActionLogs->count( \%params_renewal );
783
    $old_log_size = Koha::ActionLogs->count( \%params_renewal );
788
    AddRenewal( $renewing_borrower->{borrowernumber}, $item_7->itemnumber, $branch );
784
    AddRenewal( $renewing_borrower_obj->borrowernumber, $item_7->itemnumber, $branch );
789
    $new_log_size = Koha::ActionLogs->count( \%params_renewal );
785
    $new_log_size = Koha::ActionLogs->count( \%params_renewal );
790
    is ($new_log_size, $old_log_size + 1, 'renew log successfully added');
786
    is ($new_log_size, $old_log_size + 1, 'renew log successfully added');
791
787
792
    my $fines = Koha::Account::Lines->search( { borrowernumber => $renewing_borrower->{borrowernumber}, itemnumber => $item_7->itemnumber } );
788
    my $fines = Koha::Account::Lines->search( { borrowernumber => $renewing_borrower_obj->borrowernumber, itemnumber => $item_7->itemnumber } );
793
    is( $fines->count, 1, 'AddRenewal left fine' );
789
    is( $fines->count, 1, 'AddRenewal left fine' );
794
    is( $fines->next->status, 'RENEWED', 'Fine on renewed item is closed out properly' );
790
    is( $fines->next->status, 'RENEWED', 'Fine on renewed item is closed out properly' );
795
    $fines->delete();
791
    $fines->delete();
796
792
797
    my $old_issue_log_size = Koha::ActionLogs->count( \%params_issue );
793
    my $old_issue_log_size = Koha::ActionLogs->count( \%params_issue );
798
    my $old_renew_log_size = Koha::ActionLogs->count( \%params_renewal );
794
    my $old_renew_log_size = Koha::ActionLogs->count( \%params_renewal );
799
    AddIssue( $renewing_borrower,$item_7->barcode,Koha::DateUtils::output_pref({str=>$datedue6->date_due, dateformat =>'iso'}),0,$date, 0, undef );
795
    AddIssue(
796
        $renewing_borrower_obj->unblessed,
797
        $item_7->barcode,
798
        Koha::DateUtils::output_pref({str=>$issue_6->date_due, dateformat =>'iso'}),
799
        0,
800
        $date,
801
        0,
802
        undef
803
    ); # TODO: Already issued???
800
    $new_log_size = Koha::ActionLogs->count( \%params_renewal );
804
    $new_log_size = Koha::ActionLogs->count( \%params_renewal );
801
    is ($new_log_size, $old_renew_log_size + 1, 'renew log successfully added when renewed via issuing');
805
    is ($new_log_size, $old_renew_log_size + 1, 'renew log successfully added when renewed via issuing');
802
    $new_log_size = Koha::ActionLogs->count( \%params_issue );
806
    $new_log_size = Koha::ActionLogs->count( \%params_issue );
Lines 817-830 subtest "CanBookBeRenewed tests" => sub { Link Here
817
        }
821
        }
818
    );
822
    );
819
823
820
    $issue = AddIssue( $renewing_borrower, $item_4->barcode, undef, undef, undef, undef, { auto_renew => 1 } );
824
    my $issue_4 = AddIssue( $renewing_borrower_obj->unblessed, $item_4->barcode, undef, undef, undef, undef, { auto_renew => 1 } );
821
    my $info;
825
    my $info;
822
    ( $renewokay, $error, $info ) =
826
    ( $renewokay, $error, $info ) =
823
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
827
      CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
824
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
828
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
825
    is( $error, 'auto_too_soon',
829
    is( $error, 'auto_too_soon',
826
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = undef (returned code is auto_too_soon)' );
830
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = undef (returned code is auto_too_soon)' );
827
    is( $info->{soonest_renew_date} , dt_from_string($issue->date_due), "Due date is returned as earliest renewal date when error is 'auto_too_soon'" );
831
    is( $info->{soonest_renew_date} , dt_from_string($issue_4->date_due), "Due date is returned as earliest renewal date when error is 'auto_too_soon'" );
828
    AddReserve(
832
    AddReserve(
829
        {
833
        {
830
            branchcode       => $branch,
834
            branchcode       => $branch,
Lines 840-869 subtest "CanBookBeRenewed tests" => sub { Link Here
840
            found            => $found
844
            found            => $found
841
        }
845
        }
842
    );
846
    );
843
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
847
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
844
    is( $renewokay, 0, 'Still should not be able to renew' );
848
    is( $renewokay, 0, 'Still should not be able to renew' );
845
    is( $error, 'on_reserve', 'returned code is on_reserve, reserve checked when not checking for cron' );
849
    is( $error, 'on_reserve', 'returned code is on_reserve, reserve checked when not checking for cron' );
846
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, undef, 1 );
850
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4, undef, 1 );
847
    is( $renewokay, 0, 'Still should not be able to renew' );
851
    is( $renewokay, 0, 'Still should not be able to renew' );
848
    is( $error, 'auto_too_soon', 'returned code is auto_too_soon, reserve not checked when checking for cron' );
852
    is( $error, 'auto_too_soon', 'returned code is auto_too_soon, reserve not checked when checking for cron' );
849
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due), "Due date is returned as earliest renewal date when error is 'auto_too_soon'" );
853
    is( $info->{soonest_renew_date}, dt_from_string($issue_4->date_due), "Due date is returned as earliest renewal date when error is 'auto_too_soon'" );
850
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, 1 );
854
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4, 1 );
851
    is( $renewokay, 0, 'Still should not be able to renew' );
855
    is( $renewokay, 0, 'Still should not be able to renew' );
852
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_too_soon limit is overridden' );
856
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_too_soon limit is overridden' );
853
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, 1, 1 );
857
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4, 1, 1 );
854
    is( $renewokay, 0, 'Still should not be able to renew' );
858
    is( $renewokay, 0, 'Still should not be able to renew' );
855
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_too_soon limit is overridden' );
859
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_too_soon limit is overridden' );
856
    $dbh->do('UPDATE circulation_rules SET rule_value = 0 where rule_name = "norenewalbefore"');
860
    $dbh->do('UPDATE circulation_rules SET rule_value = 0 where rule_name = "norenewalbefore"');
857
    Koha::Cache::Memory::Lite->flush();
861
    Koha::Cache::Memory::Lite->flush();
858
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber, 1 );
862
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4, 1 );
859
    is( $renewokay, 0, 'Still should not be able to renew' );
863
    is( $renewokay, 0, 'Still should not be able to renew' );
860
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_renew only happens if not on reserve' );
864
    is( $error, 'on_reserve', 'returned code is on_reserve, auto_renew only happens if not on reserve' );
861
    ModReserveCancelAll($item_4->itemnumber, $reserving_borrowernumber);
865
    ModReserveCancelAll($item_4->itemnumber, $reserving_borrowernumber);
862
866
863
867
    $renewing_borrower_obj = Koha::Patrons->find($renewing_borrower_obj->borrowernumber);
864
865
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
868
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
866
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
869
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
867
    is( $renewokay, 1, 'No renewal before is undef, but patron opted out of auto_renewal' );
870
    is( $renewokay, 1, 'No renewal before is undef, but patron opted out of auto_renewal' );
868
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
871
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
869
872
Lines 880-905 subtest "CanBookBeRenewed tests" => sub { Link Here
880
        }
883
        }
881
    );
884
    );
882
885
883
    ( $renewokay, $error, $info ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
886
    ( $renewokay, $error, $info ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
884
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
887
    is( $renewokay, 0, 'Bug 7413: Cannot renew, renewal is premature');
885
    is( $error, 'too_soon', 'Bug 7413: Cannot renew, renewal is premature (returned code is too_soon)');
888
    is( $error, 'too_soon', 'Bug 7413: Cannot renew, renewal is premature (returned code is too_soon)');
886
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'too_soon'");
889
    is( $info->{soonest_renew_date}, dt_from_string($issue_1->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'too_soon'");
887
890
888
    # Bug 14101
891
    # Bug 14101
889
    # Test premature automatic renewal
892
    # Test premature automatic renewal
890
    ( $renewokay, $error, $info ) =
893
    ( $renewokay, $error, $info ) =
891
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
894
      CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
892
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
895
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
893
    is( $error, 'auto_too_soon',
896
    is( $error, 'auto_too_soon',
894
        'Bug 14101: Cannot renew, renewal is automatic and premature (returned code is auto_too_soon)'
897
        'Bug 14101: Cannot renew, renewal is automatic and premature (returned code is auto_too_soon)'
895
    );
898
    );
896
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'auto_too_soon'");
899
    is( $info->{soonest_renew_date}, dt_from_string($issue_4->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'auto_too_soon'");
897
900
898
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
901
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
899
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
902
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
900
    is( $renewokay, 0, 'No renewal before is 7, patron opted out of auto_renewal still cannot renew early' );
903
    is( $renewokay, 0, 'No renewal before is 7, patron opted out of auto_renewal still cannot renew early' );
901
    is( $error, 'too_soon', 'Error is too_soon, no auto' );
904
    is( $error, 'too_soon', 'Error is too_soon, no auto' );
902
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'too_soon'");
905
    is( $info->{soonest_renew_date}, dt_from_string($issue_4->date_due)->subtract( days => 7 ), "Soonest renew date returned when error is 'too_soon'");
903
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
906
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
904
907
905
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
908
    # Change policy so that loans can only be renewed exactly on due date (0 days prior to due date)
Lines 907-924 subtest "CanBookBeRenewed tests" => sub { Link Here
907
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
910
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '0' WHERE rule_name = 'norenewalbefore'});
908
    Koha::Cache::Memory::Lite->flush();
911
    Koha::Cache::Memory::Lite->flush();
909
    ( $renewokay, $error, $info ) =
912
    ( $renewokay, $error, $info ) =
910
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
913
      CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
911
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
914
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic and premature' );
912
    is( $error, 'auto_too_soon',
915
    is( $error, 'auto_too_soon',
913
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = 0 (returned code is auto_too_soon)'
916
        'Bug 14101: Cannot renew, renewal is automatic and premature, "No renewal before" = 0 (returned code is auto_too_soon)'
914
    );
917
    );
915
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due), "Soonest renew date returned when error is 'auto_too_soon'");
918
    is( $info->{soonest_renew_date}, dt_from_string($issue_4->date_due), "Soonest renew date returned when error is 'auto_too_soon'");
916
919
917
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
920
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
918
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
921
    ( $renewokay, $error, $info ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
919
    is( $renewokay, 0, 'No renewal before is 0, patron opted out of auto_renewal still cannot renew early' );
922
    is( $renewokay, 0, 'No renewal before is 0, patron opted out of auto_renewal still cannot renew early' );
920
    is( $error, 'too_soon', 'Error is too_soon, no auto' );
923
    is( $error, 'too_soon', 'Error is too_soon, no auto' );
921
    is( $info->{soonest_renew_date}, dt_from_string($issue->date_due), "Soonest renew date returned when error is 'auto_too_soon'");
924
    is( $info->{soonest_renew_date}, dt_from_string($issue_4->date_due), "Soonest renew date returned when error is 'auto_too_soon'");
922
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
925
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
923
926
924
    # Change policy so that loans can be renewed 99 days prior to the due date
927
    # Change policy so that loans can be renewed 99 days prior to the due date
Lines 926-939 subtest "CanBookBeRenewed tests" => sub { Link Here
926
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
929
    $dbh->do(q{UPDATE circulation_rules SET rule_value = '99' WHERE rule_name = 'norenewalbefore'});
927
    Koha::Cache::Memory::Lite->flush();
930
    Koha::Cache::Memory::Lite->flush();
928
    ( $renewokay, $error ) =
931
    ( $renewokay, $error ) =
929
      CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
932
      CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
930
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
933
    is( $renewokay, 0, 'Bug 14101: Cannot renew, renewal is automatic' );
931
    is( $error, 'auto_renew',
934
    is( $error, 'auto_renew',
932
        'Bug 14101: Cannot renew, renewal is automatic (returned code is auto_renew)'
935
        'Bug 14101: Cannot renew, renewal is automatic (returned code is auto_renew)'
933
    );
936
    );
934
937
935
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
938
    $renewing_borrower_obj->autorenew_checkouts(0)->store;
936
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $item_4->itemnumber );
939
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $issue_4 );
937
    is( $renewokay, 1, 'No renewal before is 99, patron opted out of auto_renewal so can renew' );
940
    is( $renewokay, 1, 'No renewal before is 99, patron opted out of auto_renewal so can renew' );
938
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
941
    $renewing_borrower_obj->autorenew_checkouts(1)->store;
939
942
Lines 948-954 subtest "CanBookBeRenewed tests" => sub { Link Here
948
951
949
        my $ten_days_before = dt_from_string->add( days => -10 );
952
        my $ten_days_before = dt_from_string->add( days => -10 );
950
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
953
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
951
        AddIssue( $renewing_borrower, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
954
        my $issue = AddIssue( $renewing_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
952
955
953
        Koha::CirculationRules->set_rules(
956
        Koha::CirculationRules->set_rules(
954
            {
957
            {
Lines 962-968 subtest "CanBookBeRenewed tests" => sub { Link Here
962
            }
965
            }
963
        );
966
        );
964
        ( $renewokay, $error ) =
967
        ( $renewokay, $error ) =
965
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
968
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
966
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
969
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
967
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
970
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
968
971
Lines 978-984 subtest "CanBookBeRenewed tests" => sub { Link Here
978
            }
981
            }
979
        );
982
        );
980
        ( $renewokay, $error ) =
983
        ( $renewokay, $error ) =
981
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
984
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
982
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
985
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
983
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
986
        is( $error, 'auto_too_late', 'Cannot auto renew, too late - no_auto_renewal_after is inclusive(returned code is auto_too_late)' );
984
987
Lines 994-1000 subtest "CanBookBeRenewed tests" => sub { Link Here
994
            }
997
            }
995
        );
998
        );
996
        ( $renewokay, $error ) =
999
        ( $renewokay, $error ) =
997
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1000
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
998
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1001
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
999
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
1002
        is( $error, 'auto_too_soon', 'Cannot auto renew, too soon - no_auto_renewal_after is defined(returned code is auto_too_soon)' );
1000
1003
Lines 1010-1016 subtest "CanBookBeRenewed tests" => sub { Link Here
1010
            }
1013
            }
1011
        );
1014
        );
1012
        ( $renewokay, $error ) =
1015
        ( $renewokay, $error ) =
1013
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1016
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1014
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
1017
        is( $renewokay, 0,            'Do not renew, renewal is automatic' );
1015
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
1018
        is( $error,     'auto_renew', 'Cannot renew, renew is automatic' );
1016
1019
Lines 1027-1033 subtest "CanBookBeRenewed tests" => sub { Link Here
1027
            }
1030
            }
1028
        );
1031
        );
1029
        ( $renewokay, $error ) =
1032
        ( $renewokay, $error ) =
1030
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1033
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1031
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1034
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1032
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
1035
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
1033
1036
Lines 1044-1050 subtest "CanBookBeRenewed tests" => sub { Link Here
1044
            }
1047
            }
1045
        );
1048
        );
1046
        ( $renewokay, $error ) =
1049
        ( $renewokay, $error ) =
1047
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1050
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1048
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1051
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1049
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
1052
        is( $error, 'auto_too_late', 'Cannot renew, too late(returned code is auto_too_late)' );
1050
1053
Lines 1061-1067 subtest "CanBookBeRenewed tests" => sub { Link Here
1061
            }
1064
            }
1062
        );
1065
        );
1063
        ( $renewokay, $error ) =
1066
        ( $renewokay, $error ) =
1064
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1067
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1065
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1068
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1066
        is( $error, 'auto_renew', 'Cannot renew, renew is automatic' );
1069
        is( $error, 'auto_renew', 'Cannot renew, renew is automatic' );
1067
    };
1070
    };
Lines 1077-1083 subtest "CanBookBeRenewed tests" => sub { Link Here
1077
1080
1078
        my $ten_days_before = dt_from_string->add( days => -10 );
1081
        my $ten_days_before = dt_from_string->add( days => -10 );
1079
        my $ten_days_ahead = dt_from_string->add( days => 10 );
1082
        my $ten_days_ahead = dt_from_string->add( days => 10 );
1080
        AddIssue( $renewing_borrower, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1083
        my $issue = AddIssue( $renewing_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1081
1084
1082
        Koha::CirculationRules->set_rules(
1085
        Koha::CirculationRules->set_rules(
1083
            {
1086
            {
Lines 1105-1111 subtest "CanBookBeRenewed tests" => sub { Link Here
1105
            }
1108
            }
1106
        )->status('RETURNED')->store;
1109
        )->status('RETURNED')->store;
1107
        ( $renewokay, $error ) =
1110
        ( $renewokay, $error ) =
1108
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1111
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1109
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1112
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1110
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, patron has 5' );
1113
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, patron has 5' );
1111
1114
Lines 1119-1125 subtest "CanBookBeRenewed tests" => sub { Link Here
1119
            }
1122
            }
1120
        )->status('RETURNED')->store;
1123
        )->status('RETURNED')->store;
1121
        ( $renewokay, $error ) =
1124
        ( $renewokay, $error ) =
1122
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1125
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1123
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1126
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1124
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, patron has 10' );
1127
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, patron has 10' );
1125
1128
Lines 1133-1139 subtest "CanBookBeRenewed tests" => sub { Link Here
1133
            }
1136
            }
1134
        )->status('RETURNED')->store;
1137
        )->status('RETURNED')->store;
1135
        ( $renewokay, $error ) =
1138
        ( $renewokay, $error ) =
1136
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1139
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1137
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1140
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1138
        is( $error, 'auto_too_much_oweing', 'Cannot auto renew, OPACFineNoRenewals=10, patron has 15' );
1141
        is( $error, 'auto_too_much_oweing', 'Cannot auto renew, OPACFineNoRenewals=10, patron has 15' );
1139
1142
Lines 1146-1158 subtest "CanBookBeRenewed tests" => sub { Link Here
1146
            }
1149
            }
1147
        )->store;
1150
        )->store;
1148
        ( $renewokay, $error ) =
1151
        ( $renewokay, $error ) =
1149
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1152
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1150
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1153
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1151
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, OPACFineNoRenewalsIncludeCredit=1, patron has 15 debt, 5 credit'  );
1154
        is( $error, 'auto_renew', 'Can auto renew, OPACFineNoRenewals=10, OPACFineNoRenewalsIncludeCredit=1, patron has 15 debt, 5 credit'  );
1152
1155
1153
        C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','0');
1156
        C4::Context->set_preference('OPACFineNoRenewalsIncludeCredit','0');
1154
        ( $renewokay, $error ) =
1157
        ( $renewokay, $error ) =
1155
          CanBookBeRenewed( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1158
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1156
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1159
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1157
        is( $error, 'auto_too_much_oweing', 'Cannot auto renew, OPACFineNoRenewals=10, OPACFineNoRenewalsIncludeCredit=1, patron has 15 debt, 5 credit'  );
1160
        is( $error, 'auto_too_much_oweing', 'Cannot auto renew, OPACFineNoRenewals=10, OPACFineNoRenewalsIncludeCredit=1, patron has 15 debt, 5 credit'  );
1158
1161
Lines 1187-1223 subtest "CanBookBeRenewed tests" => sub { Link Here
1187
        # Patron is expired and BlockExpiredPatronOpacActions=0
1190
        # Patron is expired and BlockExpiredPatronOpacActions=0
1188
        # => auto renew is allowed
1191
        # => auto renew is allowed
1189
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 0);
1192
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 0);
1190
        my $patron = $expired_borrower;
1193
        my $issue = AddIssue( $expired_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1191
        my $checkout = AddIssue( $patron, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1192
        ( $renewokay, $error ) =
1194
        ( $renewokay, $error ) =
1193
          CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->itemnumber );
1195
          CanBookBeRenewed( $expired_borrower_obj, $issue );
1194
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1196
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1195
        is( $error, 'auto_renew', 'Can auto renew, patron is expired but BlockExpiredPatronOpacActions=0' );
1197
        is( $error, 'auto_renew', 'Can auto renew, patron is expired but BlockExpiredPatronOpacActions=0' );
1196
        Koha::Checkouts->find( $checkout->issue_id )->delete;
1198
        Koha::Checkouts->find( $issue->issue_id )->delete;
1197
1199
1198
1200
1199
        # Patron is expired and BlockExpiredPatronOpacActions=1
1201
        # Patron is expired and BlockExpiredPatronOpacActions=1
1200
        # => auto renew is not allowed
1202
        # => auto renew is not allowed
1201
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1);
1203
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1);
1202
        $patron = $expired_borrower;
1204
        $issue = AddIssue( $expired_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1203
        $checkout = AddIssue( $patron, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1204
        ( $renewokay, $error ) =
1205
        ( $renewokay, $error ) =
1205
          CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->itemnumber );
1206
          CanBookBeRenewed( $expired_borrower_obj, $issue );
1206
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1207
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1207
        is( $error, 'auto_account_expired', 'Can not auto renew, lockExpiredPatronOpacActions=1 and patron is expired' );
1208
        is( $error, 'auto_account_expired', 'Can not auto renew, lockExpiredPatronOpacActions=1 and patron is expired' );
1208
        Koha::Checkouts->find( $checkout->issue_id )->delete;
1209
        $issue->delete;
1209
1210
1210
1211
        # Patron is not expired and BlockExpiredPatronOpacActions=1
1211
        # Patron is not expired and BlockExpiredPatronOpacActions=1
1212
        # => auto renew is allowed
1212
        # => auto renew is allowed
1213
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1);
1213
        t::lib::Mocks::mock_preference('BlockExpiredPatronOpacActions', 1);
1214
        $patron = $renewing_borrower;
1214
        $issue = AddIssue( $renewing_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1215
        $checkout = AddIssue( $patron, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1216
        ( $renewokay, $error ) =
1215
        ( $renewokay, $error ) =
1217
          CanBookBeRenewed( $patron->{borrowernumber}, $item_to_auto_renew->itemnumber );
1216
          CanBookBeRenewed( $renewing_borrower_obj, $issue );
1218
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1217
        is( $renewokay, 0, 'Do not renew, renewal is automatic' );
1219
        is( $error, 'auto_renew', 'Can auto renew, BlockExpiredPatronOpacActions=1 but patron is not expired' );
1218
        is( $error, 'auto_renew', 'Can auto renew, BlockExpiredPatronOpacActions=1 but patron is not expired' );
1220
        Koha::Checkouts->find( $checkout->issue_id )->delete;
1219
        $issue->delete;
1221
    };
1220
    };
1222
1221
1223
    subtest "GetLatestAutoRenewDate" => sub {
1222
    subtest "GetLatestAutoRenewDate" => sub {
Lines 1231-1237 subtest "CanBookBeRenewed tests" => sub { Link Here
1231
1230
1232
        my $ten_days_before = dt_from_string->add( days => -10 );
1231
        my $ten_days_before = dt_from_string->add( days => -10 );
1233
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1232
        my $ten_days_ahead  = dt_from_string->add( days => 10 );
1234
        AddIssue( $renewing_borrower, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1233
        my $issue = AddIssue( $renewing_borrower_obj->unblessed, $item_to_auto_renew->barcode, $ten_days_ahead, undef, $ten_days_before, undef, { auto_renew => 1 } );
1235
        Koha::CirculationRules->set_rules(
1234
        Koha::CirculationRules->set_rules(
1236
            {
1235
            {
1237
                categorycode => undef,
1236
                categorycode => undef,
Lines 1244-1250 subtest "CanBookBeRenewed tests" => sub { Link Here
1244
                }
1243
                }
1245
            }
1244
            }
1246
        );
1245
        );
1247
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1246
        my $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrower_obj, $issue );
1248
        is( $latest_auto_renew_date, undef, 'GetLatestAutoRenewDate should return undef if no_auto_renewal_after or no_auto_renewal_after_hard_limit are not defined' );
1247
        is( $latest_auto_renew_date, undef, 'GetLatestAutoRenewDate should return undef if no_auto_renewal_after or no_auto_renewal_after_hard_limit are not defined' );
1249
        my $five_days_before = dt_from_string->add( days => -5 );
1248
        my $five_days_before = dt_from_string->add( days => -5 );
1250
        Koha::CirculationRules->set_rules(
1249
        Koha::CirculationRules->set_rules(
Lines 1259-1265 subtest "CanBookBeRenewed tests" => sub { Link Here
1259
                }
1258
                }
1260
            }
1259
            }
1261
        );
1260
        );
1262
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1261
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrower_obj,, $issue );
1263
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1262
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1264
            $five_days_before->truncate( to => 'minute' ),
1263
            $five_days_before->truncate( to => 'minute' ),
1265
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
1264
            'GetLatestAutoRenewDate should return -5 days if no_auto_renewal_after = 5 and date_due is 10 days before'
Lines 1281-1287 subtest "CanBookBeRenewed tests" => sub { Link Here
1281
                }
1280
                }
1282
            }
1281
            }
1283
        );
1282
        );
1284
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1283
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrower_obj, $issue );
1285
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1284
        is( $latest_auto_renew_date->truncate( to => 'minute' ),
1286
            $five_days_ahead->truncate( to => 'minute' ),
1285
            $five_days_ahead->truncate( to => 'minute' ),
1287
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
1286
            'GetLatestAutoRenewDate should return +5 days if no_auto_renewal_after = 15 and date_due is 10 days before'
Lines 1299-1305 subtest "CanBookBeRenewed tests" => sub { Link Here
1299
                }
1298
                }
1300
            }
1299
            }
1301
        );
1300
        );
1302
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1301
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrower_obj, $issue );
1303
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1302
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1304
            $two_days_ahead->truncate( to => 'day' ),
1303
            $two_days_ahead->truncate( to => 'day' ),
1305
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
1304
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is defined and not no_auto_renewal_after'
Lines 1316-1322 subtest "CanBookBeRenewed tests" => sub { Link Here
1316
                }
1315
                }
1317
            }
1316
            }
1318
        );
1317
        );
1319
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrowernumber, $item_to_auto_renew->itemnumber );
1318
        $latest_auto_renew_date = GetLatestAutoRenewDate( $renewing_borrower_obj, $issue );
1320
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1319
        is( $latest_auto_renew_date->truncate( to => 'day' ),
1321
            $two_days_ahead->truncate( to => 'day' ),
1320
            $two_days_ahead->truncate( to => 'day' ),
1322
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is < no_auto_renewal_after'
1321
            'GetLatestAutoRenewDate should return +2 days if no_auto_renewal_after_hard_limit is < no_auto_renewal_after'
Lines 1338-1344 subtest "CanBookBeRenewed tests" => sub { Link Here
1338
        }
1337
        }
1339
    );
1338
    );
1340
1339
1341
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
1340
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
1342
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
1341
    is( $renewokay, 0, 'Cannot renew, 0 renewals allowed');
1343
    is( $error, 'too_many', 'Cannot renew, 0 renewals allowed (returned code is too_many)');
1342
    is( $error, 'too_many', 'Cannot renew, 0 renewals allowed (returned code is too_many)');
1344
1343
Lines 1355-1362 subtest "CanBookBeRenewed tests" => sub { Link Here
1355
        }
1354
        }
1356
    );
1355
    );
1357
    t::lib::Mocks::mock_preference('UnseenRenewals', 1);
1356
    t::lib::Mocks::mock_preference('UnseenRenewals', 1);
1358
    $dbh->do('UPDATE issues SET unseen_renewals = 2 where borrowernumber = ? AND itemnumber = ?', undef, ($renewing_borrowernumber, $item_1->itemnumber));
1357
    $issue_1->unseen_renewals(2)->store;
1359
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
1358
1359
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrower_obj, $issue_1);
1360
    is( $renewokay, 0, 'Cannot renew, 0 unseen renewals allowed');
1360
    is( $renewokay, 0, 'Cannot renew, 0 unseen renewals allowed');
1361
    is( $error, 'too_unseen', 'Cannot renew, returned code is too_unseen');
1361
    is( $error, 'too_unseen', 'Cannot renew, returned code is too_unseen');
1362
    Koha::CirculationRules->set_rules(
1362
    Koha::CirculationRules->set_rules(
Lines 1378-1398 subtest "CanBookBeRenewed tests" => sub { Link Here
1378
1378
1379
    C4::Overdues::UpdateFine(
1379
    C4::Overdues::UpdateFine(
1380
        {
1380
        {
1381
            issue_id       => $issue->id(),
1381
            issue_id       => $issue_1->id(),
1382
            itemnumber     => $item_1->itemnumber,
1382
            itemnumber     => $item_1->itemnumber,
1383
            borrowernumber => $renewing_borrower->{borrowernumber},
1383
            borrowernumber => $renewing_borrower_obj->borrowernumber,
1384
            amount         => 15.00,
1384
            amount         => 15.00,
1385
            type           => q{},
1385
            type           => q{},
1386
            due            => Koha::DateUtils::output_pref($datedue)
1386
            due            => Koha::DateUtils::output_pref($datedue)
1387
        }
1387
        }
1388
    );
1388
    );
1389
1389
1390
    my $line = Koha::Account::Lines->search({ borrowernumber => $renewing_borrower->{borrowernumber} })->next();
1390
    my $line = Koha::Account::Lines->search({ borrowernumber => $renewing_borrower_obj->borrowernumber })->next();
1391
    is( $line->debit_type_code, 'OVERDUE', 'Account line type is OVERDUE' );
1391
    is( $line->debit_type_code, 'OVERDUE', 'Account line type is OVERDUE' );
1392
    is( $line->status, 'UNRETURNED', 'Account line status is UNRETURNED' );
1392
    is( $line->status, 'UNRETURNED', 'Account line status is UNRETURNED' );
1393
    is( $line->amountoutstanding+0, 15, 'Account line amount outstanding is 15.00' );
1393
    is( $line->amountoutstanding+0, 15, 'Account line amount outstanding is 15.00' );
1394
    is( $line->amount+0, 15, 'Account line amount is 15.00' );
1394
    is( $line->amount+0, 15, 'Account line amount is 15.00' );
1395
    is( $line->issue_id, $issue->id, 'Account line issue id matches' );
1395
    is( $line->issue_id, $issue_1->id, 'Account line issue id matches' );
1396
1396
1397
    my $offset = Koha::Account::Offsets->search({ debit_id => $line->id })->next();
1397
    my $offset = Koha::Account::Offsets->search({ debit_id => $line->id })->next();
1398
    is( $offset->type, 'CREATE', 'Account offset type is CREATE' );
1398
    is( $offset->type, 'CREATE', 'Account offset type is CREATE' );
Lines 1414-1420 subtest "CanBookBeRenewed tests" => sub { Link Here
1414
1414
1415
    my $total_due = $dbh->selectrow_array(
1415
    my $total_due = $dbh->selectrow_array(
1416
        'SELECT SUM( amountoutstanding ) FROM accountlines WHERE borrowernumber = ?',
1416
        'SELECT SUM( amountoutstanding ) FROM accountlines WHERE borrowernumber = ?',
1417
        undef, $renewing_borrower->{borrowernumber}
1417
        undef, $renewing_borrower_obj->borrowernumber
1418
    );
1418
    );
1419
1419
1420
    is( $total_due+0, 15, 'Borrower only charged replacement fee with both WhenLostForgiveFine and WhenLostChargeReplacementFee enabled' );
1420
    is( $total_due+0, 15, 'Borrower only charged replacement fee with both WhenLostForgiveFine and WhenLostChargeReplacementFee enabled' );
Lines 1423-1431 subtest "CanBookBeRenewed tests" => sub { Link Here
1423
1423
1424
    C4::Overdues::UpdateFine(
1424
    C4::Overdues::UpdateFine(
1425
        {
1425
        {
1426
            issue_id       => $issue2->id(),
1426
            issue_id       => $issue_2->id(),
1427
            itemnumber     => $item_2->itemnumber,
1427
            itemnumber     => $item_2->itemnumber,
1428
            borrowernumber => $renewing_borrower->{borrowernumber},
1428
            borrowernumber => $renewing_borrower_obj->borrowernumber,
1429
            amount         => 15.00,
1429
            amount         => 15.00,
1430
            type           => q{},
1430
            type           => q{},
1431
            due            => Koha::DateUtils::output_pref($datedue)
1431
            due            => Koha::DateUtils::output_pref($datedue)
Lines 1440-1446 subtest "CanBookBeRenewed tests" => sub { Link Here
1440
1440
1441
    $total_due = $dbh->selectrow_array(
1441
    $total_due = $dbh->selectrow_array(
1442
        'SELECT SUM( amountoutstanding ) FROM accountlines WHERE borrowernumber = ?',
1442
        'SELECT SUM( amountoutstanding ) FROM accountlines WHERE borrowernumber = ?',
1443
        undef, $renewing_borrower->{borrowernumber}
1443
        undef, $renewing_borrower_obj->borrowernumber
1444
    );
1444
    );
1445
1445
1446
    ok( $total_due == 15, 'Borrower only charged fine with both WhenLostForgiveFine and WhenLostChargeReplacementFee disabled' );
1446
    ok( $total_due == 15, 'Borrower only charged fine with both WhenLostForgiveFine and WhenLostChargeReplacementFee disabled' );
Lines 1478-1488 subtest "CanBookBeRenewed tests" => sub { Link Here
1478
        },
1478
        },
1479
    });
1479
    });
1480
    my $recall_borrower = $builder->build_object({ class => 'Koha::Patrons' });
1480
    my $recall_borrower = $builder->build_object({ class => 'Koha::Patrons' });
1481
    my $recall_biblio = $builder->build_object({ class => 'Koha::Biblios' });
1481
    my $recall_biblio = $builder->build_sample_biblio();
1482
    my $recall_item1 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $recall_biblio->biblionumber } });
1482
    my $recall_item1 = $builder->build_sample_item({ biblionumber => $recall_biblio->biblionumber });
1483
    my $recall_item2 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $recall_biblio->biblionumber } });
1483
    my $recall_item2 = $builder->build_sample_item({ biblionumber => $recall_biblio->biblionumber });
1484
1484
1485
    AddIssue( $renewing_borrower, $recall_item1->barcode );
1485
    my $recall_issue = AddIssue( $renewing_borrower_obj->unblessed, $recall_item1->barcode );
1486
1486
1487
    # item-level and this item: renewal not allowed
1487
    # item-level and this item: renewal not allowed
1488
    my $recall = Koha::Recall->new({
1488
    my $recall = Koha::Recall->new({
Lines 1492-1498 subtest "CanBookBeRenewed tests" => sub { Link Here
1492
        pickup_library_id => $recall_borrower->branchcode,
1492
        pickup_library_id => $recall_borrower->branchcode,
1493
        item_level => 1,
1493
        item_level => 1,
1494
    })->store;
1494
    })->store;
1495
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
1495
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $recall_issue );
1496
    is( $error, 'recalled', 'Cannot renew item that has been recalled' );
1496
    is( $error, 'recalled', 'Cannot renew item that has been recalled' );
1497
    $recall->set_cancelled;
1497
    $recall->set_cancelled;
1498
1498
Lines 1504-1510 subtest "CanBookBeRenewed tests" => sub { Link Here
1504
        pickup_library_id => $recall_borrower->branchcode,
1504
        pickup_library_id => $recall_borrower->branchcode,
1505
        item_level => 0,
1505
        item_level => 0,
1506
    })->store;
1506
    })->store;
1507
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
1507
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $recall_issue );
1508
    is( $error, 'recalled', 'Cannot renew item if biblio is recalled and has no item allocated' );
1508
    is( $error, 'recalled', 'Cannot renew item if biblio is recalled and has no item allocated' );
1509
    $recall->set_cancelled;
1509
    $recall->set_cancelled;
1510
1510
Lines 1516-1522 subtest "CanBookBeRenewed tests" => sub { Link Here
1516
        pickup_library_id => $recall_borrower->branchcode,
1516
        pickup_library_id => $recall_borrower->branchcode,
1517
        item_level => 1,
1517
        item_level => 1,
1518
    })->store;
1518
    })->store;
1519
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
1519
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $recall_issue );
1520
    is( $renewokay, 1, 'Can renew item if item-level recall on biblio is not on this item' );
1520
    is( $renewokay, 1, 'Can renew item if item-level recall on biblio is not on this item' );
1521
    $recall->set_cancelled;
1521
    $recall->set_cancelled;
1522
1522
Lines 1529-1535 subtest "CanBookBeRenewed tests" => sub { Link Here
1529
        item_level => 0,
1529
        item_level => 0,
1530
    })->store;
1530
    })->store;
1531
    $recall->set_waiting({ item => $recall_item1 });
1531
    $recall->set_waiting({ item => $recall_item1 });
1532
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
1532
    ( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrower_obj, $recall_issue );
1533
    is( $renewokay, 1, 'Can renew item if biblio-level recall has already been allocated an item' );
1533
    is( $renewokay, 1, 'Can renew item if biblio-level recall has already been allocated an item' );
1534
    $recall->set_cancelled;
1534
    $recall->set_cancelled;
1535
};
1535
};
Lines 1571-1577 subtest "GetUpcomingDueIssues" => sub { Link Here
1571
1571
1572
    my $issue = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
1572
    my $issue = AddIssue( $a_borrower, $item_1->barcode, $yesterday );
1573
    my $datedue = dt_from_string( $issue->date_due() );
1573
    my $datedue = dt_from_string( $issue->date_due() );
1574
    my $issue2 = AddIssue( $a_borrower, $item_2->barcode, $two_days_ahead );
1574
    my $issue_2 = AddIssue( $a_borrower, $item_2->barcode, $two_days_ahead );
1575
    my $datedue2 = dt_from_string( $issue->date_due() );
1575
    my $datedue2 = dt_from_string( $issue->date_due() );
1576
1576
1577
    my $upcoming_dues;
1577
    my $upcoming_dues;
Lines 1697-1708 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1697
    );
1697
    );
1698
1698
1699
1699
1700
    my $borrowernumber1 = Koha::Patron->new({
1700
    my $borrower1 = Koha::Patron->new({
1701
        firstname    => 'Kyle',
1701
        firstname    => 'Kyle',
1702
        surname      => 'Hall',
1702
        surname      => 'Hall',
1703
        categorycode => $patron_category->{categorycode},
1703
        categorycode => $patron_category->{categorycode},
1704
        branchcode   => $library2->{branchcode},
1704
        branchcode   => $library2->{branchcode},
1705
    })->store->borrowernumber;
1705
    })->store;
1706
    my $borrowernumber2 = Koha::Patron->new({
1706
    my $borrowernumber2 = Koha::Patron->new({
1707
        firstname    => 'Chelsea',
1707
        firstname    => 'Chelsea',
1708
        surname      => 'Hall',
1708
        surname      => 'Hall',
Lines 1726-1737 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1726
        branchcode   => $library2->{branchcode},
1726
        branchcode   => $library2->{branchcode},
1727
    })->store->borrowernumber;
1727
    })->store->borrowernumber;
1728
1728
1729
    my $borrower1 = Koha::Patrons->find( $borrowernumber1 )->unblessed;
1729
    my $issue = AddIssue( $borrower1->unblessed, $item_1->barcode );
1730
    my $borrower2 = Koha::Patrons->find( $borrowernumber2 )->unblessed;
1731
1732
    my $issue = AddIssue( $borrower1, $item_1->barcode );
1733
1730
1734
    my ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1731
    my ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1735
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with no hold on the record' );
1732
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with no hold on the record' );
1736
1733
1737
    AddReserve(
1734
    AddReserve(
Lines 1754-1764 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1754
        }
1751
        }
1755
    );
1752
    );
1756
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1753
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1757
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1754
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1758
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1755
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1759
1756
1760
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1757
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1761
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1758
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1762
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1759
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled and onshelfholds is disabled' );
1763
1760
1764
    Koha::CirculationRules->set_rules(
1761
    Koha::CirculationRules->set_rules(
Lines 1772-1782 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1772
        }
1769
        }
1773
    );
1770
    );
1774
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1771
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1775
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1772
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1776
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1773
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is disabled and onshelfhold is enabled' );
1777
1774
1778
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1775
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 1 );
1779
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1776
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1780
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1777
    is( $renewokay, 1, 'Bug 14337 - Verify the borrower can renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled' );
1781
1778
1782
    AddReserve(
1779
    AddReserve(
Lines 1788-1794 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1788
        }
1785
        }
1789
    );
1786
    );
1790
1787
1791
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1788
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1792
    is( $renewokay, 0, 'Verify the borrower cannot renew with 2 holds on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and one other item on record' );
1789
    is( $renewokay, 0, 'Verify the borrower cannot renew with 2 holds on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and one other item on record' );
1793
1790
1794
    my $item_3= $builder->build_sample_item(
1791
    my $item_3= $builder->build_sample_item(
Lines 1799-1805 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1799
        }
1796
        }
1800
    );
1797
    );
1801
1798
1802
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1799
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1803
    is( $renewokay, 1, 'Verify the borrower cannot renew with 2 holds on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and two other items on record' );
1800
    is( $renewokay, 1, 'Verify the borrower cannot renew with 2 holds on the record if AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and two other items on record' );
1804
1801
1805
    Koha::CirculationRules->set_rules(
1802
    Koha::CirculationRules->set_rules(
Lines 1813-1819 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1813
        }
1810
        }
1814
    );
1811
    );
1815
1812
1816
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1813
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1817
    is( $renewokay, 0, 'Verify the borrower cannot renew with 2 holds on the record, but only one of those holds can be filled when AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and two other items on record' );
1814
    is( $renewokay, 0, 'Verify the borrower cannot renew with 2 holds on the record, but only one of those holds can be filled when AllowRenewalIfOtherItemsAvailable and onshelfhold are enabled and two other items on record' );
1818
1815
1819
    Koha::CirculationRules->set_rules(
1816
    Koha::CirculationRules->set_rules(
Lines 1830-1836 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1830
    # Setting item not checked out to be not for loan but holdable
1827
    # Setting item not checked out to be not for loan but holdable
1831
    $item_2->notforloan(-1)->store;
1828
    $item_2->notforloan(-1)->store;
1832
1829
1833
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1830
    ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1834
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower can not renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled but the only available item is notforloan' );
1831
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower can not renew with a hold on the record if AllowRenewalIfOtherItemsAvailable is enabled but the only available item is notforloan' );
1835
1832
1836
    my $mock_circ = Test::MockModule->new("C4::Circulation");
1833
    my $mock_circ = Test::MockModule->new("C4::Circulation");
Lines 1844-1850 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1844
    # Two items total, one item available, one issued, two holds on record
1841
    # Two items total, one item available, one issued, two holds on record
1845
1842
1846
    warnings_are{
1843
    warnings_are{
1847
       ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1844
       ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1848
    } [], "CanItemBeReserved not called when there are more possible holds than available items";
1845
    } [], "CanItemBeReserved not called when there are more possible holds than available items";
1849
    is( $renewokay, 0, 'Borrower cannot renew when there are more holds than available items' );
1846
    is( $renewokay, 0, 'Borrower cannot renew when there are more holds than available items' );
1850
1847
Lines 1868-1874 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1868
    );
1865
    );
1869
1866
1870
    warnings_are{
1867
    warnings_are{
1871
       ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1868
       ( $renewokay, $error ) = CanBookBeRenewed( $borrower1, $issue );
1872
    } ["Checked","Checked"], "CanItemBeReserved only called once per available item if it returns a negative result for all items for a borrower";
1869
    } ["Checked","Checked"], "CanItemBeReserved only called once per available item if it returns a negative result for all items for a borrower";
1873
    is( $renewokay, 0, 'Borrower cannot renew when there are more holds than available items' );
1870
    is( $renewokay, 0, 'Borrower cannot renew when there are more holds than available items' );
1874
1871
Lines 1889-1905 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1889
        }
1886
        }
1890
    );
1887
    );
1891
1888
1892
    my $borrowernumber = Koha::Patron->new({
1889
    my $borrower = Koha::Patron->new({
1893
        firstname =>  'fn',
1890
        firstname =>  'fn',
1894
        surname => 'dn',
1891
        surname => 'dn',
1895
        categorycode => $patron_category->{categorycode},
1892
        categorycode => $patron_category->{categorycode},
1896
        branchcode => $branch,
1893
        branchcode => $branch,
1897
    })->store->borrowernumber;
1894
    })->store;
1898
1899
    my $borrower = Koha::Patrons->find( $borrowernumber )->unblessed;
1900
1895
1901
    my $issue = AddIssue( $borrower, $item->barcode, undef, undef, undef, undef, { onsite_checkout => 1 } );
1896
    my $issue = AddIssue( $borrower->unblessed, $item->barcode, undef, undef, undef, undef, { onsite_checkout => 1 } );
1902
    my ( $renewed, $error ) = CanBookBeRenewed( $borrowernumber, $item->itemnumber );
1897
    my ( $renewed, $error ) = CanBookBeRenewed( $borrower, $issue );
1903
    is( $renewed, 0, 'CanBookBeRenewed should not allow to renew on-site checkout' );
1898
    is( $renewed, 0, 'CanBookBeRenewed should not allow to renew on-site checkout' );
1904
    is( $error, 'onsite_checkout', 'A correct error code should be returned by CanBookBeRenewed for on-site checkout' );
1899
    is( $error, 'onsite_checkout', 'A correct error code should be returned by CanBookBeRenewed for on-site checkout' );
1905
}
1900
}
Lines 1916-1939 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1916
            itype            => $itemtype,
1911
            itype            => $itemtype,
1917
        }
1912
        }
1918
    );
1913
    );
1914
    my $patron = $builder->build_object( { class => 'Koha::Patrons',  value => { branchcode => $library->{branchcode}, categorycode => $patron_category->{categorycode} } } );
1919
1915
1920
    my $patron = $builder->build({ source => 'Borrower', value => { branchcode => $library->{branchcode}, categorycode => $patron_category->{categorycode} } } );
1916
    my $issue = AddIssue( $patron->unblessed, $item->barcode );
1921
1922
    my $issue = AddIssue( $patron, $item->barcode );
1923
    UpdateFine(
1917
    UpdateFine(
1924
        {
1918
        {
1925
            issue_id       => $issue->id(),
1919
            issue_id       => $issue->id,
1926
            itemnumber     => $item->itemnumber,
1920
            itemnumber     => $item->itemnumber,
1927
            borrowernumber => $patron->{borrowernumber},
1921
            borrowernumber => $patron->borrowernumber,
1928
            amount         => 1,
1922
            amount         => 1,
1929
            type           => q{}
1923
            type           => q{}
1930
        }
1924
        }
1931
    );
1925
    );
1932
    UpdateFine(
1926
    UpdateFine(
1933
        {
1927
        {
1934
            issue_id       => $issue->id(),
1928
            issue_id       => $issue->id,
1935
            itemnumber     => $item->itemnumber,
1929
            itemnumber     => $item->itemnumber,
1936
            borrowernumber => $patron->{borrowernumber},
1930
            borrowernumber => $patron->borrowernumber,
1937
            amount         => 2,
1931
            amount         => 2,
1938
            type           => q{}
1932
            type           => q{}
1939
        }
1933
        }
Lines 2349-2357 subtest 'MultipleReserves' => sub { Link Here
2349
        categorycode => $patron_category->{categorycode},
2343
        categorycode => $patron_category->{categorycode},
2350
        branchcode => $branch,
2344
        branchcode => $branch,
2351
    );
2345
    );
2352
    my $renewing_borrowernumber = Koha::Patron->new(\%renewing_borrower_data)->store->borrowernumber;
2346
    my $patron = Koha::Patron->new(\%renewing_borrower_data)->store;
2353
    my $renewing_borrower = Koha::Patrons->find( $renewing_borrowernumber )->unblessed;
2347
    my $issue = AddIssue( $patron->unblessed, $item_1->barcode);
2354
    my $issue = AddIssue( $renewing_borrower, $item_1->barcode);
2355
    my $datedue = dt_from_string( $issue->date_due() );
2348
    my $datedue = dt_from_string( $issue->date_due() );
2356
    is (defined $issue->date_due(), 1, "item 1 checked out");
2349
    is (defined $issue->date_due(), 1, "item 1 checked out");
2357
    my $borrowing_borrowernumber = Koha::Checkouts->find({ itemnumber => $item_1->itemnumber })->borrowernumber;
2350
    my $borrowing_borrowernumber = Koha::Checkouts->find({ itemnumber => $item_1->itemnumber })->borrowernumber;
Lines 2399-2405 subtest 'MultipleReserves' => sub { Link Here
2399
    );
2392
    );
2400
2393
2401
    {
2394
    {
2402
        my ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber, 1);
2395
        my ( $renewokay, $error ) = CanBookBeRenewed($patron, $issue, 1);
2403
        is($renewokay, 0, 'Bug 17941 - should cover the case where 2 books are both reserved, so failing');
2396
        is($renewokay, 0, 'Bug 17941 - should cover the case where 2 books are both reserved, so failing');
2404
    }
2397
    }
2405
2398
Lines 2413-2419 subtest 'MultipleReserves' => sub { Link Here
2413
    );
2406
    );
2414
2407
2415
    {
2408
    {
2416
        my ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber, 1);
2409
        my ( $renewokay, $error ) = CanBookBeRenewed($patron, $issue, 1);
2417
        is($renewokay, 1, 'Bug 17941 - should cover the case where 2 books are reserved, but a third one is available');
2410
        is($renewokay, 1, 'Bug 17941 - should cover the case where 2 books are reserved, but a third one is available');
2418
    }
2411
    }
2419
};
2412
};
Lines 3966-3972 subtest 'Set waiting flag' => sub { Link Here
3966
    my $hold = Koha::Holds->find( $reserve_id );
3959
    my $hold = Koha::Holds->find( $reserve_id );
3967
    is( $hold->found, 'T', 'Hold is in transit' );
3960
    is( $hold->found, 'T', 'Hold is in transit' );
3968
3961
3969
    my ( $status ) = CheckReserves($item->itemnumber);
3962
    my ( $status ) = CheckReserves($item);
3970
    is( $status, 'Transferred', 'Hold is not waiting yet');
3963
    is( $status, 'Transferred', 'Hold is not waiting yet');
3971
3964
3972
    set_userenv( $library_2 );
3965
    set_userenv( $library_2 );
Lines 3975-3981 subtest 'Set waiting flag' => sub { Link Here
3975
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3968
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3976
    $hold = Koha::Holds->find( $reserve_id );
3969
    $hold = Koha::Holds->find( $reserve_id );
3977
    is( $hold->found, 'W', 'Hold is waiting' );
3970
    is( $hold->found, 'W', 'Hold is waiting' );
3978
    ( $status ) = CheckReserves($item->itemnumber);
3971
    ( $status ) = CheckReserves($item);
3979
    is( $status, 'Waiting', 'Now the hold is waiting');
3972
    is( $status, 'Waiting', 'Now the hold is waiting');
3980
3973
3981
    #Bug 21944 - Waiting transfer checked in at branch other than pickup location
3974
    #Bug 21944 - Waiting transfer checked in at branch other than pickup location
Lines 4185-4191 subtest 'ItemsDeniedRenewal preference' => sub { Link Here
4185
    my $idr_rules;
4178
    my $idr_rules;
4186
4179
4187
    my ( $idr_mayrenew, $idr_error ) =
4180
    my ( $idr_mayrenew, $idr_error ) =
4188
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4181
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4189
    is( $idr_mayrenew, 1, 'Renewal allowed when no rules' );
4182
    is( $idr_mayrenew, 1, 'Renewal allowed when no rules' );
4190
    is( $idr_error, undef, 'Renewal allowed when no rules' );
4183
    is( $idr_error, undef, 'Renewal allowed when no rules' );
4191
4184
Lines 4193-4203 subtest 'ItemsDeniedRenewal preference' => sub { Link Here
4193
4186
4194
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4187
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4195
    ( $idr_mayrenew, $idr_error ) =
4188
    ( $idr_mayrenew, $idr_error ) =
4196
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4189
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4197
    is( $idr_mayrenew, 0, 'Renewal blocked when 1 rules (withdrawn)' );
4190
    is( $idr_mayrenew, 0, 'Renewal blocked when 1 rules (withdrawn)' );
4198
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 1 rule (withdrawn)' );
4191
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 1 rule (withdrawn)' );
4199
    ( $idr_mayrenew, $idr_error ) =
4192
    ( $idr_mayrenew, $idr_error ) =
4200
    CanBookBeRenewed( $idr_borrower->borrowernumber, $allow_issue->itemnumber );
4193
    CanBookBeRenewed( $idr_borrower, $allow_issue );
4201
    is( $idr_mayrenew, 1, 'Renewal allowed when 1 rules not matched (withdrawn)' );
4194
    is( $idr_mayrenew, 1, 'Renewal allowed when 1 rules not matched (withdrawn)' );
4202
    is( $idr_error, undef, 'Renewal allowed when 1 rules not matched (withdrawn)' );
4195
    is( $idr_error, undef, 'Renewal allowed when 1 rules not matched (withdrawn)' );
4203
4196
Lines 4205-4215 subtest 'ItemsDeniedRenewal preference' => sub { Link Here
4205
4198
4206
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4199
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4207
    ( $idr_mayrenew, $idr_error ) =
4200
    ( $idr_mayrenew, $idr_error ) =
4208
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4201
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4209
    is( $idr_mayrenew, 0, 'Renewal blocked when 2 rules matched (withdrawn, itype)' );
4202
    is( $idr_mayrenew, 0, 'Renewal blocked when 2 rules matched (withdrawn, itype)' );
4210
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 2 rules matched (withdrawn,itype)' );
4203
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 2 rules matched (withdrawn,itype)' );
4211
    ( $idr_mayrenew, $idr_error ) =
4204
    ( $idr_mayrenew, $idr_error ) =
4212
    CanBookBeRenewed( $idr_borrower->borrowernumber, $allow_issue->itemnumber );
4205
    CanBookBeRenewed( $idr_borrower, $allow_issue );
4213
    is( $idr_mayrenew, 1, 'Renewal allowed when 2 rules not matched (withdrawn, itype)' );
4206
    is( $idr_mayrenew, 1, 'Renewal allowed when 2 rules not matched (withdrawn, itype)' );
4214
    is( $idr_error, undef, 'Renewal allowed when 2 rules not matched (withdrawn, itype)' );
4207
    is( $idr_error, undef, 'Renewal allowed when 2 rules not matched (withdrawn, itype)' );
4215
4208
Lines 4217-4250 subtest 'ItemsDeniedRenewal preference' => sub { Link Here
4217
4210
4218
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4211
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4219
    ( $idr_mayrenew, $idr_error ) =
4212
    ( $idr_mayrenew, $idr_error ) =
4220
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4213
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4221
    is( $idr_mayrenew, 0, 'Renewal blocked when 3 rules matched (withdrawn, itype, location)' );
4214
    is( $idr_mayrenew, 0, 'Renewal blocked when 3 rules matched (withdrawn, itype, location)' );
4222
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 3 rules matched (withdrawn,itype, location)' );
4215
    is( $idr_error, 'item_denied_renewal', 'Renewal blocked when 3 rules matched (withdrawn,itype, location)' );
4223
    ( $idr_mayrenew, $idr_error ) =
4216
    ( $idr_mayrenew, $idr_error ) =
4224
    CanBookBeRenewed( $idr_borrower->borrowernumber, $allow_issue->itemnumber );
4217
    CanBookBeRenewed( $idr_borrower, $allow_issue );
4225
    is( $idr_mayrenew, 1, 'Renewal allowed when 3 rules not matched (withdrawn, itype, location)' );
4218
    is( $idr_mayrenew, 1, 'Renewal allowed when 3 rules not matched (withdrawn, itype, location)' );
4226
    is( $idr_error, undef, 'Renewal allowed when 3 rules not matched (withdrawn, itype, location)' );
4219
    is( $idr_error, undef, 'Renewal allowed when 3 rules not matched (withdrawn, itype, location)' );
4227
4220
4228
    $idr_rules="itemcallnumber: [NULL]";
4221
    $idr_rules="itemcallnumber: [NULL]";
4229
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4222
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4230
    ( $idr_mayrenew, $idr_error ) =
4223
    ( $idr_mayrenew, $idr_error ) =
4231
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4224
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4232
    is( $idr_mayrenew, 0, 'Renewal blocked for undef when NULL in pref' );
4225
    is( $idr_mayrenew, 0, 'Renewal blocked for undef when NULL in pref' );
4233
    $idr_rules="itemcallnumber: ['']";
4226
    $idr_rules="itemcallnumber: ['']";
4234
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4227
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4235
    ( $idr_mayrenew, $idr_error ) =
4228
    ( $idr_mayrenew, $idr_error ) =
4236
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4229
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4237
    is( $idr_mayrenew, 1, 'Renewal not blocked for undef when "" in pref' );
4230
    is( $idr_mayrenew, 1, 'Renewal not blocked for undef when "" in pref' );
4238
4231
4239
    $idr_rules="itemnotes: [NULL]";
4232
    $idr_rules="itemnotes: [NULL]";
4240
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4233
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4241
    ( $idr_mayrenew, $idr_error ) =
4234
    ( $idr_mayrenew, $idr_error ) =
4242
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4235
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4243
    is( $idr_mayrenew, 1, 'Renewal not blocked for "" when NULL in pref' );
4236
    is( $idr_mayrenew, 1, 'Renewal not blocked for "" when NULL in pref' );
4244
    $idr_rules="itemnotes: ['']";
4237
    $idr_rules="itemnotes: ['']";
4245
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4238
    C4::Context->set_preference('ItemsDeniedRenewal',$idr_rules);
4246
    ( $idr_mayrenew, $idr_error ) =
4239
    ( $idr_mayrenew, $idr_error ) =
4247
    CanBookBeRenewed( $idr_borrower->borrowernumber, $deny_issue->itemnumber );
4240
    CanBookBeRenewed( $idr_borrower, $deny_issue );
4248
    is( $idr_mayrenew, 0, 'Renewal blocked for empty string when "" in pref' );
4241
    is( $idr_mayrenew, 0, 'Renewal blocked for empty string when "" in pref' );
4249
};
4242
};
4250
4243
Lines 5721-5727 subtest "GetSoonestRenewDate tests" => sub { Link Here
5721
    # Test 'exact time' setting for syspref NoRenewalBeforePrecision
5714
    # Test 'exact time' setting for syspref NoRenewalBeforePrecision
5722
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'exact_time' );
5715
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'exact_time' );
5723
    is(
5716
    is(
5724
        GetSoonestRenewDate( $patron->id, $item->itemnumber ),
5717
        GetSoonestRenewDate( $patron, $issue ),
5725
        $datedue->clone->add( days => -7 ),
5718
        $datedue->clone->add( days => -7 ),
5726
        'Bug 14395: Renewals permitted 7 days before due date, as expected'
5719
        'Bug 14395: Renewals permitted 7 days before due date, as expected'
5727
    );
5720
    );
Lines 5730-5736 subtest "GetSoonestRenewDate tests" => sub { Link Here
5730
    # Test 'date' setting for syspref NoRenewalBeforePrecision
5723
    # Test 'date' setting for syspref NoRenewalBeforePrecision
5731
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'date' );
5724
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'date' );
5732
    is(
5725
    is(
5733
        GetSoonestRenewDate( $patron->id, $item->itemnumber ),
5726
        GetSoonestRenewDate( $patron, $issue ),
5734
        $datedue->clone->add( days => -7 )->truncate( to => 'day' ),
5727
        $datedue->clone->add( days => -7 )->truncate( to => 'day' ),
5735
        'Bug 14395: Renewals permitted 7 days before due date, as expected'
5728
        'Bug 14395: Renewals permitted 7 days before due date, as expected'
5736
    );
5729
    );
Lines 5747-5753 subtest "GetSoonestRenewDate tests" => sub { Link Here
5747
    );
5740
    );
5748
5741
5749
    is(
5742
    is(
5750
        GetSoonestRenewDate( $patron->id, $item->itemnumber ),
5743
        GetSoonestRenewDate( $patron, $issue ),
5751
        dt_from_string,
5744
        dt_from_string,
5752
        'Checkouts without auto-renewal can be renewed immediately if no norenewalbefore'
5745
        'Checkouts without auto-renewal can be renewed immediately if no norenewalbefore'
5753
    );
5746
    );
Lines 5755-5767 subtest "GetSoonestRenewDate tests" => sub { Link Here
5755
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'date' );
5748
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'date' );
5756
    $issue->auto_renew(1)->store;
5749
    $issue->auto_renew(1)->store;
5757
    is(
5750
    is(
5758
        GetSoonestRenewDate( $patron->id, $item->itemnumber ),
5751
        GetSoonestRenewDate( $patron, $issue ),
5759
        $datedue->clone->truncate( to => 'day' ),
5752
        $datedue->clone->truncate( to => 'day' ),
5760
        'Checkouts with auto-renewal can be renewed earliest on due date if no renewalbefore'
5753
        'Checkouts with auto-renewal can be renewed earliest on due date if no renewalbefore'
5761
    );
5754
    );
5762
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'exact' );
5755
    t::lib::Mocks::mock_preference( 'NoRenewalBeforePrecision', 'exact' );
5763
    is(
5756
    is(
5764
        GetSoonestRenewDate( $patron->id, $item->itemnumber ),
5757
        GetSoonestRenewDate( $patron, $issue ),
5765
        $datedue,
5758
        $datedue,
5766
        'Checkouts with auto-renewal can be renewed earliest on due date if no renewalbefore'
5759
        'Checkouts with auto-renewal can be renewed earliest on due date if no renewalbefore'
5767
    );
5760
    );
(-)a/t/db_dependent/Holds.t (-5 / +4 lines)
Lines 1495-1501 subtest 'non priority holds' => sub { Link Here
1495
        }
1495
        }
1496
    );
1496
    );
1497
1497
1498
    Koha::Checkout->new(
1498
    my $issue = Koha::Checkout->new(
1499
        {
1499
        {
1500
            borrowernumber => $patron1->borrowernumber,
1500
            borrowernumber => $patron1->borrowernumber,
1501
            itemnumber     => $item->itemnumber,
1501
            itemnumber     => $item->itemnumber,
Lines 1514-1520 subtest 'non priority holds' => sub { Link Here
1514
    );
1514
    );
1515
1515
1516
    my ( $ok, $err ) =
1516
    my ( $ok, $err ) =
1517
      CanBookBeRenewed( $patron1->borrowernumber, $item->itemnumber );
1517
      CanBookBeRenewed( $patron1, $issue );
1518
1518
1519
    ok( !$ok, 'Cannot renew' );
1519
    ok( !$ok, 'Cannot renew' );
1520
    is( $err, 'on_reserve', 'Item is on hold' );
1520
    is( $err, 'on_reserve', 'Item is on hold' );
Lines 1523-1529 subtest 'non priority holds' => sub { Link Here
1523
    $hold->non_priority(1)->store;
1523
    $hold->non_priority(1)->store;
1524
1524
1525
    ( $ok, $err ) =
1525
    ( $ok, $err ) =
1526
      CanBookBeRenewed( $patron1->borrowernumber, $item->itemnumber );
1526
      CanBookBeRenewed( $patron1, $issue );
1527
1527
1528
    ok( $ok, 'Can renew' );
1528
    ok( $ok, 'Can renew' );
1529
    is( $err, undef, 'Item is on non priority hold' );
1529
    is( $err, undef, 'Item is on non priority hold' );
Lines 1547-1553 subtest 'non priority holds' => sub { Link Here
1547
    );
1547
    );
1548
1548
1549
    ( $ok, $err ) =
1549
    ( $ok, $err ) =
1550
      CanBookBeRenewed( $patron1->borrowernumber, $item->itemnumber );
1550
      CanBookBeRenewed( $patron1, $issue );
1551
1551
1552
    ok( !$ok, 'Cannot renew' );
1552
    ok( !$ok, 'Cannot renew' );
1553
    is( $err, 'on_reserve', 'Item is on hold' );
1553
    is( $err, 'on_reserve', 'Item is on hold' );
1554
- 

Return to bug 31735