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

(-)a/Koha/Checkout.pm (-1 / +43 lines)
Lines 23-29 use Modern::Perl; Link Here
23
use DateTime;
23
use DateTime;
24
use Try::Tiny qw( catch try );
24
use Try::Tiny qw( catch try );
25
25
26
use C4::Circulation qw( LostItem MarkIssueReturned );
26
use C4::Circulation qw( AddRenewal CanBookBeRenewed LostItem MarkIssueReturned );
27
use Koha::Checkouts::Renewals;
27
use Koha::Checkouts::Renewals;
28
use Koha::Checkouts::ReturnClaims;
28
use Koha::Checkouts::ReturnClaims;
29
use Koha::Database;
29
use Koha::Database;
Lines 151-156 sub renewals { Link Here
151
    return Koha::Checkouts::Renewals->_new_from_dbic( $renewals_rs );
151
    return Koha::Checkouts::Renewals->_new_from_dbic( $renewals_rs );
152
}
152
}
153
153
154
=head3 attempt_auto_renew
155
156
  my ($success, $error, $updated) = $checkout->auto_renew({ confirm => 1 });
157
158
Attempt to automatically renew a book. Return error reason if it cannot be renewed.
159
Also return whether a change has been made to avoid notifying on more than one attempt.
160
161
If not passed confirm, we will only report and no changes will be made.
162
163
=cut
164
165
sub attempt_auto_renew {
166
    my ( $self, $params ) = @_;
167
    my $confirm = $params->{confirm} // 0;
168
169
    # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script
170
    my ( $ok, $error ) = C4::Circulation::CanBookBeRenewed( $self->patron, $self, undef, 1 );
171
    if ( $error eq 'auto_renew' ) {
172
        if ($confirm) {
173
            my $date_due = C4::Circulation::AddRenewal(
174
                {
175
                    borrowernumber => $self->borrowernumber,
176
                    itemnumber     => $self->itemnumber,
177
                    branch         => $self->branchcode,
178
                    seen           => 0,
179
                    automatic      => 1,
180
                }
181
            );
182
            $self->auto_renew_error(undef)->store;
183
        }
184
        return ( 1, undef, 1 );
185
    } else {
186
        my $updated = 0;
187
        if ( !$self->auto_renew_error || $error ne $self->auto_renew_error ) {
188
            $self->auto_renew_error($error)->store if $confirm;
189
            $updated = 1;
190
        }
191
        return ( 0, $error, $updated );
192
    }
193
194
}
195
154
=head3 to_api_mapping
196
=head3 to_api_mapping
155
197
156
This method returns the mapping for representing a Koha::Checkout object
198
This method returns the mapping for representing a Koha::Checkout object
(-)a/misc/cronjobs/automatic_renewals.pl (-17 / +3 lines)
Lines 171-201 while ( my $auto_renew = $auto_renews->next ) { Link Here
171
        $wants_digest = 0;
171
        $wants_digest = 0;
172
    }
172
    }
173
173
174
    # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script
174
    my ( $success, $error, $updated ) = $auto_renew->attempt_auto_renew();
175
    my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->patron, $auto_renew, undef, 1 );
175
    if ( $success ) {
176
    my $updated;
177
    if ( $error eq 'auto_renew' ) {
178
        $updated = 1;
179
        if ($verbose) {
176
        if ($verbose) {
180
            say sprintf "Issue id: %s for borrower: %s and item: %s %s be renewed.",
177
            say sprintf "Issue id: %s for borrower: %s and item: %s %s be renewed.",
181
              $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would';
178
              $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would';
182
        }
179
        }
183
        if ($confirm){
180
        if ($confirm){
184
            my $date_due = AddRenewal(
185
                {
186
                    borrowernumber    => $auto_renew->borrowernumber,
187
                    itemnumber        => $auto_renew->itemnumber,
188
                    branch            => $auto_renew->branchcode,
189
                    seen              => 0,
190
                    automatic         => 1,
191
                }
192
            );
193
            push @item_renewal_ids, $auto_renew->itemnumber;
181
            push @item_renewal_ids, $auto_renew->itemnumber;
194
            $auto_renew->auto_renew_error(undef)->store;
195
        }
182
        }
196
        push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
183
        push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
197
            if ( $wants_messages ) && !$wants_digest;
184
            if ( $wants_messages ) && !$wants_digest;
198
    } elsif (
185
    } elsif (
186
        # FIXME Do we need to list every status? Why not simply else?
199
        $error eq 'too_many' ||
187
        $error eq 'too_many' ||
200
        $error eq 'on_reserve' ||
188
        $error eq 'on_reserve' ||
201
        $error eq 'restriction' ||
189
        $error eq 'restriction' ||
Lines 212-220 while ( my $auto_renew = $auto_renews->next ) { Link Here
212
            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)",
213
              $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;
214
        }
202
        }
