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

(-)a/C4/Circulation.pm (-9 / +8 lines)
Lines 2632-2649 sub MarkIssueReturned { Link Here
2632
        }
2632
        }
2633
2633
2634
        # Possibly remove any OVERDUES related debarment
2634
        # Possibly remove any OVERDUES related debarment
2635
        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
2635
        my $overdue_restrictions = $patron->restrictions->search( { type => 'OVERDUES' } );
2636
        if (C4::Context->preference('AutoRemoveOverduesRestrictions') ne 'no' && $patron->is_debarred) {
2636
        if ( C4::Context->preference('AutoRemoveOverduesRestrictions') ne 'no' && $patron->is_debarred ) {
2637
            my $remove_restrictions =
2637
            my $remove_restrictions =
2638
                C4::Context->preference('AutoRemoveOverduesRestrictions') eq 'when_no_overdue_causing_debarment' ?
2638
                C4::Context->preference('AutoRemoveOverduesRestrictions') eq 'when_no_overdue_causing_debarment'
2639
                    !$patron->has_restricting_overdues({ issue_branchcode => $issue_branchcode }) :
2639
                ? !$patron->has_restricting_overdues( { issue_branchcode => $issue_branchcode } )
2640
                    !$patron->has_overdues;
2640
                : !$patron->has_overdues;
2641
            if (
2641
            if ( $remove_restrictions && $overdue_restrictions->count ) {
2642
                $remove_restrictions && $overdue_restrictions->count
2642
                DelUniqueDebarment( { borrowernumber => $borrowernumber, type => 'OVERDUES' } );
2643
            ) {
2644
                DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
2645
            }
2643
            }
2646
        }
2644
        }
2645
2647
    });
2646
    });
2648
2647
2649
    return $issue_id;
2648
    return $issue_id;
