Bug 29145: Fix conditions for patron debarring overdues
Signed-off-by: Michaela <michaela.sieber@kit.edu> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
ee8ef4b174
commit
4678505e1e
3 changed files with 66 additions and 34 deletions
|
@ -2624,23 +2624,19 @@ sub MarkIssueReturned {
|
||||||
$item->last_returned_by( $patron->borrowernumber )->store;
|
$item->last_returned_by( $patron->borrowernumber )->store;
|
||||||
}
|
}
|
||||||
|
|
||||||
# The reason this is here, and not in Koha::Patron->has_overdues() is
|
|
||||||
# to make sure it will not cause any side effects elsewhere, since this
|
|
||||||
# is only relevant for removal of debarments.
|
|
||||||
my $has_overdue_ignore_unrestricted = C4::Context->preference('AutoRemoveOverduesRestrictions') eq 'when_no_overdue_causing_debarment';
|
|
||||||
|
|
||||||
# Possibly remove any OVERDUES related debarment
|
# Possibly remove any OVERDUES related debarment
|
||||||
my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
|
my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
|
||||||
if ( C4::Context->preference('AutoRemoveOverduesRestrictions' ne 'no')
|
if (C4::Context->preference('AutoRemoveOverduesRestrictions') ne 'no' && $patron->is_debarred) {
|
||||||
&& $patron->debarred
|
my $remove_restrictions =
|
||||||
&& $overdue_restrictions->count
|
C4::Context->preference('AutoRemoveOverduesRestrictions') eq 'when_no_overdue_causing_debarment' ?
|
||||||
&& !$patron->has_overdues({
|
!$patron->has_debarring_overdues({ issue_branchcode => $issue_branchcode }) :
|
||||||
ignore_unrestricted => $has_overdue_ignore_unrestricted,
|
!$patron->has_overdues;
|
||||||
issue_branch => $issue->{'branchcode'} })
|
if (
|
||||||
) {
|
$remove_restrictions && $overdue_restrictions->count
|
||||||
DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
|
) {
|
||||||
|
DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return $issue_id;
|
return $issue_id;
|
||||||
|
|
|
@ -1008,24 +1008,59 @@ Returns the number of patron's overdues
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
sub has_overdues {
|
sub has_overdues {
|
||||||
my ($self, $params) = @_;
|
my ($self) = @_;
|
||||||
my $date = dt_from_string();
|
my $date = dt_from_string();
|
||||||
|
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
|
||||||
|
return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime($date) } })->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub has_debarring_overdues {
|
||||||
|
my ($self, $params) = @_;
|
||||||
|
$params //= {};
|
||||||
|
my $date = dt_from_string()->truncate( to => 'day' );
|
||||||
|
|
||||||
# If ignoring unrestricted overdues, calculate which delay value for
|
# If ignoring unrestricted overdues, calculate which delay value for
|
||||||
# overdue messages is set with restrictions. Then only include overdue
|
# overdue messages is set with restrictions. Then only include overdue
|
||||||
# issues older than that date when counting.
|
# issues older than that date when counting.
|
||||||
if($params->{ignore_unrestricted}) {
|
#TODO: bail out/throw exception if $params->{issue_branchcode} not set?
|
||||||
my $branchcode = $params->{issue_branchcode};
|
my $debarred_delay = _get_overdue_debarred_delay($params->{issue_branchcode}, $self->categorycode());
|
||||||
my $date_offset = _get_overdue_restrict_delay($params->{issue_branchcode}, $self->categorycode());
|
return 0 unless defined $debarred_delay;
|
||||||
$date->subtract(days => $date_offset);
|
|
||||||
|
# Emulate the conditions in overdue_notices.pl.
|
||||||
|
# The overdue_notices-script effectively truncates both issues.date_due and current date
|
||||||
|
# to days when selecting overdue issues.
|
||||||
|
# Hours and minutes for issues.date_due is usually set to 23 and 59 respectively, though can theoretically
|
||||||
|
# be set to any other value (truncated to minutes, except if CalcDateDue gets a $startdate)
|
||||||
|
#
|
||||||
|
# No matter what time of day date_due is set to, overdue_notices.pl will select all issues that are due
|
||||||
|
# the current date or later. We can emulate this query by instead of truncating both to days in the SQL-query,
|
||||||
|
# using the condition that date_due must be less then the current date truncated to days (time set to 00:00:00)
|
||||||
|
# offset by one day in the future.
|
||||||
|
|
||||||
|
$date->add(days => 1);
|
||||||
|
|
||||||
|
my $calendar;
|
||||||
|
if (C4::Context->preference('OverdueNoticeCalendar')) {
|
||||||
|
$calendar = Koha::Calendar->new( branchcode => $params->{issue_branchcode} );
|
||||||
}
|
}
|
||||||
|
|
||||||
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
|
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
|
||||||
return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime( $date )} })->count;
|
my $issues = $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime($date) } });
|
||||||
|
my $now = dt_from_string();
|
||||||
|
|
||||||
|
while (my $issue = $issues->next) {
|
||||||
|
my $days_between = C4::Context->preference('OverdueNoticeCalendar') ?
|
||||||
|
$calendar->days_between(dt_from_string($issue->date_due), $now)->in_units('days') :
|
||||||
|
$now->delta_days(dt_from_string($issue->date_due))->in_units('days');
|
||||||
|
if ($days_between >= $debarred_delay) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Fetch first delayX value from overduerules where debarredX is set, or 0 for no delay
|
# Fetch first delayX value from overduerules where debarredX is set, or 0 for no delay
|
||||||
sub _get_overdue_restrict_delay {
|
sub _get_overdue_debarred_delay {
|
||||||
my ($branchcode, $categorycode) = @_;
|
my ($branchcode, $categorycode) = @_;
|
||||||
my $dbh = C4::Context->dbh();
|
my $dbh = C4::Context->dbh();
|
||||||
|
|
||||||
|
@ -1047,8 +1082,7 @@ sub _get_overdue_restrict_delay {
|
||||||
return $overdue_rules->{"delay2"} if($overdue_rules->{"debarred2"});
|
return $overdue_rules->{"delay2"} if($overdue_rules->{"debarred2"});
|
||||||
return $overdue_rules->{"delay3"} if($overdue_rules->{"debarred3"});
|
return $overdue_rules->{"delay3"} if($overdue_rules->{"debarred3"});
|
||||||
}
|
}
|
||||||
|
return undef;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
=head3 track_login
|
=head3 track_login
|
||||||
|
|
|
@ -201,9 +201,9 @@ subtest 'AutoRemoveOverduesRestrictions' => sub {
|
||||||
my $item_1 = $builder->build_sample_item;
|
my $item_1 = $builder->build_sample_item;
|
||||||
my $item_2 = $builder->build_sample_item;
|
my $item_2 = $builder->build_sample_item;
|
||||||
my $item_3 = $builder->build_sample_item;
|
my $item_3 = $builder->build_sample_item;
|
||||||
my $five_days_ago = dt_from_string->subtract( days => 5 );
|
my $nine_days_ago = dt_from_string->subtract( days => 9 ); #->set_hour(23)->set_minute(59);
|
||||||
my $checkout_1 = AddIssue( $patron, $item_1->barcode, $five_days_ago ); # overdue, but would not trigger debarment
|
my $checkout_1 = AddIssue( $patron, $item_1->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
|
||||||
my $checkout_2 = AddIssue( $patron, $item_2->barcode, $five_days_ago ); # overdue, but would not trigger debarment
|
my $checkout_2 = AddIssue( $patron, $item_2->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
|
||||||
my $checkout_3 = AddIssue( $patron, $item_3->barcode ); # not overdue
|
my $checkout_3 = AddIssue( $patron, $item_3->barcode ); # not overdue
|
||||||
|
|
||||||
Koha::Patron::Debarments::AddUniqueDebarment(
|
Koha::Patron::Debarments::AddUniqueDebarment(
|
||||||
|
@ -227,10 +227,12 @@ subtest 'AutoRemoveOverduesRestrictions' => sub {
|
||||||
|
|
||||||
t::lib::Mocks::mock_preference('AutoRemoveOverduesRestrictions', 'when_no_overdue_causing_debarment');
|
t::lib::Mocks::mock_preference('AutoRemoveOverduesRestrictions', 'when_no_overdue_causing_debarment');
|
||||||
|
|
||||||
my $eleven_days_ago = dt_from_string->subtract( days => 11 );
|
my $ten_days_ago = dt_from_string->subtract( days => 10 );
|
||||||
|
|
||||||
$checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $eleven_days_ago ); # overdue and would trigger debarment
|
$checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
|
||||||
$checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $five_days_ago ); # overdue, but would not trigger debarment
|
$checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $nine_days_ago ); # overdue, but would not trigger debarment
|
||||||
|
|
||||||
|
print STDERR "DUEDATE: " . $nine_days_ago->stringify . "\n";
|
||||||
|
|
||||||
Koha::Patron::Debarments::AddUniqueDebarment(
|
Koha::Patron::Debarments::AddUniqueDebarment(
|
||||||
{
|
{
|
||||||
|
@ -245,7 +247,7 @@ subtest 'AutoRemoveOverduesRestrictions' => sub {
|
||||||
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber });
|
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber });
|
||||||
is( scalar @$debarments, 0, 'OVERDUES debarment is removed if remaning items would not result in patron debarment' );
|
is( scalar @$debarments, 0, 'OVERDUES debarment is removed if remaning items would not result in patron debarment' );
|
||||||
|
|
||||||
$checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $eleven_days_ago ); # overdue and would trigger debarment
|
$checkout_1 = AddIssue( $patron->unblessed, $item_1->barcode, $ten_days_ago ); # overdue and would trigger debarment
|
||||||
|
|
||||||
Koha::Patron::Debarments::AddUniqueDebarment(
|
Koha::Patron::Debarments::AddUniqueDebarment(
|
||||||
{
|
{
|
||||||
|
@ -260,12 +262,12 @@ subtest 'AutoRemoveOverduesRestrictions' => sub {
|
||||||
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber });
|
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber });
|
||||||
is( $debarments->[0]->{type}, 'OVERDUES', 'OVERDUES debarment is not removed if patron still has overdues that would trigger debarment' );
|
is( $debarments->[0]->{type}, 'OVERDUES', 'OVERDUES debarment is not removed if patron still has overdues that would trigger debarment' );
|
||||||
|
|
||||||
my $thirteen_days_ago = dt_from_string->subtract( days => 13 );
|
my $eleven_days_ago = dt_from_string->subtract( days => 11 );
|
||||||
|
|
||||||
# overdue and would trigger debarment
|
# overdue and would trigger debarment
|
||||||
$checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $thirteen_days_ago );
|
$checkout_2 = AddIssue( $patron->unblessed, $item_2->barcode, $eleven_days_ago );
|
||||||
|
|
||||||
# $chechout_1 should now not trigger debarment with this new rule for specific branchcode
|
# $checkout_1 should now not trigger debarment with this new rule for specific branchcode
|
||||||
$dbh->do(qq{
|
$dbh->do(qq{
|
||||||
INSERT INTO `overduerules` (
|
INSERT INTO `overduerules` (
|
||||||
`branchcode`,
|
`branchcode`,
|
||||||
|
@ -277,7 +279,7 @@ subtest 'AutoRemoveOverduesRestrictions' => sub {
|
||||||
`letter2`,
|
`letter2`,
|
||||||
`debarred2`
|
`debarred2`
|
||||||
)
|
)
|
||||||
VALUES ('$branchcode', '$categorycode', 6, 'ODUE', 0, 12, 'ODUE2', 1)
|
VALUES ('$branchcode', '$categorycode', 6, 'ODUE', 0, 11, 'ODUE2', 1)
|
||||||
});
|
});
|
||||||
|
|
||||||
C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
|
C4::Circulation::MarkIssueReturned( $patron->borrowernumber, $item_2->itemnumber );
|
||||||
|
|
Loading…
Reference in a new issue