Browse Source

Bug 14570: Make it possible to add multiple guarantors to a record

This patch adds the ability to set an unlimited number of guarantors
for a given patron. As before, each guarantor may be linked to another
Koha patron, and all the behavior that applies to a given guarantor
remains the same.

Test Plan:
 1) Apply this patch
 2) Run updatedatabase.pl
 3) Find some patrons with guarantors, verify the still have their guarantor
 4) Test adding and removing guarantors on a patron record, both Koha users and not
 5) Verify the "Add child" button works
 6) Verify NoIssuesChargeGuarantees still works
 7) Verify tools/cleanborrowers.pl will not delete a guarantor
 8) Verify the guarantors are displayed on moremember.pl
 9) Verify the guarantor is removed by members/update-child.pl
10) Verify the guarantor is removed by misc/cronjobs/j2a.pl
11) Verify import patrons converts guarantor_id, relationship, contactfirstname,
  and contactsurname into a guarantor
12) prove t/Patron.t
13) prove t/db_dependent/Circulation.t
14) prove t/db_dependent/Circulation/NoIssuesChargeGuarantees.t
15) prove t/db_dependent/Items.t
16) prove t/db_dependent/Koha/Patrons.t
17) prove t/db_dependent/Members.t
18) prove t/db_dependent/Patron/Relationships.t

Signed-off-by: Kim Peine <kmpeine@gmail.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Agustin Moyano <agustinmoyano@theke.io>
Signed-off-by: Liz Rea <wizzyrea@gmail.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
remotes/origin/19.11.x
Kyle Hall 5 years ago
committed by Martin Renvoize
parent
commit
109334102f
Signed by: martin.renvoize GPG Key ID: 422B469130441A0F
  1. 1
      C4/Auth_with_ldap.pm
  2. 2
      C4/Circulation.pm
  3. 14
      C4/Members.pm
  4. 1
      C4/SIP/ILS/Patron.pm
  5. 5
      Koha/Object.pm
  6. 120
      Koha/Patron.pm
  7. 73
      Koha/Patron/Relationship.pm
  8. 99
      Koha/Patron/Relationships.pm
  9. 12
      Koha/Patrons.pm
  10. 16
      Koha/Patrons/Import.pm
  11. 2
      Koha/REST/V1/Auth.pm
  12. 6
      Koha/Schema/Result/Borrower.pm
  13. 118
      Koha/Schema/Result/BorrowerRelationship.pm
  14. 4
      api/v1/swagger/definitions/patron.json
  15. 16
      circ/circulation.pl
  16. 52
      installer/data/mysql/atomicupdate/bug_14570.perl
  17. 19
      installer/data/mysql/kohastructure.sql
  18. 1
      koha-tmpl/intranet-tmpl/prog/en/columns.def
  19. 13
      koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc
  20. 2
      koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
  21. 402
      koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
  22. 26
      koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember-brief.tt
  23. 19
      koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
  24. 92
      koha-tmpl/intranet-tmpl/prog/js/members.js
  25. 11
      koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
  26. 9
      koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-privacy.tt
  27. 8
      koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
  28. 6
      members/deletemem.pl
  29. 116
      members/memberentry.pl
  30. 28
      members/moremember.pl
  31. 18
      members/update-child.pl
  32. 76
      misc/cronjobs/j2a.pl
  33. 4
      opac/opac-memberentry.pl
  34. 15
      opac/opac-user.pl
  35. 24
      t/Patron.t
  36. 24
      t/db_dependent/Circulation/NoIssuesChargeGuarantees.t
  37. 6
      t/db_dependent/Items.t
  38. 149
      t/db_dependent/Koha/Patrons.t
  39. 17
      t/db_dependent/Members.t
  40. 167
      t/db_dependent/Patron/Relationships.t
  41. 1
      tools/import_borrowers.pl

1
C4/Auth_with_ldap.pm

@ -468,7 +468,6 @@ C4::Auth - Authenticates Koha users
| contactname | mediumtext | YES | | NULL | |
| contactfirstname | text | YES | | NULL | |
| contacttitle | text | YES | | NULL | |
| guarantorid | int(11) | YES | MUL | NULL | |
| borrowernotes | mediumtext | YES | | NULL | |
| relationship | varchar(100) | YES | | NULL | |
| ethnicity | varchar(50) | YES | | NULL | |

2
C4/Circulation.pm

