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

(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt (-19 / +90 lines)
Lines 1-7 Link Here
1
[% USE AuthorisedValues %]
1
[% USE Categories %]
2
[% USE Categories %]
2
[% USE Koha %]
3
[% USE Koha %]
3
[% USE Branches %]
4
[% USE Branches %]
4
[% USE KohaDates %]
5
[% USE KohaDates %]
6
[% USE Math %]
5
[% SET userupdateview = 1 %]
7
[% SET userupdateview = 1 %]
6
8
7
[% INCLUDE 'doc-head-open.inc' %]
9
[% INCLUDE 'doc-head-open.inc' %]
Lines 114-119 Link Here
114
                        </ol>
116
                        </ol>
115
                    </fieldset>
117
                    </fieldset>
116
                [% END %]
118
                [% END %]
119
                [% IF ( extended_unique_id_failed_code ) %]
120
                    <div class="alert" id="extended_unique_id_failed"><a href="#patron-attr-start-[% extended_unique_id_failed_code %]">[% extended_unique_id_failed_description %]</a> value <i>[% extended_unique_id_failed_value %]</i> is already in use.</div>
121
                [% END %]
117
122
118
                <form method="post" action="/cgi-bin/koha/opac-memberentry.pl" id="memberentry-form">
123
                <form method="post" action="/cgi-bin/koha/opac-memberentry.pl" id="memberentry-form">
119
124
Lines 885-891 Link Here
885
                    </fieldset>
890
                    </fieldset>
886
               [% END %]
891
               [% END %]
887
892
888
               [% UNLESS action == 'edit' %]
893
                [% IF ( Koha.Preference('ExtendedPatronAttributes') && patron_attribute_classes.size && !Koha.Preference('PatronSelfRegistrationVerifyByEmail') ) %]
894
                    [% FOREACH pa_class IN patron_attribute_classes %]
895
                        [% IF pa_class.class %]
896
                            <fieldset id="aai_[% pa_loo.class %]" class="rows patron-attributes">
897
                            <legend>[% pa_loo.lib %]</legend>
898
                        [% ELSE %]
899
                            <fieldset class="rows patron-attributes">
900
                            <legend>Additional information</legend>
901
                        [% END %]
902
                        <ol class="attributes_table">
903
                            [% FOREACH pa IN pa_class.items %]
904
                                [% FOREACH pa_value IN pa.values %]
905
                                    [% IF loop.first %]<a name="patron-attr-start-[% pa.type.code %]"></a>[% END %]
906
                                    [% form_id = 'patron-attr-' _ Math.int( Math.rand(1000000) ) %]
907
                                    <li data-category_code="[% pa.type.category_code %]">
908
                                        <label for="[% form_id %]">[% pa.type.description %]: </label>
909
                                        [% IF pa.type.opac_editable %]
910
                                            <input type="hidden" name="patron_attribute_code" value="[% pa.type.code |html %]" />
911
                                            [% IF ( pa.type.authorised_value_category ) %]
912
                                                <select id="[% form_id %]" name="patron_attribute_value">
913
                                                    <option value=""></option>
914
                                                    [% FOREACH auth_val IN AuthorisedValues.Get( pa.type.authorised_value_category, pa_value.value || '', 1 ) %]
915
                                                        [% IF ( auth_val.selected ) %]
916
                                                            <option value="[% auth_val.authorised_value %]" selected="selected">
917
                                                                [%# Yes, lib; GetAuthorisedValues takes care of intelligently setting this from lib_opac %]
918
                                                                [% auth_val.lib %]
919
                                                            </option>
920
                                                        [% ELSE %]
921
                                                            <option value="[% auth_val.authorised_value %]" >
922
                                                                [% auth_val.lib %]
923
                                                            </option>
924
                                                        [% END %]
925
                                                    [% END %]
926
                                                </select>
927
                                            [% ELSE %]
928
                                                <textarea rows="2" cols="30" id="[% form_id %]" name="patron_attribute_value">[% pa_value.value %]</textarea>
929
                                            [% END %]
930
                                            <a href="#" class="clear-attribute">Clear</a>
931
                                            [% IF ( pa.type.repeatable ) %]
932
                                            <a href="#" class="clone-attribute">New</a>
933
                                            [% END %]
934
                                            [% IF ( pa.type.password_allowed ) %]
935
                                                </li><li><label for="[% form_id %]_password">Password:</label>
936
                                                <input type="password" maxlength="64" value="[% pa_value.password %]" id="[% form_id %]_password" name="patron_attribute_password" />
937
                                            [% ELSE %]
938
                                                [%# To keep the form inputs lined up in the POST %]
939
                                                <input type="hidden" name="patron_attribute_password" value="" />
940
                                            [% END %]
941
                                        [% ELSE %]
942
                                            [% IF ( pa.type.authorised_value_category ) %]
943
                                                [% AuthorisedValues.GetByCode( pa.type.authorised_value, pa_value.value, 1 ) %]
944
                                            [% ELSE %]
945
                                                [% pa_value.value | html_line_break %]
946
                                            [% END %]
947
                                            [% IF ( pa_value.password ) %]
948
                                                (Password: *******)
949
                                            [% END %]
950
                                        [% END %]
951
                                    </li>
952
                                [% END %]
953
                            [% END %]
954
                        </ol>
955
                        </fieldset>
956
                    [% END %]
957
                [% END %]
958
959
                [% UNLESS action == 'edit' %]
889
                    <fieldset class="rows" id="memberentry_captcha">
960
                    <fieldset class="rows" id="memberentry_captcha">
890
                        <ol>
961
                        <ol>
891
962
Lines 901-924 Link Here
901
                    </fieldset>
972
                    </fieldset>
902
                [% END %]
973
                [% END %]
903
974
904
                [% IF ( borrower.ExtendedPatronAttributes ) %]
905
                    <fieldset class="rows">
906
                        <legend>Additional information</legend>
907
                        <ol>
908
                            [% FOREACH patron_attribute IN borrower.patron_attributes %]
909
                                <li>
910
                                    <label>[% patron_attribute.description %]:</label>
911
                                    [% IF ( patron_attribute.value_description ) %]
912
                                        [% patron_attribute.value_description %]
913
                                    [% ELSE %]
914
                                        [% patron_attribute.value |html_line_break %]
915
                                    [% END %]
916
                                </li>
917
                            [% END %]
918
                        </ol>
919
                    </fieldset>
920
                [% END %]
921
922
                [% IF action == 'edit' %]
975
                [% IF action == 'edit' %]
923
                    [% IF OPACPatronDetails %]
976
                    [% IF OPACPatronDetails %]
924
                        <fieldset class="action">
977
                        <fieldset class="action">
Lines 1006-1011 Link Here
1006
                     });
1059
                     });