(-)a/Koha/Patron.pm (-18 / +21 lines)
Lines 1001-1006 sub has_overdues { Link Here
1001
}
1001
}
1002
1002
1003
1003
1004
1004
=head3 has_restricting_overdues
1005
=head3 has_restricting_overdues
1005
1006
1006
my $has_restricting_overdues = $patron->has_restricting_overdues({ issue_branchcode => $branchcode });
1007
my $has_restricting_overdues = $patron->has_restricting_overdues({ issue_branchcode => $branchcode });
Lines 1010-1016 Returns true if patron has overdues that would result in debarment. Link Here
1010
=cut
1011
=cut
1011
1012
1012
sub has_restricting_overdues {
1013
sub has_restricting_overdues {
1013
    my ($self, $params) = @_;
1014
    my ( $self, $params ) = @_;
1014
    $params //= {};
1015
    $params //= {};
1015
    my $date = dt_from_string()->truncate( to => 'day' );
1016
    my $date = dt_from_string()->truncate( to => 'day' );
1016
1017
Lines 1018-1024 sub has_restricting_overdues { Link Here
1018
    # overdue messages is set with restrictions. Then only include overdue
1019
    # overdue messages is set with restrictions. Then only include overdue
1019
    # issues older than that date when counting.
1020
    # issues older than that date when counting.
1020
    #TODO: bail out/throw exception if $params->{issue_branchcode} not set?
1021
    #TODO: bail out/throw exception if $params->{issue_branchcode} not set?
1021
    my $debarred_delay = _get_overdue_debarred_delay($params->{issue_branchcode}, $self->categorycode());
1022
    my $debarred_delay = _get_overdue_debarred_delay( $params->{issue_branchcode}, $self->categorycode() );
1022
    return 0 unless defined $debarred_delay;
1023
    return 0 unless defined $debarred_delay;
1023
1024
1024
    # Emulate the conditions in overdue_notices.pl.
1025
    # Emulate the conditions in overdue_notices.pl.
Lines 1032-1053 sub has_restricting_overdues { Link Here
1032
    # using the condition that date_due must be less then the current date truncated to days (time set to 00:00:00)
1033
    # using the condition that date_due must be less then the current date truncated to days (time set to 00:00:00)
1033
    # offset by one day in the future.
1034
    # offset by one day in the future.
1034
1035
1035
    $date->add(days => 1);
1036
    $date->add( days => 1 );
1036
1037
1037
    my $calendar;
1038
    my $calendar;
1038
    if (C4::Context->preference('OverdueNoticeCalendar')) {
1039
    if ( C4::Context->preference('OverdueNoticeCalendar') ) {
1039
        $calendar = Koha::Calendar->new( branchcode => $params->{issue_branchcode} );
1040
        $calendar = Koha::Calendar->new( branchcode => $params->{issue_branchcode} );
1040
    }
1041
    }
1041
1042
1042
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
1043
    my $dtf    = Koha::Database->new->schema->storage->datetime_parser;
1043
    my $issues = $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime($date) } });
1044
    my $issues = $self->_result->issues->search( { date_due => { '<' => $dtf->format_datetime($date) } } );
1044
    my $now = dt_from_string();
1045
    my $now    = dt_from_string();
1045
1046
1046
    while (my $issue = $issues->next) {
1047
    while ( my $issue = $issues->next ) {
1047
        my $days_between = C4::Context->preference('OverdueNoticeCalendar') ?
1048
        my $days_between =
1048
            $calendar->days_between(dt_from_string($issue->date_due), $now)->in_units('days') :
1049
            C4::Context->preference('OverdueNoticeCalendar')
1049
            $now->delta_days(dt_from_string($issue->date_due))->in_units('days');
1050
            ? $calendar->days_between( dt_from_string( $issue->date_due ), $now )->in_units('days')
1050
        if ($days_between >= $debarred_delay) {
1051
            : $now->delta_days( dt_from_string( $issue->date_due ) )->in_units('days');
1052
        if ( $days_between >= $debarred_delay ) {
1051
            return 1;
1053
            return 1;
1052
        }
1054
        }
1053
    }
1055
    }
Lines 1056-1062 sub has_restricting_overdues { Link Here
1056
1058
1057
# Fetch first delayX value from overduerules where debarredX is set, or 0 for no delay
1059
# Fetch first delayX value from overduerules where debarredX is set, or 0 for no delay
1058
sub _get_overdue_debarred_delay {
1060
sub _get_overdue_debarred_delay {
1059
    my ($branchcode, $categorycode) = @_;
1061
    my ( $branchcode, $categorycode ) = @_;
1060
    my $dbh = C4::Context->dbh();
1062
    my $dbh = C4::Context->dbh();
1061
1063
1062
    # We get default rules if there is no rule for this branch
1064
    # We get default rules if there is no rule for this branch
Lines 1065-1085 sub _get_overdue_debarred_delay { Link Here
1065
            branchcode   => $branchcode,
1067
            branchcode   => $branchcode,
1066
            categorycode => $categorycode
1068
            categorycode => $categorycode
1067
        }
1069
        }
1068
      )
1070
        )
1069
      || Koha::OverdueRules->find(
1071
        || Koha::OverdueRules->find(
1070
        {
1072
        {
1071
            branchcode   => q{},
1073
            branchcode   => q{},
1072
            categorycode => $categorycode
1074
            categorycode => $categorycode
1073
        }
1075
        }
1074
      );
1076
        );
1075
1077
1076
    if ( $rule ) {
1078
    if ($rule) {
1077
        return $rule->delay1 if $rule->debarred1;
1079
        return $rule->delay1 if $rule->debarred1;
1078
        return $rule->delay2 if $rule->debarred2;
1080
        return $rule->delay2 if $rule->debarred2;
1079
        return $rule->delay3 if $rule->debarred3;
1081
        return $rule->delay3 if $rule->debarred3;
1080
    }
1082
    }
1081
}
1083
}
1082
1084
1085
1083
=head3 track_login
1086
=head3 track_login
1084
1087
1085
    $patron->track_login;
1088
    $patron->track_login;
(-)a/installer/data/mysql/atomicupdate/bug_29145-modify_AutoRemoveOverduesRestrictions-syspref.pl (-5 / +8 lines)
Lines 1-13 Link Here
1
use Modern::Perl;
1
use Modern::Perl;
2
2
3
return {
3
return {
4
    bug_number => "29145",
4
    bug_number  => "29145",
5
    description => "Change type of AutoRemoveOverduesRestrictions system preference",
5
    description => "Change type of AutoRemoveOverduesRestrictions system preference",
6
    up => sub {
6
    up          => sub {
7
        my ($args) = @_;
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
8
        my ( $dbh, $out ) = @$args{qw(dbh out)};
9
9
        # Do you stuffs here
10
        # Do you stuffs here
10
        $dbh->do(q{UPDATE `systempreferences` SET `type` = 'Choice', `options` = 'no|when_no_overdue|when_no_overdue_causing_debarment', `explanation` = 'Defines if and on what conditions OVERDUES debarments should automatically be lifted when overdue items are returned by the patron.', `value` = CASE `value` WHEN '1' THEN 'when_no_overdue' WHEN '0' THEN 'no' ELSE `value` END WHERE variable = 'AutoRemoveOverduesRestrictions'});
11
        $dbh->do(
12
            q{UPDATE `systempreferences` SET `type` = 'Choice', `options` = 'no|when_no_overdue|when_no_overdue_causing_debarment', `explanation` = 'Defines if and on what conditions OVERDUES debarments should automatically be lifted when overdue items are returned by the patron.', `value` = CASE `value` WHEN '1' THEN 'when_no_overdue' WHEN '0' THEN 'no' ELSE `value` END WHERE variable = 'AutoRemoveOverduesRestrictions'}
13
        );
11
        say $out "Type of AutoRemoveOverduesRestrictions system preference has been changed";
14
        say $out "Type of AutoRemoveOverduesRestrictions system preference has been changed";
12
    },
15
    },
13
}
16
    }
