--- /dev/null
+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, E<lt>kyle@bywatersolutions.comE<gt>
+
+=cut
+
+1;
+
+__END__
--- /dev/null
+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<Koha::Schema::Result::PatronListPatron>
+
+=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<Koha::Schema::Result::Borrower>
+
+=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;
--- /dev/null
+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<Koha::Schema::Result::Borrower>
+
+=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<Koha::Schema::Result::PatronList>
+
+=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;
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 */;
$dbh->{RaiseError} = 0;
}
+$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
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha › Patrons [% IF ( searching ) %]› Search results[% END %]</title>
[% INCLUDE 'doc-head-close.inc' %]
+
+<script type="text/javascript">
+//<![CDATA[
+$(document).ready(function() {
+ $('#add_to_patron_list_submit').attr('disabled', 'disabled');
+ $('#new_patron_list').hide();
+
+ $('#add_to_patron_list').change(function() {
+ var value = $('#add_to_patron_list').val();
+ if ( value == 'new' ) {
+ $('#new_patron_list').val('')
+ $('#new_patron_list').show();
+ $('#new_patron_list').focus();
+ } else if ( value ) {
+ $('#new_patron_list').hide();
+ $('#add_to_patron_list_submit').removeAttr('disabled');
+ } else {
+ $('#new_patron_list').hide();
+ $('#add_to_patron_list_submit').attr('disabled', 'disabled');
+ }
+
+ });
+
+ $('#new_patron_list').on('input', function() {
+ if ( $('#new_patron_list').val() ) {
+ $('#add_to_patron_list_submit').removeAttr('disabled');
+ } else {
+ $('#add_to_patron_list_submit').attr('disabled', 'disabled');
+ }
+ });
+});
+
+function CheckForm() {
+ if ( $('#add_to_patron_list').val() == 'new' ) {
+ if ( $('#new_patron_list').val() ) {
+ var exists = false;
+ $("#add_to_patron_list option").each(function() {
+ if ( $(this).text() == $('#new_patron_list').val() ) {
+ exists = true;
+ return false;
+ }
+ });
+
+ if ( exists ) {
+ alert( _("You already have a list with that name!") );
+ return false;
+ }
+ } else {
+ alert( _("You must give your new patron list a name!") );
+ return false;
+ }
+ }
+
+ if ( $('#add_to_patron_list_which').val() == 'all' ) {
+ return confirm( _("Are you sure you want to add the entire set of patron results to this list ( including results on other pages )?") );
+ } else {
+ if ( $("#add-patrons-to-list-form input:checkbox:checked").length == 0 ) {
+ alert( _("You have not selected any patrons to add to a list!") );
+ return false;
+ }
+ }
+
+ return true;
+}
+//]]>
+</script>
+
</head>
<body id="pat_member" class="pat">
[% INCLUDE 'header.inc' %]
<div class="yui-b">
<div class="yui-g">
+ [% IF patron_list %]
+ <div class="dialog alert">
+ Added [% patrons_added_to_list.size %] patrons to <a href="/cgi-bin/koha/patron_lists/list.pl?patron_list_id=[% patron_list.patron_list_id %]">[% patron_list.name %]</a>.
+ </div>
+ [% END %]
+
[% INCLUDE 'patron-toolbar.inc' %]
[% IF ( no_add ) %]<div class="dialog alert"><h3>Cannot add patron</h3>
</div>
[% END %]
- [% IF ( resultsloop ) %]
- <div id="searchheader"> <h3>Results [% from %] to [% to %] of [% numresults %] found for [% IF ( member ) %]'<span class="ex">[% member %]</span>'[% END %][% IF ( surname ) %]'<span class="ex">[% surname %]</span>'[% END %]</h3></div>
+ [% IF ( resultsloop ) %]
+ <form id="add-patrons-to-list-form" method="post" action="member.pl" onsubmit="return CheckForm()">
+ <div id="searchheader">
+ <h3>Results [% from %] to [% to %] of [% numresults %] found for [% IF ( member ) %]'<span class="ex">[% member %]</span>'[% END %][% IF ( surname ) %]'<span class="ex">[% surname %]</span>'[% END %]</h3>
+
+ <div>
+ <a href="javascript:void(0)" onclick="$('.selection').prop('checked', true)">Select all</a>
+ |
+ <a href="javascript:void(0)" onclick="$('.selection').prop('checked', false)">Clear all</a>
+ |
+ <span>
+ <label for="add_to_patron_list_which">Add:</label>
+ <select id="add_to_patron_list_which" name="add_to_patron_list_which">
+ <option value="selected">Selected patrons</option>
+ <option value="all">All resultant patrons</option>
+ </select>
+
+ <label for="add_to_patron_list">to:</label>
+ <select id="add_to_patron_list" name="add_to_patron_list">
+ <option value=""></option>
+ [% IF patron_lists %]
+ <optgroup label="Patron lists:">
+ [% FOREACH pl IN patron_lists %]
+ <option value="[% pl.patron_list_id %]">[% pl.name %]</option>
+ [% END %]
+ </optgroup>
+ [% END %]
+
+ <option value="new">[ New list ]</option>
+ </select>
+
+ <input type="text" id="new_patron_list" name="new_patron_list" id="new_patron_list" />
+
+ [% FOREACH key IN search_parameters.keys %]
+ <input type="hidden" name="[% key %]" value="[% search_parameters.$key %]" />
+ [% END %]
+
+ <input id="add_to_patron_list_submit" type="submit" class="submit" value="Save">
+ </span>
+ </div>
+ </div>
<div class="searchresults">
<table id="memberresultst">
<thead>
<tr>
+ <th> </th>
<th>Card</th>
<th>Name</th>
<th>Cat</th>
<tr>
[% END %]
[% END %]
+ <td><input type="checkbox" class="selection" name="borrowernumber" value="[% resultsloo.borrowernumber %]" /></td>
<td>[% resultsloo.cardnumber %]</td>
<td style="white-space: nowrap;">
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% resultsloo.borrowernumber %]">
</table>
<div class="pages">[% IF ( multipage ) %][% paginationbar %][% END %]</div>
</div>
- [% ELSE %]
- [% IF ( searching ) %]
- <div class="dialog alert">No results found</div>
- [% END %]
- [% END %]
+ </form>
+ [% ELSE %]
+ [% IF ( searching ) %]
+ <div class="dialog alert">No results found</div>
+ [% END %]
+ [% END %]
</div>
</div>
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha › Patron lists › New list</title>
+[% INCLUDE 'doc-head-close.inc' %]
+
+<script type="text/javascript">
+//<![CDATA[
+
+function CheckForm() {
+ if ( !$("#list-name").val() ) {
+ alert( _("Name is a required field!") );
+ return false;
+ }
+
+ return true;
+}
+
+//]]>
+</script>
+
+</head>
+
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="lists.pl">Patron lists</a> › Add / modify list</div>
+
+
+<div class="yui-t7">
+ <div class="yui-main">
+ <h1>New patron list</h1>
+
+ <form method="post" onsubmit="return CheckForm()">
+ <fieldset class="rows">
+
+ <legend>Create a new patron list</legend>
+
+ <ol>
+ <li>
+ <label class="required" for="name">Name:</label>
+ <input id="list-name" name="name" type="text" value="[% list.name %]" />
+ </li>
+
+ <li>
+ <span class="label">Owner: </span>[% loggedinusername %]
+ </li>
+ </ol>
+
+ </fieldset>
+
+ <input type="hidden" name="patron_list_id" value="[% list.patron_list_id %]" />
+ <input type="submit" class="btn" value="Save" />
+ <a href="lists.pl" class="cancel">Cancel</a>
+ </form>
+ </div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
--- /dev/null
+[% USE KohaDates %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha › Patron lists › New list</title>
+[% INCLUDE 'doc-head-close.inc' %]
+
+<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.min.js"></script>
+[% INCLUDE 'datatables-strings.inc' %]
+<script type="text/javascript" src="[% themelang %]/js/datatables.js"></script>
+
+<script type="text/javascript">
+//<![CDATA[
+$(document).ready(function() {
+ $('#patrons_to_add_fieldset').hide();
+
+ $('#patron-list-table').dataTable($.extend(true, {}, dataTablesDefaults));
+
+ $( "#find_patron" ).autocomplete({
+ source: "/cgi-bin/koha/circ/ysearch.pl",
+ minLength: 3,
+ select: function( event, ui ) {
+ AddPatron( ui.item.firstname + " " + ui.item.surname, ui.item.cardnumber );
+ return false;
+ }
+ })
+ .data( "autocomplete" )._renderItem = function( ul, item ) {
+ return $( "<li></li>" )
+ .data( "item.autocomplete", item )
+ .append( "<a>" + item.surname + ", " + item.firstname + " (" + item.cardnumber + ") <small>" + item.address + " " + item.city + " " + item.zipcode + " " + item.country + "</small></a>" )
+ .appendTo( ul );
+ };
+});
+
+function AddPatron( name, cardnumber ) {
+ div = "<div id='borrower_" + cardnumber + "'>" + name + " ( <a href='javascript:void()' onclick='RemovePatron(" + cardnumber + ");'> Remove </a> ) <input type='hidden' name='patrons_to_add' value='" + cardnumber + "' /></div>";
+ $('#patrons_to_add').append( div );
+
+ $('#find_patron').val('').focus();
+
+ $('#patrons_to_add_fieldset').show( 800 );
+}
+
+function RemovePatron( cardnumber ) {
+ $( '#borrower_' + cardnumber ).remove();
+
+ if ( ! $('#patrons_to_add').html() ) {
+ $('#patrons_to_add_fieldset').hide( 800 );
+ }
+}
+//]]>
+</script>
+
+</head>
+
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="lists.pl">Patron lists</a> › Add patrons</div>
+
+<div class="yui-t7">
+ <div class="yui-main">
+ <h1>[% list.name %]</h1>
+
+ <form action="list.pl" method="post">
+ <fieldset>
+ <legend>Add patrons</legend>
+
+ <label for="find_patron">Patron search: </label>
+ <input autocomplete="off" id="find_patron" type="text" style="width:150px" class="noEnterSubmit" />
+ <div id="find_patron_container"></div>
+
+ <fieldset id="patrons_to_add_fieldset">
+ <legend>Patrons to be added</legend>
+ <div id="patrons_to_add"></div>
+ </fieldset>
+
+ </fieldset>
+
+ <p>
+ <input type="submit" class="btn" value="Update" />
+ <a href="lists.pl" class="cancel">Cancel</a>
+ </p>
+
+ <table id="patron-list-table">
+ <thead>
+ <tr>
+ <th><i title="Remove patron from list" class="icon-trash"></i></th>
+ <th>Card</th>
+ <th>Firstname</th>
+ <th>Surname</th>
+ <th>Address</th>
+ <th>Category</th>
+ <th>Library</th>
+ <th>Expires on</th>
+ <th>Circ notes</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ [% FOREACH p IN list.patron_list_patrons %]
+ <tr>
+ <td><input type="checkbox" name="patrons_to_remove" value="[% p.patron_list_patron_id %]" /></td>
+ <td>
+ <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% p.borrowernumber.borrowernumber %]">
+ [% p.borrowernumber.cardnumber %]
+ </a>
+ </td>
+ <td>[% p.borrowernumber.firstname %]</td>
+ <td>[% p.borrowernumber.surname %]</td>
+ <td>
+ [% p.borrowernumber.address %]
+ [% p.borrowernumber.address2 %]
+ [% p.borrowernumber.city %]
+ [% p.borrowernumber.state %]
+ [% p.borrowernumber.country %]
+ </td>
+ <td>[% p.borrowernumber.categorycode.description %] ([% p.borrowernumber.categorycode.categorycode %])</td>
+ <td>[% p.borrowernumber.branchcode.branchname %]</td>
+ <td>[% p.borrowernumber.dateexpiry | $KohaDates %]</td>
+ <td>[% p.borrowernumber.borrowernotes %]</td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+
+ <input type="hidden" name="patron_list_id" value="[% list.patron_list_id %]" />
+ <input type="submit" class="btn" value="Update" />
+ <a href="lists.pl" class="cancel">Cancel</a>
+ </form>
+ </div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha › Patron lists</title>
+[% INCLUDE 'doc-head-close.inc' %]
+
+<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.min.js"></script>
+[% INCLUDE 'datatables-strings.inc' %]
+<script type="text/javascript" src="[% themelang %]/js/datatables.js"></script>
+
+<script type="text/javascript">
+//<![CDATA[
+ $(document).ready(function() {
+ $('#patron-lists-table').dataTable($.extend(true, {}, dataTablesDefaults));
+ });
+
+ function ConfirmDelete( list ) {
+ return confirm( _("Are you sure you want to delete the list ") + list + "?" );
+ }
+//]]>
+</script>
+
+</head>
+
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › Patron lists</div>
+
+<div class="yui-t7">
+ <div class="yui-main">
+ <h1>Your patron lists</h1>
+
+ <div class="btn-group">
+ <a class="btn btn-small" href="add-modify.pl"><i class="icon-plus"></i> New patron list</a>
+ </div>
+
+ <table id="patron-lists-table">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Patrons in list</th>
+ <th> </th>
+ <th> </th>
+ <th> </th>
+ </tr>
+ </thead>
+
+ <tbody>
+ [% FOREACH l IN lists %]
+ <tr>
+ <td>[% l.name %]</td>
+ <td>[% l.patron_list_patrons.size || 0 %]</td>
+ <td>
+ <a class="btn" href="list.pl?patron_list_id=[% l.patron_list_id %]">
+ <i class="icon-plus-sign"></i> Add patrons <i class="icon-user"></i>
+ </a>
+ </td>
+ <td>
+ <a class="btn" href="add-modify.pl?patron_list_id=[% l.patron_list_id %]">
+ <i class="icon-edit"></i> Edit
+ </a>
+ </td>
+ <td>
+ <a class="btn" href="delete.pl?patron_list_id=[% l.patron_list_id %]" onclick='return ConfirmDelete("[% l.name | html %]")'>
+ <i class="icon-trash"></i> Delete
+ </a>
+ </td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+ </div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
<h1>Batch patron modification</h1>
<form method="post" enctype="multipart/form-data" action="/cgi-bin/koha/tools/modborrowers.pl">
<fieldset class="rows">
- <legend>Use a file</legend>
- <ol>
- <li><label for="uploadfile">File: </label> <input type="file" id="uploadfile" name="uploadfile" /></li>
- </ol>
+ <legend>Use a file</legend>
+ <ol>
+ <li><label for="uploadfile">File: </label> <input type="file" id="uploadfile" name="uploadfile" /></li>
+ </ol>
</fieldset>
+
+ [% IF patron_lists %]
+ <fieldset class="rows">
+ <legend>Or use a patron list</legend>
+ <ol>
+ <li>
+ <label for="patron_list_id">Patron list: </label>
+ <select id="patron_list_id" name="patron_list_id">
+ <option value=""></option>
+ [% FOREACH pl IN patron_lists %]
+ <option value="[% pl.patron_list_id %]">[% pl.name %]</option>
+ [% END %]
+ </select>
+ </li>
+ </ol>
+ </fieldset>
+ [% END %]
+
<fieldset class="rows">
<legend>Or list cardnumbers one by one</legend>
<ol>
<div class="yui-u first">
<h3>Patrons and circulation</h3>
<dl>
- [% IF ( CAN_user_tools_moderate_comments ) %]
+ <dt><a href="/cgi-bin/koha/patron_lists/lists.pl">Patron lists</a>
+ <dd>Manage lists of patrons.</dd>
+
+[% IF ( CAN_user_tools_moderate_comments ) %]
<dt><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">Comments</a> [% IF ( pendingcomments ) %]<span class="holdcount"><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">[% pendingcomments %]</a></span>[% END %]</dt>
<dd>Moderate patron comments. </dd>
[% END %]
use C4::Category;
use Koha::DateUtils;
use File::Basename;
+use Koha::List::Patron;
my $input = new CGI;
my $quicksearch = $input->param('quicksearch') || '';
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{$_});
($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});
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;
--- /dev/null
+#!/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 );
--- /dev/null
+#!/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');
--- /dev/null
+#!/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 );
--- /dev/null
+#!/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 );
--- /dev/null
+#!/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 );
--- /dev/null
+#!/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' );
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';
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;
$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 );
$template->param( borrowers => \@borrowers );
$template->param( errors => \@errors );
+} else {
+
+ $template->param( patron_lists => [ GetPatronLists() ] );
}
$template->param(