From 96588393c8c83bf3f134a92e64d74f232fc0f38d Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Wed, 9 Feb 2022 13:41:47 +0100
Subject: [PATCH] Bug 30058: Add Koha::Patrons->filter_by_have_subpermission

This method will allow to filter a patron set by a given subpermission.
It will be useful on bug 30055 where we want to display only patron
with suggestion or acquisition subpermission.
Note that it could be extended to allow several subpermissions, but we
don't need it so far.

Test plan:
  prove t/db_dependent/Koha/Patrons.t
must return green

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
---
 Koha/Patrons.pm               | 39 ++++++++++++++++++
 t/db_dependent/Koha/Patrons.t | 78 ++++++++++++++++++++++++++++++++++-
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/Koha/Patrons.pm b/Koha/Patrons.pm
index c498ba55ca..caf6d4a251 100644
--- a/Koha/Patrons.pm
+++ b/Koha/Patrons.pm
@@ -520,6 +520,45 @@ sub filter_by_amount_owed {
     return $self->search( $where, $attrs );
 }
 
+=head3 filter_by_have_subpermission
+
+    my $patrons = Koha::Patrons->search->filter_by_have_subpermission('suggestions.suggestions_manage');
+
+Filter patrons who have a given subpermission
+
+=cut
+
+sub filter_by_have_subpermission {
+    my ($self, $subpermission) = @_;
+
+    my ($p, $sp) = split '\.', $subpermission;
+
+    my $perm = Koha::Database->new()->schema()->resultset('Userflag')->find({flag => $p});
+
+    Koha::Exceptions::ObjectNotFound->throw( sprintf( "Permission %s not found", $p ) )
+      unless $perm;
+
+    my $bit = $perm->bit;
+
+    return $self->search(
+        {
+            -and => [
+                -or => [
+                    \"me.flags & (1 << $bit)",
+                    { 'me.flags' => 1 },
+                    {
+                        -and => [
+                            { 'user_permissions.module_bit' => $bit },
+                            { 'user_permissions.code'       => $sp }
+                        ]
+                    }
+                ]
+            ]
+        },
+        { prefetch => 'user_permissions' }
+    );
+}
+
 =head3 _type
 
 =cut
diff --git a/t/db_dependent/Koha/Patrons.t b/t/db_dependent/Koha/Patrons.t
index e7c49fc14e..590ef15fa8 100755
--- a/t/db_dependent/Koha/Patrons.t
+++ b/t/db_dependent/Koha/Patrons.t
@@ -19,7 +19,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 43;
+use Test::More tests => 44;
 use Test::Warn;
 use Test::Exception;
 use Test::MockModule;
@@ -2358,4 +2358,80 @@ subtest 'filter_by_amount_owed' => sub {
 
 };
 
+subtest 'filter_by_have_subpermission' => sub {
+    plan tests => 4;
+
+    $schema->storage->txn_begin;
+
+    my $library  = $builder->build_object( { class => 'Koha::Libraries' } );
+    my $patron_1 = $builder->build_object(
+        {
+            class => 'Koha::Patrons',
+            value => { flags => 1, branchcode => $library->branchcode }
+        }
+    );
+
+    my $patron_2 = $builder->build_object( # 4096 = 1 << 12 for suggestions
+        {
+            class => 'Koha::Patrons',
+            value => { flags => 4096, branchcode => $library->branchcode }
+        }
+    );
+
+    my $patron_3 = $builder->build_object(
+        {
+            class => 'Koha::Patrons',
+            value => { flags => 0, branchcode => $library->branchcode }
+        }
+    );
+    $builder->build(
+        {
+            source => 'UserPermission',
+            value  => {
+                borrowernumber => $patron_3->borrowernumber,
+                module_bit     => 11,
+                code           => 'order_manage',
+            },
+        }
+    );
+
+    is_deeply(
+        [
+            Koha::Patrons->search( { branchcode => $library->branchcode } )
+              ->filter_by_have_subpermission('suggestions.suggestions_manage')
+              ->get_column('borrowernumber')
+        ],
+        [ $patron_1->borrowernumber, $patron_2->borrowernumber ],
+        'Superlibrarian and patron with suggestions.suggestions_manage'
+    );
+
+    is_deeply(
+        [
+            Koha::Patrons->search( { branchcode => $library->branchcode } )
+              ->filter_by_have_subpermission('acquisition.order_manage')
+              ->get_column('borrowernumber')
+        ],
+        [ $patron_1->borrowernumber, $patron_3->borrowernumber ],
+        'Superlibrarian and patron with acquisition.order_manage'
+    );
+
+    is_deeply(
+        [
+            Koha::Patrons->search( { branchcode => $library->branchcode } )
+              ->filter_by_have_subpermission('parameters.manage_cities')
+              ->get_column('borrowernumber')
+        ],
+        [ $patron_1->borrowernumber ],
+        'Only Superlibrarian is returned'
+    );
+
+    throws_ok {
+        Koha::Patrons->search( { branchcode => $library->branchcode } )
+          ->filter_by_have_subpermission('dont_exist.subperm');
+    } 'Koha::Exceptions::ObjectNotFound';
+
+
+    $schema->storage->txn_rollback;
+};
+
 $schema->storage->txn_rollback;
-- 
2.20.1