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

(-)a/C4/Members.pm (-62 lines)
Lines 48-56 BEGIN { Link Here
48
48
49
      IssueSlip
49
      IssueSlip
50
50
51
      get_cardnumber_length
52
      checkcardnumber
53
54
      DeleteUnverifiedOpacRegistrations
51
      DeleteUnverifiedOpacRegistrations
55
      DeleteExpiredOpacRegistrations
52
      DeleteExpiredOpacRegistrations
56
    );
53
    );
Lines 287-351 sub GetAllIssues { Link Here
287
    return $sth->fetchall_arrayref( {} );
284
    return $sth->fetchall_arrayref( {} );
288
}
285
}
289
286
290
sub checkcardnumber {
291
    my ( $cardnumber, $borrowernumber ) = @_;
292
293
    # If cardnumber is null, we assume they're allowed.
294
    return 0 unless defined $cardnumber;
295
296
    my $dbh = C4::Context->dbh;
297
    my $query = "SELECT * FROM borrowers WHERE cardnumber=?";
298
    $query .= " AND borrowernumber <> ?" if ($borrowernumber);
299
    my $sth = $dbh->prepare($query);
300
    $sth->execute(
301
        $cardnumber,
302
        ( $borrowernumber ? $borrowernumber : () )
303
    );
304
305
    return 1 if $sth->fetchrow_hashref;
306
307
    my ( $min_length, $max_length ) = get_cardnumber_length();
308
    return 2
309
        if length $cardnumber > $max_length
310
        or length $cardnumber < $min_length;
311
312
    return 0;
313
}
314
315
=head2 get_cardnumber_length
316
317
    my ($min, $max) = C4::Members::get_cardnumber_length()