215
        $updated = 1 if (!$auto_renew->auto_renew_error || $error ne $auto_renew->auto_renew_error);
216
        if ( $updated ) {
203
        if ( $updated ) {
217
            $auto_renew->auto_renew_error($error)->store if $confirm;
218
            push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
204
            push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
219
              if $error ne 'auto_too_soon' && ( $wants_messages  && !$wants_digest );    # Do not notify if it's too soon
205
              if $error ne 'auto_too_soon' && ( $wants_messages  && !$wants_digest );    # Do not notify if it's too soon
220
        }
206
        }
(-)a/t/db_dependent/Koha/Checkouts.t (-3 / +68 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 11;
22
use Test::More tests => 12;
23
use Test::MockModule;
24
use Test::Warn;
23
25
24
use C4::Circulation qw( MarkIssueReturned AddReturn );
26
use C4::Circulation qw( MarkIssueReturned AddReturn );
25
use Koha::Checkouts;
27
use Koha::Checkouts;
Lines 406-409 subtest 'automatic_checkin' => sub { Link Here
406
    is( dt_from_string($searched->returndate), $yesterday, 'old checkout for odue_ac_item has the right return date' );
408
    is( dt_from_string($searched->returndate), $yesterday, 'old checkout for odue_ac_item has the right return date' );
407
409
408
    $schema->storage->txn_rollback;
410
    $schema->storage->txn_rollback;
409
}
411
};
412
413
subtest 'attempt_auto_renew' => sub {
414
415
    plan tests => 17;
416
417
    $schema->storage->txn_begin;
418
419
    my $renew_error = 'auto_renew';
420
    my $module      = Test::MockModule->new('C4::Circulation');
421
    $module->mock( 'CanBookBeRenewed', sub { return ( 1, $renew_error ) } );
422
    my $around_now = dt_from_string();
423
    $module->mock( 'AddRenewal', sub { warn "AddRenewal called" } );
424
    my $checkout = $builder->build_object(
425
        {
426
            class => 'Koha::Checkouts',
427
            value => {
428
                date_due         => '2023-01-01 23:59:59',
429
                returndate       => undef,
430
                auto_renew       => 1,
431
                auto_renew_error => undef,
432
                onsite_checkout  => 0,
433
                renewals_count   => 0,
434
            }
435
        }
436
    );
437
438
    my ( $success, $error, $updated );
439
    warning_is {
440
        ( $success, $error, $updated ) = $checkout->attempt_auto_renew();
441
    }
442
    undef, "AddRenewal not called without confirm";
443
    ok( $success, "Issue is renewed when error is 'auto_renew'" );
444
    is( $error, undef, "No error when renewed" );
445
    ok( $updated, "Issue reported as updated when renewed" );
446
447
    warning_is {
448
        ( $success, $error, $updated ) = $checkout->attempt_auto_renew( { confirm => 1 } );
449
    }
450
    "AddRenewal called", "AddRenewal called when confirm is passed";
451
    ok( $success, "Issue is renewed when error is 'auto_renew'" );
452
    is( $error, undef, "No error when renewed" );
453
    ok( $updated, "Issue reported as updated when renewed" );
454
455
    $renew_error = 'anything_else';
456
    ( $success, $error, $updated ) = $checkout->attempt_auto_renew();
457
    ok( !$success, "Success is untrue for any other status" );
458
    is( $error, 'anything_else', "The error is passed through" );
459
    ok( $updated, "Issue reported as updated when status changes" );
460
    $checkout->discard_changes();
461
    is( $checkout->auto_renew_error, undef, "Error not updated if confirm not passed" );
462
463
    ( $success, $error, $updated ) = $checkout->attempt_auto_renew( { confirm => 1 } );
464
    ok( !$success, "Success is untrue for any other status" );
465
    is( $error, 'anything_else', "The error is passed through" );
466
    ok( $updated, "Issue updated when confirm passed" );
467
    $checkout->discard_changes();
468
    is( $checkout->auto_renew_error, 'anything_else', "Error updated if confirm passed" );
469
470
    # Error now equals 'anything_else'
471
    ( $success, $error, $updated ) = $checkout->attempt_auto_renew();
472
    ok( !$updated, "Issue not reported as updated when status has not changed" );
473
474
    $schema->storage->txn_rollback;
475
};
410
- 

Return to bug 34924