From 8ef98254bf81c06781363f6a3717ac06c8c2763f Mon Sep 17 00:00:00 2001
From: Matthias Meusburger <matthias.meusburger@biblibre.com>
Date: Thu, 23 Jul 2020 16:24:39 +0200
Subject: [PATCH] Bug 26937: Add an optional delay to the CheckPrevCheckout
 syspref.

The CheckPrevCheckout allows to check a borrower's checkout history to see if
the current item has been checked out before.

This patch adds an optional syspref: CheckPrevCheckoutDelay

It allows to specify the maximum number of days since the last checkin
that will trigger CheckPrevCheckout's warning.

Test plan:

 - Apply the patch.

 - Set CheckPrevCheckout to "Do" and CheckPrevCheckoutDelay to n.

 - Checkout and check-in an item for a patron.

 - Try to checkout the same item.

 - Check that you have a warning:
   "Patron has previously checked out this title: Check out anyway?"

 - Update the returndate column from the old_issues table to have a returndate
   older than n days ago.

 - Try to checkout the same item.

 - Check that you don't have the warning.

 - Prove t/db_dependent/Patron/Borrower_PrevCheckout.t
---
 Koha/Patron.pm                                     |  7 +++++
 installer/data/mysql/atomicupdate/MT29572.perl     |  9 ++++++
 installer/data/mysql/mandatory/sysprefs.sql        |  1 +
 .../prog/en/modules/admin/preferences/patrons.pref |  4 +++
 t/db_dependent/Patron/Borrower_PrevCheckout.t      | 35 +++++++++++++++++++++-
 5 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 installer/data/mysql/atomicupdate/MT29572.perl

diff --git a/Koha/Patron.pm b/Koha/Patron.pm
index 8f3d8e6990..f7de023496 100644
--- a/Koha/Patron.pm
+++ b/Koha/Patron.pm
@@ -694,6 +694,13 @@ sub do_check_for_previous_checkout {
         itemnumber => \@item_nos,
     };
 
+    my $delay = C4::Context->preference('CheckPrevCheckoutDelay') || 0;
+    if ($delay) {
+        my $dtf = Koha::Database->new->schema->storage->datetime_parser;
+        my $newer_than = dt_from_string()->subtract( days => $delay );
+        $criteria->{'returndate'} = { '>'   =>  $dtf->format_datetime($newer_than), };
+    }
+
     # Check current issues table
     my $issues = Koha::Checkouts->search($criteria);
     return 1 if $issues->count; # 0 || N
diff --git a/installer/data/mysql/atomicupdate/MT29572.perl b/installer/data/mysql/atomicupdate/MT29572.perl
new file mode 100644
index 0000000000..7afac27ff8
--- /dev/null
+++ b/installer/data/mysql/atomicupdate/MT29572.perl
@@ -0,0 +1,9 @@
+$DBversion = 'XXX'; # will be replaced by the RM
+if( CheckVersion( $DBversion ) ) {
+    # you can use $dbh here like:
+    $dbh->do( "INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CheckPrevCheckoutDelay','0', 'Maximum number of days that will trigger a warning if the patron has borrowed that item in the past when CheckPrevCheckout is enabled. Disabled if 0 or empty.', NULL, 'free')" );
+
+    # Always end with this (adjust the bug info)
+    SetVersion( $DBversion );
+    print "Upgrade to $DBversion done (MT 29572 - description)\n";
+}
diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql
index 0e9f488055..5d3f1c4814 100644
--- a/installer/data/mysql/mandatory/sysprefs.sql
+++ b/installer/data/mysql/mandatory/sysprefs.sql
@@ -122,6 +122,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
 ('CatalogModuleRelink','0',NULL,'If OFF the linker will never replace the authids that are set in the cataloging module.','YesNo'),
 ('CataloguingLog','1',NULL,'If ON, log edit/create/delete actions on bibliographic data. WARNING: this feature is very resource consuming.','YesNo'),
 ('CheckPrevCheckout','hardno','hardyes|softyes|softno|hardno','By default, for every item checked out, should we warn if the patron has borrowed that item in the past?','Choice'),