318
319
Returns the minimum and maximum length for patron cardnumbers as
320
determined by the CardnumberLength system preference, the
321
BorrowerMandatoryField system preference, and the width of the
322
database column.
323
324
=cut
325
326
sub get_cardnumber_length {
327
    my $borrower = Koha::Database->new->schema->resultset('Borrower');
328
    my $field_size = $borrower->result_source->column_info('cardnumber')->{size};
329
    my ( $min, $max ) = ( 0, $field_size ); # borrowers.cardnumber is a nullable varchar(20)
330
    $min = 1 if C4::Context->preference('BorrowerMandatoryField') =~ /cardnumber/;
331
    if ( my $cardnumber_length = C4::Context->preference('CardnumberLength') ) {
332
        # Is integer and length match
333
        if ( $cardnumber_length =~ m|^\d+$| ) {
334
            $min = $max = $cardnumber_length
335
                if $cardnumber_length >= $min
336
                    and $cardnumber_length <= $max;
337
        }
338
        # Else assuming it is a range
339
        elsif ( $cardnumber_length =~ m|(\d*),(\d*)| ) {
340
            $min = $1 if $1 and $min < $1;
341
            $max = $2 if $2 and $max > $2;
342
        }
343
344
    }
345
    $min = $max if $min > $max;
346
    return ( $min, $max );
347
}
348
349
=head2 GetBorrowersToExpunge
287
=head2 GetBorrowersToExpunge
350
288
351
  $borrowers = &GetBorrowersToExpunge(
289
  $borrowers = &GetBorrowersToExpunge(
(-)a/Koha/Patrons/Import.pm (-2 / +3 lines)
Lines 23-35 use Text::CSV; Link Here
23
use Encode qw( decode_utf8 );
23
use Encode qw( decode_utf8 );
24
use Try::Tiny qw( catch try );
24
use Try::Tiny qw( catch try );
25
25
26
use C4::Members qw( checkcardnumber );
27
use C4::Letters qw( GetPreparedLetter EnqueueLetter );
26
use C4::Letters qw( GetPreparedLetter EnqueueLetter );
28
27
29
use Koha::Libraries;
28
use Koha::Libraries;
30
use Koha::Patrons;
29
use Koha::Patrons;
31
use Koha::Patron::Categories;
30
use Koha::Patron::Categories;
32
use Koha::Patron::Debarments qw( AddDebarment );
31
use Koha::Patron::Debarments qw( AddDebarment );
32
use Koha::Policy::Patrons::Cardnumber;
33
use Koha::DateUtils qw( dt_from_string output_pref );
33
use Koha::DateUtils qw( dt_from_string output_pref );
34
34
35
=head1 NAME
35
=head1 NAME
Lines 212-218 sub import_patrons { Link Here
212
            $is_new = 1;
212
            $is_new = 1;
213
        }
213
        }
214
214
215
        if ( C4::Members::checkcardnumber( $borrower{cardnumber}, $borrowernumber ) ) {
215
        my $is_valid = Koha::Policy::Patrons::Cardnumber->is_valid($borrower{cardnumber}, $patron);
216
        unless ( $is_valid ) {
216
            push @errors,
217
            push @errors,
217
              {
218
              {
218
                invalid_cardnumber => 1,
219
                invalid_cardnumber => 1,
(-)a/Koha/Policy/Patrons/Cardnumber.pm (+110 lines)
Line 0 Link Here
1
package Koha::Policy::Patrons::Cardnumber;
2
3
# Copyright 2023 Koha Development team
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
24
use Koha::Patrons;
25
use Koha::Result::Boolean;
26
27
=head1 NAME
28
29
Koha::Policy::Patrons::Cardnumber - module to deal with cardnumbers policy
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=head3 new
36
37
=cut
38
39
sub new {
40
    return bless {}, shift;
41
}
42
43
=head3 is_valid
44
45
    my $is_valid = Koha::Policy::Patrons::Cardnumber->is_valid( $cardnumber, [$patron] );
46
47
Returns whether a cardnumber is valid of not for a given I<Koha::Patron> object.
48
49
=cut
50
51
sub is_valid {
52
    my ( $class, $cardnumber, $patron ) = @_;
53
54
    return Koha::Result::Boolean->new(0)->add_message( { message => "is_empty" } )
55
        unless defined $cardnumber;
56
57
    return Koha::Result::Boolean->new(0)->add_message( { message => "already_exists" } )
58
        if Koha::Patrons->search(
59
        {
60
            cardnumber => $cardnumber,
61
            ( $patron ? ( borrowernumber => { '!=' => $patron->borrowernumber } ) : () )
62
        }
63
    )->count;
64
65
    my ( $min_length, $max_length ) = $class->get_valid_length();
66
    return Koha::Result::Boolean->new(0)->add_message( { message => "invalid_length" } )
67
        if length $cardnumber > $max_length
68
        or length $cardnumber < $min_length;
69
70
    return Koha::Result::Boolean->new(1);
71
}
72
73
=head2 get_valid_length
74
75
    my ($min, $max) = Koha::Policy::Patrons::Cardnumber::get_valid_length();
76
77
Returns the minimum and maximum length for patron cardnumbers as
78
determined by the CardnumberLength system preference, the
79
BorrowerMandatoryField system preference, and the width of the
80
database column.
81
82
=cut
83
84
sub get_valid_length {
85
    my ($class)    = @_;
86
    my $borrower   = Koha::Database->new->schema->resultset('Borrower');
87
    my $field_size = $borrower->result_source->column_info('cardnumber')->{size};
88
    my ( $min, $max ) = ( 0, $field_size );    # borrowers.cardnumber is a nullable varchar(20)
89
    $min = 1 if C4::Context->preference('BorrowerMandatoryField') =~ /cardnumber/;
90
    if ( my $cardnumber_length = C4::Context->preference('CardnumberLength') ) {
91
92
        # Is integer and length match
93
        if ( $cardnumber_length =~ m|^\d+$| ) {
94
            $min = $max = $cardnumber_length
95
                if $cardnumber_length >= $min
96
                and $cardnumber_length <= $max;
97
        }
98
99
        # Else assuming it is a range
100
        elsif ( $cardnumber_length =~ m|(\d*),(\d*)| ) {
101
            $min = $1 if $1 and $min < $1;
102
            $max = $2 if $2 and $max > $2;
103
        }
104
105
    }
106
    $min = $max if $min > $max;
107
    return ( $min, $max );
108
}
109
110
1;
(-)a/installer/onboarding.pl (-7 / +11 lines)
Lines 22-33 use C4::Context; Link Here
22
use C4::InstallAuth qw( checkauth get_template_and_user );
22
use C4::InstallAuth qw( checkauth get_template_and_user );
23
use CGI qw ( -utf8 );
23
use CGI qw ( -utf8 );
24
use C4::Output qw( output_html_with_http_headers );
24
use C4::Output qw( output_html_with_http_headers );
25
use C4::Members qw( checkcardnumber );
26
use Koha::Patrons;
25
use Koha::Patrons;
27
use Koha::Libraries;
26
use Koha::Libraries;
28
use Koha::Database;
27
use Koha::Database;
29
use Koha::Patrons;
28
use Koha::Patrons;
30
use Koha::Patron::Categories;
29
use Koha::Patron::Categories;
30
use Koha::Policy::Patrons::Cardnumber;
31
use Koha::ItemTypes;
31
use Koha::ItemTypes;
32
use Koha::CirculationRules;
32
use Koha::CirculationRules;
33
33
Lines 141-152 if ( $step == 3 ) { Link Here
141
            $patron_category );
141
            $patron_category );
142
142
143
143
144
        if ( my $error_code = checkcardnumber($cardnumber) ) {
144
        my $is_cardnumber_valid = Koha::Policy::Patrons::Cardnumber->is_valid($cardnumber);
145
            if ( $error_code == 1 ) {
145
        unless ( $is_cardnumber_valid ) {
146
                push @messages, { code => 'ERROR_cardnumber_already_exists' };
146
            for my $m ( @{ $is_cardnumber_valid->messages } ) {
147
            }
147
                my $message = $m->message;
148
            elsif ( $error_code == 2 ) {
148
                if ( $message eq 'already_exists' ) {
149
                push @messages, { code => 'ERROR_cardnumber_length' };
149
                    push @messages, { code => 'ERROR_cardnumber_already_exists' };
150
                }
151
                elsif ( $message eq 'invalid_length' ) {
152
                    push @messages, { code => 'ERROR_cardnumber_length' };
153
                }
150
            }
154
            }
151
        }
155
        }
152
        elsif ( $firstpassword ne $secondpassword ) {
156
        elsif ( $firstpassword ne $secondpassword ) {
(-)a/members/memberentry.pl (-8 / +12 lines)
Lines 29-35 use CGI qw ( -utf8 ); Link Here
29
use C4::Auth qw( get_template_and_user haspermission );
29
use C4::Auth qw( get_template_and_user haspermission );
30
use C4::Context;
30
use C4::Context;
31
use C4::Output qw( output_and_exit output_and_exit_if_error output_html_with_http_headers );
31
use C4::Output qw( output_and_exit output_and_exit_if_error output_html_with_http_headers );
32
use C4::Members qw( checkcardnumber get_cardnumber_length );
33
use C4::Koha qw( GetAuthorisedValues );
32
use C4::Koha qw( GetAuthorisedValues );
34
use C4::Letters qw( GetPreparedLetter EnqueueLetter SendQueuedMessages );
33
use C4::Letters qw( GetPreparedLetter EnqueueLetter SendQueuedMessages );
35
use C4::Form::MessagingPreferences;
34
use C4::Form::MessagingPreferences;
Lines 46-51 use Koha::Patron::Attribute::Types; Link Here
46
use Koha::Patron::Categories;
45
use Koha::Patron::Categories;
47
use Koha::Patron::HouseboundRole;
46
use Koha::Patron::HouseboundRole;
48
use Koha::Patron::HouseboundRoles;
47
use Koha::Patron::HouseboundRoles;
48
use Koha::Policy::Patrons::Cardnumber;
49
use Koha::Plugins;
49
use Koha::Plugins;
50
use Koha::Token;
50
use Koha::Token;
51
use Koha::SMS::Providers;
51
use Koha::SMS::Providers;
Lines 293-304 if ($op eq 'save' || $op eq 'insert'){ Link Here
293
293
294
    $newdata{'cardnumber'} = $new_barcode;
294
    $newdata{'cardnumber'} = $new_barcode;
295
295
296
    if (my $error_code = checkcardnumber( $newdata{cardnumber}, $borrowernumber )){
296
    my $is_valid = Koha::Policy::Patrons::Cardnumber->is_valid($newdata{cardnumber}, $patron );
297
        push @errors, $error_code == 1
297
    unless ($is_valid) {
298
            ? 'ERROR_cardnumber_already_exists'
298
        for my $m ( @{ $is_valid->messages } ) {
299
            : $error_code == 2
299
            my $message = $m->message;
300
                ? 'ERROR_cardnumber_length'
300
            if ( $message eq 'already_exists' ) {
301
                : ()
301
                $template->param( ERROR_cardnumber_already_exists => 1 );
302
            } elsif ( $message eq 'invalid_length' ) {
303
                $template->param( ERROR_cardnumber_length => 1 );
304
            }
305
        }
302
    }
306
    }
303
307
304
    my $dateofbirth;
308
    my $dateofbirth;
Lines 786-792 if(defined($data{'contacttitle'})){ Link Here
786
}
790
}
787
791
788
792
789
my ( $min, $max ) = C4::Members::get_cardnumber_length();
793
my ( $min, $max ) = Koha::Policy::Patrons::Cardnumber->get_valid_length();
790
if ( defined $min ) {
794
if ( defined $min ) {
791
    $template->param(
795
    $template->param(
792
        minlength_cardnumber => $min,
796
        minlength_cardnumber => $min,
(-)a/opac/opac-memberentry.pl (-10 / +16 lines)
Lines 28-34 use C4::Auth qw( get_template_and_user ); Link Here
28
use C4::Output qw( output_html_with_http_headers );
28
use C4::Output qw( output_html_with_http_headers );
29
use C4::Context;
29
use C4::Context;
30
use C4::Letters qw( GetPreparedLetter EnqueueLetter SendQueuedMessages );
30
use C4::Letters qw( GetPreparedLetter EnqueueLetter SendQueuedMessages );
31
use C4::Members qw( checkcardnumber );
32
use C4::Form::MessagingPreferences;
31
use C4::Form::MessagingPreferences;
33
use Koha::AuthUtils;
32
use Koha::AuthUtils;
34
use Koha::Patrons;
33
use Koha::Patrons;
Lines 43-48 use Koha::Patron::Attribute::Types; Link Here
43
use Koha::Patron::Attributes;
42
use Koha::Patron::Attributes;
44
use Koha::Patron::Images;
43
use Koha::Patron::Images;
45
use Koha::Patron::Categories;
44
use Koha::Patron::Categories;
45
use Koha::Policy::Patrons::Cardnumber;
46
use Koha::Token;
46
use Koha::Token;
47
use Koha::AuthorisedValues;
47
use Koha::AuthorisedValues;
48
my $cgi = CGI->new;
48
my $cgi = CGI->new;
Lines 88-94 if ( $action eq 'create' || $action eq 'new' ) { Link Here
88
}
88
}
89
my $libraries = Koha::Libraries->search($params);
89
my $libraries = Koha::Libraries->search($params);
90
90
91
my ( $min, $max ) = C4::Members::get_cardnumber_length();
91
my ( $min, $max ) = Koha::Policy::Patrons::Cardnumber->get_valid_length();
92
if ( defined $min ) {
92
if ( defined $min ) {
93
     $template->param(
93
     $template->param(
94
         minlength_cardnumber => $min,
94
         minlength_cardnumber => $min,
Lines 133-151 if ( $action eq 'create' ) { Link Here
133
    my @empty_mandatory_fields = (CheckMandatoryFields( \%borrower, $action ), CheckMandatoryAttributes( \%borrower, $attributes ) );
133
    my @empty_mandatory_fields = (CheckMandatoryFields( \%borrower, $action ), CheckMandatoryAttributes( \%borrower, $attributes ) );
134
    my $invalidformfields = CheckForInvalidFields(\%borrower);
134
    my $invalidformfields = CheckForInvalidFields(\%borrower);
135
    delete $borrower{'password2'};
135
    delete $borrower{'password2'};
136
    my $cardnumber_error_code;
136
    my $is_cardnumber_valid;
137
    if ( !grep { $_ eq 'cardnumber' } @empty_mandatory_fields ) {
137
    if ( !grep { $_ eq 'cardnumber' } @empty_mandatory_fields ) {
138
        # No point in checking the cardnumber if it's missing and mandatory, it'll just generate a
138
        # No point in checking the cardnumber if it's missing and mandatory, it'll just generate a
139
        # spurious length warning.
139
        # spurious length warning.
140
        $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
140
        my $patron = Koha::Patrons->find($borrower{borrowernumber});
141
        $is_cardnumber_valid = Koha::Policy::Patrons::Cardnumber->is_valid($borrower{cardnumber}, $patron);
142
        unless ($is_cardnumber_valid) {
143
            for my $m ( @{ $is_cardnumber_valid->messages } ) {
144
                my $message = $m->message;
145
                if ( $message eq 'already_exists' ) {
146
                    $template->param( cardnumber_already_exists => 1 );
147
                } elsif ( $message eq 'invalid_length' ) {
148
                    $template->param( cardnumber_wrong_length => 1 );
149
                }
150
            }
151
        }
141
    }
152
    }
142
153
143
    if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code || $conflicting_attribute ) {
154
    if ( @empty_mandatory_fields || @$invalidformfields || !$is_cardnumber_valid || $conflicting_attribute ) {
144
        if ( $cardnumber_error_code == 1 ) {
145
            $template->param( cardnumber_already_exists => 1 );
146
        } elsif ( $cardnumber_error_code == 2 ) {
147
            $template->param( cardnumber_wrong_length => 1 );
148
        }
149
155
150
        $template->param(
156
        $template->param(
151
            empty_mandatory_fields => \@empty_mandatory_fields,
157
            empty_mandatory_fields => \@empty_mandatory_fields,
(-)a/t/Members/cardnumber.t (-96 lines)
Lines 1-96 Link Here
1
#!/usr/bin/env perl
2
3
use Modern::Perl;
4
use Module::Load::Conditional qw/check_install/;
5
use Test::More;
6
use Test::MockModule;
7
8
use t::lib::Mocks;
9
10
use_ok('C4::Members', qw( get_cardnumber_length checkcardnumber ));
11
12
BEGIN {
13
    if ( check_install( module => 'Test::DBIx::Class' ) ) {
14
        plan tests => 25;
15
    } else {
16
        plan skip_all => "Need Test::DBIx::Class"
17
    }
18
}
19
20
use Test::DBIx::Class;
21
22
my $db = Test::MockModule->new('Koha::Database');
23
$db->mock( _new_schema => sub { return Schema(); } );
24
25
my $dbh = C4::Context->dbh;
26
my $rs = [];
27
28
my $borrower = Koha::Schema->resultset('Borrower');
29
my $cardnumber_size = $borrower->result_source->column_info('cardnumber')->{size};
30
31
t::lib::Mocks::mock_preference('BorrowerMandatoryField', '');
32
my $pref = "10";
33
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
34
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 10, 10 ], '10 => min=10 and max=10');
35
$dbh->{mock_add_resultset} = $rs;
36
is( C4::Members::checkcardnumber( q{123456789} ), 2, "123456789 is shorter than $pref");
37
$dbh->{mock_add_resultset} = $rs;
38
is( C4::Members::checkcardnumber( q{1234567890123456} ), 2, "1234567890123456 is longer than $pref");
39
$dbh->{mock_add_resultset} = $rs;
40
is( C4::Members::checkcardnumber( q{1234567890} ), 0, "1234567890 is equal to $pref");
41
42
$pref = q|10,10|; # Same as before !
43
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
44
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 10, 10 ], '10,10 => min=10 and max=10');
45
$dbh->{mock_add_resultset} = $rs;
46
is( C4::Members::checkcardnumber( q{123456789} ), 2, "123456789 is shorter than $pref");
47
$dbh->{mock_add_resultset} = $rs;
48
is( C4::Members::checkcardnumber( q{1234567890123456} ), 2, "1234567890123456 is longer than $pref");
49
$dbh->{mock_add_resultset} = $rs;
50
is( C4::Members::checkcardnumber( q{1234567890} ), 0, "1234567890 is equal to $pref");
51
52
$pref = q|8,10|; # between 8 and 10 chars
53
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
54
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 8, 10 ], '8,10 => min=8 and max=10');
55
$dbh->{mock_add_resultset} = $rs;
56
is( C4::Members::checkcardnumber( q{12345678} ), 0, "12345678 matches $pref");
57
$dbh->{mock_add_resultset} = $rs;
58
is( C4::Members::checkcardnumber( q{1234567890123456} ), 2, "1234567890123456 is longer than $pref");
59
$dbh->{mock_add_resultset} = $rs;
60
is( C4::Members::checkcardnumber( q{1234567} ), 2, "1234567 is shorter than $pref");
61
$dbh->{mock_add_resultset} = $rs;
62
is( C4::Members::checkcardnumber( q{1234567890} ), 0, "1234567890 matches $pref");
63
64
$pref = q|8,|; # At least 8 chars
65
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
66
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 8, $cardnumber_size ], "8, => min=8 and max=$cardnumber_size");
67
$dbh->{mock_add_resultset} = $rs;
68
is( C4::Members::checkcardnumber( q{1234567} ), 2, "1234567 is shorter than $pref");
69
$dbh->{mock_add_resultset} = $rs;
70
is( C4::Members::checkcardnumber( q{1234567890123456} ), 0, "1234567890123456 matches $pref");
71
$dbh->{mock_add_resultset} = $rs;
72
is( C4::Members::checkcardnumber( q{1234567890} ), 0, "1234567890 matches $pref");
73
74
$pref = q|,8|; # max 8 chars
75
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
76
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 0, 8 ], ',8 => min=0 and max=8');
77
$dbh->{mock_add_resultset} = $rs;
78
is( C4::Members::checkcardnumber( q{1234567} ), 0, "1234567 matches $pref");
79
$dbh->{mock_add_resultset} = $rs;
80
is( C4::Members::checkcardnumber( q{1234567890123456} ), 2, "1234567890123456 is longer than $pref");
81
$dbh->{mock_add_resultset} = $rs;
82
is( C4::Members::checkcardnumber( q{1234567890} ), 2, "1234567890 is longer than $pref");
83
84
$pref = sprintf(',%d', $cardnumber_size+1);
85
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
86
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 0, $cardnumber_size ],
87
    sprintf(",%d => min=0 and max=%d",$cardnumber_size+1,$cardnumber_size) );
88
$dbh->{mock_add_resultset} = $rs;
89
90
my $generated_cardnumber = sprintf("%s1234567890",q|9|x$cardnumber_size);
91
is( C4::Members::checkcardnumber( $generated_cardnumber ), 2, "$generated_cardnumber is longer than $pref => $cardnumber_size is max!");
92
93
$pref = q|,8|; # max 8 chars
94
t::lib::Mocks::mock_preference('CardnumberLength', $pref);
95
t::lib::Mocks::mock_preference('BorrowerMandatoryField', 'cardnumber');
96
is_deeply( [ C4::Members::get_cardnumber_length() ], [ 1, 8 ], ',8 => min=1 and max=8 if cardnumber is mandatory');
(-)a/t/db_dependent/Koha/Policy/Patrons/Cardnumber.t (+160 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2023 Koha Development team
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 3;
23
24
use Koha::Database;
25
use Koha::Policy::Patrons::Cardnumber;
26
use t::lib::Mocks;
27
use t::lib::TestBuilder;
28
29
my $schema  = Koha::Database->new->schema;
30
my $builder = t::lib::TestBuilder->new;
31
32
subtest 'is_valid' => sub {
33
34
    plan tests => 21;
35
36
    $schema->storage->txn_begin;
37
38
    my $patron = $builder->build_object({ class => 'Koha::Patrons' });
39
40
    t::lib::Mocks::mock_preference( 'CardnumberLength', '' );
41
42
    my $policy = Koha::Policy::Patrons::Cardnumber->new;
43
44
    my $is_valid = $policy->is_valid( $patron->cardnumber );
45
    ok( !$is_valid, "Cardnumber in use, cannot be reused");
46
47
    $is_valid = $policy->is_valid( $patron->cardnumber, $patron );
48
    ok( $is_valid, "Cardnumber in use but can be used by the same patron");
49
50
    my $tmp_patron = $builder->build_object({ class => 'Koha::Patrons' });
51
    my $available_cardnumber = $tmp_patron->cardnumber;
52
    $tmp_patron->delete;
53
    $is_valid = $policy->is_valid( $available_cardnumber );
54
    ok( $is_valid, "Cardnumber not in use");
55
56
    t::lib::Mocks::mock_preference( 'CardnumberLength', '4' );
57
58
    $is_valid = $policy->is_valid( "12345" );
59
    ok( !$is_valid, "Invalid cardnumber length");
60
61
    $is_valid = $policy->is_valid( "123" );
62
    ok( !$is_valid, "Invalid cardnumber length");
63
64
    my $pref = "10";
65
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
66
    ok( !$policy->is_valid( q{123456789} ), "123456789 is shorter than $pref");
67
    ok( !$policy->is_valid( q{1234567890123456} ), "1234567890123456 is longer than $pref");
68
    ok( $policy->is_valid( q{1234567890} ), "1234567890 is equal to $pref");
69
70
    $pref = q|10,10|; # Same as before !
71
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
72
    ok( !$policy->is_valid( q{123456789} ), "123456789 is shorter than $pref");
73
    ok( !$policy->is_valid( q{1234567890123456} ), "1234567890123456 is longer than $pref");
74
    ok( $policy->is_valid( q{1234567890} ), "1234567890 is equal to $pref");
75
76
    $pref = q|8,10|; # between 8 and 10 chars
77
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
78
    ok( $policy->is_valid( q{12345678} ), "12345678 matches $pref");
79
    ok( !$policy->is_valid( q{1234567890123456} ), "1234567890123456 is longer than $pref");
80
    ok( !$policy->is_valid( q{1234567} ), "1234567 is shorter than $pref");
81
    ok( $policy->is_valid( q{1234567890} ), "1234567890 matches $pref");
82
83
    $pref = q|8,|; # At least 8 chars
84
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
85
    ok( !$policy->is_valid( q{1234567} ), "1234567 is shorter than $pref");
86
    ok( $policy->is_valid( q{1234567890123456} ), "1234567890123456 matches $pref");
87
    ok( $policy->is_valid( q{1234567890} ), "1234567890 matches $pref");
88
89
    $pref = q|,8|; # max 8 chars
90
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
91
    ok( $policy->is_valid( q{1234567} ), "1234567 matches $pref");
92
    ok( !$policy->is_valid( q{1234567890123456} ), "1234567890123456 is longer than $pref");
93
    ok( !$policy->is_valid( q{1234567890} ), "1234567890 is longer than $pref");
94
95
    $schema->storage->txn_rollback;
96
};
97
98
subtest 'get_valid_length' => sub {
99
100
    plan tests => 5;
101
102
    $schema->storage->txn_begin;
103
104
    my $policy = Koha::Policy::Patrons::Cardnumber->new;
105
106
    t::lib::Mocks::mock_preference('BorrowerMandatoryField', '');
107
108
    my $pref = "10";
109
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
110
    is_deeply( [ $policy->get_valid_length() ], [ 10, 10 ], '10 => min=10 and max=10' );
111
112
    $pref = q|10,10|;    # Same as before !
113
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
114
    is_deeply( [ $policy->get_valid_length() ], [ 10, 10 ], '10,10 => min=10 and max=10' );
115
116
    $pref = q|8,10|;     # between 8 and 10 chars
117
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
118
    is_deeply( [ $policy->get_valid_length() ], [ 8, 10 ], '8,10 => min=8 and max=10' );
119
120
    $pref = q|,8|;       # max 8 chars
121
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
122
    is_deeply( [ $policy->get_valid_length() ], [ 0, 8 ], ',8 => min=0 and max=8' );
123
124
    $pref = q|,8|; # max 8 chars
125
    t::lib::Mocks::mock_preference('CardnumberLength', $pref);
126
    t::lib::Mocks::mock_preference('BorrowerMandatoryField', 'cardnumber');
127
    is_deeply( [ $policy->get_valid_length() ], [ 1, 8 ], ',8 => min=1 and max=8 if cardnumber is mandatory');
128
129
    $schema->storage->txn_rollback;
130
131
};
132
133
subtest 'compare with DB data size' => sub {
134
135
    plan tests => 3;
136
137
    $schema->storage->txn_begin;
138
139
    my $policy = Koha::Policy::Patrons::Cardnumber->new;
140
    my $borrower        = Koha::Schema->resultset('Borrower');
141
    my $cardnumber_size = $borrower->result_source->column_info('cardnumber')->{size};
142
    t::lib::Mocks::mock_preference('BorrowerMandatoryField', '');
143
144
    my $pref = q|8,|;       # At least 8 chars
145
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
146
    is_deeply( [ $policy->get_valid_length() ], [ 8, $cardnumber_size ], "8, => min=8 and max=$cardnumber_size" );
147
148
    $pref = sprintf( ',%d', $cardnumber_size + 1 );
149
    t::lib::Mocks::mock_preference( 'CardnumberLength', $pref );
150
    is_deeply(
151
        [ $policy->get_valid_length() ], [ 0, $cardnumber_size ],
152
        sprintf( ",%d => min=0 and max=%d", $cardnumber_size + 1, $cardnumber_size )
153
    );
154
155
    my $generated_cardnumber = sprintf("%s1234567890",q|9|x$cardnumber_size);
156
    ok( !$policy->is_valid( $generated_cardnumber ), "$generated_cardnumber is longer than $pref => $cardnumber_size is max!");
157
158
    $schema->storage->txn_rollback;
159
160
};
(-)a/t/db_dependent/Members.t (-22 / +2 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 53;
20
use Test::More tests => 50;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Exception;
22
use Test::Exception;
23
23
Lines 33-39 use t::lib::Mocks; Link Here
33
use t::lib::TestBuilder;
33
use t::lib::TestBuilder;
34
34
35
BEGIN {
35
BEGIN {
36
        use_ok('C4::Members', qw( checkcardnumber GetBorrowersToExpunge DeleteUnverifiedOpacRegistrations DeleteExpiredOpacRegistrations ));
36
        use_ok('C4::Members', qw( GetBorrowersToExpunge DeleteUnverifiedOpacRegistrations DeleteExpiredOpacRegistrations ));
37
}
37
}
38
38
39
my $schema = Koha::Database->schema;
39
my $schema = Koha::Database->schema;
Lines 58-66 my $EMAIL = "Marie\@email.com"; Link Here
58
my $EMAILPRO          = "Marie\@work.com";
58
my $EMAILPRO          = "Marie\@work.com";
59
my $PHONE             = "555-12123";
59
my $PHONE             = "555-12123";
60
60
61
# XXX should be randomised and checked against the database
62
my $IMPOSSIBLE_CARDNUMBER = "XYZZZ999";
63
64
t::lib::Mocks::mock_userenv();
61
t::lib::Mocks::mock_userenv();
65
62
66
# Make a borrower for testing
63
# Make a borrower for testing
Lines 104-125 ok ( $changedmember->{firstname} eq $CHANGED_FIRSTNAME && Link Here
104
     , "Member Changed")
101
     , "Member Changed")
105
  or diag("Mismatching member details: ".Dumper($member, $changedmember));
102
  or diag("Mismatching member details: ".Dumper($member, $changedmember));
106
103
107
t::lib::Mocks::mock_preference( 'CardnumberLength', '' );
108
C4::Context->clear_syspref_cache();
109
110
my $checkcardnum=C4::Members::checkcardnumber($CARDNUMBER, "");
111
is ($checkcardnum, "1", "Card No. in use");
112
113
$checkcardnum=C4::Members::checkcardnumber($IMPOSSIBLE_CARDNUMBER, "");
114
is ($checkcardnum, "0", "Card No. not used");
115
116
t::lib::Mocks::mock_preference( 'CardnumberLength', '4' );
117
C4::Context->clear_syspref_cache();
118
119
$checkcardnum=C4::Members::checkcardnumber($IMPOSSIBLE_CARDNUMBER, "");
120
is ($checkcardnum, "2", "Card number is too long");
121
122
123
# Add a new borrower
104
# Add a new borrower
124
%data = (
105
%data = (
125
    cardnumber   => "123456789",
106
    cardnumber   => "123456789",
126
- 

Return to bug 33940