(-)a/t/db_dependent/Circulation/MarkIssueReturned.t (-26 / +42 lines)
Lines 177-188 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
177
177
178
    $schema->storage->txn_begin;
178
    $schema->storage->txn_begin;
179
179
180
    my $dbh = C4::Context->dbh;
180
    my $dbh          = C4::Context->dbh;
181
    my $patron = $builder->build_object({ class => 'Koha::Patrons' });
181
    my $patron       = $builder->build_object( { class => 'Koha::Patrons' } );
182
    my $categorycode = $patron->categorycode;
182
    my $categorycode = $patron->categorycode;
183
    my $branchcode = $patron->branchcode;
183
    my $branchcode   = $patron->branchcode;
184
184
185
    $dbh->do(qq{
185
    $dbh->do(
186
        qq{
186
        INSERT INTO `overduerules` (
187
        INSERT INTO `overduerules` (
187
            `categorycode`,
188
            `categorycode`,
188
            `delay1`,
189
            `delay1`,
Lines 193-222 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
193
            `debarred2`
194
            `debarred2`
194
        )
195
        )
195
        VALUES ('$categorycode', 6, 'ODUE', 0, 10, 'ODUE2', 1)
196
        VALUES ('$categorycode', 6, 'ODUE', 0, 10, 'ODUE2', 1)
196
    });
197
    }
198
    );
197
199
198
    t::lib::Mocks::mock_preference('AutoRemoveOverduesRestrictions', 'when_no_overdue');
200
    t::lib::Mocks::mock_preference( 'AutoRemoveOverduesRestrictions', 'when_no_overdue' );
199
201
200
    t::lib::Mocks::mock_userenv( { branchcode => $branchcode } );
202
    t::lib::Mocks::mock_userenv( { branchcode => $branchcode } );
201
    my $item_1 = $builder->build_sample_item;
203
    my $item_1        = $builder->build_sample_item;
202
    my $item_2 = $builder->build_sample_item;
204
    my $item_2        = $builder->build_sample_item;
203
    my $item_3 = $builder->build_sample_item;
205
    my $item_3        = $builder->build_sample_item;
204
    my $nine_days_ago = dt_from_string->subtract( days => 9 ); #->set_hour(23)->set_minute(59);
206
    my $nine_days_ago = dt_from_string->subtract( days => 9 );    #->set_hour(23)->set_minute(59);
205
    my $checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
207
    my $checkout_1 =
206
    my $checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
208
        AddIssue( $patron->unblessed, $item_1->barcode, $nine_days_ago );    # overdue, but would not trigger debarment
207
    my $checkout_3 = AddIssue( $patron->unblessed, $item_3->barcode ); # not overdue
209
    my $checkout_2 =
210
        AddIssue( $patron->unblessed, $item_2->barcode, $nine_days_ago );    # overdue, but would not trigger debarment
211
    my $checkout_3 = AddIssue( $patron->unblessed, $item_3->barcode );       # not overdue
208
212
209
    Koha::Patron::Debarments::AddUniqueDebarment(
213
    Koha::Patron::Debarments::AddUniqueDebarment(
210
        {
214
        {
211
            borrowernumber => $patron->borrowernumber,
215
            borrowernumber => $patron->borrowernumber,
212
            type           => 'OVERDUES',
216
            type           => 'OVERDUES',
213
            comment => "OVERDUES_PROCESS simulation",
217
            comment        => "OVERDUES_PROCESS simulation",
214
        }
218
        }
215
    );
219
    );
216
220
217
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_1->itemnumber );
221
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_1->itemnumber );
218
222
219
    my $restrictions = $patron->restrictions;
223
    my $restrictions    = $patron->restrictions;
220
    my $THE_restriction = $restrictions->next;
224
    my $THE_restriction = $restrictions->next;
221
    is( $THE_restriction->type->code, 'OVERDUES', 'OVERDUES debarment is not removed if patron still has overdues' );
225
    is( $THE_restriction->type->code, 'OVERDUES', 'OVERDUES debarment is not removed if patron still has overdues' );