1007
                });
1060
                });
1008
            [% END %]
1061
            [% END %]
1062
1063
            $(".patron-attributes").on( 'click', '.clear-attribute', function() {
1064
                $(this).parent()
1065
                    .find('textarea').attr('value', '').end()
1066
                    .find('select').attr('value', '').end();
1067
1068
                return false;
1069
            } );
1070
1071
            $(".patron-attributes").on( 'click', '.clone-attribute', function() {
1072
                var clone = $(this).parent().clone().insertAfter( $(this).parent() );
1073
1074
                var newId = 50 + parseInt(Math.random() * 100000);
1075
                $('input[type!="hidden"],select,textarea', clone).attr('id', 'patron-attr-' + newId).attr('value', '');
1076
                $("label", clone).attr('for', 'patron-attr-' + newId).attr('value', '');
1077
1078
                return false;
1079
            } );
1009
        });
1080
        });
1010
1081
1011
    $(".cleardate").on("click", function(){
1082
    $(".cleardate").on("click", function(){
(-)a/opac/opac-memberentry.pl (-10 / +111 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use CGI qw ( -utf8 );
20
use CGI qw ( -utf8 );
21
use Digest::MD5 qw( md5_base64 md5_hex );
21
use Digest::MD5 qw( md5_base64 md5_hex );
22
use Encode qw( encode );
22
use Encode qw( encode );
23
use List::MoreUtils qw( each_array uniq );
23
use String::Random qw( random_string );
24
use String::Random qw( random_string );
24
25
25
use C4::Auth;
26
use C4::Auth;
Lines 86-91 $template->param( Link Here
86
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
87
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
87
);
88
);
88
89
90
my $attributes = ParsePatronAttributes($cgi);
91
my $conflicting_attribute = 0;
92
93
foreach my $attr (@$attributes) {
94
    unless ( C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber) ) {
95
        my $attr_info = C4::Members::AttributeTypes->fetch($attr->{code});
96
        $template->param(
97
            extended_unique_id_failed_code => $attr->{code},
98
            extended_unique_id_failed_value => $attr->{value},
99
            extended_unique_id_failed_description => $attr_info->description()
100
        );
101
        $conflicting_attribute = 1;
102
    }
103
}
104
89
if ( $action eq 'create' ) {
105
if ( $action eq 'create' ) {
90
106
91
    my %borrower = ParseCgiForBorrower($cgi);
107
    my %borrower = ParseCgiForBorrower($cgi);
Lines 102-108 if ( $action eq 'create' ) { Link Here
102
        $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
118
        $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
103
    }
119
    }
104
120
105
    if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code ) {
121
    if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code || $conflicting_attribute ) {
106
        if ( $cardnumber_error_code == 1 ) {
122
        if ( $cardnumber_error_code == 1 ) {
107
            $template->param( cardnumber_already_exists => 1 );
123
            $template->param( cardnumber_already_exists => 1 );
108
        } elsif ( $cardnumber_error_code == 2 ) {
124
        } elsif ( $cardnumber_error_code == 2 ) {
Lines 114-119 if ( $action eq 'create' ) { Link Here
114
            invalid_form_fields    => $invalidformfields,
130
            invalid_form_fields    => $invalidformfields,
115
            borrower               => \%borrower
131
            borrower               => \%borrower
116
        );
132
        );
133
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
117
    }
134
    }
118
    elsif (
135
    elsif (
119
        md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') )
136
        md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') )
Lines 122-127 if ( $action eq 'create' ) { Link Here
122
            failed_captcha => 1,
139
            failed_captcha => 1,
123
            borrower       => \%borrower
140
            borrower       => \%borrower
124
        );
141
        );
142
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
125
    }
143
    }
126
    else {
144
    else {
127
        if (
145
        if (
Lines 182-187 if ( $action eq 'create' ) { Link Here
182
                  C4::Context->preference('OpacPasswordChange') );
200
                  C4::Context->preference('OpacPasswordChange') );
183
201
184
            my ( $borrowernumber, $password ) = AddMember_Opac(%borrower);
202
            my ( $borrowernumber, $password ) = AddMember_Opac(%borrower);
203
            C4::Members::Attributes::SetBorrowerAttributes( $borrowernumber, $attributes );
185
            C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences');
204
            C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences');
186
205
187
            $template->param( password_cleartext => $password );
206
            $template->param( password_cleartext => $password );
Lines 225-230 elsif ( $action eq 'update' ) { Link Here
225
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
244
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
226
            }),
245
            }),
227
        );
246
        );
