From b99ce5c26236e1fc467b7d99b8683a09057246f8 Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Mon, 3 Jan 2022 15:06:23 -0300
Subject: [PATCH] Bug 29525: Add Koha::Old::Holds->filter_by_anonymizable

This patch adds the 'filter_by_anonymizable' method, and tests for it. A
new DBIC relationship is added as well to the OldReserve schema file.

To test:
1. Apply this patch
2. Run:
   $ kshell
  k$ t/db_dependent/Koha/Old/Holds.t
=> SUCCESS: Tests pass!
3. Sign off :-D
---
 Koha/Old/Holds.pm                | 33 ++++++++++++-
 Koha/Schema/Result/OldReserve.pm | 12 +++++
 t/db_dependent/Koha/Old/Holds.t  | 80 +++++++++++++++++++++++++++++++-
 3 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/Koha/Old/Holds.pm b/Koha/Old/Holds.pm
index 40bf2dcdf2..1a7cb0d5a7 100644
--- a/Koha/Old/Holds.pm
+++ b/Koha/Old/Holds.pm
@@ -19,7 +19,6 @@ package Koha::Old::Holds;
 
 use Modern::Perl;
 
-
 use Koha::Database;
 
 use Koha::Old::Hold;
@@ -36,6 +35,38 @@ This object represents a set of holds that have been filled or canceled
 
 =head2 Class methods
 
+=head3 filter_by_anonymizable
+
+    my $holds = $patron->old_holds;
+    my $anonymizable_holds = $holds->filter_by_anonymizable;
+
+This method filters a I<Koha::Old::Holds> resultset, so it only contains holds that can be
+anonymized given the patron privacy settings.
+
+=cut
+
+sub filter_by_anonymizable {
+    my ( $self, $params ) = @_;
+
+    my $anonymous_patron = C4::Context->preference('AnonymousPatron') || undef;
+
+    return $self->search(
+        {
+            'me.borrowernumber' => { 'not' => undef },
+            'patron.privacy' => { '<>'  => 0 },
+            (
+                $anonymous_patron
+                ? ( 'me.borrowernumber' => { '!=' => $anonymous_patron } )
+                : ()
+            ),
+        },
+        {
+            join     => ['patron'],
+            order_by => ['me.reserve_id'],
+        }
+    );
+}
+
 =head3 anonymize
 
     $patron->old_holds->anonymize();
diff --git a/Koha/Schema/Result/OldReserve.pm b/Koha/Schema/Result/OldReserve.pm
index 05174e1566..cd19cbe101 100644
--- a/Koha/Schema/Result/OldReserve.pm
+++ b/Koha/Schema/Result/OldReserve.pm
@@ -394,6 +394,18 @@ __PACKAGE__->belongs_to(
   },
 );
 
+__PACKAGE__->belongs_to(
+  "patron",
+  "Koha::Schema::Result::Borrower",
+  { borrowernumber => "borrowernumber" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "SET NULL",
+    on_update     => "SET NULL",
+  },
+);
+
 __PACKAGE__->add_columns(
     '+item_level_hold' => { is_boolean => 1 },
     '+lowestPriority'  => { is_boolean => 1 },
diff --git a/t/db_dependent/Koha/Old/Holds.t b/t/db_dependent/Koha/Old/Holds.t
index fc1f5592cd..befaefe7d1 100755
--- a/t/db_dependent/Koha/Old/Holds.t
+++ b/t/db_dependent/Koha/Old/Holds.t
@@ -17,7 +17,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 1;
+use Test::More tests => 2;
 
 use Koha::Database;
 use Koha::DateUtils qw(dt_from_string);
@@ -85,3 +85,81 @@ subtest 'anonymize() tests' => sub {
 
     $schema->storage->txn_rollback;
 };
+
+subtest 'filter_by_anonymizable() tests' => sub {
+
+    plan tests => 7;
+
+    $schema->storage->txn_begin;
+
+    # patron_1 => keep records forever
+    my $patron_1 = $builder->build_object(
+        { class => 'Koha::Patrons', value => { privacy => 0 } } );
+
+    # patron_2 => never keep records
+    my $patron_2 = $builder->build_object(
+        { class => 'Koha::Patrons', value => { privacy => 1 } } );
+
+    is( $patron_1->old_holds->count, 0, 'patron_1 has no old holds' );
+    is( $patron_2->old_holds->count, 0, 'patron_2 has no old holds' );
+
+    my $hold_1 = $builder->build_object(
+        {
+            class => 'Koha::Holds',
+            value => {
+                borrowernumber => $patron_1->id,
+            }
+        }
+    )->_move_to_old;
+    my $hold_2 = $builder->build_object(
+        {
+            class => 'Koha::Holds',
+            value => {
+                borrowernumber => $patron_2->id,
+            }
+        }
+    )->_move_to_old;
+    my $hold_3 = $builder->build_object(
+        {
+            class => 'Koha::Holds',
+            value => {
+                borrowernumber => $patron_1->id,
+            }
+        }
+    )->_move_to_old;
+    my $hold_4 = $builder->build_object(
+        {
+            class => 'Koha::Holds',
+            value => {
+                borrowernumber => $patron_2->id,
+            }
+        }
+    )->_move_to_old;
+
+    $hold_1 = Koha::Old::Holds->find( $hold_1->id )
+      ->set( { timestamp => dt_from_string() } )->store;
+    $hold_2 = Koha::Old::Holds->find( $hold_2->id )
+      ->set( { timestamp => dt_from_string()->subtract( days => 1 ) } )->store;
+    $hold_3 = Koha::Old::Holds->find( $hold_3->id )
+      ->set( { timestamp => dt_from_string()->subtract( days => 2 ) } )->store;
+    $hold_4 = Koha::Old::Holds->find( $hold_4->id )
+      ->set( { timestamp => dt_from_string()->subtract( days => 3 ) } )->store;
+
+    is( $patron_1->old_holds->count, 2, 'patron_1 has 2 completed holds' );
+    is( $patron_2->old_holds->count, 2, 'patron_2 has 2 completed holds' );
+
+    # filter them so only the older two are part of the resultset
+    my $holds = Koha::Old::Holds->search(
+        { 'me.borrowernumber' => [ $patron_1->id, $patron_2->id ] } );
+    is( $holds->count, 4, 'Total of 4 holds returned correctly' );
+    my $rs = $holds->filter_by_anonymizable;
+    is( $rs->count, 2, 'Only 2 can be anonymized' );
+
+    $rs = $holds
+            ->filter_by_anonymizable
+            ->filter_by_last_update( { days => 1 } );
+
+    is( $rs->count, 1, 'Only 1 can be anonymized with date filter applied' );
+
+    $schema->storage->txn_rollback;
+};
-- 
2.32.0