View | Details | Raw Unified | Return to bug 13704
Collapse All | Expand All

(-)a/C4/Members/AttributeTypes.pm (-50 / +45 lines)
Lines 20-25 package C4::Members::AttributeTypes; Link Here
20
use strict;
20
use strict;
21
#use warnings; FIXME - Bug 2505
21
#use warnings; FIXME - Bug 2505
22
use C4::Context;
22
use C4::Context;
23
use Koha::Database;
23
24
24
use vars qw($VERSION);
25
use vars qw($VERSION);
25
26
Lines 135-140 sub new { Link Here
135
    $self->{'category_code'} = '';
136
    $self->{'category_code'} = '';
136
    $self->{'category_description'} = '';
137
    $self->{'category_description'} = '';
137
    $self->{'class'} = '';
138
    $self->{'class'} = '';
139
    $self->{'backup_for'} = '';
138
140
139
    bless $self, $class;
141
    bless $self, $class;
140
    return $self;
142
    return $self;
Lines 177-182 sub fetch { Link Here
177
    $self->{'category_code'}             = $row->{'category_code'};
179
    $self->{'category_code'}             = $row->{'category_code'};
178
    $self->{'category_description'}      = $row->{'category_description'};
180
    $self->{'category_description'}      = $row->{'category_description'};
179
    $self->{'class'}                     = $row->{'class'};
181
    $self->{'class'}                     = $row->{'class'};
182
    $self->{'backup_for'}                = $row->{'backup_for'};
180
183
181
    $sth = $dbh->prepare("SELECT branchcode, branchname FROM borrower_attribute_types_branches, branches WHERE b_branchcode = branchcode AND bat_code = ?;");
184
    $sth = $dbh->prepare("SELECT branchcode, branchname FROM borrower_attribute_types_branches, branches WHERE b_branchcode = branchcode AND bat_code = ?;");
182
    $sth->execute( $code );
185
    $sth->execute( $code );
Lines 202-259 method, the DB representation of the type is replaced. Link Here
202
sub store {
205
sub store {
203
    my $self = shift;
206
    my $self = shift;
204
207
205
    my $dbh = C4::Context->dbh;
208
    my $schema = Koha::Database->new()->schema();
206
    my $sth;
209
207
    my $existing = __PACKAGE__->fetch($self->{'code'});
210
    my $type = $schema->resultset('BorrowerAttributeType')->update_or_create(
208
    if (defined $existing) {
211
        {
209
        $sth = $dbh->prepare_cached("UPDATE borrower_attribute_types
212
210
                                     SET description = ?,
213
            code                      => $self->{'code'},
211
                                         repeatable = ?,
214
            description               => $self->{'description'},
212
                                         unique_id = ?,
215
            repeatable                => $self->{'repeatable'},
213
                                         opac_display = ?,
216
            unique_id                 => $self->{'unique_id'},
214
                                         password_allowed = ?,
217
            opac_display              => $self->{'opac_display'},
215
                                         staff_searchable = ?,
218
            password_allowed          => $self->{'password_allowed'},
216
                                         authorised_value_category = ?,
219
            staff_searchable          => $self->{'staff_searchable'},
217
                                         display_checkout = ?,
220
            authorised_value_category => $self->{'authorised_value_category'},
218
                                         category_code = ?,
221
            display_checkout          => $self->{'display_checkout'},
219
                                         class = ?
222
            category_code             => $self->{'category_code'} || undef,
220
                                     WHERE code = ?");
223
            class                     => $self->{'class'},
221
    } else {
224
            backup_for                => $self->{'backup_for'} || undef,
222
        $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types 
225
        }
223
                                        (description, repeatable, unique_id, opac_display, password_allowed,
226
    );
224
                                         staff_searchable, authorised_value_category, display_checkout, category_code, class, code)
227
225
                                        VALUES (?, ?, ?, ?, ?,
228
    if ( defined $self->{branches} ) {
226
                                                ?, ?, ?, ?, ?, ?)");
229
        $type->borrower_attribute_types_branches()->delete();
227
    }
230
228
    $sth->bind_param(1, $self->{'description'});
231
        my $rs = $schema->resultset('BorrowerAttributeTypesBranch');
229
    $sth->bind_param(2, $self->{'repeatable'});
232
230
    $sth->bind_param(3, $self->{'unique_id'});
233
        for my $branchcode ( @{ $$self{branches} } ) {
231
    $sth->bind_param(4, $self->{'opac_display'});
234
            next unless $branchcode;
232
    $sth->bind_param(5, $self->{'password_allowed'});
235
            $rs->create( { bat_code => $self->{code}, b_branchcode => $branchcode } );
233
    $sth->bind_param(6, $self->{'staff_searchable'});
234
    $sth->bind_param(7, $self->{'authorised_value_category'});
235
    $sth->bind_param(8, $self->{'display_checkout'});
236
    $sth->bind_param(9, $self->{'category_code'} || undef);
237
    $sth->bind_param(10, $self->{'class'});
238
    $sth->bind_param(11, $self->{'code'});
239
    $sth->execute;
240
241
    if ( defined $$self{branches} ) {
242
        $sth = $dbh->prepare("DELETE FROM borrower_attribute_types_branches WHERE bat_code = ?");
243
        $sth->execute( $$self{code} );
244
        $sth = $dbh->prepare(
245
            "INSERT INTO borrower_attribute_types_branches
246
                        ( bat_code, b_branchcode )
247
                        VALUES ( ?, ? )"
248
        );
249
        for my $branchcode ( @{$$self{branches}} ) {
250
            next if not $branchcode;
251
            $sth->bind_param( 1, $$self{code} );
252
            $sth->bind_param( 2, $branchcode );
253
            $sth->execute;
254
        }
236
        }
255
    }
237
    }
256
    $sth->finish;
257
}
238
}
258
239
259
=head2 code
240
=head2 code
Lines 442-447 sub class { Link Here
442
    @_ ? $self->{'class'} = shift : $self->{'class'};
423
    @_ ? $self->{'class'} = shift : $self->{'class'};
443
}
424
}
444
425
426
=head2 backup_for
427
428
my $backup_for = $attr_type->backup_for();
429
$attr_type->backup_for($backup_for);
430
431
Accessor.
432
433
=cut
434
435
sub backup_for {
436
    my $self = shift;
437
    @_ ? $self->{'backup_for'} = shift : $self->{'backup_for'};
438
}
439
445
440
446
=head2 delete
441
=head2 delete
447
442
(-)a/C4/Members/Attributes.pm (-13 / +45 lines)
Lines 23-28 use warnings; Link Here
23
use Text::CSV;      # Don't be tempted to use Text::CSV::Unicode -- even in binary mode it fails.
23
use Text::CSV;      # Don't be tempted to use Text::CSV::Unicode -- even in binary mode it fails.
24
use C4::Context;
24
use C4::Context;
25
use C4::Members::AttributeTypes;
25
use C4::Members::AttributeTypes;
26
use Koha::Database;
26
27
27
use vars qw($VERSION @ISA @EXPORT_OK @EXPORT %EXPORT_TAGS);
28
use vars qw($VERSION @ISA @EXPORT_OK @EXPORT %EXPORT_TAGS);
28
our ($csv, $AttributeTypes);
29
our ($csv, $AttributeTypes);
Lines 216-239 replacing any that existed previously. Link Here
216
=cut
217
=cut
217
218
218
sub SetBorrowerAttributes {
219
sub SetBorrowerAttributes {
219
    my $borrowernumber = shift;
220
    my ( $borrowernumber, $attr_list, $backup ) = @_;
220
    my $attr_list = shift;
221
221
222
    my $dbh = C4::Context->dbh;
222
    my $schema = Koha::Database->new()->schema();
223
    my $delsth = $dbh->prepare("DELETE FROM borrower_attributes WHERE borrowernumber = ?");
223
224
    $delsth->execute($borrowernumber);
224
    my $rs = $schema->resultset('BorrowerAttribute');
225
226
    my @attributes = $rs->search( { borrowernumber => $borrowernumber, backup_for => undef }, { prefetch => 'code' } );
227
228
    warn "TEST";
229
    if ($backup) {
230
        foreach my $a (@attributes) {
231
            warn "CODE: " . $a->get_column('code');
232
            warn "VAL: " . $a->attribute();
233
            my $attribute_type = $a->code();
234
235
            my @backup_attribute_type = $attribute_type->backup_to();
236
237
            foreach my $b (@backup_attribute_type) {
238
                warn "BACKUP CODE: " . $b->code();
239
                $b->borrower_attributes( { borrowernumber => $borrowernumber } )->delete() unless $b->repeatable();
240
241
                $rs->create(
242
                    {
243
                        borrowernumber => $borrowernumber,
244
                        code           => $b->get_column('code'),
245
                        attribute      => $a->attribute(),
246
                        password       => $a->password(),
247
                    }
248
                );
249
            }
250
        }
251
    }
252
253
    map { $_->delete } @attributes;
225
254
226
    my $sth = $dbh->prepare("INSERT INTO borrower_attributes (borrowernumber, code, attribute, password)
227
                             VALUES (?, ?, ?, ?)");
228
    foreach my $attr (@$attr_list) {
255
    foreach my $attr (@$attr_list) {
229
        $attr->{password} = undef unless exists $attr->{password};
256
        $attr->{borrowernumber} = $borrowernumber;
230
        $sth->execute($borrowernumber, $attr->{code}, $attr->{value}, $attr->{password});
257
231
        if ($sth->err) {
258
        $attr->{attribute} = $attr->{value};    # move 'value' to 'attribute'
232
            warn sprintf('Database returned the following error: %s', $sth->errstr);
259
        delete( $attr->{value} );
233
            return; # bail immediately on errors
260
261
        my $a = $rs->create($attr);
262
263
        unless ($a) {
264
            return;                             # bail immediately on errors
234
        }
265
        }
235
    }
266
    }
236
    return 1; # borower attributes successfully set
267
268
    return 1;    # borrower attributes successfully set
237
}
269
}
238
270
239
=head2 DeleteBorrowerAttribute
271
=head2 DeleteBorrowerAttribute
(-)a/Koha/Patrons/Import.pm (-2 / +4 lines)
Lines 21-26 use Carp; Link Here
21
use Text::CSV;
21
use Text::CSV;
22
22
23
use C4::Members;
23
use C4::Members;
24
use C4::Members::Attributes qw(extended_attributes_code_value_arrayref SetBorrowerAttributes);
24
use C4::Branch;
25
use C4::Branch;
25
26
26
sub import_patrons {
27
sub import_patrons {
Lines 30-35 sub import_patrons { Link Here
30
    my $matchpoint           = $params->{matchpoint};
31
    my $matchpoint           = $params->{matchpoint};
31
    my $defaults             = $params->{defaults};
32
    my $defaults             = $params->{defaults};
32
    my $ext_preserve         = $params->{preserve_extended_attributes};
33
    my $ext_preserve         = $params->{preserve_extended_attributes};
34
    my $ext_backup           = $params->{backup_extended_attributes};
33
    my $overwrite_cardnumber = $params->{overwrite_cardnumber};
35
    my $overwrite_cardnumber = $params->{overwrite_cardnumber};
34
36
35
    carp("No file handle passed in!") && return unless $handle;
37
    carp("No file handle passed in!") && return unless $handle;
Lines 280-286 sub import_patrons { Link Here
280
                    $patron_attributes = extended_attributes_merge( $old_attributes, $patron_attributes );
282
                    $patron_attributes = extended_attributes_merge( $old_attributes, $patron_attributes );
281
                }
283
                }
282
                push @errors, { unknown_error => 1 }
284
                push @errors, { unknown_error => 1 }
283
                  unless SetBorrowerAttributes( $borrower{'borrowernumber'}, $patron_attributes );
285
                  unless SetBorrowerAttributes( $borrower{'borrowernumber'}, $patron_attributes, $ext_backup );
284
            }
286
            }
285
            $overwritten++;
287
            $overwritten++;
286
            push(
288
            push(
Lines 311-317 sub import_patrons { Link Here
311
                }
313
                }
312
314
313
                if ($extended) {
315
                if ($extended) {
314
                    SetBorrowerAttributes( $borrowernumber, $patron_attributes );
316
                    SetBorrowerAttributes( $borrowernumber, $patron_attributes, $ext_backup );
315
                }
317
                }
316
318
317
                if ($set_messaging_prefs) {
319
                if ($set_messaging_prefs) {
(-)a/Koha/Schema/Result/BorrowerAttribute.pm (-2 / +22 lines)
Lines 23-28 __PACKAGE__->table("borrower_attributes"); Link Here
23
23
24
=head1 ACCESSORS
24
=head1 ACCESSORS
25
25
26
=head2 borrower_attribute_id
27
28
  data_type: 'integer'
29
  is_auto_increment: 1
30
  is_nullable: 0
31
26
=head2 borrowernumber
32
=head2 borrowernumber
27
33
28
  data_type: 'integer'
34
  data_type: 'integer'
Lines 51-56 __PACKAGE__->table("borrower_attributes"); Link Here
51
=cut
57
=cut
52
58
53
__PACKAGE__->add_columns(
59
__PACKAGE__->add_columns(
60
  "borrower_attribute_id",
61
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
54
  "borrowernumber",
62
  "borrowernumber",
55
  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
63
  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
56
  "code",
64
  "code",
Lines 61-66 __PACKAGE__->add_columns( Link Here
61
  { data_type => "varchar", is_nullable => 1, size => 64 },
69
  { data_type => "varchar", is_nullable => 1, size => 64 },
62
);
70
);
63
71
72
=head1 PRIMARY KEY
73
74
=over 4
75
76
=item * L</borrower_attribute_id>
77
78
=back
79
80
=cut
81
82
__PACKAGE__->set_primary_key("borrower_attribute_id");
83
64
=head1 RELATIONS
84
=head1 RELATIONS
65
85
66
=head2 borrowernumber
86
=head2 borrowernumber
Lines 94-101 __PACKAGE__->belongs_to( Link Here
94
);
114
);
95
115
96
116
97
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
117
# Created by DBIx::Class::Schema::Loader v0.07040 @ 2015-02-12 10:44:36
98
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9oRy+X25+b7vB03WSnpFTg
118
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:oqWX6PRIe/RFV2VAImN3bA
99
119
100
120
101
# You can replace this text with custom content, and it will be preserved on regeneration
121
# You can replace this text with custom content, and it will be preserved on regeneration
(-)a/Koha/Schema/Result/BorrowerAttributeType.pm (-3 / +52 lines)
Lines 90-95 __PACKAGE__->table("borrower_attribute_types"); Link Here
90
  is_nullable: 0
90
  is_nullable: 0
91
  size: 255
91
  size: 255
92
92
93
=head2 backup_for
94
95
  data_type: 'varchar'
96
  is_foreign_key: 1
97
  is_nullable: 1
98
  size: 10
99
93
=cut
100
=cut
94
101
95
__PACKAGE__->add_columns(
102
__PACKAGE__->add_columns(
Lines 115-120 __PACKAGE__->add_columns( Link Here
115
  { data_type => "varchar", is_nullable => 1, size => 10 },
122
  { data_type => "varchar", is_nullable => 1, size => 10 },
116
  "class",
123
  "class",
117
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 255 },
124
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 255 },
125
  "backup_for",
126
  { data_type => "varchar", is_foreign_key => 1, is_nullable => 1, size => 10 },
118
);
127
);
119
128
120
=head1 PRIMARY KEY
129
=head1 PRIMARY KEY
Lines 131-136 __PACKAGE__->set_primary_key("code"); Link Here
131
140
132
=head1 RELATIONS
141
=head1 RELATIONS
133
142
143
=head2 backup_for
144
145
Type: belongs_to
146
147
Related object: L<Koha::Schema::Result::BorrowerAttributeType>
148
149
=cut
150
151
__PACKAGE__->belongs_to(
152
  "backup_for",
153
  "Koha::Schema::Result::BorrowerAttributeType",
154
  { code => "backup_for" },
155
  {
156
    is_deferrable => 1,
157
    join_type     => "LEFT",
158
    on_delete     => "NO ACTION",
159
    on_update     => "NO ACTION",
160
  },
161
);
162
163
=head2 borrower_attribute_types
164
165
Type: has_many
166
167
Related object: L<Koha::Schema::Result::BorrowerAttributeType>
168
169
=cut
170
171
__PACKAGE__->has_many(
172
  "borrower_attribute_types",
173
  "Koha::Schema::Result::BorrowerAttributeType",
174
  { "foreign.backup_for" => "self.code" },
175
  { cascade_copy => 0, cascade_delete => 0 },
176
);
177
134
=head2 borrower_attribute_types_branches
178
=head2 borrower_attribute_types_branches
135
179
136
Type: has_many
180
Type: has_many
Lines 162-170 __PACKAGE__->has_many( Link Here
162
);
206
);
163
207
164
208
165
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-01-13 13:14:54
209
# Created by DBIx::Class::Schema::Loader v0.07040 @ 2015-02-12 09:12:49
166
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9fLFZ/u89xmeCollneyUIg
210
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QNYfvxrDzUhlFIU2p4whLw
167
211
212
__PACKAGE__->has_many(
213
  "backup_to",
214
  "Koha::Schema::Result::BorrowerAttributeType",
215
  { "foreign.backup_for" => "self.code" },
216
  { cascade_copy => 0, cascade_delete => 0 },
217
);
168
218
169
# You can replace this text with custom content, and it will be preserved on regeneration
170
1;
219
1;
(-)a/admin/patron-attr-types.pl (-1 / +6 lines)
Lines 53-58 my $code = $input->param("code"); Link Here
53
53
54
my $display_list = 0;
54
my $display_list = 0;
55
if ($op eq "edit_attribute_type") {
55
if ($op eq "edit_attribute_type") {
56
    patron_attribute_type_list($template);
56
    edit_attribute_type_form($template, $code);
57
    edit_attribute_type_form($template, $code);
57
} elsif ($op eq "edit_attribute_type_confirmed") {
58
} elsif ($op eq "edit_attribute_type_confirmed") {
58
    $display_list = add_update_attribute_type('edit', $template, $code);
59
    $display_list = add_update_attribute_type('edit', $template, $code);
Lines 74-79 if ($display_list) { Link Here
74
        $template->param(WARNING_extended_attributes_off => 1); 
75
        $template->param(WARNING_extended_attributes_off => 1); 
75
    }
76
    }
76
    patron_attribute_type_list($template);
77
    patron_attribute_type_list($template);
78
    $template->param(display_list => 1);
77
}
79
}
78
80
79
output_html_with_http_headers $input, $cookie, $template->output;
81
output_html_with_http_headers $input, $cookie, $template->output;
Lines 129-134 sub error_add_attribute_type_form { Link Here
129
    $template->param( category_code => $input->param('category_code') );
131
    $template->param( category_code => $input->param('category_code') );
130
    $template->param( class => $input->param('class') );
132
    $template->param( class => $input->param('class') );
131
133
134
    $template->param( backup_for => $input->param('backup_for') );
135
132
    $template->param(
136
    $template->param(
133
        attribute_type_form => 1,
137
        attribute_type_form => 1,
134
        confirm_op => 'add_attribute_type_confirmed',
138
        confirm_op => 'add_attribute_type_confirmed',
Lines 173-178 sub add_update_attribute_type { Link Here
173
    $attr_type->display_checkout($display_checkout);
177
    $attr_type->display_checkout($display_checkout);
174
    $attr_type->category_code($input->param('category_code'));
178
    $attr_type->category_code($input->param('category_code'));
175
    $attr_type->class($input->param('class'));
179
    $attr_type->class($input->param('class'));
180
    $attr_type->backup_for($input->param('backup_for'));
176
    my @branches = $input->param('branches');
181
    my @branches = $input->param('branches');
177
    $attr_type->branches( \@branches );
182
    $attr_type->branches( \@branches );
178
183
Lines 233-238 sub edit_attribute_type_form { Link Here
233
    $template->param(code => $code);
238
    $template->param(code => $code);
234
    $template->param(description => $attr_type->description());
239
    $template->param(description => $attr_type->description());
235
    $template->param(class => $attr_type->class());
240
    $template->param(class => $attr_type->class());
241
    $template->param(backup_for => $attr_type->backup_for());
236
242
237
    if ($attr_type->repeatable()) {
243
    if ($attr_type->repeatable()) {
238
        $template->param(repeatable_checked => 1);
244
        $template->param(repeatable_checked => 1);
Lines 309-315 sub patron_attribute_type_list { Link Here
309
        };
315
        };
310
    }
316
    }
311
    $template->param(available_attribute_types => \@attributes_loop);
317
    $template->param(available_attribute_types => \@attributes_loop);
312
    $template->param(display_list => 1);
313
}
318
}
314
319
315
sub authorised_value_category_list {
320
sub authorised_value_category_list {
(-)a/installer/data/mysql/kohastructure.sql (+6 lines)
Lines 295-302 CREATE TABLE `borrower_attribute_types` ( -- definitions for custom patron field Link Here
295
  `display_checkout` tinyint(1) NOT NULL default 0,-- defines if this field displays in checkout screens
295
  `display_checkout` tinyint(1) NOT NULL default 0,-- defines if this field displays in checkout screens
296
  `category_code` VARCHAR(10) NULL DEFAULT NULL,-- defines a category for an attribute_type
296
  `category_code` VARCHAR(10) NULL DEFAULT NULL,-- defines a category for an attribute_type
297
  `class` VARCHAR(255) NOT NULL DEFAULT '',-- defines a class for an attribute_type
297
  `class` VARCHAR(255) NOT NULL DEFAULT '',-- defines a class for an attribute_type
298
  `backup_for` varchar(10) DEFAULT NULL, -- reference to another type that it can be used as a backup for
298
  PRIMARY KEY  (`code`),
299
  PRIMARY KEY  (`code`),
299
  KEY `auth_val_cat_idx` (`authorised_value_category`)
300
  KEY `auth_val_cat_idx` (`authorised_value_category`)
301
  KEY `backup_for` (`backup_for`)
302
  CONSTRAINT `borrower_attribute_types_ibfk_1` FOREIGN KEY (`backup_for`) REFERENCES `borrower_attribute_types` (`code`)
303
    ON DELETE NO ACTION ON UPDATE NO ACTION
300
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
304
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
301
305
302
--
306
--
Lines 305-314 CREATE TABLE `borrower_attribute_types` ( -- definitions for custom patron field Link Here
305
309
306
DROP TABLE IF EXISTS `borrower_attributes`;
310
DROP TABLE IF EXISTS `borrower_attributes`;
307
CREATE TABLE `borrower_attributes` ( -- values of custom patron fields known as extended patron attributes linked to patrons/borrowers
311
CREATE TABLE `borrower_attributes` ( -- values of custom patron fields known as extended patron attributes linked to patrons/borrowers
312
  `borrower_attribute_id` int(11) NOT NULL AUTO_INCREMENT,
308
  `borrowernumber` int(11) NOT NULL, -- foreign key from the borrowers table, defines which patron/borrower has this attribute
313
  `borrowernumber` int(11) NOT NULL, -- foreign key from the borrowers table, defines which patron/borrower has this attribute
309
  `code` varchar(10) NOT NULL, -- foreign key from the borrower_attribute_types table, defines which custom field this value was entered for
314
  `code` varchar(10) NOT NULL, -- foreign key from the borrower_attribute_types table, defines which custom field this value was entered for
310
  `attribute` varchar(255) default NULL, -- custom patron field value
315
  `attribute` varchar(255) default NULL, -- custom patron field value
311
  `password` varchar(64) default NULL, -- password associated with this field
316
  `password` varchar(64) default NULL, -- password associated with this field
317
  PRIMARY KEY (`borrower_attribute_id`),
312
  KEY `borrowernumber` (`borrowernumber`),
318
  KEY `borrowernumber` (`borrowernumber`),
313
  KEY `code_attribute` (`code`, `attribute`),
319
  KEY `code_attribute` (`code`, `attribute`),
314
  CONSTRAINT `borrower_attributes_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`)
320
  CONSTRAINT `borrower_attributes_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`)
(-)a/installer/data/mysql/updatedatabase.pl (+9 lines)
Lines 9759-9764 if ( CheckVersion($DBversion) ) { Link Here
9759
    SetVersion ($DBversion);
9759
    SetVersion ($DBversion);
9760
}
9760
}
9761
9761
9762
$DBversion = "3.19.00.XXX";
9763
if ( CheckVersion($DBversion) ) {
9764
    $dbh->do("ALTER TABLE borrower_attribute_types ADD backup_for VARCHAR( 10 ) NULL, ADD INDEX ( backup_for )");
9765
    $dbh->do("ALTER TABLE borrower_attribute_types ADD FOREIGN KEY ( backup_for ) REFERENCES borrower_attribute_types ( code ) ON DELETE NO ACTION ON UPDATE NO ACTION");
9766
    $dbh->do("ALTER TABLE borrower_attributes ADD borrower_attribute_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST");
9767
    print "Upgrade to $DBversion done (Bug 13704 - Add ability to backup patron attributes when updated)";
9768
    SetVersion ($DBversion);
9769
}
9770
9762
=head1 FUNCTIONS
9771
=head1 FUNCTIONS
9763
9772
9764
=head2 TableExists($table)
9773
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt (+22 lines)
Lines 233-238 function CheckAttributeTypeForm(f) { Link Here
233
            </select>
233
            </select>
234
            <span>Group attributes types with a block title (based on authorized values category 'PA_CLASS')</span>
234
            <span>Group attributes types with a block title (based on authorized values category 'PA_CLASS')</span>
235
        </li>
235
        </li>
236
        <li>
237
            <label for="backup_for">Backup for: </label>
238
            <select name="backup_for">
239
                <option value="" />
240
                [% FOREACH aat IN available_attribute_types %]
241
                    [% FOREACH a IN aat.items %]
242
                        [% IF a.code != code %]
243
                            [% IF ( a.code == backup_for ) %]
244
                                <option value="[% a.code %]" selected="selected">
245
                                    [% a.code %] - [% a.description %]
246
                                </option>
247
                            [% ELSE %]
248
                                <option value="[% a.code %]">
249
                                    [% a.code %] - [% a.description %]
250
                                </option>
251
                            [% END %]
252
                        [% END %]
253
                    [% END %]
254
                [% END %]
255
            </select>
256
            <span>Use this attribute to backup another patron attribute when updating it.</span>
257
        </li>
236
    </ol>
258
    </ol>
237
  </fieldset>
259
  </fieldset>
238
  <fieldset class="action">
260
  <fieldset class="action">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/import_borrowers.tt (+8 lines)
Lines 55-60 Link Here
55
</li>
55
</li>
56
</ul>
56
</ul>
57
57
58
<h3 id="patron-attributes">Patron attributes</h3>
59
60
<p>
61
    If the 'save attributes values being replaced' checkbox is checked, <i>and</i> there is an attribute with the same code, but with _B appended to it ( e.g. EXAMPLE => EXAMPLE_B ), Koha will move the current
62
    attribute value to an instance of this _B value. If the _B attribute is repeatable, a new instance of the attribute will be created for each backup. If the _B instance is <i>not</i> repeatable, only the last
63
    value of the attribute will be kept.
64
</p>
65
58
<p><strong>See the full documentation for Patron Import in the <a href="http://manual.koha-community.org/[% helpVersion %]/en/patronimport.html">manual</a> (online).</strong></p>
66
<p><strong>See the full documentation for Patron Import in the <a href="http://manual.koha-community.org/[% helpVersion %]/en/patronimport.html">manual</a> (online).</strong></p>
59
67
60
[% INCLUDE 'help-bottom.inc' %]
68
[% INCLUDE 'help-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt (+4 lines)
Lines 222-227 Link Here
222
                    <li class="radio">
222
                    <li class="radio">
223
                        <input type="radio" id="ext_preserve_1" name="ext_preserve" value="1" /><label for="ext_preserve_1">Replace only included patron attributes</label>
223
                        <input type="radio" id="ext_preserve_1" name="ext_preserve" value="1" /><label for="ext_preserve_1">Replace only included patron attributes</label>
224
                    </li>
224
                    </li>
225
226
                    <li class="radio">
227
                        <input type="checkbox" id="ext_backup" name="ext_backup" /><label for="ext_backup">Save the attribute values being replaced.<sup><a href="/cgi-bin/koha/help.pl#patron-attributes">Details</a></sup></label>
228
                    </li>
225
                </ol>
229
                </ol>
226
            </fieldset>
230
            </fieldset>
227
        [% END %]
231
        [% END %]
(-)a/tools/import_borrowers.pl (-1 / +1 lines)
Lines 117-122 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
117
            matchpoint                   => $matchpoint,
117
            matchpoint                   => $matchpoint,
118
            overwrite_cardnumber         => $input->param('overwrite_cardnumber'),
118
            overwrite_cardnumber         => $input->param('overwrite_cardnumber'),
119
            preserve_extended_attributes => $input->param('ext_preserve') || 0,
119
            preserve_extended_attributes => $input->param('ext_preserve') || 0,
120
            backup_extended_attributes   => $input->param('ext_backup') || 0,
120
        }
121
        }
121
    );
122
    );
122
123
123
- 

Return to bug 13704