247
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
228
248
229
        $template->param( action => 'edit' );
249
        $template->param( action => 'edit' );
230
    }
250
    }
Lines 272-285 elsif ( $action eq 'update' ) { Link Here
272
elsif ( $action eq 'edit' ) {    #Display logged in borrower's data
292
elsif ( $action eq 'edit' ) {    #Display logged in borrower's data
273
    my $borrower = GetMember( borrowernumber => $borrowernumber );
293
    my $borrower = GetMember( borrowernumber => $borrowernumber );
274
294
275
    if (C4::Context->preference('ExtendedPatronAttributes')) {
276
        my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac');
277
        if (scalar(@$attributes) > 0) {
278
            $borrower->{ExtendedPatronAttributes} = 1;
279
            $borrower->{patron_attributes} = $attributes;
280
        }
281
    }
282
283
    $template->param(
295
    $template->param(
284
        borrower  => $borrower,
296
        borrower  => $borrower,
285
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
297
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
Lines 295-300 elsif ( $action eq 'edit' ) { #Display logged in borrower's data Link Here
295
        $template->param( display_patron_image => 1 ) if $patron_image;
307
        $template->param( display_patron_image => 1 ) if $patron_image;
296
    }
308
    }
297
309
310
    $template->param( patron_attribute_classes => GeneratePatronAttributesForm( $borrower ) );
311
} else {
312
    $template->param( patron_attribute_classes => GeneratePatronAttributesForm() );
298
}
313
}
299
314
300
my $captcha = random_string("CCCCC");
315
my $captcha = random_string("CCCCC");
Lines 448-450 sub DelEmptyFields { Link Here
448
463
449
    return %borrower;
464
    return %borrower;
450
}
465
}
451
- 
466
467
sub GeneratePatronAttributesForm {
468
    my ( $borrower, $entered_attributes ) = @_;
469
470
    # Get all attribute types and the values for this patron (if applicable)
471
    my @types = C4::Members::AttributeTypes::GetAttributeTypes();
472
473
    if (scalar(@types) == 0) {
474
        return [];
475
    }
476
477
    my %attr_values = ();
478
479
    if ( $borrower ) {
480
        my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber);
481
482
        # Remap the patron's attributes into a hash of arrayrefs per attribute (depends on
483
        # autovivification)
484
        foreach my $attr (@$attributes) {
485
            push @{ $attr_values{ $attr->{code} } }, $attr;
486
        }
487
    }
488
489
    if ( $entered_attributes ) {
490
        foreach my $attr (@$entered_attributes) {
491
            push @{ $attr_values{ $attr->{code} } }, $attr;
492
        }
493
    }
494
495
    # Find all existing classes
496
    my @classes = uniq( map { $_->{class} } @types );
497
    @classes = sort @classes;
498
    my %items_by_class;
499
500
    foreach my $attr_type_desc (@types) {
501
        my $attr_type = C4::Members::AttributeTypes->fetch( $attr_type_desc->{code} );
502
        # Make sure this attribute should be displayed in the OPAC
503
        next unless ( $attr_type->opac_display() );
504
        # Then, make sure it either has values or is editable
505
        next unless ( $attr_values{ $attr_type->code() } || $attr_type->opac_editable() );
506
507
        push @{ $items_by_class{ $attr_type->class() } }, {
508
            type => $attr_type,
509
            # If editable, make sure there's at least one empty entry, to make the template's job easier
510
            values => $attr_values{ $attr_type->code() } || [{}]
511
        };
512
    }
513
514
    # Finally, build a list of containing classes
515
    my @class_loop;
516
    foreach my $class (@classes) {
517
        next unless ( $items_by_class{$class} );
518
519
        my $av = Koha::AuthorisedValues->search({ category => 'PA_CLASS', authorised_value => $class });
520
        my $lib = $av->count ? $av->next->opac_description : $class;
521
522
        push @class_loop, {
523
            class => $class,
524
            items => $items_by_class{$class},
525
            lib   => $lib,
526
        };
527
    }
528
529
    return \@class_loop;
530
}
531
532
sub ParsePatronAttributes {
533
    my ( $cgi ) = @_;
534
535
    my @codes = $cgi->param('patron_attribute_code');
536
    my @values = $cgi->param('patron_attribute_value');
537
    my @passwords = $cgi->param('patron_attribute_password');
538
539
    my $ea = each_array( @codes, @values, @passwords );
540
    my @attributes;
541
    my %dups = ();
542
543
    while ( my ( $code, $value, $password ) = $ea->() ) {
544
        next unless defined($value) and $value ne '';
545
        next if exists $dups{$code}->{$value};
546
        $dups{$code}->{$value} = 1;
547
548
        push @attributes, { code => $code, value => $value, password => $password };
549
    }
550
551
    return \@attributes;
552
}

Return to bug 13757