@ -785,7 +785,7 @@ sub CanBookBeIssued {
my $no_issues_charge_guarantees = C4::Context->preference("NoIssuesChargeGuarantees");
$no_issues_charge_guarantees = undef unless looks_like_number( $no_issues_charge_guarantees );
if ( defined $no_issues_charge_guarantees ) {
my @guarantees = $patron->guarantees();
my @guarantees = map { $_->guarantee } $patron->guarantee_relationships();
my $guarantees_non_issues_charges;
foreach my $g ( @guarantees ) {
$guarantees_non_issues_charges += $g->account->non_issues_charges;

14
C4/Members.pm

@ -176,7 +176,7 @@ sub patronflags {
$no_issues_charge_guarantees = undef unless looks_like_number( $no_issues_charge_guarantees );
if ( defined $no_issues_charge_guarantees ) {
my $p = Koha::Patrons->find( $patroninformation->{borrowernumber} );
my @guarantees = $p->guarantees();
my @guarantees = map { $_->guarantee } $p->guarantee_relationships;
my $guarantees_non_issues_charges;
foreach my $g ( @guarantees ) {
$guarantees_non_issues_charges += $g->account->non_issues_charges;
@ -397,18 +397,18 @@ sub GetBorrowersToExpunge {
FROM borrowers
JOIN categories USING (categorycode)
LEFT JOIN (
SELECT guarantorid
FROM borrowers
WHERE guarantorid IS NOT NULL
AND guarantorid <> 0
) as tmp ON borrowers.borrowernumber=tmp.guarantorid
SELECT guarantor_id
FROM borrower_relationships
WHERE guarantor_id IS NOT NULL
AND guarantor_id <> 0
) as tmp ON borrowers.borrowernumber=tmp.guarantor_id
LEFT JOIN old_issues USING (borrowernumber)
LEFT JOIN issues USING (borrowernumber)|;
if ( $filterpatronlist ){
$query .= q| LEFT JOIN patron_list_patrons USING (borrowernumber)|;
}
$query .= q| WHERE category_type <> 'S'
AND tmp.guarantorid IS NULL
AND tmp.guarantor_id IS NULL
|;
my @query_params;
if ( $filterbranch && $filterbranch ne "" ) {

1
C4/SIP/ILS/Patron.pm

@ -627,7 +627,6 @@ __END__
| contactname | mediumtext | YES | | NULL | |
| contactfirstname | text | YES | | NULL | |
| contacttitle | text | YES | | NULL | |
| guarantorid | int(11) | YES | MUL | NULL | |
| borrowernotes | mediumtext | YES | | NULL | |
| relationship | varchar(100) | YES | | NULL | |
| ethnicity | varchar(50) | YES | | NULL | |

5
Koha/Object.pm

@ -72,8 +72,9 @@ sub new {
next if not exists $attributes->{$column_name} or defined $attributes->{$column_name};
delete $attributes->{$column_name};
}
$self->{_result} = $schema->resultset( $class->_type() )
->new($attributes);
$self->{_result} =
$schema->resultset( $class->_type() )->new($attributes);
}
croak("No _type found! Koha::Object must be subclassed!")

120
Koha/Patron.pm

@ -27,8 +27,10 @@ use Text::Unaccent qw( unac_string );
use C4::Context;
use C4::Log;
use Koha::Account;
use Koha::AuthUtils;
use Koha::Checkouts;
use Koha::Club::Enrollments;
use Koha::Database;
use Koha::DateUtils;
use Koha::Exceptions::Password;
@ -39,12 +41,11 @@ use Koha::Patron::Categories;
use Koha::Patron::HouseboundProfile;
use Koha::Patron::HouseboundRole;
use Koha::Patron::Images;
use Koha::Patron::Relationships;
use Koha::Patrons;
use Koha::Virtualshelves;
use Koha::Club::Enrollments;
use Koha::Account;
use Koha::Subscription::Routinglists;
use Koha::Token;
use Koha::Virtualshelves;
use base qw(Koha::Object);
@ -372,41 +373,67 @@ sub category {
return Koha::Patron::Category->_new_from_dbic( $self->_result->categorycode );
}
=head3 guarantor
Returns a Koha::Patron object for this patron's guarantor
=head3 image
=cut
sub guarantor {
my ( $self ) = @_;
return unless $self->guarantorid();
return Koha::Patrons->find( $self->guarantorid() );
}
sub image {
my ( $self ) = @_;
return scalar Koha::Patron::Images->find( $self->borrowernumber );
}
=head3 library
Returns a Koha::Library object representing the patron's home library.
=cut
sub library {
my ( $self ) = @_;
return Koha::Library->_new_from_dbic($self->_result->branchcode);
}
=head3 guarantees
=head3 guarantor_relationships
Returns Koha::Patron::Relationships object for this patron's guarantors
Returns the guarantees (list of Koha::Patron) of this patron
Returns the set of relationships for the patrons that are guarantors for this patron.
This is returned instead of a Koha::Patron object because the guarantor
may not exist as a patron in Koha. If this is true, the guarantors name
exists in the Koha::Patron::Relationship object and will have no guarantor_id.
=cut
sub guarantees {
my ( $self ) = @_;
sub guarantor_relationships {
my ($self) = @_;
return Koha::Patrons->search( { guarantorid => $self->borrowernumber }, { order_by => { -asc => ['surname','firstname'] } } );
return Koha::Patron::Relationships->search( { guarantee_id => $self->id } );
}
=head3 guarantee_relationships
Returns Koha::Patron::Relationships object for this patron's guarantors
Returns the set of relationships for the patrons that are guarantees for this patron.
The method returns Koha::Patron::Relationship objects for the sake
of consistency with the guantors method.
A guarantee by definition must exist as a patron in Koha.
=cut
sub guarantee_relationships {
my ($self) = @_;
return Koha::Patron::Relationships->search(
{ guarantor_id => $self->id },
{
prefetch => 'guarantee',
order_by => { -asc => [ 'guarantee.surname', 'guarantee.firstname' ] },
}
);
}
=head3 housebound_profile
@ -444,23 +471,22 @@ Returns the siblings of this patron.
=cut
sub siblings {
my ( $self ) = @_;
my ($self) = @_;
my $guarantor = $self->guarantor;
my @guarantors = $self->guarantor_relationships()->guarantors();
return unless $guarantor;
return unless @guarantors;
return Koha::Patrons->search(
{
guarantorid => {
'!=' => undef,
'=' => $guarantor->id,
},
borrowernumber => {
'!=' => $self->borrowernumber,
}
}
);
my @siblings =
map { $_->guarantee_relationships()->guarantees() } @guarantors;
return unless @siblings;
my %seen;
@siblings =
grep { !$seen{ $_->id }++ && ( $_->id != $self->id ) } @siblings;
return wantarray ? @siblings : Koha::Patrons->search( { borrowernumber => { -in => [ map { $_->id } @siblings ] } } );
}
=head3 merge_with
@ -1419,6 +1445,34 @@ sub _anonymize_column {
$self->$col($val);
}
=head3 add_guarantor
my @relationships = $patron->add_guarantor(
{
borrowernumber => $borrowernumber,
relationships => $relationship,
}
);
Adds a new guarantor to a patron.
=cut
sub add_guarantor {
my ( $self, $params ) = @_;
my $guarantor_id = $params->{guarantor_id};
my $relationship = $params->{relationship};
return Koha::Patron::Relationship->new(
{
guarantee_id => $self->id,
guarantor_id => $guarantor_id,
relationship => $relationship
}
)->store();
}
=head2 Internal methods
=head3 _type

73
Koha/Patron/Relationship.pm

@ -0,0 +1,73 @@
package Koha::Patron::Relationship;
# 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 3 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 Carp;
use Koha::Database;
use base qw(Koha::Object);
=head1 NAME
Koha::Patron::Relationship - A class to represent relationships between patrons
Patrons in Koha may be guarantors or guarantees. This class models that relationship
and provides a way to access those relationships.
=head1 API
=head2 Class Methods
=cut
=head3 guarantor
Returns the Koha::Patron object for the guarantor, if there is one
=cut
sub guarantor {
my ( $self ) = @_;
return unless $self->guarantor_id;
return scalar Koha::Patrons->find( $self->guarantor_id );
}
=head3 guarantee
Returns the Koha::Patron object for the guarantee
=cut
sub guarantee {
my ( $self ) = @_;
return scalar Koha::Patrons->find( $self->guarantee_id );
}
=head3 type
=cut
sub _type {
return 'BorrowerRelationship';
}
1;

99
Koha/Patron/Relationships.pm

@ -0,0 +1,99 @@
package Koha::Patron::Relationships;
# 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 3 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 Carp;
use List::MoreUtils qw( uniq );
use Koha::Database;
use Koha::Patrons;
use Koha::Patron::Relationship;
use base qw(Koha::Objects);
=head1 NAME
Koha::Patron::Relationships - Koha Patron Relationship Object set class
=head1 API
=head2 Class Methods
=cut
=head3 guarantors
Returns all the guarantors in this set of relationships as a list of Koha::Patron objects
or as a Koha::Patrons object depending on the calling context
=cut
sub guarantors {
my ($self) = @_;
my $rs = $self->_resultset();
my @guarantor_ids = $rs->get_column('guarantor_id')->all();
# Guarantors may not have a guarantor_id, strip out undefs
@guarantor_ids = grep { defined $_ } @guarantor_ids;
@guarantor_ids = uniq( @guarantor_ids );
my $guarantors = Koha::Patrons->search( { borrowernumber => \@guarantor_ids } );
return wantarray ? $guarantors->as_list : $guarantors;
}
=head3 guarantees
Returns all the guarantees in this set of relationships as a list of Koha::Patron objects
or as a Koha::Patrons object depending on the calling context
=cut
sub guarantees {
my ($self) = @_;
my $rs = $self->_resultset();
my @guarantee_ids = uniq( $rs->get_column('guarantee_id')->all() );
my $guarantees = Koha::Patrons->search(
{ borrowernumber => \@guarantee_ids },
{
order_by => { -asc => [ 'surname', 'firstname' ] }
},
);
return wantarray ? $guarantees->as_list : $guarantees;
}
=cut
=head3 type
=cut
sub _type {
return 'BorrowerRelationship';
}
sub object_class {
return 'Koha::Patron::Relationship';
}
1;

12
Koha/Patrons.pm

@ -125,18 +125,6 @@ sub search_upcoming_membership_expires {
);
}
=head3 guarantor
Returns a Koha::Patron object for this borrower's guarantor
=cut
sub guarantor {
my ( $self ) = @_;
return Koha::Patrons->find( $self->guarantorid() );
}
=head3 search_patrons_to_anonymise
my $patrons = Koha::Patrons->search_patrons_to_anonymise( { before => $older_than_date, [ library => $library ] } );

16
Koha/Patrons/Import.pm

@ -216,6 +216,11 @@ sub import_patrons {
next LINE;
}
my $relationship = $borrower{relationship};
my $guarantor_id = $borrower{guarantor_id};
delete $borrower{relationship};
delete $borrower{guarantor_id};
if ($borrowernumber) {
# borrower exists
@ -352,6 +357,17 @@ sub import_patrons {
);
}
}
# Add a guarantor if we are given a relationship
if ( $guarantor_id ) {
Koha::Patron::Relationship->new(
{
guarantee_id => $borrowernumber,
relationship => $relationship,
guarantor_id => $guarantor_id,
}
)->store();
}
}
return {

2
Koha/REST/V1/Auth.pm

@ -320,7 +320,7 @@ sub allow_guarantor {
return;
}
my $guarantees = $user->guarantees->as_list;
my $guarantees = $user->guarantee_relationships->guarantees->as_list;
foreach my $guarantee (@{$guarantees}) {
return 1 if check_object_ownership($c, $guarantee);
}

6
Koha/Schema/Result/Borrower.pm

@ -1532,12 +1532,6 @@ __PACKAGE__->many_to_many("ordernumbers", "aqorder_users", "ordernumber");
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-04-25 10:08:38
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3qd/l8OkObSn8gTKTsHrkA
__PACKAGE__->belongs_to(
"guarantor",
"Koha::Schema::Result::Borrower",
{ borrowernumber => "guarantorid" },
);
__PACKAGE__->add_columns(
'+anonymized' => { is_boolean => 1 },
'+lost' => { is_boolean => 1 },

118
Koha/Schema/Result/BorrowerRelationship.pm

@ -0,0 +1,118 @@
use utf8;
package Koha::Schema::Result::BorrowerRelationship;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Koha::Schema::Result::BorrowerRelationship
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 TABLE: C<borrower_relationships>
=cut
__PACKAGE__->table("borrower_relationships");
=head1 ACCESSORS
=head2 id
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 guarantor_id
data_type: 'integer'
is_foreign_key: 1
is_nullable: 1
=head2 guarantee_id
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 relationship
data_type: 'varchar'
is_nullable: 0
size: 100
=cut
__PACKAGE__->add_columns(
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"guarantor_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"guarantee_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"relationship",
{ data_type => "varchar", is_nullable => 0, size => 100 },
);
=head1 PRIMARY KEY
=over 4
=item * L</id>
=back
=cut
__PACKAGE__->set_primary_key("id");
=head1 RELATIONS
=head2 guarantee
Type: belongs_to
Related object: L<Koha::Schema::Result::Borrower>
=cut
__PACKAGE__->belongs_to(
"guarantee",
"Koha::Schema::Result::Borrower",
{ borrowernumber => "guarantee_id" },
{ is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);
=head2 guarantor
Type: belongs_to
Related object: L<Koha::Schema::Result::Borrower>
=cut
__PACKAGE__->belongs_to(
"guarantor",
"Koha::Schema::Result::Borrower",
{ borrowernumber => "guarantor_id" },
{
is_deferrable => 1,
join_type => "LEFT",
on_delete => "CASCADE",
on_update => "CASCADE",
},
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2018-07-18 10:52:59
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:R8RThgcrct40Zq0UMW3TWQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

4
api/v1/swagger/definitions/patron.json

@ -159,10 +159,6 @@
"readOnly": true,
"description": "If any restriction applies to the patron"
},
"guarantor_id": {
"type": ["integer", "null"],
"description": "patron_id used for children or professionals to link them to guarantor or organizations"
},
"staff_notes": {
"type": ["string", "null"],
"description": "a note on the patron's account"

16
circ/circulation.pl

@ -512,7 +512,7 @@ if ( $patron ) {
$no_issues_charge_guarantees = undef unless looks_like_number( $no_issues_charge_guarantees );
if ( defined $no_issues_charge_guarantees ) {
my $guarantees_non_issues_charges = 0;
my $guarantees = $patron->guarantees;
my $guarantees = $patron->guarantee_relationships->guarantees;
while ( my $g = $guarantees->next ) {
$guarantees_non_issues_charges += $g->account->non_issues_charges;
}
@ -567,14 +567,12 @@ my $view = $batch
: 'circview';
my @relatives;
if ( $borrowernumber ) {
if ( $patron ) {
if ( my $guarantor = $patron->guarantor ) {
push @relatives, $guarantor->borrowernumber;
push @relatives, $_->borrowernumber for $patron->siblings;
} else {
push @relatives, $_->borrowernumber for $patron->guarantees;
}
if ( $patron ) {
if ( my @guarantors = $patron->guarantor_relationships()->guarantors() ) {
push( @relatives, $_->id ) for @guarantors;
push( @relatives, $_->id ) for $patron->siblings();
} else {
push( @relatives, $_->id ) for $patron->guarantee_relationships()->guarantees();
}
}
my $relatives_issues_count =

52
installer/data/mysql/atomicupdate/bug_14570.perl

@ -0,0 +1,52 @@
$DBversion = 'XXX'; # will be replaced by the RM
if( CheckVersion( $DBversion ) ) {
# you can use $dbh here like:
# $dbh->do( "ALTER TABLE biblio ADD COLUMN badtaste int" );
unless (TableExists('borrower_relationships')){
$dbh->do(q{
CREATE TABLE `borrower_relationships` (
id INT(11) NOT NULL AUTO_INCREMENT,
guarantor_id INT(11) NOT NULL,
guarantee_id INT(11) NOT NULL,
relationship VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT r_guarantor FOREIGN KEY ( guarantor_id ) REFERENCES borrowers ( borrowernumber ) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT r_guarantee FOREIGN KEY ( guarantee_id ) REFERENCES borrowers ( borrowernumber ) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
});
$dbh->do(q{
UPDATE borrowers
LEFT JOIN borrowers guarantor ON ( borrowers.guarantorid = guarantor.borrowernumber )
SET borrowers.guarantorid = NULL WHERE guarantor.borrowernumber IS NULL;
});
$dbh->do(q{
INSERT INTO borrower_relationships ( guarantor_id, guarantee_id, relationship )
SELECT guarantorid, borrowernumber, relationship FROM borrowers WHERE guarantorid IS NOT NULL;
});
}
if( column_exists( 'borrowers', 'guarantorid' ) ) {
$dbh->do(q{
ALTER TABLE borrowers DROP guarantorid;
});
}
if( column_exists( 'deletedborrowers', 'guarantorid' ) ) {
$dbh->do(q{
ALTER TABLE deletedborrowers DROP guarantorid;
});
}
if( column_exists( 'borrower_modifications', 'guarantorid' ) ) {
$dbh->do(q{
ALTER TABLE borrower_modifications DROP guarantorid;
});
}
# Always end with this (adjust the bug info)
SetVersion( $DBversion );
print "Upgrade to $DBversion done (Bug 14570 - Make it possible to add multiple guarantors to a record)\n";
}

19
installer/data/mysql/kohastructure.sql

@ -559,7 +559,6 @@ CREATE TABLE `deletedborrowers` ( -- stores data related to the patrons/borrower
`contactname` LONGTEXT, -- used for children and profesionals to include surname or last name of guarantor or organization name
`contactfirstname` MEDIUMTEXT, -- used for children to include first name of guarantor
`contacttitle` MEDIUMTEXT, -- used for children to include title (Mr., Mrs., etc) of guarantor
`guarantorid` int(11) default NULL, -- borrowernumber used for children or professionals to link them to guarantors or organizations
`borrowernotes` LONGTEXT, -- a note on the patron/borrower's account that is only visible in the staff client
`relationship` varchar(100) default NULL, -- used for children to include the relationship to their guarantor
`sex` varchar(1) default NULL, -- patron/borrower's gender
@ -1548,7 +1547,6 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons
`contactname` LONGTEXT, -- used for children and profesionals to include surname or last name of guarantor or organization name
`contactfirstname` MEDIUMTEXT, -- used for children to include first name of guarantor
`contacttitle` MEDIUMTEXT, -- used for children to include title (Mr., Mrs., etc) of guarantor
`guarantorid` int(11) default NULL, -- borrowernumber used for children or professionals to link them to guarantors or organizations
`borrowernotes` LONGTEXT, -- a note on the patron/borrower's account that is only visible in the staff client
`relationship` varchar(100) default NULL, -- used for children to include the relationship to their guarantor
`sex` varchar(1) default NULL, -- patron/borrower's gender
@ -1584,7 +1582,6 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons
KEY `categorycode` (`categorycode`),
KEY `branchcode` (`branchcode`),
UNIQUE KEY `userid` (`userid`),
KEY `guarantorid` (`guarantorid`),
KEY `surname_idx` (`surname` (191)),
KEY `firstname_idx` (`firstname` (191)),
KEY `othernames_idx` (`othernames` (191)),
@ -3364,7 +3361,6 @@ CREATE TABLE IF NOT EXISTS `borrower_modifications` (
`contactname` LONGTEXT,
`contactfirstname` MEDIUMTEXT,
`contacttitle` MEDIUMTEXT,
`guarantorid` int(11) DEFAULT NULL,
`borrowernotes` LONGTEXT,
`relationship` varchar(100) DEFAULT NULL,
`sex` varchar(1) DEFAULT NULL,
@ -4073,6 +4069,21 @@ CREATE TABLE IF NOT EXISTS club_fields (
CONSTRAINT club_fields_ibfk_4 FOREIGN KEY (club_id) REFERENCES clubs (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Table structure for table 'guarantors_guarantees'
--
DROP TABLE IF EXISTS borrower_relationships;
CREATE TABLE `borrower_relationships` (
id INT(11) NOT NULL AUTO_INCREMENT,
guarantor_id INT(11) NULL DEFAULT NULL,
guarantee_id INT(11) NOT NULL,
relationship VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT r_guarantor FOREIGN KEY ( guarantor_id ) REFERENCES borrowers ( borrowernumber ) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT r_guarantee FOREIGN KEY ( guarantee_id ) REFERENCES borrowers ( borrowernumber ) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Table structure for table `illrequests`
--

1
koha-tmpl/intranet-tmpl/prog/en/columns.def

@ -7,7 +7,6 @@
<field name="borrowers.othernames">Other name</field>
<field name="borrowers.sex">Gender</field>
<field name="borrowers.relationship">Relationship</field>
<field name="borrowers.guarantorid">Guarantor borrower number</field>
<field name="borrowers.streetnumber">Street number</field>
<field name="borrowers.streettype">Street type</field>
<field name="borrowers.address">Address</field>

13
koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc

@ -7,21 +7,14 @@
[% USE scalar %]
<div id="toolbar" class="btn-toolbar">
[% IF CAN_user_borrowers_edit_borrowers %]
[% IF ( guarantor ) %]
<a id="editpatron" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=modify&amp;destination=circ&amp;borrowernumber=[% patron.borrowernumber | html %]&amp;guarantorid=[% guarantor.borrowernumber | html %]&amp;categorycode=[% patron.categorycode | html %]">
[% ELSE %]
<a id="editpatron" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=modify&amp;destination=circ&amp;borrowernumber=[% patron.borrowernumber | html %]&amp;categorycode=[% patron.categorycode | html %]">
[% END %]
<i class="fa fa-pencil"></i> Edit</a>
<a id="editpatron" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=modify&amp;destination=circ&amp;borrowernumber=[% patron.borrowernumber | html %]&amp;categorycode=[% patron.categorycode | html %]"><i class="fa fa-pencil"></i> Edit</a>
[% END %]
[% IF CAN_user_borrowers_edit_borrowers %]
[% IF patron.is_adult AND Koha.Preference("borrowerRelationship") %]
<a id="addchild" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=add&amp;guarantorid=[% patron.borrowernumber | html %]"><i class="fa fa-plus"></i> Add child</a>
[% END %]
[% IF CAN_user_borrowers_edit_borrowers %]
<a id="changepassword" class="btn btn-default" href="/cgi-bin/koha/members/member-password.pl?member=[% patron.borrowernumber | html %]"><i class="fa fa-lock"></i> Change password</a>
<a id="addchild" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=add&amp;guarantor_id=[% patron.borrowernumber | html %]"><i class="fa fa-plus"></i> Add child</a>
[% END %]
<a id="changepassword" class="btn btn-default" href="/cgi-bin/koha/members/member-password.pl?member=[% patron.borrowernumber | html %]"><i class="fa fa-lock"></i> Change password</a>
<a id="duplicate" class="btn btn-default" href="/cgi-bin/koha/members/memberentry.pl?op=duplicate&amp;borrowernumber=[% patron.borrowernumber | html %]&amp;categorycode=[% patron.categorycode | html %]"><i class="fa fa-copy"></i> Duplicate</a>
[% END %]

2
koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt

@ -824,7 +824,7 @@
</li>
[% IF relatives_issues_count %]
<li><a id="relatives-issues-tab" href="#relatives-issues">Relatives' checkouts</a></li>
<li><a id="relatives-issues-tab" href="#relatives-issues">[% relatives_issues_count %] Relatives' checkouts</a></li>
[% END %]
<li>

402
koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt

@ -1,5 +1,6 @@
[% USE raw %]
[% USE Asset %]
[% USE To %]
[% USE Koha %]
[% USE KohaDates %]
[% USE Branches %]
@ -317,113 +318,122 @@
</fieldset>
[% END # hide fieldset %]
[% IF ( showguarantor ) %]
<input type="hidden" id="guarantorid" name="guarantorid" value="[% guarantorid | html %]" />
[% UNLESS step_6 %]
<input type="hidden" name="branchcode" value="[% branchcode | html %]" />
[% END %]
<fieldset id="memberentry_guarantor" class="rows">
<legend id="guarantor_lgd">Guarantor information</legend>
<ol>
[% IF ( P ) %]
[% IF ( guarantorid ) %]
<li id="contact-details">
[% ELSE %]
<li id="contact-details" style="display: none">
[% END %]
<span class="label">Organization #:</span> [% IF ( guarantorid ) %] <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantorid | uri %]" target="blank">[% guarantorid | html %]</a>[% END %]
</li>
<li>
<label for="contactname">Organization name: </label>
[% IF ( guarantorid ) %]
<span>[% contactname | html %]</span>
<input name="contactname" id="contactname" type="hidden" size="20" value="[% contactname | html %]" />
[% ELSE %]
<input name="contactname" id="contactname" type="text" size="20" value="[% contactname | html %]" />
[% END %]
</li>
[% ELSE %]
[% IF ( C ) %]
[% IF ( guarantorid ) %]
<li id="contact-details">
[% ELSE %]
<li id="contact-details" style="display: none">
[% END %]
<span class="label">Patron #:</span>
[% IF guarantorid %]
[% IF logged_in_user.can_see_patron_infos( guarantor ) %]
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantorid | uri %]" target="blank">[% guarantorid | html %]</a>
[% ELSE %]
[% guarantorid | html %]
[% END %]
[% END %]
</li>
[% UNLESS nocontactname %]
<li>
<label for="contactname">Surname: </label>
[% IF ( guarantorid ) %]
<span>[% contactname | html %]</span>
<input name="contactname" id="contactname" type="hidden" size="20" value="[% contactname | html %]" />
[% ELSE %]
<input name="contactname" id="contactname" type="text" size="20" value="[% contactname | html %]" />
[% END %]
</li>
[% END %]
[% UNLESS nocontactfirstname %]
<li>
<label for="contactfirstname">First name: </label>
[% IF ( guarantorid ) %]
<span>[% contactfirstname | html %]</span>
<input name="contactfirstname" id="contactfirstname" type="hidden" size="20" value="[% contactfirstname | html %]" />
[% ELSE %]
<input name="contactfirstname" id="contactfirstname" type="text" size="20" value="[% contactfirstname | html %]" />
[% END %]
</li>
[% END %]
[% IF ( relshiploop ) %]
<li>
<label for="relationship">Relationship: </label>
<select name="relationship" id="relationship" >
[% FOREACH relshiploo IN relshiploop %]
[% IF ( relshiploo.selected ) %]
<option value="[% relshiploo.relationship | html %]" selected="selected" >[% relshiploo.relationship | html %]</option>
[% ELSE %]
<option value="[% relshiploo.relationship | html %]">[% relshiploo.relationship | html %]</option>
[% END %]
[% END %]
</select>
</li>
[% END %]
[% END %]
[% END %]
<li>
<span class="label">&nbsp;</span>
[% IF ( guarantorid ) %]
<input id="guarantorsearch" type="button" value="Change" onclick="Dopopguarantor('guarantor_search.pl');" />
[% ELSE %]
<input id="guarantorsearch" type="button" value="Set to patron" onclick="Dopopguarantor('guarantor_search.pl');" />
[% END %]
<input id="guarantordelete" type="button" value="Delete" />
</li>
[% IF guarantorid && Koha.Preference('AllowStaffToSetCheckoutsVisibilityForGuarantor') %]
<li>
<label for="privacy_guarantor_checkouts">Show checkouts to guarantor</label>
<select name="privacy_guarantor_checkouts" id="privacy_guarantor_checkouts">
[% IF privacy_guarantor_checkouts %]
<option value="0">No</option>
<option value="1" selected>Yes</option>
[% ELSE %]
<option value="0" selected>No</option>
<option value="1">Yes</option>
[% IF show_guarantor || guarantor %]
[% SET possible_relationships = Koha.Preference('borrowerRelationship') %]
<fieldset class="rows">
<legend>Guarantor information</legend>
<span id="guarantor_relationships">
[% FOREACH r IN relationships %]
<fieldset class="rows">
<ol>
[% IF category_type == 'P' %]
<li id="contact-details">
<span class="label">Organization #:</span> [% IF ( r.guarantor_id ) %] <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% r.guarantor_id | uri %]" target="blank">[% r.guarantor_id | html %]</a>[% END %]
</li>
<li>
<label for="guarantor_surname">Organization name: </label>
<span>[% r.guarantor.surname | html %]</span>
</li>
[% ELSE %]
<li id="contact-details">
<span class="label">Patron #:</span>
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% r.guarantor_id | uri %]" target="blank">[% r.guarantor_id | html %]</a>
</li>
[% IF r.guarantor.surname %]
<li>
<label for="guarantor_surname">Surname: </label>
<span>[% r.guarantor.surname | html %]</span>
</li>
[% END %]
[% IF r.guarantor.firstname %]
<li>
<label for="guarantor_firstname">First name: </label>
<span>[% r.guarantor.firstname | html %]</span>
</li>
[% END %]
<li>
<label for="relationship">Relationship: </label>
<span>[% r.relationship | html %]</span>
</li>
<li>
<label for="delete_guarantor-[% r.id | uri %]">Delete: </label>
<input type="checkbox" id="delete_guarantor-[% r.id | uri %]" name="delete_guarantor" value="[% r.id | html %]" />
</li>
[% END %]
</ol>
</fieldset>
[% END # END relationships foreach %]
</span>
<fieldset class="rows guarantor" id="guarantor_template">
<ol>
<li class="guarantor_id">
<span class="label">Patron #:</span>
<span class="new_guarantor_id_text"></span>
<input type="hidden" class="new_guarantor_id" name="new_guarantor_id" value=""/>
</li>
<li>
<label for="guarantor_surname">Surname: </label>
<span class="new_guarantor_surname_text"></span>
</li>
<li>
<label for="guarantor_firstname">First name: </label>
<span class="new_guarantor_firstname_text"></span>
</li>
<li>
<label for="guarantor_relationship">Relationship: </label>
<select class="new_guarantor_relationship" name="new_guarantor_relationship">
[% FOREACH pr IN possible_relationships.split('\|') %]
<option value="[% pr | html %]">[% pr | html %]</option>
[% END %]
</select>
</li>
<li>
<label for="guarantor_cancel">&nbsp;</label>
<span><a href="#" class="guarantor_cancel">Cancel</a></span>
</li>
</ol>
</fieldset>
<ol>
<input type="hidden" id="guarantor_id" value="" />
<input name="guarantor_surname" id="guarantor_surname" type="hidden" />
<input name="guarantor_firstname" id="guarantor_firstname" type="hidden" />
<li>
<a href="#" id="guarantor_search" class="btn btn-sm"><i class="fa fa-search"></i> Search</a>
</li>
[% IF relationships && Koha.Preference('AllowStaffToSetCheckoutsVisibilityForGuarantor') %]
<li>
<label for="privacy_guarantor_checkouts">Show checkouts to guarantors</label>
<select name="privacy_guarantor_checkouts" id="privacy_guarantor_checkouts">
[% IF privacy_guarantor_checkouts %]
<option value="0">No</option>
<option value="1" selected>Yes</option>
[% ELSE %]
<option value="0" selected>No</option>
<option value="1">Yes</option>
[% END %]
</select>
<div class="hint">Allow guarantors of this patron to view this patron's checkouts from the OPAC</div>
</li>
[% END %]
</select>
<div class="hint">Allow guarantor of this patron to view this patron's checkouts from the OPAC</div>
</li>
[% END %]
</ol>
</ol>
</fieldset>
[% END %]
[% UNLESS noaddress && noaddress2 && nocity && nostate && nozipcode && nocountry %]
[% IF Koha.Preference( 'AddressFormat' ) %]
[% INCLUDE "member-main-address-style-${ Koha.Preference( 'AddressFormat' ) }.inc" %]
@ -431,84 +441,132 @@
[% END # nostreet && nocity etc group%]
[% UNLESS nophone && nophonepro && nomobile && noemail && noemailpro && nofax %]
<fieldset class="rows" id="memberentry_contact">
<legend id="contact_lgd">Contact</legend><ol>
[% UNLESS nophone %]
<li>
[% IF ( mandatoryphone ) %]
<label for="phone" class="required">
[% ELSE %]
<label for="phone">
[% END %]
Primary phone: </label>
<input type="text" id="phone" name="phone" value="[% phone | html %]" />
[% IF ( mandatoryphone ) %]<span class="required">Required</span>[% END %]<div class="hint">Shows on transit slips</div>
<fieldset class="rows" id="memberentry_contact">
<legend id="contact_lgd">Contact</legend><ol>
</li>
[% UNLESS nocontactname %]
<li>
[% IF ( mandatorycontactname ) %]
<label for="contactname" class="required">
[% ELSE %]
<label for="contactname">
[% END %]
Guarantor surname: </label>
<input type="text" id="contactname" name="contactname" value="[% contactname | html %]" />
[% IF ( mandatorycontactname ) %]<span class="required">Required</span>[% END %]<div class="hint">Non-patron guarantor surname</div>
</li>
[% END %]
[% UNLESS nocontactfirstname %]
<li>
[% IF ( mandatorycontactfirstname ) %]
<label for="contactfirstname" class="required">
[% ELSE %]
<label for="contactfirstname">
[% END %]
Guarantor first name: </label>
<input type="text" id="contactfirstname" name="contactfirstname" value="[% contactfirstname | html %]" />
[% IF ( mandatorycontactfirstname ) %]<span class="required">Required</span>[% END %]<div class="hint">Non-patron guarantor first name</div>
</li>
[% END %]
[% UNLESS norelationship %]
[% IF possible_relationships %]
<li>
<label for="relationship">Relationship: </label>
<select class="relationship" name="relationship">
<option value=""></option>
[% FOREACH pr IN possible_relationships.split('\|') %]
[% IF pr == relationship %]
<option value="[% pr %]" selected="selected">[% pr %]</option>
[% ELSE %]
<option value="[% pr %]">[% pr %]</option>
[% END %]
[% END %]
</select>
</li>
[% END %]
[% END %]
[% UNLESS nophone %]
<li>
[% IF ( mandatoryphone ) %]
<label for="phone" class="required">
[% ELSE %]
<label for="phone">
[% END %]
Primary phone: </label>
<input type="text" id="phone" name="phone" value="[% phone | html %]" />
[% IF ( mandatoryphone ) %]<span class="required">Required</span>[% END %]<div class="hint">Shows on transit slips</div>
</li>
[% END %]
[% UNLESS nophonepro %]
<li>
[% IF ( mandatoryphonepro ) %]
<label for="phonepro" class="required">
[% ELSE %]
<label for="phonepro">
[% END %]
Secondary phone: </label>
<input type="text" id="phonepro" name="phonepro" value="[% phonepro | html %]" />
[% IF ( mandatoryphonepro ) %]<span class="required">Required</span>[% END %]
</li>
<li>
[% IF ( mandatoryphonepro ) %]
<label for="phonepro" class="required">
[% ELSE %]
<label for="phonepro">
[% END %]
Secondary phone: </label>
<input type="text" id="phonepro" name="phonepro" value="[% phonepro | html %]" />
[% IF ( mandatoryphonepro ) %]<span class="required">Required</span>[% END %]
</li>
[% END %]
[% UNLESS nomobile %]
<li>
[% IF ( mandatorymobile ) %]
<label for="mobile" class="required">
[% ELSE %]
<label for="mobile">
[% END %]
Other phone: </label>
<input type="text" id="mobile" name="mobile" value="[% mobile | html %]" />
[% IF ( mandatorymobile ) %]<span class="required">Required</span>[% END %]
</li>
<li>
[% IF ( mandatorymobile ) %]
<label for="mobile" class="required">
[% ELSE %]
<label for="mobile">
[% END %]
Other phone: </label>
<input type="text" id="mobile" name="mobile" value="[% mobile | html %]" />
[% IF ( mandatorymobile ) %]<span class="required">Required</span>[% END %]
</li>
[% END %]
[% UNLESS noemail %]
<li>
[% IF ( mandatoryemail ) %]
<label for="email" class="required">
[% ELSE %]
<label for="email">
[% END %]
Primary email: </label>
<input type="text" id="email" name="email" size="45" value="[% email | html %]" />
[% IF ( mandatoryemail ) %]<span class="required">Required</span>[% END %]<div class="hint">Shows on transit slips</div>
</li>
[% UNLESS noemail %]
<li>
[% IF ( mandatoryemail ) %]
<label for="email" class="required">
[% ELSE %]
<label for="email">
[% END %]
Primary email: </label>
<input type="text" id="email" name="email" size="45" value="[% email | html %]" />
[% IF ( mandatoryemail ) %]<span class="required">Required</span>[% END %]<div class="hint">Shows on transit slips</div>
</li>
[% END %]
[% UNLESS noemailpro %]
<li>
[% IF ( mandatoryemailpro ) %]
<label for="emailpro" class="required">
[% ELSE %]
<label for="emailpro">
[% END %]
Secondary email: </label>
<input type="text" id="emailpro" name="emailpro" size="45" value="[% emailpro | html %]" />
[% IF ( mandatoryemailpro ) %]<span class="required">Required</span>[% END %]
</li>
<li>
[% IF ( mandatoryemailpro ) %]
<label for="emailpro" class="required">
[% ELSE %]
<label for="emailpro">
[% END %]
Secondary email: </label>
<input type="text" id="emailpro" name="emailpro" size="45" value="[% emailpro | html %]" />
[% IF ( mandatoryemailpro ) %]<span class="required">Required</span>[% END %]
</li>
[% END %]
[% UNLESS nofax %]
<li>
[% IF ( mandatoryfax ) %]
<label for="fax" class="required">
[% ELSE %]
<label for="fax">
[% END %]
Fax: </label>
<input type="text" id="fax" name="fax" value="[% fax | html %]" />
[% IF ( mandatoryfax ) %]<span class="required">Required</span>[% END %]
</li>
<li>
[% IF ( mandatoryfax ) %]
<label for="fax" class="required">
[% ELSE %]
<label for="fax">
[% END %]
Fax: </label>
<input type="text" id="fax" name="fax" value="[% fax | html %]" />
[% IF ( mandatoryfax ) %]<span class="required">Required</span>[% END %]
</li>
[% END %]
</ol>
</fieldset>
</ol>
</fieldset>
[%END # hide fieldset %]
<!-- ************************ STEP_1 *********************** -->
@ -1172,6 +1230,10 @@
}
[% END %]
[% IF guarantor %]
select_user( '[% guarantor.borrowernumber %]', [% To.json( guarantor.unblessed ) | $raw %] );
[% END %]
$("#cn_max").hide();
var content;
$("#cardnumber").on("keydown", function(e){

26
koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember-brief.tt

@ -1,3 +1,4 @@
[% USE raw %]
[% USE Koha %]
[% USE KohaDates %]
[% SET footerjs = 1 %]
@ -40,13 +41,26 @@
[% IF ( patron.dateofbirth ) %]<li><span class="label">Date of birth:</span>[% patron.dateofbirth | $KohaDates %]</li>[% END %]
[% IF ( patron.sex ) %]<li><span class="label">Gender:</span>[% IF ( patron.sex == 'F' ) %]Female[% ELSIF ( patron.sex == 'M' ) %]Male[% ELSE %][% patron.sex | html %][% END %]</li>[% END %]
[% END %]
[% IF ( guarantees ) %]
<li><span class="label">Guarantees:</span><ul>[% FOREACH guarantee IN guarantees %]<li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantee.borrowernumber | uri %]">[% INCLUDE 'patron-title.inc' patron=guarantee %]</a></li>[% END %]</ul></li>
[% END %]
[% IF ( guarantor ) %]
<li><span class="label">Guarantor:</span><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantor.borrowernumber | uri %]">[% guarantor.surname | html %], [% guarantor.firstname | html %]</a></li>
[% IF guarantees %]
<li>
<span class="label">Guarantees:</span>
<ul>
[% FOREACH guarantee IN guarantees %]
<li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantee.borrowernumber | uri %]">[% guarantee.firstname | html %] [% guarantee.surname | html %]</a></li>
[% END %]
</ul>
</li>
[% ELSIF guarantor_relationships %]
[% FOREACH gr IN guarantor_relationships %]
<li>
<span class="label">Guarantor:</span>
[% SET guarantor = gr.guarantor %]
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantor.id | uri %]">[% guarantor.firstname | html %] [% guarantor.surname | html %]</a>
</li>
[% END %]
[% END %]
</ol>
</ol>
</div>
</div>
</div>

19
koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt

@ -270,15 +270,16 @@
[% END %]
</ul>
</li>
[% ELSIF guarantor %]
<li>
<span class="label">Guarantor:</span>
[% IF guarantor.borrowernumber AND logged_in_user.can_see_patron_infos( guarantor ) %]
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantor.borrowernumber | uri %]">[% guarantor.firstname | html %] [% guarantor.surname | html %]</a>
[% ELSE %]
[% guarantor.firstname | html %] [% guarantor.surname | html %]
[% END %]
</li>
[% ELSIF guarantor_relationships %]
[% FOREACH gr IN guarantor_relationships %]
<li>
<span class="label">Guarantor:</span>
[% SET guarantor = gr.guarantor %]
[% IF logged_in_user.can_see_patron_infos( guarantor ) %]
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% guarantor.id | uri %]">[% guarantor.firstname | html %] [% guarantor.surname | html %]</a>
[% END %]
</li>
[% END %]
[% END %]
</ol>
</div> [% # /div.rows %]

92
koha-tmpl/intranet-tmpl/prog/js/members.js

@ -129,10 +129,6 @@ function Dopop(link) {
var newin=window.open(link,'popup','width=600,height=400,resizable=no,toolbar=false,scrollbars=no,top');
}
function Dopopguarantor(link) {
var newin=window.open(link,'popup','width=800,height=500,resizable=no,toolbar=false,scrollbars=yes,top');
}
function clear_entry(node) {
var original = $(node).parent();
$("textarea", original).attr('value', '');
@ -170,48 +166,38 @@ function update_category_code(category_code) {
}
function select_user(borrowernumber, borrower) {
var form = $('#entryform').get(0);
if (form.guarantorid.value) {
$("#contact-details, #quick_add_form #contact-details").find('a').remove();
$("#contactname, #contactfirstname, #quick_add_form #contactname, #quick_add_form #contactfirstname").parent().find('span').remove();
$('#guarantor_id').val(borrower.borrowernumber);
$('#guarantor_surname').val(borrower.surname);
$('#guarantor_firstname').val(borrower.firstname);
var fieldset = $('#guarantor_template').clone();
fieldset.removeAttr('id');
var guarantor_id = $('#guarantor_id').val();
if ( guarantor_id ) {
fieldset.find('.new_guarantor_id').first().val( guarantor_id );
fieldset.find('.new_guarantor_id_text').first().text( guarantor_id );
} else {
fieldset.find('.guarantor_id').first().hide();
}
$('#guarantor_id').val("");
var guarantor_surname = $('#guarantor_surname').val();
fieldset.find('.new_guarantor_surname').first().val( guarantor_surname );
fieldset.find('.new_guarantor_surname_text').first().text( guarantor_surname );
$('#guarantor_surname').val("");
var guarantor_firstname = $('#guarantor_firstname').val();
fieldset.find('.new_guarantor_firstname').first().val( guarantor_firstname );
fieldset.find('.new_guarantor_firstname_text').first().text( guarantor_firstname );
$('#guarantor_firstname').val("");
var id = borrower.borrowernumber;
form.guarantorid.value = id;
$('#contact-details, #quick_add_form #contact-details')
.show()
.find('span')
.after('<a target="blank" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=' + id + '">' + id + '</a>');
$(form.contactname)
.val(borrower.surname)
.before('<span>' + borrower.surname + '</span>').get(0).type = 'hidden';
$("#quick_add_form #contactname").val(borrower.surname).before('<span>'+borrower.surname+'</span.').attr({type:"hidden"});
$(form.contactfirstname,"#quick_add_form #contactfirstname")
.val(borrower.firstname)
.before('<span>' + borrower.firstname + '</span>').get(0).type = 'hidden';
$("#quick_add_form #contactfirstname").val(borrower.firstname).before('<span>'+borrower.firstname+'</span.').attr({type:"hidden"});
form.streetnumber.value = borrower.streetnumber;
form.address.value = borrower.address;
form.address2.value = borrower.address2;
form.city.value = borrower.city;
form.state.value = borrower.state;
form.zipcode.value = borrower.zipcode;
form.country.value = borrower.country;
form.branchcode.value = borrower.branchcode;
$("#quick_add_form #streetnumber").val(borrower.streetnumber);
$("#quick_add_form #address").val(borrower.address);
$("#quick_add_form #address2").val(borrower.address2);
$("#quick_add_form #city").val(borrower.city);
$("#quick_add_form #state").val(borrower.state);
$("#quick_add_form #zipcode").val(borrower.zipcode);
$("#quick_add_form #country").val(borrower.country);
$("#quick_add_form select[name='branchcode']").val(borrower.branchcode);
form.guarantorsearch.value = LABEL_CHANGE;
$("#quick_add_form #guarantorsearch").val(LABEL_CHANGE);
var guarantor_relationship = $('#relationship').val();
fieldset.find('.new_guarantor_relationship').first().val( guarantor_relationship );
$('#relationship').find('option:eq(0)').prop('selected', true);;
$('#guarantor_relationships').append( fieldset );
fieldset.show();
return 0;
}
@ -284,13 +270,17 @@ $(document).ready(function(){
});
$("fieldset.rows input, fieldset.rows select").addClass("noEnterSubmit");
$("#guarantordelete").click(function() {
$("#quick_add_form #contact-details, #contact-details").hide().find('a').remove();
$("#quick_add_form #guarantorid, #quick_add_form #contactname, #quick_add_form #contactfirstname, #guarantorid, #contactname, #contactfirstname").each(function () { this.value = ""; });
$("#quick_add_form #contactname, #quick_add_form #contactfirstname, #contactname, #contactfirstname")
.each(function () { this.type = 'text'; })
.parent().find('span').remove();
$("#quick_add_form #guarantorsearch, #guarantorsearch").val(LABEL_SET_TO_PATRON);
$('#guarantor_template').hide();
$('#guarantor_search').on('click', function(e) {
e.preventDefault();
var newin = window.open('guarantor_search.pl','popup','width=600,height=400,resizable=no,toolbar=false,scrollbars=yes,top');
});
$('#guarantor_relationships').on('click', '.guarantor_cancel', function(e) {
e.preventDefault();
$(this).parents('fieldset').first().remove();
});
$(document.body).on('change','.select_city',function(){

11
koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt

@ -114,7 +114,7 @@
<div class="alert">You typed in the wrong characters in the box before submitting. Please try again.</div>
[% END %]
[% IF borrower.guarantorid && !Koha.Preference('OPACPrivacy') && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
[% IF patron.guarantor_relationships && !Koha.Preference('OPACPrivacy') && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
<fieldset class="rows" id="memberentry_privacy">