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 ) %]
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
                                            [% IF ( pa.type.password_allowed ) %]
931
                                                (<label class="lradio" for="[% form_id %]_password">Password:</label>
932
                                                <input type="password" maxlength="64" value="[% pa_value.password %]" id="[% form_id %]_password" name="patron_attribute_password" />)
933
                                            [% ELSE %]
934
                                                [%# To keep the form inputs lined up in the POST %]
935
                                                <input type="hidden" name="patron_attribute_password" value="" />
936
                                            [% END %]
937
                                            <a href="#" class="clear-attribute">Clear</a>
938
                                            [% IF ( pa.type.repeatable ) %]
939
                                            <a href="#" class="clone-attribute">New</a>
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 / +114 lines)
Lines 19-27 use Modern::Perl; Link Here
19
19
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 List::MoreUtils qw( each_array uniq );
22
use String::Random qw( random_string );
23
use String::Random qw( random_string );
23
24
24
use C4::Auth;
25
use C4::Auth;
26
use C4::Koha qw( GetAuthorisedValueByCode );
25
use C4::Output;
27
use C4::Output;
26
use C4::Members;
28
use C4::Members;
27
use C4::Form::MessagingPreferences;
29
use C4::Form::MessagingPreferences;
Lines 85-90 $template->param( Link Here
85
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
87
    OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
86
);
88
);
87
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
88
if ( $action eq 'create' ) {
105
if ( $action eq 'create' ) {
89
106
90
    my %borrower = ParseCgiForBorrower($cgi);
107
    my %borrower = ParseCgiForBorrower($cgi);
Lines 101-107 if ( $action eq 'create' ) { Link Here
101
        $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
118
        $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
102
    }
119
    }
103
120
104
    if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code ) {
121
    if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code || $conflicting_attribute ) {
105
        if ( $cardnumber_error_code == 1 ) {
122
        if ( $cardnumber_error_code == 1 ) {
106
            $template->param( cardnumber_already_exists => 1 );
123
            $template->param( cardnumber_already_exists => 1 );
107
        } elsif ( $cardnumber_error_code == 2 ) {
124
        } elsif ( $cardnumber_error_code == 2 ) {
Lines 113-118 if ( $action eq 'create' ) { Link Here
113
            invalid_form_fields    => $invalidformfields,
130
            invalid_form_fields    => $invalidformfields,
114
            borrower               => \%borrower
131
            borrower               => \%borrower
115
        );
132
        );
133
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
116
    }
134
    }
117
    elsif (
135
    elsif (
118
        md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') )
136
        md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') )
Lines 121-126 if ( $action eq 'create' ) { Link Here
121
            failed_captcha => 1,
139
            failed_captcha => 1,
122
            borrower       => \%borrower
140
            borrower       => \%borrower
123
        );
141
        );
142
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
124
    }
143
    }
125
    else {
144
    else {
126
        if (
145
        if (
Lines 178-183 if ( $action eq 'create' ) { Link Here
178
                  C4::Context->preference('OpacPasswordChange') );
197
                  C4::Context->preference('OpacPasswordChange') );
179
198
180
            my ( $borrowernumber, $password ) = AddMember_Opac(%borrower);
199
            my ( $borrowernumber, $password ) = AddMember_Opac(%borrower);
200
            C4::Members::Attributes::SetBorrowerAttributes( $borrowernumber, $attributes );
181
            C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences');
201
            C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences');
182
202
183
            $template->param( password_cleartext => $password );
203
            $template->param( password_cleartext => $password );
Lines 221-226 elsif ( $action eq 'update' ) { Link Here
221
                secret => md5_base64( C4::Context->config('pass') ),
241
                secret => md5_base64( C4::Context->config('pass') ),
222
            }),
242
            }),
223
        );
243
        );
244
        $template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) );
224
245
225
        $template->param( action => 'edit' );
246
        $template->param( action => 'edit' );
226
    }
247
    }
