From 082191d0c04f36752aca1a6e73f1eeae80acad0b Mon Sep 17 00:00:00 2001 From: Michael Hafen Date: Tue, 11 Apr 2023 14:21:01 -0600 Subject: [PATCH] Bug 32105 - Add Library and Individual sharing modes to Patron Lists Content-Type: text/plain; charset="utf-8" Test Plan: 1. apply patch, restart Plack, etc. 2. create or select three users, two at the same library and one not. 3. create or select a patron list owned by one of the users at the same library. 4. edit list and change sharing mode to 'Library and individuals'. 5. login as the other user at the same library and navigate to patron lists. 6. observe that the list is shared. 7. login as the third user and navigate to patron lists. 8. observe that the list is not shared with this user. 9. login as the owner of the list. 10. edit the list and add the third user as an individual. 11. login as the third user and navigate to patron lists. 12. observe that the list is now shared with the third user. 13. login as the owner of the list. 14. edit the list to change the sharing mode to 'Individuals'. 15. login as the second and third users. 16. observet that the list is not shared with the second user, but still is with the third user. --- Koha/List/Patron.pm | 160 +++++++++++++++--- Koha/Schema/Result/PatronList.pm | 152 +++++++++++++++++ Koha/Schema/Result/PatronListUser.pm | 113 +++++++++++++ .../bug_32105-add_patron_list_users_table.pl | 22 +++ installer/data/mysql/kohastructure.sql | 22 ++- .../en/modules/patron_lists/add-modify.tt | 135 ++++++++++++++- members/member.pl | 4 +- members/members-home.pl | 4 +- patron_lists/add-modify.pl | 32 +++- patron_lists/delete.pl | 4 +- patron_lists/list.pl | 14 +- patron_lists/lists.pl | 4 +- patron_lists/patron-lists-tab.pl | 10 +- patron_lists/patrons.pl | 8 +- patroncards/create-pdf.pl | 4 +- patroncards/manage.pl | 4 +- svc/members/add_to_list | 8 +- t/db_dependent/PatronLists.t | 93 ++++++---- tools/cleanborrowers.pl | 4 +- tools/modborrowers.pl | 6 +- 20 files changed, 695 insertions(+), 108 deletions(-) create mode 100644 Koha/Schema/Result/PatronListUser.pm create mode 100644 installer/data/mysql/atomicupdate/bug_32105-add_patron_list_users_table.pl diff --git a/Koha/List/Patron.pm b/Koha/List/Patron.pm index cb91275d85..a115bb0320 100644 --- a/Koha/List/Patron.pm +++ b/Koha/List/Patron.pm @@ -36,29 +36,57 @@ BEGIN { require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw( - GetPatronLists + get_patron_list + get_patron_lists - DelPatronList - AddPatronList - ModPatronList + del_patron_list + add_patron_list + mod_patron_list - AddPatronsToList - DelPatronsFromList + add_patrons_to_list + del_patrons_from_list + + grant_patrons_access_to_list + revoke_patrons_access_from_list ); } -=head2 GetPatronLists +=head2 get_patron_list + + my @lists = get_patron_list( $params ); + + Returns the patron list with patron_list_id. +=cut + +sub get_patron_list { + my ($params) = @_; + + unless ( $params->{'patron_list_id'} ) { + carp("No list id passed in or defined!"); + return; + } + + my $schema = Koha::Database->new()->schema(); + + my $patron_list = $schema->resultset('PatronList')->find($params); + + return $patron_list; +} + +=head2 get_patron_lists - my @lists = GetPatronLists( $params ); + my @lists = get_patron_lists( $params ); Returns an array of lists created by the the given user or the logged in user if none is passed in. =cut -sub GetPatronLists { +sub get_patron_lists { my ($params) = @_; $params->{owner} ||= C4::Context->userenv->{'number'}; + my $user_branch = C4::Context->userenv->{'branch'}; + my $search_attrs = {}; unless ( $params->{owner} ) { carp("No owner passed in or defined!"); @@ -72,23 +100,35 @@ sub GetPatronLists { $params->{'-or'} = [ owner => $owner, shared => 1, + '-and' => [ + shared => 2, + branchcode => $user_branch, + ], + '-and' => [ + shared => { 'IN' => [2,3] }, + 'patron_list_users.borrowernumber' => $owner, + ], ]; + $search_attrs = { + join => [ 'owner', 'patron_list_users' ], + group_by => 'patron_list_id', + }; } my $schema = Koha::Database->new()->schema(); - my @patron_lists = $schema->resultset('PatronList')->search($params); + my @patron_lists = $schema->resultset('PatronList')->search($params, $search_attrs); return wantarray() ? @patron_lists : \@patron_lists; } -=head2 DelPatronList +=head2 del_patron_list - DelPatronList( { patron_list_id => $list_id [, owner => $owner ] } ); + del_patron_list( { patron_list_id => $list_id [, owner => $owner ] } ); =cut -sub DelPatronList { +sub del_patron_list { my ($params) = @_; $params->{owner} ||= C4::Context->userenv->{'number'}; @@ -107,13 +147,13 @@ sub DelPatronList { ->search($params)->single()->delete(); } -=head2 AddPatronList +=head2 add_patron_list - AddPatronList( { name => $name [, owner => $owner ] } ); + add_patron_list( { name => $name [, owner => $owner ] } ); =cut -sub AddPatronList { +sub add_patron_list { my ($params) = @_; $params->{owner} ||= C4::Context->userenv->{'number'}; @@ -132,13 +172,13 @@ sub AddPatronList { ->create($params); } -=head2 ModPatronList +=head2 mod_patron_list - ModPatronList( { patron_list_id => $id, name => $name [, owner => $owner ] } ); + mod_patron_list( { patron_list_id => $id, name => $name [, owner => $owner ] } ); =cut -sub ModPatronList { +sub mod_patron_list { my ($params) = @_; unless ( $params->{patron_list_id} ) { @@ -146,23 +186,22 @@ sub ModPatronList { return; } - my ($list) = GetPatronLists( + my $list = get_patron_list( { patron_list_id => $params->{patron_list_id}, - owner => $params->{owner} } ); return $list->update($params); } -=head2 AddPatronsToList +=head2 add_patrons_to_list - AddPatronsToList({ list => $list, cardnumbers => \@cardnumbers }); + add_patrons_to_list({ list => $list, cardnumbers => \@cardnumbers }); =cut -sub AddPatronsToList { +sub add_patrons_to_list { my ($params) = @_; my $list = $params->{list}; @@ -204,13 +243,13 @@ sub AddPatronsToList { return wantarray() ? @results : \@results; } -=head2 DelPatronsFromList +=head2 del_patrons_from_list - DelPatronsFromList({ list => $list, patron_list_patrons => \@patron_list_patron_ids }); + del_patrons_from_list({ list => $list, patron_list_patrons => \@patron_list_patron_ids }); =cut -sub DelPatronsFromList { +sub del_patrons_from_list { my ($params) = @_; my $list = $params->{list}; @@ -223,6 +262,73 @@ sub DelPatronsFromList { ->delete(); } +=head2 grant_patrons_access_to_list + + grant_patrons_access_to_list({ list => $list, cardnumbers => \@cardnumbers }); + +=cut + +sub grant_patrons_access_to_list { + my ($params) = @_; + + my $list = $params->{list}; + my $cardnumbers = $params->{'cardnumbers'}; + my $borrowernumbers = $params->{'borrowernumbers'}; + + return unless ( $list && ( $cardnumbers || $borrowernumbers ) ); + + my @borrowernumbers; + + my %search_param; + if ($cardnumbers) { + $search_param{cardnumber} = { 'IN' => $cardnumbers }; + } else { + $search_param{borrowernumber} = { 'IN' => $borrowernumbers }; + } + + @borrowernumbers = + Koha::Database->new()->schema()->resultset('Borrower')->search( + \%search_param, + { columns => [qw/ borrowernumber /] } + )->get_column('borrowernumber')->all(); + + my $patron_list_id = $list->patron_list_id(); + + my $plu_rs = Koha::Database->new()->schema()->resultset('PatronListUser'); + + my @results; + foreach my $borrowernumber (@borrowernumbers) { + my $result = $plu_rs->update_or_create( + { + patron_list_id => $patron_list_id, + borrowernumber => $borrowernumber + } + ); + push( @results, $result ); + } + + return wantarray() ? @results : \@results; +} + +=head2 revoke_patrons_access_from_list + + revoke_patrons_access_from_list({ list => $list, patron_list_users => \@patron_list_user_ids }); + +=cut + +sub revoke_patrons_access_from_list { + my ($params) = @_; + + my $list = $params->{list}; + my $patron_list_users = $params->{patron_list_users}; + + return unless ( $list && $patron_list_users ); + + return Koha::Database->new()->schema()->resultset('PatronListUser') + ->search( { patron_list_user_id => { 'IN' => $patron_list_users } } ) + ->delete(); +} + =head1 AUTHOR Kyle M Hall, Ekyle@bywatersolutions.comE diff --git a/Koha/Schema/Result/PatronList.pm b/Koha/Schema/Result/PatronList.pm index ccb9fb1d5c..6c778e7cde 100644 --- a/Koha/Schema/Result/PatronList.pm +++ b/Koha/Schema/Result/PatronList.pm @@ -23,6 +23,138 @@ __PACKAGE__->table("patron_lists"); =head1 ACCESSORS +=head2 patron_list_id + + data_type: 'integer' + is_auto_increment: 1 + is_nullable: 0 + +=head2 name + + data_type: 'varchar' + is_nullable: 0 + size: 255 + +=head2 owner + + data_type: 'integer' + is_foreign_key: 1 + is_nullable: 0 + +=head2 shared + + data_type: 'tinyint' + default_value: 0 + is_nullable: 1 + +=cut + +__PACKAGE__->add_columns( + "patron_list_id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "name", + { data_type => "varchar", is_nullable => 0, size => 255 }, + "owner", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "shared", + { data_type => "tinyint", default_value => 0, is_nullable => 1 }, +); + +=head1 PRIMARY KEY + +=over 4 + +=item * L + +=back + +=cut + +__PACKAGE__->set_primary_key("patron_list_id"); + +=head1 RELATIONS + +=head2 owner + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "owner", + "Koha::Schema::Result::Borrower", + { borrowernumber => "owner" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + +=head2 patron_list_patrons + +Type: has_many + +Related object: L + +=cut + +__PACKAGE__->has_many( + "patron_list_patrons", + "Koha::Schema::Result::PatronListPatron", + { "foreign.patron_list_id" => "self.patron_list_id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +=head2 patron_list_users + +Type: has_many + +Related object: L + +=cut + +__PACKAGE__->has_many( + "patron_list_users", + "Koha::Schema::Result::PatronListUser", + { "foreign.patron_list_id" => "self.patron_list_id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-02-28 16:35:34 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:YepHXHQHtxjorkGhef0rmQ +# These lines were loaded from './Koha/Schema/Result/PatronList.pm' found in @INC. +# They are now part of the custom portion of this file +# for you to hand-edit. If you do not either delete +# this section or remove that file from @INC, this section +# will be repeated redundantly when you re-create this +# file again via Loader! See skip_load_external to disable +# this feature. + +use utf8; +package Koha::Schema::Result::PatronList; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +=head1 NAME + +Koha::Schema::Result::PatronList + +=cut + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + +=head1 TABLE: C + +=cut + +__PACKAGE__->table("patron_lists"); + +=head1 ACCESSORS + =head2 patron_list_id data_type: 'integer' @@ -114,6 +246,26 @@ __PACKAGE__->has_many( # Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-01-21 13:39:29 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:+gAlf5GQ7YSgAtFIXgqVWw +=head2 patron_list_patrons + +Type: has_many + +Related object: L + +=cut + +__PACKAGE__->has_many( + "patron_list_users", + "Koha::Schema::Result::PatronListUser", + { "foreign.patron_list_id" => "self.patron_list_id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + # You can replace this text with custom content, and it will be preserved on regeneration 1; +# End of lines loaded from './Koha/Schema/Result/PatronList.pm' + + +# You can replace this text with custom code or comments, and it will be preserved on regeneration +1; diff --git a/Koha/Schema/Result/PatronListUser.pm b/Koha/Schema/Result/PatronListUser.pm new file mode 100644 index 0000000000..c3349458dc --- /dev/null +++ b/Koha/Schema/Result/PatronListUser.pm @@ -0,0 +1,113 @@ +use utf8; +package Koha::Schema::Result::PatronListUser; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +=head1 NAME + +Koha::Schema::Result::PatronListUser + +=cut + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + +=head1 TABLE: C + +=cut + +__PACKAGE__->table("patron_list_users"); + +=head1 ACCESSORS + +=head2 patron_list_user_id + + data_type: 'integer' + is_auto_increment: 1 + is_nullable: 0 + +=head2 patron_list_id + + data_type: 'integer' + is_foreign_key: 1 + is_nullable: 0 + +=head2 borrowernumber + + data_type: 'integer' + is_foreign_key: 1 + is_nullable: 0 + +=head2 can_edit + + data_type: 'tinyint' + default_value: 0 + is_nullable: 1 + +=cut + +__PACKAGE__->add_columns( + "patron_list_user_id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "patron_list_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "borrowernumber", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "can_edit", + { data_type => "tinyint", default_value => 0, is_nullable => 1 }, +); + +=head1 PRIMARY KEY + +=over 4 + +=item * L + +=back + +=cut + +__PACKAGE__->set_primary_key("patron_list_user_id"); + +=head1 RELATIONS + +=head2 borrowernumber + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "borrowernumber", + "Koha::Schema::Result::Borrower", + { borrowernumber => "borrowernumber" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + +=head2 patron_list + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "patron_list", + "Koha::Schema::Result::PatronList", + { patron_list_id => "patron_list_id" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-02-28 16:35:34 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3K+501CuiCeq6Jk7W6TE2w + + +# You can replace this text with custom code or comments, and it will be preserved on regeneration +1; diff --git a/installer/data/mysql/atomicupdate/bug_32105-add_patron_list_users_table.pl b/installer/data/mysql/atomicupdate/bug_32105-add_patron_list_users_table.pl new file mode 100644 index 0000000000..31bd0bebe4 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_32105-add_patron_list_users_table.pl @@ -0,0 +1,22 @@ +use Modern::Perl; + +return { + bug_number => "32105", + description => "Add patron list users table", + up => sub { + my ($args) = @_; + my ($dbh, $out) = @$args{qw(dbh out)}; + $dbh->do(q{CREATE TABLE `patron_list_users` ( + `patron_list_user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique identifier', + `patron_list_id` int(11) NOT NULL COMMENT 'the list this entry is part of', + `borrowernumber` int(11) NOT NULL COMMENT 'the borrower that is given access to this list', + `can_edit` tinyint(1) NOT NULL DEFAULt 0 COMMENT 'whether this borrower can edit the list and it''s patrons', + PRIMARY KEY (`patron_list_user_id`), + KEY `patron_list_id` (`patron_list_id`), + KEY `borrowernumber` (`borrowernumber`), + CONSTRAINT `patron_list_users_ibfk_1` FOREIGN KEY (`patron_list_id`) REFERENCES `patron_lists` (`patron_list_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `patron_list_users_ibfk_2` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci}); + say $out "Added new table 'patron_list_users'"; + }, +}; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index cba889d5e0..409e1eaf1e 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -4593,6 +4593,26 @@ CREATE TABLE `patron_list_patrons` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `patron_list_users` +-- + +DROP TABLE IF EXISTS `patron_list_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `patron_list_users` ( + `patron_list_user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique identifier', + `patron_list_id` int(11) NOT NULL COMMENT 'the list this entry is part of', + `borrowernumber` int(11) NOT NULL COMMENT 'the borrower that is given access to this list', + `can_edit` tinyint(1) NOT NULL DEFAULt 0 COMMENT 'whether this borrower can edit the list and it''s patrons', + PRIMARY KEY (`patron_list_user_id`), + KEY `patron_list_id` (`patron_list_id`), + KEY `borrowernumber` (`borrowernumber`), + CONSTRAINT `patron_list_users_ibfk_1` FOREIGN KEY (`patron_list_id`) REFERENCES `patron_lists` (`patron_list_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `patron_list_users_ibfk_2` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `patron_lists` -- @@ -4604,7 +4624,7 @@ CREATE TABLE `patron_lists` ( `patron_list_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique identifier', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'the list''s name', `owner` int(11) NOT NULL COMMENT 'borrowernumber of the list creator', - `shared` tinyint(1) DEFAULT 0, + `shared` tinyint(1) DEFAULT 0 COMMENT '1 for everyone, 2 for library and individuals, 3 for individuals', PRIMARY KEY (`patron_list_id`), KEY `owner` (`owner`), CONSTRAINT `patron_lists_ibfk_1` FOREIGN KEY (`owner`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt index 265c817fa3..0d5dd0bc07 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt @@ -1,5 +1,7 @@ [% USE raw %] [% USE Asset %] +[% USE Branches %] +[% USE Categories %] [% SET footerjs = 1 %] [% INCLUDE 'doc-head-open.inc' %] @@ -9,6 +11,14 @@ New patron list [% END %] › Patron lists › Tools › Koha +[% PROCESS 'patronfields.inc' %] +[% IF Branches.InIndependentBranchesMode({syspref=>'IndependentBranchesHideOtherBranchesItems'}) %] + [% SET libraries = Branches.all( search_params => { branchcode => Branches.GetLoggedInBranchcode() }, selected => Branches.GetLoggedInBranchcode() ) %] +[% ELSE %] + [% SET libraries = Branches.all %] +[% END %] +[% SET categories = Categories.all.unblessed %] +[% PROCESS 'patron-search.inc' %] [% INCLUDE 'doc-head-close.inc' %] @@ -72,16 +82,29 @@
  • - - [% IF list.shared %] - - [% ELSE %] - - [% END %] + +
  • - Owner: [% logged_in_user.userid | html %] + Owner: [% INCLUDE 'patron-title.inc' patron=list.owner %]
  • @@ -93,11 +116,109 @@ Cancel + + [% IF list.shared == 2 || list.shared == 3 %] +
    + + Manage individuals with access to list + + Users: + + + + + + [% FOREACH u IN list.patron_list_users %] + + + + + + [% END %] + +
    NameLibraryCategory
    [% INCLUDE 'patron-title.inc' patron=u.borrowernumber | html %][% u.borrowernumber.library_id.name | html %][% u.borrowernumber.category_id.name | html %]Remove +
    +
    + [% PROCESS patron_search_filters_simple %] +
    +
    + + +
    + [% END %] + [% MACRO jsinclude BLOCK %] + [% INCLUDE 'datatables.inc' %] [% Asset.js("js/tools-menu.js") | $raw %] + + [% PROCESS patron_search_js table_id => 'memberresultst', columns => ['checkbox','cardnumber','name','branch','category'], default_sort_column => 'name-address', display_search_description => 1, libraries => libraries, categories => categories %] + [% END %] [% INCLUDE 'intranet-bottom.inc' %] diff --git a/members/member.pl b/members/member.pl index 54c3e81ac1..ee5e9bdfb0 100755 --- a/members/member.pl +++ b/members/member.pl @@ -27,7 +27,7 @@ use Modern::Perl; use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); use CGI qw( -utf8 ); -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); use Koha::Patrons; use Koha::Patron::Attribute::Types; @@ -71,7 +71,7 @@ $template->param( 'alphabet' => C4::Context->preference('alphabet') || join ' ', my $defer_loading = $input->request_method() eq "GET" && !$circsearch ? 1 : 0; $template->param( - patron_lists => [ GetPatronLists() ], + patron_lists => [ get_patron_lists() ], searchmember => $searchmember, branchcode_filter => scalar $input->param('branchcode_filter'), categorycode_filter => scalar $input->param('categorycode_filter'), diff --git a/members/members-home.pl b/members/members-home.pl index e3b903f463..1284c0d306 100755 --- a/members/members-home.pl +++ b/members/members-home.pl @@ -25,7 +25,7 @@ use C4::Context; use C4::Members; use Koha::Patron::Modifications; use Koha::Libraries; -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); use Koha::Patron::Categories; use Koha::Patron::Attribute::Types; @@ -71,7 +71,7 @@ $template->param( $template->param( alphabet => C4::Context->preference('alphabet') || join (' ', 'A' .. 'Z'), PatronAutoComplete => C4::Context->preference('PatronAutoComplete'), - patron_lists => [ GetPatronLists() ], + patron_lists => [ get_patron_lists() ], PatronsPerPage => C4::Context->preference("PatronsPerPage") || 20, attribute_type_codes => ( C4::Context->preference('ExtendedPatronAttributes') ? [ Koha::Patron::Attribute::Types->search( { staff_searchable => 1 } )->get_column('code') ] diff --git a/patron_lists/add-modify.pl b/patron_lists/add-modify.pl index 95ff728707..0ecaa23bf1 100755 --- a/patron_lists/add-modify.pl +++ b/patron_lists/add-modify.pl @@ -23,7 +23,7 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); -use Koha::List::Patron qw( AddPatronList GetPatronLists ModPatronList ); +use Koha::List::Patron qw( get_patron_list add_patron_list mod_patron_list grant_patrons_access_to_list revoke_patrons_access_from_list ); my $cgi = CGI->new; @@ -38,20 +38,22 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $id = $cgi->param('patron_list_id'); my $name = $cgi->param('name'); -my $shared = $cgi->param('shared') ? 1 : 0; +my $shared = $cgi->param('shared'); +my @grant_user = $cgi->multi_param('grant_borrowernumber'); +my @revoke_user = $cgi->multi_param('revoke_list_users_id'); if ($id) { - my ($list) = GetPatronLists( { patron_list_id => $id } ); + my $list = get_patron_list( { 'patron_list_id' => $id } ); $template->param( list => $list ); } if ($name) { if ($id) { - ModPatronList( { patron_list_id => $id, name => $name, shared => $shared } ); + mod_patron_list( { patron_list_id => $id, name => $name, shared => $shared } ); print $cgi->redirect('lists.pl'); } else { - my $list = AddPatronList( { name => $name, shared => $shared } ); + my $list = add_patron_list( { name => $name, shared => $shared } ); print $cgi->redirect( "list.pl?patron_list_id=" . $list->patron_list_id() ); } @@ -59,4 +61,24 @@ if ($name) { exit; } +if (@grant_user) { + my $list = get_patron_list( { 'patron_list_id' => $id } ); + my $results = grant_patrons_access_to_list({ + list => $list, + borrowernumbers => \@grant_user, + }); + print $cgi->redirect("add-modify.pl?patron_list_id=" . $list->patron_list_id() ); + exit; +} + +if (@revoke_user) { + my $list = get_patron_list( { 'patron_list_id' => $id } ); + my $results = revoke_patrons_access_from_list({ + list => $list, + patron_list_users => \@revoke_user, + }); + print $cgi->redirect("add-modify.pl?patron_list_id=" . $list->patron_list_id() ); + exit; +} + output_html_with_http_headers( $cgi, $cookie, $template->output ); diff --git a/patron_lists/delete.pl b/patron_lists/delete.pl index 773ec3d168..405900c1a5 100755 --- a/patron_lists/delete.pl +++ b/patron_lists/delete.pl @@ -23,7 +23,7 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output; -use Koha::List::Patron qw( DelPatronList ); +use Koha::List::Patron qw( del_patron_list ); my $cgi = CGI->new; @@ -38,6 +38,6 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $id = $cgi->param('patron_list_id'); -DelPatronList( { patron_list_id => $id } ); +del_patron_list( { patron_list_id => $id } ); print $cgi->redirect('lists.pl'); diff --git a/patron_lists/list.pl b/patron_lists/list.pl index 45b11a1667..61ecc3f29c 100755 --- a/patron_lists/list.pl +++ b/patron_lists/list.pl @@ -24,9 +24,9 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); use Koha::List::Patron qw( - AddPatronsToList - DelPatronsFromList - GetPatronLists + get_patron_list + add_patrons_to_list + del_patrons_from_list ); use List::MoreUtils qw( uniq ); @@ -42,7 +42,7 @@ my ( $template, $logged_in_user, $cookie ) = get_template_and_user( ); my ($list) = - GetPatronLists( { patron_list_id => scalar $cgi->param('patron_list_id') } ); + get_patron_list( { patron_list_id => scalar $cgi->param('patron_list_id') } ); my @existing = $list->patron_list_patrons; @@ -54,7 +54,7 @@ if ( $patrons_by_id ){ my %add_params; $add_params{list} = $list; $add_params{ $id_column } = \@patrons_list; - my @results = AddPatronsToList(\%add_params); + my @results = add_patrons_to_list(\%add_params); my $id = $id_column eq 'borrowernumbers' ? 'borrowernumber' : 'cardnumber'; my %found = map { $_->borrowernumber->$id => 1 } @results; my %exist = map { $_->borrowernumber->$id => 1 } @existing; @@ -72,12 +72,12 @@ if ( $patrons_by_id ){ my @patrons_to_add = $cgi->multi_param('patrons_to_add'); if (@patrons_to_add) { - AddPatronsToList( { list => $list, cardnumbers => \@patrons_to_add } ); + add_patrons_to_list( { list => $list, cardnumbers => \@patrons_to_add } ); } my @patrons_to_remove = $cgi->multi_param('patrons_to_remove'); if (@patrons_to_remove) { - DelPatronsFromList( { list => $list, patron_list_patrons => \@patrons_to_remove } ); + del_patrons_from_list( { list => $list, patron_list_patrons => \@patrons_to_remove } ); } $template->param( list => $list ); diff --git a/patron_lists/lists.pl b/patron_lists/lists.pl index f599cd164b..4ed88b248f 100755 --- a/patron_lists/lists.pl +++ b/patron_lists/lists.pl @@ -23,7 +23,7 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); my $cgi = CGI->new; @@ -36,7 +36,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); -my @lists = GetPatronLists(); +my @lists = get_patron_lists(); $template->param( lists => \@lists ); diff --git a/patron_lists/patron-lists-tab.pl b/patron_lists/patron-lists-tab.pl index ee2e749782..d91c1b328d 100755 --- a/patron_lists/patron-lists-tab.pl +++ b/patron_lists/patron-lists-tab.pl @@ -25,7 +25,7 @@ use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); use Koha::Patrons; -use Koha::List::Patron qw( GetPatronLists AddPatronsToList DelPatronsFromList ); +use Koha::List::Patron qw( get_patron_lists get_patron_list add_patrons_to_list del_patrons_from_list ); my $cgi = CGI->new; @@ -53,14 +53,14 @@ if ( ! $logged_in_user->can_see_patron_infos($patron) ) { else { my $has_perms = C4::Auth::haspermission($logged_in_user->userid, {'tools'=>'manage_patron_lists'}); if ( $list_id && $has_perms ) { - my ($list) = GetPatronLists( { patron_list_id => $list_id } ); + my ($list) = get_patron_list( { patron_list_id => $list_id } ); if (@patrons_to_add) { - AddPatronsToList( { list => $list, cardnumbers => \@patrons_to_add } ); + add_patrons_to_list( { list => $list, cardnumbers => \@patrons_to_add } ); } if (@patrons_to_remove) { - DelPatronsFromList( { list => $list, patron_list_patrons => \@patrons_to_remove } ); + del_patrons_from_list( { list => $list, patron_list_patrons => \@patrons_to_remove } ); } } @@ -76,7 +76,7 @@ else { } } } - @available_lists = GetPatronLists(); + @available_lists = get_patron_lists(); @available_lists = grep { ! $list_id_lookup{$_->patron_list_id} } @available_lists; } diff --git a/patron_lists/patrons.pl b/patron_lists/patrons.pl index f97fcf4662..c797e8a800 100755 --- a/patron_lists/patrons.pl +++ b/patron_lists/patrons.pl @@ -23,7 +23,7 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); -use Koha::List::Patron qw( AddPatronList GetPatronLists ModPatronList ); +use Koha::List::Patron qw( get_patron_list add_patron_list mod_patron_list ); my $cgi = CGI->new; @@ -40,16 +40,16 @@ my $id = $cgi->param('patron_list_id'); my $name = $cgi->param('name'); if ($id) { - my ($list) = GetPatronLists( { patron_list_id => $id } ); + my ($list) = get_patron_list( { patron_list_id => $id } ); $template->param( list => $list ); } if ($name) { if ($id) { - ModPatronList( { patron_list_id => $id, name => $name } ); + mod_patron_list( { patron_list_id => $id, name => $name } ); } else { - AddPatronList( { name => $name } ); + add_patron_list( { name => $name } ); } print $cgi->redirect('lists.pl'); diff --git a/patroncards/create-pdf.pl b/patroncards/create-pdf.pl index e994ddbbb2..08b26a0416 100755 --- a/patroncards/create-pdf.pl +++ b/patroncards/create-pdf.pl @@ -29,7 +29,7 @@ use autouse 'Data::Dumper' => qw(Dumper); use C4::Context; use C4::Creators; use C4::Patroncards; -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); use Koha::Patrons; use Koha::Patron::Images; @@ -96,7 +96,7 @@ elsif (@borrower_numbers) { } @borrower_numbers; } elsif ( $patronlist_id ) { - my ($list) = GetPatronLists( { patron_list_id => $patronlist_id } ); + my ($list) = get_patron_lists( { patron_list_id => $patronlist_id } ); my @borrowerlist = $list->patron_list_patrons()->search_related('borrowernumber') ->get_column('borrowernumber')->all(); grep { diff --git a/patroncards/manage.pl b/patroncards/manage.pl index 4366955d87..f5a86a6ccf 100755 --- a/patroncards/manage.pl +++ b/patroncards/manage.pl @@ -33,7 +33,7 @@ use C4::Creators qw( html_table ); use C4::Labels; -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); my $cgi = CGI->new; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( @@ -117,7 +117,7 @@ else { # trap unsupported operations here my $table = html_table($display_columns->{$card_element}, $db_rows); $template->param(print => 1) if ($card_element eq 'batch'); -$template->param( patron_lists => [ GetPatronLists() ] ) if ($card_element eq 'batch'); +$template->param( patron_lists => [ get_patron_lists() ] ) if ($card_element eq 'batch'); $template->param( error => $errstr, diff --git a/svc/members/add_to_list b/svc/members/add_to_list index 2219717003..1642cec624 100755 --- a/svc/members/add_to_list +++ b/svc/members/add_to_list @@ -22,7 +22,7 @@ use CGI; use C4::Auth qw( check_cookie_auth ); use JSON qw( to_json ); -use Koha::List::Patron qw( AddPatronList GetPatronLists AddPatronsToList ); +use Koha::List::Patron qw( add_patron_list get_patron_lists add_patrons_to_list ); my $input = CGI->new; @@ -41,14 +41,14 @@ if ($add_to_patron_list) { my $patron_list = []; if ( $add_to_patron_list eq 'new' ) { - $patron_list = AddPatronList( { name => $new_patron_list } ); + $patron_list = add_patron_list( { name => $new_patron_list } ); } else { $patron_list = - [ GetPatronLists( { patron_list_id => $add_to_patron_list } ) ]->[0]; + [ get_patron_lists( { patron_list_id => $add_to_patron_list } ) ]->[0]; } - my @patrons_added_to_list = AddPatronsToList( { list => $patron_list, borrowernumbers => \@borrowernumbers } ); + my @patrons_added_to_list = add_patrons_to_list( { list => $patron_list, borrowernumbers => \@borrowernumbers } ); $response->{patron_list} = { patron_list_id => $patron_list->patron_list_id, name => $patron_list->name }; $response->{patrons_added_to_list} = scalar( @patrons_added_to_list ); diff --git a/t/db_dependent/PatronLists.t b/t/db_dependent/PatronLists.t index b2edc8d8ff..a72fcfbf5b 100755 --- a/t/db_dependent/PatronLists.t +++ b/t/db_dependent/PatronLists.t @@ -17,21 +17,22 @@ use Modern::Perl; -use Test::More tests => 12; +use Test::More tests => 16; use t::lib::TestBuilder; use t::lib::Mocks; use Koha::Database; use Koha::List::Patron - qw( AddPatronList AddPatronsToList DelPatronList DelPatronsFromList GetPatronLists ModPatronList ); + qw( add_patron_list add_patrons_to_list del_patron_list del_patrons_from_list get_patron_list get_patron_lists mod_patron_list grant_patrons_access_to_list revoke_patrons_access_from_list ); use Koha::Patrons; my $schema = Koha::Database->schema; $schema->storage->txn_begin; my $builder = t::lib::TestBuilder->new; +my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; -t::lib::Mocks::mock_userenv(); +t::lib::Mocks::mock_userenv({branchcode => $branchcode}); # Create 10 sample borrowers my @borrowers = (); @@ -42,15 +43,24 @@ foreach (1..10) { my $owner = $borrowers[0]->{borrowernumber}; my $owner2 = $borrowers[1]->{borrowernumber}; -my @lists = GetPatronLists( { owner => $owner } ); +my $owner3 = Koha::Patron->new( + { + surname => 'Test 1', + branchcode => $branchcode, + categorycode => $borrowers[0]->{categorycode} + } +); +$owner3->store(); + +my @lists = get_patron_lists( { owner => $owner } ); my $list_count_original = @lists; -my $list1 = AddPatronList( { name => 'Test List 1', owner => $owner } ); -is( $list1->name(), 'Test List 1', 'AddPatronList works' ); +my $list1 = add_patron_list( { name => 'Test List 1', owner => $owner } ); +is( $list1->name(), 'Test List 1', 'add_patron_list works' ); -my $list2 = AddPatronList( { name => 'Test List 2', owner => $owner } ); +my $list2 = add_patron_list( { name => 'Test List 2', owner => $owner } ); -ModPatronList( +mod_patron_list( { patron_list_id => $list2->patron_list_id(), name => 'Test List 3', @@ -58,18 +68,22 @@ ModPatronList( } ); $list2->discard_changes(); -is( $list2->name(), 'Test List 3', 'ModPatronList works' ); +is( $list2->name(), 'Test List 3', 'mod_patron_list works' ); + +$list1 = + get_patron_list( { patron_list_id => $list1->patron_list_id() } ); +is( $list1->name(), 'Test List 1', 'get_patron_list works' ); -AddPatronsToList( +add_patrons_to_list( { list => $list1, cardnumbers => [ map { $_->{cardnumber} } @borrowers ] } ); is( scalar @borrowers, $list1->patron_list_patrons()->search_related('borrowernumber')->all(), - 'AddPatronsToList works for cardnumbers' + 'add_patrons_to_list works for cardnumbers' ); -AddPatronsToList( +add_patrons_to_list( { list => $list2, borrowernumbers => [ map { $_->{borrowernumber} } @borrowers ] @@ -78,49 +92,66 @@ AddPatronsToList( is( scalar @borrowers, $list2->patron_list_patrons()->search_related('borrowernumber')->all(), - 'AddPatronsToList works for borrowernumbers' + 'add_patrons_to_list works for borrowernumbers' ); my $deleted_patron = $builder->build_object({ class => 'Koha::Patrons' }); $deleted_patron->delete; -my @result = AddPatronsToList({list => $list2,borrowernumbers => [ $deleted_patron->borrowernumber ]}); +my @result = add_patrons_to_list({list => $list2,borrowernumbers => [ $deleted_patron->borrowernumber ]}); is( scalar @result, 0,'Invalid borrowernumber not added'); -@result = AddPatronsToList({list => $list2,cardnumbers => [ $deleted_patron->cardnumber ]}); +@result = add_patrons_to_list({list => $list2,cardnumbers => [ $deleted_patron->cardnumber ]}); is( scalar @result, 0,'Invalid cardnumber not added'); my @ids = $list1->patron_list_patrons()->get_column('patron_list_patron_id')->all(); -DelPatronsFromList( +del_patrons_from_list( { list => $list1, patron_list_patrons => \@ids, } ); $list1->discard_changes(); -is( $list1->patron_list_patrons()->count(), 0, 'DelPatronsFromList works.' ); +is( $list1->patron_list_patrons()->count(), 0, 'del_patrons_from_list works.' ); my $patron = $builder->build_object({ class => 'Koha::Patrons' }); -AddPatronsToList({list => $list2,borrowernumbers => [ $patron->borrowernumber ]}); +add_patrons_to_list({list => $list2,borrowernumbers => [ $patron->borrowernumber ]}); @lists = $patron->get_lists_with_patron; is( scalar @lists, 1, 'get_lists_with_patron works' ); -@lists = GetPatronLists( { owner => $owner } ); -is( scalar @lists, $list_count_original + 2, 'GetPatronLists works' ); +@lists = get_patron_lists( { owner => $owner } ); +is( scalar @lists, $list_count_original + 2, 'get_patron_lists works' ); + +my $list3 = add_patron_list( { name => 'Test List 3', owner => $owner2, shared => 0 } ); +@lists = get_patron_lists( { owner => $owner } ); +is( scalar @lists, $list_count_original + 2, 'get_patron_lists does not return non-shared list' ); + +my $list4 = add_patron_list( { name => 'Test List 4', owner => $owner2, shared => 1 } ); +@lists = get_patron_lists( { owner => $owner } ); +is( scalar @lists, $list_count_original + 3, 'get_patron_lists does return shared list' ); + +del_patron_list( { patron_list_id => $list1->patron_list_id(), owner => $owner } ); +del_patron_list( { patron_list_id => $list2->patron_list_id(), owner => $owner } ); + +$list1 = + get_patron_list( { patron_list_id => $list1->patron_list_id() } ); +is( $list1, undef, 'del_patron_list works' ); -my $list3 = AddPatronList( { name => 'Test List 3', owner => $owner2, shared => 0 } ); -@lists = GetPatronLists( { owner => $owner } ); -is( scalar @lists, $list_count_original + 2, 'GetPatronLists does not return non-shared list' ); +@lists = get_patron_lists(); +my $lib_list_count = @lists; +my $list5 = add_patron_list( { name => 'Test List 5', owner => $owner3->borrowernumber, shared => 2 } ); +my $list6 = add_patron_list( { name => 'Test List 6', owner => $owner3->borrowernumber, shared => 3 } ); +@lists = get_patron_lists(); +is( scalar @lists, $lib_list_count + 1, 'get_patron_lists returns list shared with library' ); -my $list4 = AddPatronList( { name => 'Test List 4', owner => $owner2, shared => 1 } ); -@lists = GetPatronLists( { owner => $owner } ); -is( scalar @lists, $list_count_original + 3, 'GetPatronLists does return shared list' ); +grant_patrons_access_to_list( { list => $list6, borrowernumbers => [ $patron->borrowernumber ] } ); -DelPatronList( { patron_list_id => $list1->patron_list_id(), owner => $owner } ); -DelPatronList( { patron_list_id => $list2->patron_list_id(), owner => $owner } ); +@lists = get_patron_lists({ owner => $patron->borrowernumber }); +is( scalar @lists, $lib_list_count + 2, 'get_patron_lists returns list shared with individual, grant_patrons_access_to_list works' ); -@lists = - GetPatronLists( { patron_list_id => $list1->patron_list_id(), owner => $owner } ); -is( scalar @lists, 0, 'DelPatronList works' ); +my @list_users = $list6->patron_list_users->get_column('patron_list_user_id')->all(); +revoke_patrons_access_from_list({ list => $list6, patron_list_users => \@list_users }); +@lists = get_patron_lists(); +is( scalar @lists, $lib_list_count + 1, 'revoke_patrons_access_from_list works' ); $schema->storage->txn_rollback; diff --git a/tools/cleanborrowers.pl b/tools/cleanborrowers.pl index 632ed5ccd6..a256857a18 100755 --- a/tools/cleanborrowers.pl +++ b/tools/cleanborrowers.pl @@ -40,7 +40,7 @@ use C4::Members qw( GetBorrowersToExpunge ); use Koha::Old::Checkouts; use Koha::Patron::Categories; use Koha::Patrons; -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); my $cgi = CGI->new; @@ -161,7 +161,7 @@ elsif ( $step == 3 ) { testrun => ( $radio eq "testrun" ) ? 1: 0, ); } else { # $step == 1 - my @all_lists = GetPatronLists(); + my @all_lists = get_patron_lists(); my @non_empty_lists; foreach my $list (@all_lists){ my @patrons = $list->patron_list_patrons(); diff --git a/tools/modborrowers.pl b/tools/modborrowers.pl index 46f79d70eb..0592eed2ee 100755 --- a/tools/modborrowers.pl +++ b/tools/modborrowers.pl @@ -32,7 +32,7 @@ use C4::Koha qw( GetAuthorisedValues ); use C4::Members; use C4::Output qw( output_html_with_http_headers ); use Koha::DateUtils qw( dt_from_string ); -use Koha::List::Patron qw( GetPatronLists ); +use Koha::List::Patron qw( get_patron_lists ); use Koha::Libraries; use Koha::Patron::Categories; use Koha::Patron::Debarments qw( AddDebarment DelDebarment ); @@ -89,7 +89,7 @@ if ( $op eq 'show' ) { } } elsif ( my $patron_list_id = $input->param('patron_list_id') ){ # User selected a patron list - my ($list) = GetPatronLists( { patron_list_id => $patron_list_id } ); + my ($list) = get_patron_lists( { patron_list_id => $patron_list_id } ); @patronidnumbers = $list->patron_list_patrons()->search_related('borrowernumber') ->get_column('cardnumber')->all(); @@ -462,7 +462,7 @@ if ( $op eq 'do' ) { $template->param( errors => \@errors ); } else { - $template->param( patron_lists => [ GetPatronLists() ] ); + $template->param( patron_lists => [ get_patron_lists() ] ); } $template->param( -- 2.34.1