From 35f99c1a58a41fb781206dd8a2d50c3ca0d0b6d2 Mon Sep 17 00:00:00 2001
From: Stefan Berndtsson <stefan.berndtsson@gmail.com>
Date: Thu, 8 Feb 2018 15:54:44 +0100
Subject: [PATCH] Bug 29145: use overdues restrict delays when removing
 overdues restriction upon return

How to test:
1) Run tests in t/db_dependent/Circulation/MarkIssueReturned.t

Sponsored by: Gothenburg University Library

Signed-off-by: Michaela <michaela.sieber@kit.edu>
---
 C4/Circulation.pm                             | 12 +++++-
 Koha/Patron.pm                                | 42 ++++++++++++++++++-
 ...ue-debarment-removal-allow-unrestricted.pl | 14 +++++++
 .../admin/preferences/circulation.pref        |  6 +++
 misc/cronjobs/overdue_notices.pl              |  4 +-
 5 files changed, 73 insertions(+), 5 deletions(-)
 create mode 100644 installer/data/mysql/atomicupdate/odue-debarment-removal-allow-unrestricted.pl

diff --git a/C4/Circulation.pm b/C4/Circulation.pm
index d74305aebc..eca6d2d778 100644
--- a/C4/Circulation.pm
+++ b/C4/Circulation.pm
@@ -2529,10 +2529,20 @@ sub MarkIssueReturned {
             $item->last_returned_by( $patron );
         }
 
+        # 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 = 0;
+        if(C4::Context->preference('ODueDebarmentRemovalAllowUnrestricted')) {
+            $has_overdue_ignore_unrestricted = 1;
+        }
+
         # Remove any OVERDUES related debarment if the borrower has no overdues
         if ( C4::Context->preference('AutoRemoveOverduesRestrictions')
           && $patron->debarred
-          && !$patron->has_overdues
+          && !$patron->has_overdues({
+              ignore_unrestricted => $has_overdue_ignore_unrestricted,
+              issue_branch => $issue->{'branchcode'} })
           && @{ GetDebarments({ borrowernumber => $borrowernumber, type => 'OVERDUES' }) }
         ) {
             DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
diff --git a/Koha/Patron.pm b/Koha/Patron.pm
index 96a72a393a..2cb28dd86b 100644
--- a/Koha/Patron.pm
+++ b/Koha/Patron.pm
@@ -979,9 +979,47 @@ Returns the number of patron's overdues
 =cut
 
 sub has_overdues {
-    my ($self) = @_;
+    my ($self, $params) = @_;
+    my $date = dt_from_string();
+
+    # If ignoring unrestricted overdues, calculate which delay value for
+    # overdue messages is set with restrictions. Then only include overdue
+    # issues older than that date when counting.
+    if($params->{ignore_unrestricted}) {
+        my $branchcode = $params->{issue_branchcode};
+        my $date_offset = _get_overdue_restrict_delay($params->{issue_branchcode}, $self->categorycode());
+        $date->subtract(days => $date_offset);
+    }
+
     my $dtf = Koha::Database->new->schema->storage->datetime_parser;
-    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime( dt_from_string() ) } })->count;
+    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime( $date )} })->count;
+}
+
+# Fetch first delayX value from overduerules where debarredX is set, or 0 for no delay
+sub _get_overdue_restrict_delay {
+    my ($branchcode, $categorycode) = @_;
+    my $dbh = C4::Context->dbh();
+
+    my $query = "SELECT * FROM overduerules WHERE delay1 IS NOT NULL AND branchcode = ? AND categorycode = ?";
+
+    my $rqoverduerules =  $dbh->prepare($query);
+    $rqoverduerules->execute($branchcode, $categorycode);
+
+    # We get default rules if there is no rule for this branch
+    if($rqoverduerules->rows == 0){
+        $query = "SELECT * FROM overduerules WHERE delay1 IS NOT NULL AND branchcode = '' AND categorycode = ?";
+
+        $rqoverduerules = $dbh->prepare($query);
+        $rqoverduerules->execute($categorycode);
+    }
+
+    while ( my $overdue_rules = $rqoverduerules->fetchrow_hashref ) {
+        return $overdue_rules->{"delay1"} if($overdue_rules->{"debarred1"});
+        return $overdue_rules->{"delay2"} if($overdue_rules->{"debarred2"});
+        return $overdue_rules->{"delay3"} if($overdue_rules->{"debarred3"});
+    }
+
+    return 0;
 }
 
 =head3 track_login
diff --git a/installer/data/mysql/atomicupdate/odue-debarment-removal-allow-unrestricted.pl b/installer/data/mysql/atomicupdate/odue-debarment-removal-allow-unrestricted.pl
new file mode 100644
index 0000000000..3a019999d1
--- /dev/null
+++ b/installer/data/mysql/atomicupdate/odue-debarment-removal-allow-unrestricted.pl
@@ -0,0 +1,14 @@
+use Modern::Perl;
+
+return {
+    bug_number => "",
+    description => "Add system preference",
+    up => sub {
+        my ($args) = @_;
+        my ($dbh, $out) = @$args{qw(dbh out)};
+        # Do you stuffs here
+        $dbh->do(q{INSERT IGNORE INTO systempreferences (`variable`, `value`, `options`, `explanation`, `type`) VALUES ('ODueDebarmentRemovalAllowUnrestricted', '0', null, 'Allow removal of OVERDUES debarment when overdues still exist, but has not reached restricting delay', 'YesNo')});
+        # Print useful stuff here
+        say $out "System preference added";
+    },
+}
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
index 6aea72198b..26803bd0ba 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -663,6 +663,12 @@ Circulation:
                   1: Store
                   0: "Don't store"
             - 'the last patron to return an item. This setting is independent of the <a href="/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=opacreadinghistory">opacreadinghistory</a> and <a href="/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=AnonymousPatron">AnonymousPatron</a> system preferences.'
+        -
+            - pref: ODueDebarmentRemovalAllowUnrestricted
+              choices:
+                  yes: Allow
+                  no: Do not allow
+            - removal of Overdue debarments when patron has overdue items but none are old enough to have reached restricting delay. Used in combination with AutoRemoveOverduesRestrictions.
     Holds policy:
         -
             - pref: EnableItemGroups
diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl
index f8fc79203c..cab148e048 100755
--- a/misc/cronjobs/overdue_notices.pl
+++ b/misc/cronjobs/overdue_notices.pl
@@ -500,8 +500,8 @@ END_SQL
     
     my $rqoverduerules =  $dbh->prepare($query);
     $rqoverduerules->execute($branchcode, @myborcat, @myborcatout);
-    
-    # We get default rules is there is no rule for this branch
+
+    # We get default rules if there is no rule for this branch
     if($rqoverduerules->rows == 0){
         $query = "SELECT * FROM overduerules WHERE delay1 IS NOT NULL AND branchcode = '' ";
         $query .= " AND categorycode IN (".join( ',' , ('?') x @myborcat ).") " if (@myborcat);
-- 
2.30.2