@@ -, +, @@ 0) Apply the patch for Bug 8798 1) Apply this patch 2) Run updatedatabase.pl 3) Access the patron lists feature from Koha's Tools menu. 4) Create a new list via the "New patron list" button. 5) For this list, click the "Edit" button, and change the list name. 6) For this list, click the "Add patrons" button, and search for and add some patrons to your list. 7) For this list select some patrons to remove them. 8) Try both adding some new patrons, and removing some old patrons as a single action. 9) Click the "Patrons" link on the Koha toolbar selected patrons to your existing list. and add them to your list. selected patrons to a new list. modification tool. --- Koha/List/Patron.pm | 222 ++++++++++++++++++++ Koha/Schema/Result/PatronList.pm | 90 ++++++++ Koha/Schema/Result/PatronListPatron.pm | 90 ++++++++ installer/data/mysql/kohastructure.sql | 41 ++++ installer/data/mysql/updatedatabase.pl | 39 ++++ .../prog/en/modules/members/member.tt | 129 +++++++++++- .../prog/en/modules/patron_lists/add-modify.tt | 56 +++++ .../prog/en/modules/patron_lists/list.tt | 132 ++++++++++++ .../prog/en/modules/patron_lists/lists.tt | 74 +++++++ .../prog/en/modules/tools/modborrowers.tt | 26 ++- .../prog/en/modules/tools/tools-home.tt | 5 +- members/member.pl | 70 +++++-- patron_lists/add-modify.pl | 61 ++++++ patron_lists/delete.pl | 43 ++++ patron_lists/list.pl | 54 +++++ patron_lists/lists.pl | 43 ++++ patron_lists/patrons.pl | 59 +++++ t/db_dependent/PatronLists.t | 75 +++++++ tools/modborrowers.pl | 18 ++- 19 files changed, 1295 insertions(+), 32 deletions(-) create mode 100644 Koha/List/Patron.pm create mode 100644 Koha/Schema/Result/PatronList.pm create mode 100644 Koha/Schema/Result/PatronListPatron.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/list.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/lists.tt create mode 100755 patron_lists/add-modify.pl create mode 100755 patron_lists/delete.pl create mode 100755 patron_lists/list.pl create mode 100755 patron_lists/lists.pl create mode 100755 patron_lists/patrons.pl create mode 100755 t/db_dependent/PatronLists.t --- a/Koha/List/Patron.pm +++ a/Koha/List/Patron.pm @@ -0,0 +1,222 @@ +package Koha::List::Patron; + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +Koha::List::Patron - Managment of lists of patrons + +=head1 FUNCTIONS + +=cut + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use base 'Exporter'; +our @EXPORT = ( + qw( + GetPatronLists + + DelPatronList + AddPatronList + ModPatronList + + AddPatronsToList + DelPatronsFromList + ) +); + +=head2 GetPatronLists + + my @lists = GetPatronLists( $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 { + my ($params) = @_; + + $params->{owner} ||= C4::Context->userenv->{'number'}; + + unless ( $params->{owner} ) { + carp("No owner passed in or defined!"); + return; + } + + delete( $params->{owner} ) if ( C4::Context->IsSuperLibrarian() ); + + my $schema = Koha::Database->new()->schema(); + + my @patron_lists = $schema->resultset('PatronList')->search($params); + + return wantarray() ? @patron_lists : \@patron_lists; +} + +=head2 DelPatronList + + DelPatronList( { patron_list_id => $list_id [, owner => $owner ] } ); + +=cut + +sub DelPatronList { + my ($params) = @_; + + $params->{owner} ||= C4::Context->userenv->{'number'}; + + unless ( $params->{patron_list_id} ) { + croak("No patron list id passed in!"); + } + unless ( $params->{owner} ) { + carp("No owner passed in or defined!"); + return; + } + + delete( $params->{owner} ) if ( C4::Context->IsSuperLibrarian() ); + + return Koha::Database->new()->schema()->resultset('PatronList') + ->search($params)->single()->delete(); +} + +=head2 AddPatronList + + AddPatronList( { name => $name [, owner => $owner ] } ); + +=cut + +sub AddPatronList { + my ($params) = @_; + + $params->{owner} ||= C4::Context->userenv->{'number'}; + + unless ( $params->{owner} ) { + carp("No owner passed in or defined!"); + return; + } + + unless ( $params->{name} ) { + carp("No list name passed in!"); + return; + } + + return Koha::Database->new()->schema()->resultset('PatronList') + ->create($params); +} + +=head2 ModPatronList + + ModPatronList( { patron_list_id => $id, name => $name [, owner => $owner ] } ); + +=cut + +sub ModPatronList { + my ($params) = @_; + + unless ( $params->{patron_list_id} ) { + carp("No patron list id passed in!"); + return; + } + + my ($list) = GetPatronLists( + { + patron_list_id => $params->{patron_list_id}, + owner => $params->{owner} + } + ); + + return $list->update($params); +} + +=head2 AddPatronsToList + + AddPatronsToList({ list => $list, cardnumbers => \@cardnumbers }); + +=cut + +sub AddPatronsToList { + my ($params) = @_; + + my $list = $params->{list}; + my $cardnumbers = $params->{'cardnumbers'}; + my $borrowernumbers = $params->{'borrowernumbers'}; + + return unless ( $list && ( $cardnumbers || $borrowernumbers ) ); + + my @borrowernumbers; + + if ($cardnumbers) { + @borrowernumbers = + Koha::Database->new()->schema()->resultset('Borrower')->search( + { cardnumber => { 'IN' => $cardnumbers } }, + { columns => [qw/ borrowernumber /] } + )->get_column('borrowernumber')->all(); + } + else { + @borrowernumbers = @$borrowernumbers; + } + + my $patron_list_id = $list->patron_list_id(); + + my $plp_rs = Koha::Database->new()->schema()->resultset('PatronListPatron'); + + my @results; + foreach my $borrowernumber (@borrowernumbers) { + my $result = $plp_rs->update_or_create( + { + patron_list_id => $patron_list_id, + borrowernumber => $borrowernumber + } + ); + push( @results, $result ); + } + + return wantarray() ? @results : \@results; +} + +=head2 DelPatronsFromList + + DelPatronsFromList({ list => $list, patron_list_patrons => \@patron_list_patron_ids }); + +=cut + +sub DelPatronsFromList { + my ($params) = @_; + + my $list = $params->{list}; + my $patron_list_patrons = $params->{patron_list_patrons}; + + return unless ( $list && $patron_list_patrons ); + + return Koha::Database->new()->schema()->resultset('PatronListPatron') + ->search( { patron_list_patron_id => { 'IN' => $patron_list_patrons } } ) + ->delete(); +} + +=head1 AUTHOR + +Kyle M Hall, Ekyle@bywatersolutions.comE + +=cut + +1; + +__END__ --- a/Koha/Schema/Result/PatronList.pm +++ a/Koha/Schema/Result/PatronList.pm @@ -0,0 +1,90 @@ +package Koha::Schema::Result::PatronList; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + + +=head1 NAME + +Koha::Schema::Result::PatronList + +=cut + +__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 + +=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 }, +); +__PACKAGE__->set_primary_key("patron_list_id"); + +=head1 RELATIONS + +=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 owner + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "owner", + "Koha::Schema::Result::Borrower", + { borrowernumber => "owner" }, + { on_delete => "CASCADE", on_update => "CASCADE" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-07-10 10:39:50 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:XegvNUkfR/cYwxlLLX3h3A + + +# You can replace this text with custom content, and it will be preserved on regeneration +1; --- a/Koha/Schema/Result/PatronListPatron.pm +++ a/Koha/Schema/Result/PatronListPatron.pm @@ -0,0 +1,90 @@ +package Koha::Schema::Result::PatronListPatron; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; + + +=head1 NAME + +Koha::Schema::Result::PatronListPatron + +=cut + +__PACKAGE__->table("patron_list_patrons"); + +=head1 ACCESSORS + +=head2 patron_list_patron_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 + +=cut + +__PACKAGE__->add_columns( + "patron_list_patron_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 }, +); +__PACKAGE__->set_primary_key("patron_list_patron_id"); + +=head1 RELATIONS + +=head2 borrowernumber + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "borrowernumber", + "Koha::Schema::Result::Borrower", + { borrowernumber => "borrowernumber" }, + { 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" }, + { on_delete => "CASCADE", on_update => "CASCADE" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07000 @ 2013-07-10 10:39:50 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:c+znpWBlv6I+yi1EuGUKrQ + + +# You can replace this text with custom content, and it will be preserved on regeneration +1; --- a/installer/data/mysql/kohastructure.sql +++ a/installer/data/mysql/kohastructure.sql @@ -3214,6 +3214,47 @@ CREATE TABLE IF NOT EXISTS plugin_data ( PRIMARY KEY (plugin_class,plugin_key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- +-- Table structure for table `patron_lists` +-- + +DROP TABLE IF EXISTS patron_lists; +CREATE TABLE patron_lists ( + patron_list_id int(11) NOT NULL AUTO_INCREMENT, -- unique identifier + name varchar(255) CHARACTER SET utf8 NOT NULL, -- the list's name + owner int(11) NOT NULL, -- borrowernumber of the list creator + PRIMARY KEY (patron_list_id), + KEY owner (owner) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Constraints for table `patron_lists` +-- +ALTER TABLE `patron_lists` + ADD CONSTRAINT patron_lists_ibfk_1 FOREIGN KEY (`owner`) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; + +-- +-- Table structure for table 'patron_list_patrons' +-- + +DROP TABLE IF EXISTS patron_list_patrons; +CREATE TABLE patron_list_patrons ( + patron_list_patron_id int(11) NOT NULL AUTO_INCREMENT, -- unique identifier + patron_list_id int(11) NOT NULL, -- the list this entry is part of + borrowernumber int(11) NOT NULL, -- the borrower that is part of this list + PRIMARY KEY (patron_list_patron_id), + KEY patron_list_id (patron_list_id), + KEY borrowernumber (borrowernumber) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Constraints for table `patron_list_patrons` +-- +ALTER TABLE `patron_list_patrons` + ADD CONSTRAINT patron_list_patrons_ibfk_1 FOREIGN KEY (patron_list_id) REFERENCES patron_lists (patron_list_id) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT patron_list_patrons_ibfk_2 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; + + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -7044,6 +7044,45 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; +if ( CheckVersion($DBversion) ) { + + $dbh->do(q{ + CREATE TABLE IF NOT EXISTS `patron_lists` ( + patron_list_id int(11) NOT NULL AUTO_INCREMENT, + name varchar(255) CHARACTER SET utf8 NOT NULL, + owner int(11) NOT NULL, + PRIMARY KEY (patron_list_id), + KEY owner (owner) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + }); + + $dbh->do(q{ + ALTER TABLE `patron_lists` + ADD CONSTRAINT patron_lists_ibfk_1 FOREIGN KEY (`owner`) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; + }); + + $dbh->do(q{ + CREATE TABLE patron_list_patrons ( + patron_list_patron_id int(11) NOT NULL AUTO_INCREMENT, + patron_list_id int(11) NOT NULL, + borrowernumber int(11) NOT NULL, + PRIMARY KEY (patron_list_patron_id), + KEY patron_list_id (patron_list_id), + KEY borrowernumber (borrowernumber) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + }); + + $dbh->do(q{ + ALTER TABLE `patron_list_patrons` + ADD CONSTRAINT patron_list_patrons_ibfk_1 FOREIGN KEY (patron_list_id) REFERENCES patron_lists (patron_list_id) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT patron_list_patrons_ibfk_2 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE; + }); + + print "Upgrade to $DBversion done (Bug 10565 - Add a 'Patron List' feature for storing and manipulating collections of patrons)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt @@ -1,6 +1,73 @@ [% INCLUDE 'doc-head-open.inc' %] Koha › Patrons [% IF ( searching ) %]› Search results[% END %] [% INCLUDE 'doc-head-close.inc' %] + + + [% INCLUDE 'header.inc' %] @@ -15,6 +82,12 @@
+ [% IF patron_list %] +
+ Added [% patrons_added_to_list.size %] patrons to [% patron_list.name %]. +
+ [% END %] + [% INCLUDE 'patron-toolbar.inc' %] [% IF ( no_add ) %]

Cannot add patron

@@ -36,13 +109,53 @@
[% END %] - [% IF ( resultsloop ) %] -

Results [% from %] to [% to %] of [% numresults %] found for [% IF ( member ) %]'[% member %]'[% END %][% IF ( surname ) %]'[% surname %]'[% END %]

+ [% IF ( resultsloop ) %] +
+
+

Results [% from %] to [% to %] of [% numresults %] found for [% IF ( member ) %]'[% member %]'[% END %][% IF ( surname ) %]'[% surname %]'[% END %]

+ +
+ Select all + | + Clear all + | + + + + + + + + + + [% FOREACH key IN search_parameters.keys %] + + [% END %] + + + +
+
+ @@ -65,6 +178,7 @@ [% END %] [% END %] +
  Card Name Cat
[% resultsloo.cardnumber %] @@ -92,11 +206,12 @@
[% IF ( multipage ) %][% paginationbar %][% END %]
- [% ELSE %] - [% IF ( searching ) %] -
No results found
- [% END %] - [% END %] +
+ [% ELSE %] + [% IF ( searching ) %] +
No results found
+ [% END %] + [% END %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/add-modify.tt @@ -0,0 +1,56 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Patron lists › New list +[% INCLUDE 'doc-head-close.inc' %] + + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cat-search.inc' %] + + + +
+
+

New patron list

+ +
+
+ + Create a new patron list + +
    +
  1. + + +
  2. + +
  3. + Owner: [% loggedinusername %] +
  4. +
+ +
+ + + + Cancel +
+
+
+[% INCLUDE 'intranet-bottom.inc' %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/list.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/list.tt @@ -0,0 +1,132 @@ +[% USE KohaDates %] +[% INCLUDE 'doc-head-open.inc' %] +Koha › Patron lists › New list +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'datatables-strings.inc' %] + + + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cat-search.inc' %] + + +
+
+

[% list.name %]

+ +
+
+ Add patrons + + + +
+ +
+ Patrons to be added +
+
+ +
+ +

+ + Cancel +

+ + + + + + + + + + + + + + + + + + [% FOREACH p IN list.patron_list_patrons %] + + + + + + + + + + + + [% END %] + +
CardFirstnameSurnameAddressCategoryLibraryExpires onCirc notes
+ + [% p.borrowernumber.cardnumber %] + + [% p.borrowernumber.firstname %][% p.borrowernumber.surname %] + [% p.borrowernumber.address %] + [% p.borrowernumber.address2 %] + [% p.borrowernumber.city %] + [% p.borrowernumber.state %] + [% p.borrowernumber.country %] + [% p.borrowernumber.categorycode.description %] ([% p.borrowernumber.categorycode.categorycode %])[% p.borrowernumber.branchcode.branchname %][% p.borrowernumber.dateexpiry | $KohaDates %][% p.borrowernumber.borrowernotes %]
+ + + + Cancel +
+
+
+[% INCLUDE 'intranet-bottom.inc' %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/lists.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/lists.tt @@ -0,0 +1,74 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Patron lists +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'datatables-strings.inc' %] + + + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cat-search.inc' %] + + +
+
+

Your patron lists

+ + + + + + + + + + + + + + + + [% FOREACH l IN lists %] + + + + + + + + [% END %] + +
NamePatrons in list   
[% l.name %][% l.patron_list_patrons.size || 0 %] + + Add patrons + + + + Edit + + + + Delete + +
+
+
+[% INCLUDE 'intranet-bottom.inc' %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/modborrowers.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/modborrowers.tt @@ -128,11 +128,29 @@

Batch patron modification

- Use a file -
    -
  1. -
+ Use a file +
    +
  1. +
+ + [% IF patron_lists %] +
+ Or use a patron list +
    +
  1. + + +
  2. +
+
+ [% END %] +
Or list cardnumbers one by one
    --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt @@ -15,7 +15,10 @@

    Patrons and circulation

    - [% IF ( CAN_user_tools_moderate_comments ) %] +
    Patron lists +
    Manage lists of patrons.
    + +[% IF ( CAN_user_tools_moderate_comments ) %]
    Comments [% IF ( pendingcomments ) %][% pendingcomments %][% END %]
    Moderate patron comments.
    [% END %] --- a/members/member.pl +++ a/members/member.pl @@ -33,6 +33,7 @@ use C4::Branch; use C4::Category; use Koha::DateUtils; use File::Basename; +use Koha::List::Patron; my $input = new CGI; my $quicksearch = $input->param('quicksearch'); @@ -49,6 +50,15 @@ my ($template, $loggedinuser, $cookie) my $theme = $input->param('theme') || "default"; +my $add_to_patron_list = $input->param('add_to_patron_list'); +my $add_to_patron_list_which = $input->param('add_to_patron_list_which'); +my $new_patron_list = $input->param('new_patron_list'); +my @borrowernumbers = $input->param('borrowernumber'); +$input->delete( + 'add_to_patron_list', 'add_to_patron_list_which', + 'new_patron_list', 'borrowernumber', +); + my $patron = $input->Vars; foreach (keys %$patron){ delete $$patron{$_} unless($$patron{$_}); @@ -115,6 +125,29 @@ if ($member || keys %$patron) { ($results) = Search( $member || $patron, \@orderby, undef, undef, \@searchfields, $search_scope ); } +if ($add_to_patron_list) { + my $patron_list; + + if ( $add_to_patron_list eq 'new' ) { + $patron_list = AddPatronList( { name => $new_patron_list } ); + } + else { + $patron_list = + [ GetPatronLists( { patron_list_id => $add_to_patron_list } ) ]->[0]; + } + + if ( $add_to_patron_list_which eq 'all' ) { + @borrowernumbers = map { $_->{borrowernumber} } @$results; + } + + my @patrons_added_to_list = AddPatronsToList( { list => $patron_list, borrowernumbers => \@borrowernumbers } ); + + $template->param( + patron_list => $patron_list, + patrons_added_to_list => \@patrons_added_to_list, + ) +} + if ($results) { for my $field ('categorycode','branchcode'){ next unless ($patron->{$field}); @@ -170,24 +203,29 @@ my $base_url = my @letters = map { {letter => $_} } ( 'A' .. 'Z'); $template->param( - letters => \@letters, + %$patron, + letters => \@letters, paginationbar => pagination_bar( $base_url, - int( $count / $resultsperpage ) + ($count % $resultsperpage ? 1 : 0), - $startfrom, 'startfrom' + int( $count / $resultsperpage ) + ( $count % $resultsperpage ? 1 : 0 ), + $startfrom, + 'startfrom' ), - startfrom => $startfrom, - from => ($startfrom-1)*$resultsperpage+1, - to => $to, - multipage => ($count != $to || $startfrom!=1), - advsearch => ($$patron{categorycode} || $$patron{branchcode}), - branchloop=>\@branchloop, - categories=>\@categories, - searching => "1", - actionname =>basename($0), - %$patron, - numresults => $count, - resultsloop => \@resultsdata, - ); + startfrom => $startfrom, + from => ( $startfrom - 1 ) * $resultsperpage + 1, + to => $to, + multipage => ( $count != $to || $startfrom != 1 ), + advsearch => ( $$patron{categorycode} || $$patron{branchcode} ), + branchloop => \@branchloop, + categories => \@categories, + searching => "1", + actionname => basename($0), + numresults => $count, + resultsloop => \@resultsdata, + results_per_page => $resultsperpage, + member => $member, + search_parameters => \%parameters, + patron_lists => [ GetPatronLists() ], +); output_html_with_http_headers $input, $cookie, $template->output; --- a/patron_lists/add-modify.pl +++ a/patron_lists/add-modify.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use Koha::List::Patron; + +my $cgi = new CGI; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "patron_lists/add-modify.tt", + query => $cgi, + type => "intranet", + authnotrequired => 1, + } +); + +my $id = $cgi->param('patron_list_id'); +my $name = $cgi->param('name'); + +if ($id) { + my ($list) = GetPatronLists( { patron_list_id => $id } ); + $template->param( list => $list ); +} + +if ($name) { + if ($id) { + ModPatronList( { patron_list_id => $id, name => $name } ); + print $cgi->redirect('lists.pl'); + } + else { + my $list = AddPatronList( { name => $name } ); + print $cgi->redirect( + "list.pl?patron_list_id=" . $list->patron_list_id() ); + } + + exit; +} + +output_html_with_http_headers( $cgi, $cookie, $template->output ); --- a/patron_lists/delete.pl +++ a/patron_lists/delete.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use Koha::List::Patron; + +my $cgi = new CGI; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "patron_lists/lists.tt", + query => $cgi, + type => "intranet", + authnotrequired => 1, + } +); + +my $id = $cgi->param('patron_list_id'); + +DelPatronList( { patron_list_id => $id } ); + +print $cgi->redirect('lists.pl'); --- a/patron_lists/list.pl +++ a/patron_lists/list.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use Koha::List::Patron; + +my $cgi = new CGI; + +my ( $template, $logged_in_user, $cookie ) = get_template_and_user( + { + template_name => "patron_lists/list.tt", + query => $cgi, + type => "intranet", + authnotrequired => 1, + } +); + +my ($list) = + GetPatronLists( { patron_list_id => $cgi->param('patron_list_id') } ); + +my @patrons_to_add = $cgi->param('patrons_to_add'); +if (@patrons_to_add) { + AddPatronsToList( { list => $list, cardnumbers => \@patrons_to_add } ); +} + +my @patrons_to_remove = $cgi->param('patrons_to_remove'); +if (@patrons_to_remove) { + DelPatronsFromList( { list => $list, patron_list_patrons => \@patrons_to_remove } ); +} + +$template->param( list => $list ); + +output_html_with_http_headers( $cgi, $cookie, $template->output ); --- a/patron_lists/lists.pl +++ a/patron_lists/lists.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use Koha::List::Patron; + +my $cgi = new CGI; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "patron_lists/lists.tt", + query => $cgi, + type => "intranet", + authnotrequired => 1, + } +); + +my @lists = GetPatronLists(); + +$template->param( lists => \@lists ); + +output_html_with_http_headers( $cgi, $cookie, $template->output ); --- a/patron_lists/patrons.pl +++ a/patron_lists/patrons.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl + +# Copyright 2013 ByWater Solutions +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use Koha::List::Patron; + +my $cgi = new CGI; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "patron_lists/add-modify.tt", + query => $cgi, + type => "intranet", + authnotrequired => 1, + } +); + +my $id = $cgi->param('patron_list_id'); +my $name = $cgi->param('name'); + +if ($id) { + my ($list) = GetPatronLists( { patron_list_id => $id } ); + $template->param( list => $list ); +} + +if ($name) { + if ($id) { + ModPatronList( { patron_list_id => $id, name => $name } ); + } + else { + AddPatronList( { name => $name } ); + } + + print $cgi->redirect('lists.pl'); + exit; +} + +output_html_with_http_headers( $cgi, $cookie, $template->output ); --- a/t/db_dependent/PatronLists.t +++ a/t/db_dependent/PatronLists.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl +# +use Modern::Perl; + +use Test::More tests => 9; + +BEGIN { + use_ok('C4::Context'); + use_ok('Koha::List::Patron'); +} + +my $dbh = C4::Context->dbh; +my $sth = $dbh->prepare("SELECT * FROM borrowers ORDER BY RAND() LIMIT 10"); +$sth->execute(); +my @borrowers = @{ $sth->fetchall_arrayref( {} ) }; + +my @lists = GetPatronLists( { owner => 1 } ); +my $list_count_original = @lists; + +my $list1 = AddPatronList( { name => 'Test List 1', owner => 1 } ); +ok( $list1->name() eq 'Test List 1', 'AddPatronList works' ); + +my $list2 = AddPatronList( { name => 'Test List 2', owner => 1 } ); + +ModPatronList( + { + patron_list_id => $list2->patron_list_id(), + name => 'Test List 3', + owner => 1 + } +); +$list2->discard_changes(); +ok( $list2->name() eq 'Test List 3', 'ModPatronList works' ); + +AddPatronsToList( + { list => $list1, cardnumbers => [ map { $_->{cardnumber} } @borrowers ] } +); +ok( + scalar @borrowers == + $list1->patron_list_patrons()->search_related('borrowernumber')->all(), + 'AddPatronsToList works for cardnumbers' +); + +AddPatronsToList( + { + list => $list2, + borrowernumbers => [ map { $_->{borrowernumber} } @borrowers ] + } +); +ok( + scalar @borrowers == + $list2->patron_list_patrons()->search_related('borrowernumber')->all(), + 'AddPatronsToList works for borrowernumbers' +); + +my @ids = + $list1->patron_list_patrons()->get_column('patron_list_patron_id')->all(); +DelPatronsFromList( + { + list => $list1, + patron_list_patrons => \@ids, + } +); +$list1->discard_changes(); +ok( !$list1->patron_list_patrons()->count(), 'DelPatronsFromList works.' ); + +@lists = GetPatronLists( { owner => 1 } ); +ok( @lists == $list_count_original + 2, 'GetPatronLists works' ); + +DelPatronList( { patron_list_id => $list1->patron_list_id(), owner => 1 } ); +DelPatronList( { patron_list_id => $list2->patron_list_id(), owner => 1 } ); + +@lists = + GetPatronLists( { patron_list_id => $list1->patron_list_id(), owner => 1 } ); +ok( !@lists, 'DelPatronList works' ); --- a/tools/modborrowers.pl +++ a/tools/modborrowers.pl @@ -34,6 +34,7 @@ use C4::Members::Attributes; use C4::Members::AttributeTypes qw/GetAttributeTypes_hashref/; use C4::Output; use List::MoreUtils qw /any uniq/; +use Koha::List::Patron; my $input = new CGI; my $op = $input->param('op') || 'show_form'; @@ -50,12 +51,11 @@ my %cookies = parse CGI::Cookie($cookie); my $sessionID = $cookies{'CGISESSID'}->value; my $dbh = C4::Context->dbh; - - # Show borrower informations if ( $op eq 'show' ) { - my $filefh = $input->upload('uploadfile'); - my $filecontent = $input->param('filecontent'); + my $filefh = $input->upload('uploadfile'); + my $filecontent = $input->param('filecontent'); + my $patron_list_id = $input->param('patron_list_id'); my @borrowers; my @cardnumbers; my @notfoundcardnumbers; @@ -67,6 +67,13 @@ if ( $op eq 'show' ) { $content =~ s/[\r\n]*$//g; push @cardnumbers, $content if $content; } + } elsif ( $patron_list_id ) { + my ($list) = GetPatronLists( { patron_list_id => $patron_list_id } ); + + @cardnumbers = + $list->patron_list_patrons()->search_related('borrowernumber') + ->get_column('cardnumber')->all(); + } else { if ( my $list = $input->param('cardnumberlist') ) { push @cardnumbers, split( /\s\n/, $list ); @@ -314,6 +321,9 @@ if ( $op eq 'do' ) { $template->param( borrowers => \@borrowers ); $template->param( errors => \@errors ); +} else { + + $template->param( patron_lists => [ GetPatronLists() ] ); } $template->param( --