+('CheckPrevCheckoutDelay','0', NULL,'Maximum number of days that will trigger a warning if the patron has borrowed that item in the past when CheckPrevCheckout is enabled.','free'),
 ('CircAutoPrintQuickSlip','qslip',NULL,'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window, Display a print slip window or Clear the screen.','Choice'),
 ('CircConfirmItemParts', '0', NULL, 'Require staff to confirm that all parts of an item are present at checkin/checkout.', 'Yes/No'),
 ('CircControl','ItemHomeLibrary','PickupLibrary|PatronLibrary|ItemHomeLibrary','Specify the agency that controls the circulation and fines policy','Choice'),
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
index fc8e8b6c7e..ca8ed8cd63 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
@@ -10,6 +10,10 @@ Patrons:
                hardno: "Do not"
          - " check borrower checkout history to see if the current item has been checked out before."
      -
+         - pref: CheckPrevCheckoutDelay
+           default: 0
+         - "Maximum number of days that will trigger a warning if the patron has borrowed that item in the past when CheckPrevCheckout is enabled. Disabled if 0 or empty."
+     -
          - pref: ExtendedPatronAttributes
            choices:
                yes: Enable
diff --git a/t/db_dependent/Patron/Borrower_PrevCheckout.t b/t/db_dependent/Patron/Borrower_PrevCheckout.t
index 00e21e612d..8a240cec4b 100755
--- a/t/db_dependent/Patron/Borrower_PrevCheckout.t
+++ b/t/db_dependent/Patron/Borrower_PrevCheckout.t
@@ -4,9 +4,10 @@ use Modern::Perl;
 use C4::Members;
 use C4::Circulation;
 use Koha::Database;
+use Koha::DateUtils;
 use Koha::Patrons;
 
-use Test::More tests => 60;
+use Test::More tests => 61;
 
 use_ok('Koha::Patron');
 
@@ -450,4 +451,36 @@ subtest 'Check previous checkouts for serial' => sub {
     is($patron->do_check_for_previous_checkout($item2->unblessed), 0, 'Check only one item if bibliographic record is serial');
 
     $schema->storage->txn_rollback;
+};
+
+subtest 'Check previous checkouts with delay' => sub {
+    plan tests => 3;
+    $schema->storage->txn_begin;
+    my $library = $builder->build_object({ class => 'Koha::Libraries'});
+    my $biblio = $builder->build_sample_biblio;
+    my $patron = $builder->build({source => 'Borrower'});
+    my $item_object = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
+
+    my $issue = Koha::Checkout->new({ branchcode => $library->branchcode, borrowernumber => $patron->{borrowernumber}, itemnumber => $item_object->itemnumber })->store;
+    my $returndate = dt_from_string()->subtract( days => 3 );
+    my $return = AddReturn($item_object->barcode, $library->branchcode, undef, $returndate);
+
+    t::lib::Mocks::mock_preference('checkprevcheckout', 'hardyes');
+    t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 0);
+    my $patron1 = Koha::Patrons->find($patron->{borrowernumber});
+    is(
+            $patron1->do_check_for_previous_checkout($item_object->unblessed),
+            1, "Checking CheckPrevCheckoutDelay disabled"
+    );
+    t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 5);
+    is(
+            $patron1->do_check_for_previous_checkout($item_object->unblessed),
+            1, "Checking CheckPrevCheckoutDelay enabled within delay"
+    );
+    t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 1);
+    is(
+            $patron1->do_check_for_previous_checkout($item_object->unblessed),
+            0, "Checking CheckPrevCheckoutDelay enabled after delay"
+    );
+    $schema->storage->txn_rollback;
 }
-- 
2.11.0