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

(-)a/Koha/Patron/Attribute.pm (+19 lines)
Lines 71-76 sub store { Link Here
71
    Koha::Exceptions::Patron::Attribute::NonRepeatable->throw( attribute => $self )
71
    Koha::Exceptions::Patron::Attribute::NonRepeatable->throw( attribute => $self )
72
        unless $self->repeatable_ok();
72
        unless $self->repeatable_ok();
73
73
74
    $self->do_trim_value_if_needed();
75
74
    Koha::Exceptions::Patron::Attribute::UniqueIDConstraint->throw( attribute => $self )
76
    Koha::Exceptions::Patron::Attribute::UniqueIDConstraint->throw( attribute => $self )
75
        unless $self->unique_ok();
77
        unless $self->unique_ok();
76
78
Lines 235-240 sub value_ok { Link Here
235
    return $ok;
237
    return $ok;
236
}
238
}
237
239
240
=head3 do_trim_value_if_needed
241
242
---
243
244
=cut
245
246
sub do_trim_value_if_needed {
247
248
    my ($self) = @_;
249
250
    if ( $self->type->trim_value ) {
251
        my $value_to_trim = $self->attribute;
252
        $value_to_trim =~ s/^\s+|\s+$//g;
253
        $self->attribute($value_to_trim);
254
    }
255
}
256
238
=head2 Internal methods
257
=head2 Internal methods
239
258
240
=head3 _type
259
=head3 _type
(-)a/Koha/Patron/Attribute/Type.pm (+23 lines)
Lines 46-51 sub store { Link Here
46
46
47
    $self->check_repeatables;
47
    $self->check_repeatables;
48
    $self->check_unique_ids;
48
    $self->check_unique_ids;
49
    $self->check_untrimmed_values;
49
50
50
    return $self->SUPER::store();
51
    return $self->SUPER::store();
51
}
52
}
Lines 112-117 sub check_unique_ids { Link Here
112
    return $self;
113
    return $self;
113
}
114
}
114
115
116
=head3 check_untrimmed_values
117
118
=cut
119
120
sub check_untrimmed_values {
121
    my ($self) = @_;
122
123
    return $self unless $self->trim_value;
124
125
    my $count = $self->attributes->search(
126
        {
127
            attribute => { -regexp => '^\s+|\s+$' }
128
        }
129
    )->count;
130
131
        Koha::Exceptions::Patron::Attribute::Type::CannotChangeProperty->throw(
132
        property => 'trim_value' )
133
      if $count;
134
135
    return $self;
136
}
137
115
=head3 _type
138
=head3 _type
116
139
117
=cut
140
=cut
(-)a/Koha/Schema/Result/BorrowerAttributeType.pm (+11 lines)
Lines 55-60 defines whether one patron/borrower can have multiple values for this custom fie Link Here
55
55
56
defines if this value needs to be unique (1 for yes, 0 for no)
56
defines if this value needs to be unique (1 for yes, 0 for no)
57
57
58
=head2 trim_value
59
60
  data_type: 'tinyint'
61
  default_value: 0
62
  is_nullable: 0
63
64
defines if this value needs to be trimmed of whitespaces (1 for yes, 0 for no)
65
58
=head2 is_date
66
=head2 is_date
59
67
60
  data_type: 'tinyint'
68
  data_type: 'tinyint'