222
226
Lines 225-249 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
225
    $restrictions = $patron->restrictions;
229
    $restrictions = $patron->restrictions;
226
    is( $restrictions->count, 0, 'OVERDUES debarment is removed if patron does not have overdues' );
230
    is( $restrictions->count, 0, 'OVERDUES debarment is removed if patron does not have overdues' );
227
231
228
    t::lib::Mocks::mock_preference('AutoRemoveOverduesRestrictions', 'when_no_overdue_causing_debarment');
232
    t::lib::Mocks::mock_preference( 'AutoRemoveOverduesRestrictions', 'when_no_overdue_causing_debarment' );
229
233
230
    my $ten_days_ago = dt_from_string->subtract( days => 10 );
234
    my $ten_days_ago = dt_from_string->subtract( days => 10 );
231
235
232
    $checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
236
    $checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
233
    $checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
237
    $checkout_2 =
238
        AddIssue( $patron->unblessed, $item_2->barcode, $nine_days_ago );    # overdue, but would not trigger debarment
234
239
235
    Koha::Patron::Debarments::AddUniqueDebarment(
240
    Koha::Patron::Debarments::AddUniqueDebarment(
236
        {
241
        {
237
            borrowernumber => $patron->borrowernumber,
242
            borrowernumber => $patron->borrowernumber,
238
            type           => 'OVERDUES',
243
            type           => 'OVERDUES',
239
            comment => "OVERDUES_PROCESS simulation",
244
            comment        => "OVERDUES_PROCESS simulation",
240
        }
245
        }
241
    );
246
    );
242
247
243
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_1->itemnumber );
248
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_1->itemnumber );
244
249
245
    $restrictions = $patron->restrictions;
250
    $restrictions = $patron->restrictions;
246
    is($restrictions->count, 0, 'OVERDUES debarment is removed if remaining items would not result in patron debarment' );
251
    is(
252
        $restrictions->count, 0,
253
        'OVERDUES debarment is removed if remaining items would not result in patron debarment'
254
    );
247
255
248
    $checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
256
    $checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
249
257
Lines 251-264 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
251
        {
259
        {
252
            borrowernumber => $patron->borrowernumber,
260
            borrowernumber => $patron->borrowernumber,
253
            type           => 'OVERDUES',
261
            type           => 'OVERDUES',
254
            comment => "OVERDUES_PROCESS simulation",
262
            comment        => "OVERDUES_PROCESS simulation",
255
        }
263
        }
256
    );
264
    );
257
265
258
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
266
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
259
267
260
    $restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
268
    $restrictions = $patron->restrictions->search( { type => 'OVERDUES' } );
261
    is( $restrictions->count, 1, 'OVERDUES debarment is not removed if patron still has overdues that would trigger debarment' );
269
    is(
270
        $restrictions->count, 1,
271
        'OVERDUES debarment is not removed if patron still has overdues that would trigger debarment'
272
    );
262
273
263
    my $eleven_days_ago = dt_from_string->subtract( days => 11 );
274
    my $eleven_days_ago = dt_from_string->subtract( days => 11 );
264
275
Lines 266-272 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
266
    $checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $eleven_days_ago );
277
    $checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $eleven_days_ago );
267
278
268
    # $checkout_1 should now not trigger debarment with this new rule for specific branchcode
279
    # $checkout_1 should now not trigger debarment with this new rule for specific branchcode
269
    $dbh->do(qq{
280
    $dbh->do(
281
        qq{
270
        INSERT INTO `overduerules` (
282
        INSERT INTO `overduerules` (
271
            `branchcode`,
283
            `branchcode`,
272
            `categorycode`,
284
            `categorycode`,
Lines 278-289 subtest 'AutoRemoveOverduesRestrictions' => sub { Link Here
278
            `debarred2`
290
            `debarred2`
279
        )
291
        )
280
        VALUES ('$branchcode', '$categorycode', 6, 'ODUE', 0, 11, 'ODUE2', 1)
292
        VALUES ('$branchcode', '$categorycode', 6, 'ODUE', 0, 11, 'ODUE2', 1)
281
    });
293
    }
294
    );
282
295
283
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
296
    C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
284
297
285
    $restrictions = $patron->restrictions;
298
    $restrictions = $patron->restrictions;
286
    is( $restrictions->count, 0, 'OVERDUES debarment is removed if remaining items would not result in patron debarment' );
299
    is(
300
        $restrictions->count, 0,
301
        'OVERDUES debarment is removed if remaining items would not result in patron debarment'
302
    );
287
303
288
    $schema->storage->txn_rollback;
304
    $schema->storage->txn_rollback;
289
};
305
};
290
- 
306

Return to bug 29145