Lines 268-281 elsif ( $action eq 'update' ) { Link Here
268
elsif ( $action eq 'edit' ) {    #Display logged in borrower's data
289
elsif ( $action eq 'edit' ) {    #Display logged in borrower's data
269
    my $borrower = GetMember( borrowernumber => $borrowernumber );
290
    my $borrower = GetMember( borrowernumber => $borrowernumber );
270
291
271
    if (C4::Context->preference('ExtendedPatronAttributes')) {
272
        my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac');
273
        if (scalar(@$attributes) > 0) {
274
            $borrower->{ExtendedPatronAttributes} = 1;
275
            $borrower->{patron_attributes} = $attributes;
276
        }
277
    }
278
279
    $template->param(
292
    $template->param(
280
        borrower  => $borrower,
293
        borrower  => $borrower,
281
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
294
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
Lines 291-296 elsif ( $action eq 'edit' ) { #Display logged in borrower's data Link Here
291
        $template->param( display_patron_image => 1 ) if $patron_image;
304
        $template->param( display_patron_image => 1 ) if $patron_image;
292
    }
305
    }
293
306
307
    $template->param( patron_attribute_classes => GeneratePatronAttributesForm( $borrower ) );
308
} else {
309
    $template->param( patron_attribute_classes => GeneratePatronAttributesForm() );
294
}
310
}
295
311
296
my $captcha = random_string("CCCCC");
312
my $captcha = random_string("CCCCC");
Lines 444-446 sub DelEmptyFields { Link Here
444
460
445
    return %borrower;
461
    return %borrower;
446
}
462
}
447
- 
463
464
sub GeneratePatronAttributesForm {
465
    my ( $borrower, $entered_attributes ) = @_;
466
467
    use Data::Dumper; warn Dumper( $entered_attributes );
468
469
    # Get all attribute types and the values for this patron (if applicable)
470
    my @types = C4::Members::AttributeTypes::GetAttributeTypes();
471
472
    if (scalar(@types) == 0) {
473
        return [];
474
    }
475
476
    my %attr_values = ();
477
478
    if ( $borrower ) {
479
        my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber);
480
481
        # Remap the patron's attributes into a hash of arrayrefs per attribute (depends on
482
        # autovivification)
483
        foreach my $attr (@$attributes) {
484
            push @{ $attr_values{ $attr->{code} } }, $attr;
485
        }
486
    }
487
488
    if ( $entered_attributes ) {
489
        foreach my $attr (@$entered_attributes) {
490
            push @{ $attr_values{ $attr->{code} } }, $attr;
491
        }
492
    }
493
494
    # Find all existing classes
495
    my @classes = uniq( map { $_->{class} } @types );
496
    @classes = sort @classes;
497
    my %items_by_class;
498
499
    foreach my $attr_type_desc (@types) {
500
        my $attr_type = C4::Members::AttributeTypes->fetch( $attr_type_desc->{code} );
501
        # Make sure this attribute should be displayed in the OPAC
502
        next unless ( $attr_type->opac_display() );
503
        # Then, make sure it either has values or is editable
504
        next unless ( $attr_values{ $attr_type->code() } || $attr_type->opac_editable() );
505
506
        push @{ $items_by_class{ $attr_type->class() } }, {
507
            type => $attr_type,
508
            # If editable, make sure there's at least one empty entry, to make the template's job easier
509
            values => $attr_values{ $attr_type->code() } || [{}]
510
        };
511
    }
512
513
    use Data::Dumper; warn Dumper( \%items_by_class );
514
515
    # Finally, build a list of containing classes
516
    my @class_loop;
517
    foreach my $class (@classes) {
518
        next unless ( $items_by_class{$class} );
519
520
        my $lib = GetAuthorisedValueByCode( 'PA_CLASS', $class, 1 ) || $class;
521
        push @class_loop, {
522
            class => $class,
523
            items => $items_by_class{$class},
524
            lib   => $lib,
525
        };
526
    }
527
528
    return \@class_loop;
529
}
530
531
sub ParsePatronAttributes {
532
    my ( $cgi ) = @_;
533
534
    my @codes = $cgi->param('patron_attribute_code');
535
    my @values = $cgi->param('patron_attribute_value');
536
    my @passwords = $cgi->param('patron_attribute_password');
537
538
    my $ea = each_array( @codes, @values, @passwords );
539
    my @attributes;
540
    my %dups = ();
541
542
    while ( my ( $code, $value, $password ) = $ea->() ) {
543
        next unless defined($value) and $value ne '';
544
        next if exists $dups{$code}->{$value};
545
        $dups{$code}->{$value} = 1;
546
547
        push @attributes, { code => $code, value => $value, password => $password };
548
    }
549
550
    return \@attributes;
551
}

Return to bug 13757