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

(-)a/Koha/Patrons/Import.pm (-65 / +139 lines)
Lines 16-21 package Koha::Patrons::Import; Link Here
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
use Moo;
20
use namespace::clean;
19
21
20
use Carp;
22
use Carp;
21
use Text::CSV;
23
use Text::CSV;
Lines 50-73 Further pod documentation needed here. Link Here
50
52
51
=cut
53
=cut
52
54
55
has 'today_iso' => (
56
    is      => 'ro',
57
    lazy    => 1,
58
    default => sub { output_pref( { dt => dt_from_string(), dateonly => 1, dateformat => 'iso' } ); },
59
  );
60
61
has 'text_csv' => (
62
    is      => 'ro',
63
    lazy    => 1,
64
    default => sub { Text::CSV->new( { binary => 1 } ), },
65
  );
66
53
sub import_patrons {
67
sub import_patrons {
54
    my ($params) = @_;
68
    my ($self, $params) = @_;
69
70
    my $handle = $params->{file};
71
    unless( $handle ) { carp('No file handle passed in!'); return; }
55
72
56
    my $handle               = $params->{file};
57
    my $matchpoint           = $params->{matchpoint};
73
    my $matchpoint           = $params->{matchpoint};
58
    my $defaults             = $params->{defaults};
74
    my $defaults             = $params->{defaults};
59
    my $ext_preserve         = $params->{preserve_extended_attributes};
75
    my $ext_preserve         = $params->{preserve_extended_attributes};
60
    my $overwrite_cardnumber = $params->{overwrite_cardnumber};
76
    my $overwrite_cardnumber = $params->{overwrite_cardnumber};
77
    my $extended             = C4::Context->preference('ExtendedPatronAttributes');
78
    my $set_messaging_prefs  = C4::Context->preference('EnhancedMessagingPreferences');
61
79
62
    unless( $handle ) { carp("No file handle passed in!"); return; }
80
    my @columnkeys = set_column_keys($extended);
63
    my $extended            = C4::Context->preference('ExtendedPatronAttributes');
64
    my $set_messaging_prefs = C4::Context->preference('EnhancedMessagingPreferences');
65
66
    my @columnkeys = map { $_ ne 'borrowernumber' ? $_ : () } C4::Members::columns();
67
    push( @columnkeys, 'patron_attributes' ) if $extended;
68
69
    our $csv = Text::CSV->new( { binary => 1 } );    # binary needed for non-ASCII Unicode
70
71
    my @feedback;
81
    my @feedback;
72
    my @errors;
82
    my @errors;
73
83
Lines 79-87 sub import_patrons { Link Here
79
89
80
    # use header line to construct key to column map
90
    # use header line to construct key to column map
81
    my $borrowerline = <$handle>;
91
    my $borrowerline = <$handle>;
82
    my $status       = $csv->parse($borrowerline);
92
    my $status       = $self->text_csv->parse($borrowerline);
83
    ($status) or push @errors, { badheader => 1, line => $., lineraw => $borrowerline };
93
    ($status) or push @errors, { badheader => 1, line => $., lineraw => $borrowerline };
84
    my @csvcolumns = $csv->fields();
94
95
    my @csvcolumns = $self->text_csv->fields();
85
    my %csvkeycol;
96
    my %csvkeycol;
86
    my $col = 0;
97
    my $col = 0;
87
    foreach my $keycol (@csvcolumns) {
98
    foreach my $keycol (@csvcolumns) {
Lines 91-111 sub import_patrons { Link Here
91
        $csvkeycol{$keycol} = $col++;
102
        $csvkeycol{$keycol} = $col++;
92
    }
103
    }
93
104
94
    #warn($borrowerline);
95
    if ($extended) {
105
    if ($extended) {
96
        $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint);
106
        $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint);
97
    }
107
    }
98
108
99
    push @feedback, { feedback => 1, name => 'headerrow', value => join( ', ', @csvcolumns ) };
109
    push @feedback, { feedback => 1, name => 'headerrow', value => join( ', ', @csvcolumns ) };
100
    my $today_iso = output_pref( { dt => dt_from_string, dateonly => 1, dateformat => 'iso' } );
110
    my @criticals = qw( surname );    # there probably should be others - rm branchcode && categorycode
101
    my @criticals = qw(surname branchcode categorycode);    # there probably should be others
102
    my @bad_dates;                                          # I've had a few.
103
  LINE: while ( my $borrowerline = <$handle> ) {
111
  LINE: while ( my $borrowerline = <$handle> ) {
112
        my $line_number = $.;
104
        my %borrower;
113
        my %borrower;
105
        my @missing_criticals;
114
        my @missing_criticals;
106
        my $patron_attributes;
115
107
        my $status  = $csv->parse($borrowerline);
116
        my $status  = $self->text_csv->parse($borrowerline);
108
        my @columns = $csv->fields();
117
        my @columns = $self->text_csv->fields();
109
        if ( !$status ) {
118
        if ( !$status ) {
110
            push @missing_criticals, { badparse => 1, line => $., lineraw => $borrowerline };
119
            push @missing_criticals, { badparse => 1, line => $., lineraw => $borrowerline };
111
        }
120
        }
Lines 139-173 sub import_patrons { Link Here
139
            }
148
            }
140
        }
149
        }
141
150
142
        #warn join(':',%borrower);
151
        # Checking if borrower category code exists and if it matches to a known category. Pushing error to missing_criticals otherwise.
143
        if ( $borrower{categorycode} ) {
152
        check_borrower_category($borrower{categorycode}, $borrowerline, $line_number, \@missing_criticals);
144
            push @missing_criticals,
153
145
              {
154
        # Checking if branch code exists and if it matches to a branch name. Pushing error to missing_criticals otherwise.
146
                key          => 'categorycode',
155
        check_branch_code($borrower{branchcode}, $borrowerline, $line_number, \@missing_criticals);
147
                line         => $.,
156
148
                lineraw      => $borrowerline,
149
                value        => $borrower{categorycode},
150
                category_map => 1
151
              }
152
              unless GetBorrowercategory( $borrower{categorycode} );
153
        }
154
        else {
155
            push @missing_criticals, { key => 'categorycode', line => $., lineraw => $borrowerline };
156
        }
157
        if ( $borrower{branchcode} ) {
158
            push @missing_criticals,
159
              {
160
                key        => 'branchcode',
161
                line       => $.,
162
                lineraw    => $borrowerline,
163
                value      => $borrower{branchcode},
164
                branch_map => 1
165
              }
166
              unless GetBranchName( $borrower{branchcode} );
167
        }
168
        else {
169
            push @missing_criticals, { key => 'branchcode', line => $., lineraw => $borrowerline };
170
        }
171
        if (@missing_criticals) {
157
        if (@missing_criticals) {
172
            foreach (@missing_criticals) {
158
            foreach (@missing_criticals) {
173
                $_->{borrowernumber} = $borrower{borrowernumber} || 'UNDEF';
159
                $_->{borrowernumber} = $borrower{borrowernumber} || 'UNDEF';
Lines 179-210 sub import_patrons { Link Here
179
            # The first 25 errors are enough.  Keeping track of 30,000+ would destroy performance.
165
            # The first 25 errors are enough.  Keeping track of 30,000+ would destroy performance.
180
            next LINE;
166
            next LINE;
181
        }
167
        }
182
        if ($extended) {
168
183
            my $attr_str = $borrower{patron_attributes};
169
        # Setting patron attributes if extended.
184
            $attr_str =~ s/\xe2\x80\x9c/"/g;    # fixup double quotes in case we are passed smart quotes
170
        my $patron_attributes = set_patron_attributes($extended, $borrower{patron_attributes}, \@feedback);
185
            $attr_str =~ s/\xe2\x80\x9d/"/g;
171
186
            push @feedback, { feedback => 1, name => 'attribute string', value => $attr_str };
172
        # Not really a field in borrowers, so we don't want to pass it to ModMember.
187
            delete $borrower{patron_attributes}; # not really a field in borrowers, so we don't want to pass it to ModMember.
173
        if ($extended) { delete $borrower{patron_attributes}; }
188
            $patron_attributes = extended_attributes_code_value_arrayref($attr_str);
189
        }
190
174
191
        # Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
175
        # Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
192
        foreach (qw(dateofbirth dateenrolled dateexpiry)) {
176
        foreach (qw(dateofbirth dateenrolled dateexpiry)) {
193
            my $tempdate = $borrower{$_} or next;
177
            my $tempdate = $borrower{$_} or next;
178
194
            $tempdate = eval { output_pref( { dt => dt_from_string( $tempdate ), dateonly => 1, dateformat => 'iso' } ); };
179
            $tempdate = eval { output_pref( { dt => dt_from_string( $tempdate ), dateonly => 1, dateformat => 'iso' } ); };
180
195
            if ($tempdate) {
181
            if ($tempdate) {
196
                $borrower{$_} = $tempdate;
182
                $borrower{$_} = $tempdate;
197
            } else {
183
            } else {
198
                $borrower{$_} = '';
184
                $borrower{$_} = '';
199
                push @missing_criticals, { key => $_, line => $., lineraw => $borrowerline, bad_date => 1 };
185
                push @missing_criticals, { key => $_, line => $line_number, lineraw => $borrowerline, bad_date => 1 };
200
            }
186
            }
201
        }
187
        }
202
        $borrower{dateenrolled} = $today_iso unless $borrower{dateenrolled};
188
        $borrower{dateenrolled} = $self->today_iso() unless $borrower{dateenrolled};
203
        $borrower{dateexpiry} = GetExpiryDate( $borrower{categorycode}, $borrower{dateenrolled} )
189
        $borrower{dateexpiry} = GetExpiryDate( $borrower{categorycode}, $borrower{dateenrolled} ) unless $borrower{dateexpiry};
204
          unless $borrower{dateexpiry};
190
205
        my $borrowernumber;
191
        my $borrowernumber;
206
        my $member;
192
        my $member;
207
        if ( ( $matchpoint eq 'cardnumber' ) && ( $borrower{'cardnumber'} ) ) {
193
        if ( defined($matchpoint) && ( $matchpoint eq 'cardnumber' ) && ( $borrower{'cardnumber'} ) ) {
208
            $member = GetMember( 'cardnumber' => $borrower{'cardnumber'} );
194
            $member = GetMember( 'cardnumber' => $borrower{'cardnumber'} );
209
            if ($member) {
195
            if ($member) {
210
                $borrowernumber = $member->{'borrowernumber'};
196
                $borrowernumber = $member->{'borrowernumber'};
Lines 384-394 sub import_patrons { Link Here
384
    };
370
    };
385
}
371
}
386
372
387
END { }    # module clean-up code here (global destructor)
373
=head2 set_column_keys
388
374
389
1;
375
 my @columnkeys = set_column_keys($extended);
376
377
Returns an array of borrowers' table columns.
378
379
=cut
380
381
sub set_column_keys {
382
    my ($extended) = @_;
383
384
    my @columnkeys = map { $_ ne 'borrowernumber' ? $_ : () } C4::Members::columns();
385
    push( @columnkeys, 'patron_attributes' ) if $extended;
386
387
    return @columnkeys;
388
}
390
389
391
__END__
390
=head2 set_patron_attributes
391
392
 my $patron_attributes = set_patron_attributes($extended, $borrower{patron_attributes}, $feedback);
393
394
Returns a reference to array of hashrefs data structure as expected by SetBorrowerAttributes.
395
396
=cut
397
398
sub set_patron_attributes {
399
    my ($extended, $patron_attributes, $feedback) = @_;
400
401
    unless($extended) { return; }
402
    unless( defined($patron_attributes) ) { return; }
403
404
    # Fixup double quotes in case we are passed smart quotes
405
    $patron_attributes =~ s/\xe2\x80\x9c/"/g;
406
    $patron_attributes =~ s/\xe2\x80\x9d/"/g;
407
408
    push (@$feedback, { feedback => 1, name => 'attribute string', value => $patron_attributes });
409
410
    my $result = extended_attributes_code_value_arrayref($patron_attributes);
411
412
    return $result;
413
}
414
415
=head2 check_branch_code
416
417
 check_branch_code($borrower{branchcode}, $borrowerline, $line_number, \@missing_criticals);
418
419
Pushes a 'missing_criticals' error entry if no branch code or branch code does not map to a branch name.
420
421
=cut
422
423
sub check_branch_code {
424
    my ($branchcode, $borrowerline, $line_number, $missing_criticals) = @_;
425
426
    # No branch code
427
    unless( $branchcode ) {
428
        push (@$missing_criticals, { key => 'branchcode', line => $line_number, lineraw => $borrowerline, });
429
        return;
430
    }
431
432
    # look for branch code
433
    my $branch_name = GetBranchName( $branchcode );
434
    unless( $branch_name ) {
435
        push (@$missing_criticals, { key => 'branchcode', line => $line_number, lineraw => $borrowerline,
436
                                     value => $branchcode, branch_map => 1, });
437
    }
438
}
439
440
=head2 check_borrower_category
441
442
 check_borrower_category($borrower{categorycode}, $borrowerline, $line_number, \@missing_criticals);
443
444
Pushes a 'missing_criticals' error entry if no category code or category code does not map to a known category.
445
446
=cut
447
448
sub check_borrower_category {
449
    my ($categorycode, $borrowerline, $line_number, $missing_criticals) = @_;
450
451
    # No branch code
452
    unless( $categorycode ) {
453
        push (@$missing_criticals, { key => 'categorycode', line => $line_number, lineraw => $borrowerline, });
454
        return;
455
    }
456
457
    # Looking for borrower category
458
    my $category = GetBorrowercategory( $categorycode );
459
    unless( $category ) {
460
        push (@$missing_criticals, { key => 'categorycode', line => $line_number, lineraw => $borrowerline,
461
                                     value => $categorycode, category_map => 1, });
462
    }
463
}
464
465
1;
392
466
393
=head1 AUTHOR
467
=head1 AUTHOR
394
468
(-)a/t/db_dependent/Koha/Patrons/Import.t (-18 / +336 lines)
Lines 18-24 Link Here
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
use Test::More;
21
use Test::More tests => 98;
22
use Test::MockModule;
22
use Test::MockModule;
23
23
24
use Koha::Database;
24
use Koha::Database;
Lines 36-55 $schema->storage->txn_begin; Link Here
36
# Given ... we can use the module
36
# Given ... we can use the module
37
BEGIN { use_ok('Koha::Patrons::Import'); }
37
BEGIN { use_ok('Koha::Patrons::Import'); }
38
38
39
# Given ... we can reach the method(s)
39
my $patrons_import = new_ok('Koha::Patrons::Import');
40
my @methods = ('import_patrons');
40
41
can_ok('Koha::Patrons::Import', @methods);
41
subtest 'test_methods' => sub {
42
    plan tests => 1;
43
44
    # Given ... we can reach the method(s)
45
    my @methods = ('import_patrons', 'set_column_keys', 'set_patron_attributes', 'check_branch_code');
46
    can_ok('Koha::Patrons::Import', @methods);
47
};
48
49
subtest 'test_attributes' => sub {
50
    plan tests => 1;
51
52
    my @attributes = ('today_iso', 'text_csv');
53
    can_ok('Koha::Patrons::Import', @attributes);
54
};
42
55
43
# Tests for Koha::Patrons::Import::import_patrons()
56
# Tests for Koha::Patrons::Import::import_patrons()
44
# Given ... nothing much. When ... Then ...
57
# Given ... nothing much. When ... Then ...
45
my $result = Koha::Patrons::Import::import_patrons(undef);
58
my $result = $patrons_import->import_patrons(undef);
46
is($result, undef, 'Got the expected undef from import_patrons with nothing much');
59
is($result, undef, 'Got the expected undef from import_patrons with nothing much');
47
60
48
# Given ... some params but no file handle.
61
# Given ... some params but no file handle.
49
my $params_0 = { some_stuff => 'random stuff', };
62
my $params_0 = { some_stuff => 'random stuff', };
50
63
51
# When ... Then ...
64
# When ... Then ...
52
my $result_0 = Koha::Patrons::Import::import_patrons($params_0);
65
my $result_0 = $patrons_import->import_patrons($params_0);
53
is($result_0, undef, 'Got the expected undef from import_patrons with no file handle');
66
is($result_0, undef, 'Got the expected undef from import_patrons with no file handle');
54
67
55
# Given ... a file handle to file with headers only.
68
# Given ... a file handle to file with headers only.
Lines 61-71 open(my $handle_1, "<", $filename_1) or die "cannot open < $filename_1: $!"; Link Here
61
my $params_1 = { file => $handle_1, };
74
my $params_1 = { file => $handle_1, };
62
75
63
# When ...
76
# When ...
64
my $result_1 = Koha::Patrons::Import::import_patrons($params_1);
77
my $result_1 = $patrons_import->import_patrons($params_1);
65
78
66
# Then ...
79
# Then ...
80
is($result_1->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons with no matchpoint defined');
81
is(scalar @{$result_1->{errors}}, 0, 'Got the expected 0 size error array from import_patrons with no matchpoint defined');
82
83
is($result_1->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons with no matchpoint defined');
84
is($result_1->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons with no matchpoint defined');
85
is($result_1->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
86
                                        'Got the expected header row value from import_patrons with no matchpoint defined');
87
88
is($result_1->{feedback}->[1]->{feedback}, 1, 'Got the expected second feedback from import_patrons with no matchpoint defined');
89
is($result_1->{feedback}->[1]->{name}, 'lastimported', 'Got the expected last imported name from import_patrons with no matchpoint defined');
90
like($result_1->{feedback}->[1]->{value}, qr/^Nancy \/ \d+/, 'Got the expected second header row value from import_patrons with no matchpoint defined');
91
67
is($result_1->{imported}, 1, 'Got the expected 1 imported result from import_patrons with no matchpoint defined');
92
is($result_1->{imported}, 1, 'Got the expected 1 imported result from import_patrons with no matchpoint defined');
68
is($result_1->{invalid}, 0, 'Got the expected 0 invalid result from import_patrons with no matchpoint defined');
93
is($result_1->{invalid}, 0, 'Got the expected 0 invalid result from import_patrons with no matchpoint defined');
94
is($result_1->{overwritten}, 0, 'Got the expected 0 overwritten result from import_patrons with no matchpoint defined');
69
95
70
# Given ... a valid file handle, a bad matchpoint resulting in invalid card number
96
# Given ... a valid file handle, a bad matchpoint resulting in invalid card number
71
my $filename_2 = make_csv($temp_dir, $csv_headers, $csv_one_line);
97
my $filename_2 = make_csv($temp_dir, $csv_headers, $csv_one_line);
Lines 73-100 open(my $handle_2, "<", $filename_2) or die "cannot open < $filename_2: $!"; Link Here
73
my $params_2 = { file => $handle_2, matchpoint => 'SHOW_BCODE', };
99
my $params_2 = { file => $handle_2, matchpoint => 'SHOW_BCODE', };
74
100
75
# When ...
101
# When ...
76
my $result_2 = Koha::Patrons::Import::import_patrons($params_2);
102
my $result_2 = $patrons_import->import_patrons($params_2);
77
103
78
# Then ...
104
# Then ...
79
is($result_2->{imported}, 0, 'Got the expected 0 imported result from import_patrons with no matchpoint defined');
105
is($result_2->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons with invalid card number');
80
is($result_2->{invalid}, 1, 'Got the expected 1 invalid result from import_patrons with no matchpoint defined');
106
is($result_2->{errors}->[0]->{borrowernumber}, undef, 'Got the expected undef borrower number from import patrons with invalid card number');
107
is($result_2->{errors}->[0]->{cardnumber}, 1000, 'Got the expected 1000 card number from import patrons with invalid card number');
81
is($result_2->{errors}->[0]->{invalid_cardnumber}, 1, 'Got the expected invalid card number from import patrons with invalid card number');
108
is($result_2->{errors}->[0]->{invalid_cardnumber}, 1, 'Got the expected invalid card number from import patrons with invalid card number');
82
109
110
is($result_2->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons with invalid card number');
111
is($result_2->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons with invalid card number');
112
is($result_2->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
113
                                        'Got the expected header row value from import_patrons with invalid card number');
114
115
is($result_2->{imported}, 0, 'Got the expected 0 imported result from import_patrons with invalid card number');
116
is($result_2->{invalid}, 1, 'Got the expected 1 invalid result from import_patrons with invalid card number');
117
is($result_2->{overwritten}, 0, 'Got the expected 0 overwritten result from import_patrons with invalid card number');
118
83
# Given ... valid file handle, good matchpoint but same input as prior test.
119
# Given ... valid file handle, good matchpoint but same input as prior test.
84
my $filename_3 = make_csv($temp_dir, $csv_headers, $csv_one_line);
120
my $filename_3 = make_csv($temp_dir, $csv_headers, $csv_one_line);
85
open(my $handle_3, "<", $filename_3) or die "cannot open < $filename_3: $!";
121
open(my $handle_3, "<", $filename_3) or die "cannot open < $filename_3: $!";
86
my $params_3 = { file => $handle_3, matchpoint => 'cardnumber', };
122
my $params_3 = { file => $handle_3, matchpoint => 'cardnumber', };
87
123
88
# When ...
124
# When ...
89
my $result_3 = Koha::Patrons::Import::import_patrons($params_3);
125
my $result_3 = $patrons_import->import_patrons($params_3);
90
126
91
# Then ...
127
# Then ...
128
is($result_3->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons with duplicate userid');
129
is($result_3->{errors}->[0]->{duplicate_userid}, 1, 'Got the expected duplicate userid error from import patrons with duplicate userid');
130
is($result_3->{errors}->[0]->{userid}, 'jjenkins0', 'Got the expected userid error from import patrons with duplicate userid');
131
132
is($result_3->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons with duplicate userid');
133
is($result_3->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons with duplicate userid');
134
is($result_3->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
135
                                        'Got the expected header row value from import_patrons with duplicate userid');
136
92
is($result_3->{imported}, 0, 'Got the expected 0 imported result from import_patrons with duplicate userid');
137
is($result_3->{imported}, 0, 'Got the expected 0 imported result from import_patrons with duplicate userid');
93
is($result_3->{invalid}, 1, 'Got the expected 1 invalid result from import_patrons with duplicate userid');
138
is($result_3->{invalid}, 1, 'Got the expected 1 invalid result from import_patrons with duplicate userid');
94
is($result_3->{errors}->[0]->{duplicate_userid}, 1, 'Got the expected duplicate userid error from import patrons with duplicate userid');
139
is($result_3->{overwritten}, 0, 'Got the expected 0 overwritten result from import_patrons with duplicate userid');
95
140
96
# Given ... a new input and mocked C4::Context
141
# Given ... a new input and mocked C4::Context
97
my $context = new Test::MockModule('C4::Context');
142
my $context = Test::MockModule->new('C4::Context');
98
$context->mock('preference', sub { my ($mod, $meth) = @_; if ( $meth eq 'ExtendedPatronAttributes' ) { return 1; } });
143
$context->mock('preference', sub { my ($mod, $meth) = @_; if ( $meth eq 'ExtendedPatronAttributes' ) { return 1; } });
99
144
100
my $new_input_line = '1001,Donna,Sullivan,Mrs,Henry,DS,59,Court,Burrows,Reading,Salt Lake City,Pennsylvania,19605,United States,hsullivan1@purevolume.com,3-(864)009-3006,7-(291)885-8423,1-(879)095-5038,19/09/1970,LPL,PT,04/03/2015,01/07/2015,hsullivan1,8j6P6Dmap';
145
my $new_input_line = '1001,Donna,Sullivan,Mrs,Henry,DS,59,Court,Burrows,Reading,Salt Lake City,Pennsylvania,19605,United States,hsullivan1@purevolume.com,3-(864)009-3006,7-(291)885-8423,1-(879)095-5038,19/09/1970,LPL,PT,04/03/2015,01/07/2015,hsullivan1,8j6P6Dmap';
Lines 102-111 my $filename_4 = make_csv($temp_dir, $csv_headers, $new_input_line); Link Here
102
open(my $handle_4, "<", $filename_4) or die "cannot open < $filename_4: $!";
147
open(my $handle_4, "<", $filename_4) or die "cannot open < $filename_4: $!";
103
my $params_4 = { file => $handle_4, matchpoint => 'cardnumber', };
148
my $params_4 = { file => $handle_4, matchpoint => 'cardnumber', };
104
149
105
# When ... Then ...
150
# When ...
106
my $result_4 = Koha::Patrons::Import::import_patrons($params_4);
151
my $result_4 = $patrons_import->import_patrons($params_4);
152
153
# Then ...
154
is($result_4->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons with extended user');
155
is(scalar @{$result_4->{errors}}, 0, 'Got the expected 0 size error array from import_patrons with extended user');
156
157
is($result_4->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons with extended user');
158
is($result_4->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons with extended user');
159
is($result_4->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
160
                                        'Got the expected header row value from import_patrons with extended user');
161
162
is($result_4->{feedback}->[1]->{feedback}, 1, 'Got the expected second feedback from import_patrons with extended user');
163
is($result_4->{feedback}->[1]->{name}, 'attribute string', 'Got the expected attribute string from import_patrons with extended user');
164
is($result_4->{feedback}->[1]->{value}, '', 'Got the expected second feedback value from import_patrons with extended user');
165
166
is($result_4->{feedback}->[2]->{feedback}, 1, 'Got the expected third feedback from import_patrons with extended user');
167
is($result_4->{feedback}->[2]->{name}, 'lastimported', 'Got the expected last imported name from import_patrons with extended user');
168
like($result_4->{feedback}->[2]->{value}, qr/^Donna \/ \d+/, 'Got the expected third feedback value from import_patrons with extended user');
169
107
is($result_4->{imported}, 1, 'Got the expected 1 imported result from import_patrons with extended user');
170
is($result_4->{imported}, 1, 'Got the expected 1 imported result from import_patrons with extended user');
171
is($result_4->{invalid}, 0, 'Got the expected 0 invalid result from import_patrons with extended user');
172
is($result_4->{overwritten}, 0, 'Got the expected 0 overwritten result from import_patrons with extended user');
173
174
$context->unmock('preference');
175
176
# Given ... 3 new inputs. One with no branch code, one with unexpected branch code.
177
my $input_no_branch   = '1002,Johnny,Reynolds,Mr,Patricia,JR,12,Hill,Kennedy,Saint Louis,Colorado Springs,Missouri,63131,United States,preynolds2@washington.edu,7-(925)314-9514,0-(315)973-8956,4-(510)556-2323,18/09/1967,,PT,07/05/2015,01/07/2015,preynolds2,K3HiDzl';
178
my $input_good_branch = '1003,Linda,Richardson,Mr,Kimberly,LR,90,Place,Bayside,Atlanta,Erie,Georgia,31190,United States,krichardson3@pcworld.com,8-(035)185-0387,4-(796)518-3676,3-(644)960-3789,13/04/1954,RPL,PT,06/06/2015,01/07/2015,krichardson3,P3EO0MVRPXbM';
179
my $input_na_branch   = '1005,Ruth,Greene,Mr,Michael,RG,3,Avenue,Grim,Peoria,Jacksonville,Illinois,61614,United States,mgreene5@seesaa.net,3-(941)565-5752,1-(483)885-8138,4-(979)577-6908,09/02/1957,ZZZ,ST,02/04/2015,01/07/2015,mgreene5,or4ORT6JH';
180
181
my $filename_5 = make_csv($temp_dir, $csv_headers, $input_no_branch, $input_good_branch, $input_na_branch);
182
open(my $handle_5, "<", $filename_5) or die "cannot open < $filename_5: $!";
183
my $params_5 = { file => $handle_5, matchpoint => 'cardnumber', };
184
185
# When ...
186
my $result_5 = $patrons_import->import_patrons($params_5);
187
188
# Then ...
189
is($result_5->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons for branch tests');
190
191
is($result_5->{errors}->[0]->{missing_criticals}->[0]->{borrowernumber}, 'UNDEF', 'Got the expected undef borrower number error from import patrons for branch tests');
192
is($result_5->{errors}->[0]->{missing_criticals}->[0]->{key}, 'branchcode', 'Got the expected branch code key from import patrons for branch tests');
193
is($result_5->{errors}->[0]->{missing_criticals}->[0]->{line}, 2, 'Got the expected 2 line number error from import patrons for branch tests');
194
is($result_5->{errors}->[0]->{missing_criticals}->[0]->{lineraw}, $input_no_branch."\r\n", 'Got the expected lineraw error from import patrons for branch tests');
195
is($result_5->{errors}->[0]->{missing_criticals}->[0]->{surname}, 'Johnny', 'Got the expected surname error from import patrons for branch tests');
196
197
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{borrowernumber}, 'UNDEF', 'Got the expected undef borrower number error from import patrons for branch tests');
198
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{branch_map}, 1, 'Got the expected 1 branchmap error from import patrons for branch tests');
199
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{key}, 'branchcode', 'Got the expected branch code key from import patrons for branch tests');
200
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{line}, 4, 'Got the expected 4 line number error from import patrons for branch tests');
201
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{lineraw}, $input_na_branch."\r\n", 'Got the expected lineraw error from import patrons for branch tests');
202
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{surname}, 'Ruth', 'Got the expected surname error from import patrons for branch tests');
203
is($result_5->{errors}->[1]->{missing_criticals}->[0]->{value}, 'ZZZ', 'Got the expected ZZZ value error from import patrons for branch tests');
204
205
is($result_5->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons for branch tests');
206
is($result_5->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons for branch tests');
207
is($result_5->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
208
                                        'Got the expected header row value from import_patrons for branch tests');
209
210
is($result_5->{feedback}->[1]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons for branch tests');
211
is($result_5->{feedback}->[1]->{name}, 'lastimported', 'Got the expected lastimported name from import_patrons for branch tests');
212
like($result_5->{feedback}->[1]->{value},  qr/^Linda \/ \d+/, 'Got the expected last imported value from import_patrons with for branch tests');
213
214
is($result_5->{imported}, 1, 'Got the expected 1 imported result from import patrons for branch tests');
215
is($result_5->{invalid}, 2, 'Got the expected 2 invalid result from import patrons for branch tests');
216
is($result_5->{overwritten}, 0, 'Got the expected 0 overwritten result from import patrons for branch tests');
217
218
# Given ... 3 new inputs. One with no category code, one with unexpected category code.
219
my $input_no_category   = '1006,Christina,Olson,Rev,Kimberly,CO,8,Avenue,Northridge,Lexington,Wilmington,Kentucky,40510,United States,kolson6@dropbox.com,7-(810)636-6048,1-(052)012-8984,8-(567)232-7818,26/03/1952,FFL,,07/09/2014,01/07/2015,kolson6,x5D3qGbLlptx';
220
my $input_good_category = '1007,Peter,Peters,Mrs,Lawrence,PP,6,Trail,South,Oklahoma City,Topeka,Oklahoma,73135,United States,lpeters7@bandcamp.com,5-(992)205-9318,0-(732)586-9365,3-(448)146-7936,16/08/1983,PVL,T,24/03/2015,01/07/2015,lpeters7,Z19BrQ4';
221
my $input_na_category   = '1008,Emily,Richards,Ms,Judy,ER,73,Way,Kedzie,Fort Wayne,Phoenix,Indiana,46825,United States,jrichards8@arstechnica.com,5-(266)658-8957,3-(550)500-9107,7-(816)675-9822,09/08/1984,FFL,ZZ,09/11/2014,01/07/2015,jrichards8,D5PvU6H2R';
222
223
my $filename_6 = make_csv($temp_dir, $csv_headers, $input_no_category, $input_good_category, $input_na_category);
224
open(my $handle_6, "<", $filename_6) or die "cannot open < $filename_6: $!";
225
my $params_6 = { file => $handle_6, matchpoint => 'cardnumber', };
226
227
# When ...
228
my $result_6 = $patrons_import->import_patrons($params_6);
229
230
# Then ...
231
is($result_6->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons for category tests');
232
233
is($result_6->{errors}->[0]->{missing_criticals}->[0]->{borrowernumber}, 'UNDEF', 'Got the expected undef borrower number error from import patrons for category tests');
234
is($result_6->{errors}->[0]->{missing_criticals}->[0]->{key}, 'categorycode', 'Got the expected category code key from import patrons for category tests');
235
is($result_6->{errors}->[0]->{missing_criticals}->[0]->{line}, 2, 'Got the expected 2 line number error from import patrons for category tests');
236
is($result_6->{errors}->[0]->{missing_criticals}->[0]->{lineraw}, $input_no_category."\r\n", 'Got the expected lineraw error from import patrons for category tests');
237
is($result_6->{errors}->[0]->{missing_criticals}->[0]->{surname}, 'Christina', 'Got the expected surname error from import patrons for category tests');
238
239
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{borrowernumber}, 'UNDEF', 'Got the expected undef borrower number error from import patrons for category tests');
240
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{category_map}, 1, 'Got the expected 1 category_map error from import patrons for category tests');
241
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{key}, 'categorycode', 'Got the expected category code key from import patrons for category tests');
242
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{line}, 4, 'Got the expected 4 line number error from import patrons for category tests');
243
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{lineraw}, $input_na_category."\r\n", 'Got the expected lineraw error from import patrons for category tests');
244
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{surname}, 'Emily', 'Got the expected surname error from import patrons for category tests');
245
is($result_6->{errors}->[1]->{missing_criticals}->[0]->{value}, 'ZZ', 'Got the expected ZZ value error from import patrons for category tests');
246
247
is($result_6->{feedback}->[0]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons for category tests');
248
is($result_6->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons for category tests');
249
is($result_6->{feedback}->[0]->{value}, 'cardnumber, surname, firstname, title, othernames, initials, streetnumber, streettype, address, address2, city, state, zipcode, country, email, phone, mobile, fax, dateofbirth, branchcode, categorycode, dateenrolled, dateexpiry, userid, password',
250
                                        'Got the expected header row value from import_patrons for category tests');
251
252
is($result_6->{feedback}->[1]->{feedback}, 1, 'Got the expected 1 feedback from import_patrons for category tests');
253
is($result_6->{feedback}->[1]->{name}, 'lastimported', 'Got the expected lastimported name from import_patrons for category tests');
254
like($result_6->{feedback}->[1]->{value},  qr/^Peter \/ \d+/, 'Got the expected last imported value from import_patrons with for category tests');
108
255
256
is($result_6->{imported}, 1, 'Got the expected 1 imported result from import patrons for category tests');
257
is($result_6->{invalid}, 2, 'Got the expected 2 invalid result from import patrons for category tests');
258
is($result_6->{overwritten}, 0, 'Got the expected 0 overwritten result from import patrons for category tests');
259
260
# Given ... 2 new inputs. One without dateofbirth, dateenrolled and dateexpiry values.
261
my $input_complete = '1009,Christina,Harris,Dr,Philip,CH,99,Street,Grayhawk,Baton Rouge,Dallas,Louisiana,70810,United States,pharris9@hp.com,9-(317)603-5513,7-(005)062-7593,8-(349)134-1627,19/06/1969,IPT,PT,09/04/2015,01/07/2015,pharris9,NcAhcvvnB';
262
my $input_no_date  = '1010,Ralph,Warren,Ms,Linda,RW,6,Way,Barby,Orlando,Albany,Florida,32803,United States,lwarrena@multiply.com,7-(579)753-7752,6-(847)086-7566,9-(122)729-8226,,LPL,T,,,lwarrena,tJ56RD4uV';
263
264
my $filename_7 = make_csv($temp_dir, $csv_headers, $input_complete, $input_no_date);
265
open(my $handle_7, "<", $filename_7) or die "cannot open < $filename_7: $!";
266
my $params_7 = { file => $handle_7, matchpoint => 'cardnumber', };
267
268
# Need upgrade to Moo
269
subtest 'test_set_column_keys' => sub {
270
    plan tests => 2;
271
272
    # Given ... nothing at all
273
    # When ... Then ...
274
    my @columnkeys_0 = Koha::Patrons::Import::set_column_keys(undef);
275
    is(scalar @columnkeys_0, 66, 'Got the expected array size from set column keys with undef extended');
276
277
    # Given ... extended.
278
    my $extended = 1;
279
280
    # When ... Then ...
281
    my @columnkeys_1 = Koha::Patrons::Import::set_column_keys($extended);
282
    is(scalar @columnkeys_1, 67, 'Got the expected array size from set column keys with extended');
283
};
284
285
subtest 'test_set_patron_attributes' => sub {
286
    plan tests => 13;
287
288
    # Given ... nothing at all
289
    # When ... Then ...
290
    my $result_0 = Koha::Patrons::Import::set_patron_attributes(undef, undef, undef);
291
    is($result_0, undef, 'Got the expected undef from set patron attributes with nothing');
292
293
    # Given ... not extended.
294
    my $extended_1 = 0;
295
296
    # When ... Then ...
297
    my $result_1 = Koha::Patrons::Import::set_patron_attributes($extended_1, undef, undef);
298
    is($result_1, undef, 'Got the expected undef from set patron attributes with not extended');
299
300
    # Given ... NO patrons attributes
301
    my $extended_2          = 1;
302
    my $patron_attributes_2 = undef;
303
    my @feedback_2;
304
305
    # When ...
306
    my $result_2 = Koha::Patrons::Import::set_patron_attributes($extended_2, $patron_attributes_2, \@feedback_2);
307
308
    # Then ...
309
    is($result_2, undef, 'Got the expected undef from set patron attributes with no patrons attributes');
310
    is(scalar @feedback_2, 0, 'Got the expected 0 size feedback array from set patron attributes with no patrons attributes');
311
312
    # Given ... some patrons attributes
313
    my $patron_attributes_3 = "homeroom:1150605,grade:01";
314
    my @feedback_3;
315
316
    # When ...
317
    my $result_3 = Koha::Patrons::Import::set_patron_attributes($extended_2, $patron_attributes_3, \@feedback_3);
318
319
    # Then ...
320
    ok($result_3, 'Got some data back from set patron attributes');
321
    is($result_3->[0]->{code}, 'grade', 'Got the expected first code from set patron attributes');
322
    is($result_3->[0]->{value}, '01', 'Got the expected first value from set patron attributes');
323
324
    is($result_3->[1]->{code}, 'homeroom', 'Got the expected second code from set patron attributes');
325
    is($result_3->[1]->{value}, 1150605, 'Got the expected second value from set patron attributes');
326
327
    is(scalar @feedback_3, 1, 'Got the expected 1 array size from set patron attributes with extended user');
328
    is($feedback_3[0]->{feedback}, 1, 'Got the expected second feedback from set patron attributes with extended user');
329
    is($feedback_3[0]->{name}, 'attribute string', 'Got the expected attribute string from set patron attributes with extended user');
330
    is($feedback_3[0]->{value}, 'homeroom:1150605,grade:01', 'Got the expected feedback value from set patron attributes with extended user');
331
};
332
333
subtest 'test_check_branch_code' => sub {
334
    plan tests => 11;
335
336
    # Given ... no branch code.
337
    my $borrowerline      = 'some, line';
338
    my $line_number       = 78;
339
    my @missing_criticals = ();
340
341
    # When ...
342
    Koha::Patrons::Import::check_branch_code(undef, $borrowerline, $line_number, \@missing_criticals);
343
344
    # Then ...
345
    is(scalar @missing_criticals, 1, 'Got the expected missing critical array size of 1 from check_branch_code with no branch code');
346
347
    is($missing_criticals[0]->{key}, 'branchcode', 'Got the expected branchcode key from check_branch_code with no branch code');
348
    is($missing_criticals[0]->{line}, $line_number, 'Got the expected line number from check_branch_code with no branch code');
349
    is($missing_criticals[0]->{lineraw}, $borrowerline, 'Got the expected lineraw value from check_branch_code with no branch code');
350
351
    # Given ... unknown branch code
352
    my $branchcode_1        = 'unexpected';
353
    my $borrowerline_1      = 'some, line,'.$branchcode_1;
354
    my $line_number_1       = 79;
355
    my @missing_criticals_1 = ();
356
357
    # When ...
358
    Koha::Patrons::Import::check_branch_code($branchcode_1, $borrowerline_1, $line_number_1, \@missing_criticals_1);
359
360
    # Then ...
361
    is(scalar @missing_criticals_1, 1, 'Got the expected missing critical array size of 1 from check_branch_code with unexpected branch code');
362
363
    is($missing_criticals_1[0]->{branch_map}, 1, 'Got the expected 1 branch_map from check_branch_code with unexpected branch code');
364
    is($missing_criticals_1[0]->{key}, 'branchcode', 'Got the expected branchcode key from check_branch_code with unexpected branch code');
365
    is($missing_criticals_1[0]->{line}, $line_number_1, 'Got the expected line number from check_branch_code with unexpected branch code');
366
    is($missing_criticals_1[0]->{lineraw}, $borrowerline_1, 'Got the expected lineraw value from check_branch_code with unexpected branch code');
367
    is($missing_criticals_1[0]->{value}, $branchcode_1, 'Got the expected value from check_branch_code with unexpected branch code');
368
369
    # Given ... a known branch code. Relies on database sample data
370
    my $branchcode_2        = 'FFL';
371
    my $borrowerline_2      = 'some, line,'.$branchcode_2;
372
    my $line_number_2       = 80;
373
    my @missing_criticals_2 = ();
374
375
    # When ...
376
    Koha::Patrons::Import::check_branch_code($branchcode_2, $borrowerline_2, $line_number_2, \@missing_criticals_2);
377
378
    # Then ...
379
    is(scalar @missing_criticals_2, 0, 'Got the expected missing critical array size of 0 from check_branch_code');
380
};
381
382
subtest 'test_check_borrower_category' => sub {
383
    plan tests => 11;
384
385
    # Given ... no category code.
386
    my $borrowerline      = 'some, line';
387
    my $line_number       = 781;
388
    my @missing_criticals = ();
389
390
    # When ...
391
    Koha::Patrons::Import::check_borrower_category(undef, $borrowerline, $line_number, \@missing_criticals);
392
393
    # Then ...
394
    is(scalar @missing_criticals, 1, 'Got the expected missing critical array size of 1 from check_branch_code with no category code');
395
396
    is($missing_criticals[0]->{key}, 'categorycode', 'Got the expected categorycode key from check_branch_code with no category code');
397
    is($missing_criticals[0]->{line}, $line_number, 'Got the expected line number from check_branch_code with no category code');
398
    is($missing_criticals[0]->{lineraw}, $borrowerline, 'Got the expected lineraw value from check_branch_code with no category code');
399
400
    # Given ... unknown category code
401
    my $categorycode_1      = 'unexpected';
402
    my $borrowerline_1      = 'some, line, line, '.$categorycode_1;
403
    my $line_number_1       = 791;
404
    my @missing_criticals_1 = ();
405
406
    # When ...
407
    Koha::Patrons::Import::check_borrower_category($categorycode_1, $borrowerline_1, $line_number_1, \@missing_criticals_1);
408
409
    # Then ...
410
    is(scalar @missing_criticals_1, 1, 'Got the expected missing critical array size of 1 from check_branch_code with unexpected category code');
411
412
    is($missing_criticals_1[0]->{category_map}, 1, 'Got the expected 1 category_map from check_branch_code with unexpected category code');
413
    is($missing_criticals_1[0]->{key}, 'categorycode', 'Got the expected branchcode key from check_branch_code with unexpected category code');
414
    is($missing_criticals_1[0]->{line}, $line_number_1, 'Got the expected line number from check_branch_code with unexpected category code');
415
    is($missing_criticals_1[0]->{lineraw}, $borrowerline_1, 'Got the expected lineraw value from check_branch_code with unexpected category code');
416
    is($missing_criticals_1[0]->{value}, $categorycode_1, 'Got the expected value from check_branch_code with unexpected category code');
417
418
    # Given ... a known category code. Relies on database sample data.
419
    my $categorycode_2      = 'T';
420
    my $borrowerline_2      = 'some, line,'.$categorycode_2;
421
    my $line_number_2       = 801;
422
    my @missing_criticals_2 = ();
423
424
    # When ...
425
    Koha::Patrons::Import::check_borrower_category($categorycode_2, $borrowerline_2, $line_number_2, \@missing_criticals_2);
426
427
    # Then ...
428
    is(scalar @missing_criticals_2, 0, 'Got the expected missing critical array size of 0 from check_branch_code');
429
};
109
# ###### Test utility ###########
430
# ###### Test utility ###########
110
sub make_csv {
431
sub make_csv {
111
    my ($temp_dir, @lines) = @_;
432
    my ($temp_dir, @lines) = @_;
Lines 117-122 sub make_csv { Link Here
117
    return $filename;
438
    return $filename;
118
}
439
}
119
440
120
done_testing();
121
122
1;
441
1;
123
- 

Return to bug 12598