Lines 164-169 __PACKAGE__->add_columns( Link Here
164
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
172
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
165
  "unique_id",
173
  "unique_id",
166
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
174
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
175
  "trim_value",
176
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
167
  "is_date",
177
  "is_date",
168
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
178
  { data_type => "tinyint", default_value => 0, is_nullable => 0 },
169
  "opac_display",
179
  "opac_display",
Lines 282-287 __PACKAGE__->add_columns( Link Here
282
);
292
);
283
293
284
__PACKAGE__->add_columns(
294
__PACKAGE__->add_columns(
295
    '+trim_value' => { is_boolean => 1 },
285
    '+is_date' => { is_boolean => 1 },
296
    '+is_date' => { is_boolean => 1 },
286
);
297
);
287
298
(-)a/admin/patron-attr-types.pl (+10 lines)
Lines 109-114 sub add_update_attribute_type { Link Here
109
    my $description               = $input->param('description');
109
    my $description               = $input->param('description');
110
    my $repeatable                = $input->param('repeatable')                ? 1 : 0;
110
    my $repeatable                = $input->param('repeatable')                ? 1 : 0;
111
    my $unique_id                 = $input->param('unique_id')                 ? 1 : 0;
111
    my $unique_id                 = $input->param('unique_id')                 ? 1 : 0;
112
    my $trim_value                = $input->param('trim_value')                ? 1 : 0;
112
    my $is_date                   = $input->param('is_date')                   ? 1 : 0;
113
    my $is_date                   = $input->param('is_date')                   ? 1 : 0;
113
    my $opac_display              = $input->param('opac_display')              ? 1 : 0;
114
    my $opac_display              = $input->param('opac_display')              ? 1 : 0;
114
    my $opac_editable             = $input->param('opac_editable')             ? 1 : 0;
115
    my $opac_editable             = $input->param('opac_editable')             ? 1 : 0;
Lines 146-151 sub add_update_attribute_type { Link Here
146
        {
147
        {
147
            repeatable                => $repeatable,
148
            repeatable                => $repeatable,
148
            unique_id                 => $unique_id,
149
            unique_id                 => $unique_id,
150
            trim_value                => $trim_value,
149
            is_date                   => $is_date,
151
            is_date                   => $is_date,
150
            opac_display              => $opac_display,
152
            opac_display              => $opac_display,
151
            opac_editable             => $opac_editable,
153
            opac_editable             => $opac_editable,
Lines 237-248 sub edit_attribute_type_form { Link Here
237
        $can_be_set_to_unique = 0 if $@;
239
        $can_be_set_to_unique = 0 if $@;
238
        $attr_type->unique_id(0);
240
        $attr_type->unique_id(0);
239
    }
241
    }
242
    my $can_be_trimmed = 1;
243
    if ( $attr_type->trim_value == 0 ) {
244
        $attr_type->trim_value(1);
245
        eval {$attr_type->check_untrimmed_values};
246
        $can_be_trimmed = 0 if $@;
247
        $attr_type->trim_value(0);
248
    }
240
    $template->param(
249
    $template->param(
241
        attribute_type              => $attr_type,
250
        attribute_type              => $attr_type,
242
        attribute_type_form         => 1,
251
        attribute_type_form         => 1,
243
        edit_attribute_type         => 1,
252
        edit_attribute_type         => 1,
244
        can_be_set_to_nonrepeatable => $can_be_set_to_nonrepeatable,
253
        can_be_set_to_nonrepeatable => $can_be_set_to_nonrepeatable,
245
        can_be_set_to_unique        => $can_be_set_to_unique,
254
        can_be_set_to_unique        => $can_be_set_to_unique,
255
        can_be_trimmed              => $can_be_trimmed,
246
        confirm_op                  => 'cud-edit_attribute_type_confirmed',
256
        confirm_op                  => 'cud-edit_attribute_type_confirmed',
247
        categories                  => $patron_categories,
257
        categories                  => $patron_categories,
248
    );
258
    );
(-)a/installer/data/mysql/atomicupdate/bug_32767-trim-attr-feature.pl (+14 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number => "32767",
5
    description => "New feature that trims attributes (if enabled) to avoid duplicates",
6
    up => sub {
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
9
10
        unless ( column_exists( 'borrower_attribute_types', 'trim_value' ) ) {
11
            $dbh->do( "ALTER TABLE `borrower_attribute_types` ADD COLUMN `trim_value` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this value needs to be trimmed of whitespaces (1 for yes, 0 for no)' AFTER unique_id" );
12
        }
13
    },
14
};
(-)a/installer/data/mysql/kohastructure.sql (+1 lines)
Lines 1249-1254 CREATE TABLE `borrower_attribute_types` ( Link Here
1249
  `description` varchar(255) NOT NULL COMMENT 'description for each custom field',
1249
  `description` varchar(255) NOT NULL COMMENT 'description for each custom field',
1250
  `repeatable` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines whether one patron/borrower can have multiple values for this custom field  (1 for yes, 0 for no)',
1250
  `repeatable` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines whether one patron/borrower can have multiple values for this custom field  (1 for yes, 0 for no)',
1251
  `unique_id` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this value needs to be unique (1 for yes, 0 for no)',
1251
  `unique_id` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this value needs to be unique (1 for yes, 0 for no)',
1252
  `trim_value` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this value needs to be trimmed of whitespaces (1 for yes, 0 for no)',
1252
  `is_date` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is displayed as a date',
1253
  `is_date` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is displayed as a date',
1253
  `opac_display` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is visible to patrons on their account in the OPAC (1 for yes, 0 for no)',
1254
  `opac_display` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is visible to patrons on their account in the OPAC (1 for yes, 0 for no)',
1254
  `opac_editable` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is editable by patrons on their account in the OPAC (1 for yes, 0 for no)',
1255
  `opac_editable` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'defines if this field is editable by patrons on their account in the OPAC (1 for yes, 0 for no)',
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt (+21 lines)
Lines 139-144 Link Here
139
                        [% END %]
139
                        [% END %]
140
                        <span class="hint">If checked, attribute will be a unique identifier. If a value is given to a patron record, the same value cannot be given to a different record.</span>
140
                        <span class="hint">If checked, attribute will be a unique identifier. If a value is given to a patron record, the same value cannot be given to a different record.</span>
141
                    </li>
141
                    </li>
142
                    [% IF attribute_type AND attribute_type.trim_value %]
143
                        <li aria-disabled="true">
144
                    [% ELSE %]
145
                        <li>
146
                    [% END %]
147
                        <label for="trim_value">Trim identifier: </label>
148
                        [% IF attribute_type %]
149
                            [% IF NOT can_be_trimmed %]
150
                                <input type="checkbox" id="trim_value" name="trim_value" disabled="disabled" title="At least one patron has attribute with whitespaces at the start or/end of it." />
151
                                <input type="hidden" name="trim_value" value="0" />
152
                                <span class="hint">At least one patron has attribute with whitespaces at the start or/end of it. Please fix that.</span>
153
                            [% ELSIF attribute_type.trim_value %]
154
                                <input type="checkbox" id="trim_value" name="trim_value" checked="checked" />
155
                            [% ELSE %]
156
                                <input type="checkbox" id="trim_value" name="trim_value" />
157
                            [% END %]
158
                        [% ELSE %]
159
                            <input type="checkbox" id="trim_value" name="trim_value" />
160
                        [% END %]
161
                        <span class="hint">Check to always trim whitespaces around the identifier to avoid creating duplicates.</span>
162
                    </li>
142
                    <li
163
                    <li
143
                        ><label for="is_date">Is a date: </label>
164
                        ><label for="is_date">Is a date: </label>
144
                        [% IF attribute_type AND attribute_type.is_date %]
165
                        [% IF attribute_type AND attribute_type.is_date %]
(-)a/members/memberentry.pl (+1 lines)
Lines 413-418 if ( $op eq 'cud-save' || $op eq 'cud-insert' ) { Link Here
413
        for my $attr (@$extended_patron_attributes) {
413
        for my $attr (@$extended_patron_attributes) {
414
            $attr->{borrowernumber} = $borrowernumber if $borrowernumber;
414
            $attr->{borrowernumber} = $borrowernumber if $borrowernumber;
415
            my $attribute = Koha::Patron::Attribute->new($attr);
415
            my $attribute = Koha::Patron::Attribute->new($attr);
416
            $attribute->do_trim_value_if_needed;
416
            if ( !$attribute->unique_ok ) {
417
            if ( !$attribute->unique_ok ) {
417
                push @errors, "ERROR_extended_unique_id_failed";
418
                push @errors, "ERROR_extended_unique_id_failed";
418
                my $attr_type = Koha::Patron::Attribute::Types->find( $attr->{code} );
419
                my $attr_type = Koha::Patron::Attribute::Types->find( $attr->{code} );
(-)a/opac/opac-memberentry.pl (-1 / +1 lines)
Lines 117-122 my $conflicting_attribute = 0; Link Here
117
117
118
foreach my $attr (@$attributes) {
118
foreach my $attr (@$attributes) {
119
    my $attribute = Koha::Patron::Attribute->new($attr);
119
    my $attribute = Koha::Patron::Attribute->new($attr);
120
    $attribute->do_trim_value_if_needed;
120
    if ( !$attribute->unique_ok ) {
121
    if ( !$attribute->unique_ok ) {
121
        my $attr_type = Koha::Patron::Attribute::Types->find( $attr->{code} );
122
        my $attr_type = Koha::Patron::Attribute::Types->find( $attr->{code} );
122
        $template->param(
123
        $template->param(
123
- 

Return to bug 32767