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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt (-42 / +49 lines)
Lines 23-34 Link Here
23
[% IF ( uploadborrowers ) %]
23
[% IF ( uploadborrowers ) %]
24
<h5>Import results :</h5>
24
<h5>Import results :</h5>
25
<ul>
25
<ul>
26
	<li>[% imported %] imported records [% IF ( lastimported ) %](last was [% lastimported %])[% END %]</li>
26
    <li>[% imported %] imported records [% IF ( lastimported ) %](last was [% lastimported %])[% END %]</li>
27
	<li>[% overwritten %] overwritten [% IF ( lastoverwritten ) %](last was [% lastoverwritten %])[% END %]</li>
27
    <li>[% overwritten %] overwritten [% IF ( lastoverwritten ) %](last was [% lastoverwritten %])[% END %]</li>
28
	<li>[% alreadyindb %] not imported because already in borrowers table and overwrite disabled [% IF ( lastalreadyindb ) %](last was [% lastalreadyindb %])[% END %]</li>
28
    <li>[% alreadyindb %] not imported because already in borrowers table and overwrite disabled [% IF ( lastalreadyindb ) %](last was [% lastalreadyindb %])[% END %]</li>
29
	<li>[% invalid %] not imported because they are not in the expected format [% IF ( lastinvalid ) %](last was [% lastinvalid %])[% END %]</li>
29
    <li>[% invalid %] not imported because they are not in the expected format [% IF ( lastinvalid ) %](last was [% lastinvalid %])[% END %]</li>
30
	<li>[% total %] records parsed</li>
30
    <li>[% total %] records parsed</li>
31
	<li><a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a></li>
31
    <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a></li>
32
</ul>
32
</ul>
33
  [% IF ( FEEDBACK ) %]
33
  [% IF ( FEEDBACK ) %]
34
  <br /><br />
34
  <br /><br />
Lines 48-94 Link Here
48
    </div>
48
    </div>
49
  [% END %]
49
  [% END %]
50
  [% IF ( ERRORS ) %]
50
  [% IF ( ERRORS ) %]
51
  <br /><br />
52
    <div>
51
    <div>
53
    <h5>Error analysis:</h5>
52
    <h5>Error analysis:</h5>
54
    <ul>
53
    [% IF download_errors %]
55
    [% FOREACH ERROR IN ERRORS %]
54
      <form method="post">
55
        <input type="hidden" name="errors_filename" value="[% errors_filename %]" />
56
        <input type="hidden" name="report" value="report" />
57
        <input type="submit" value="Download report" />
58
      </form>
59
    [% ELSE %]
60
      <ul>
61
      [% FOREACH ERROR IN ERRORS %]
56
        [% IF ( ERROR.badheader ) %]<li>Header row could not be parsed</li>[% END %]
62
        [% IF ( ERROR.badheader ) %]<li>Header row could not be parsed</li>[% END %]
57
        [% FOREACH missing_critical IN ERROR.missing_criticals %]
63
          [% FOREACH missing_critical IN ERROR.missing_criticals %]
58
        <li class="line_error">
64
          <li class="line_error">
59
            Line <span class="linenumber">[% missing_critical.line %]</span>
65
              Line <span class="linenumber">[% missing_critical.line %]</span>
60
            [% IF ( missing_critical.badparse ) %]
66
              [% IF ( missing_critical.badparse ) %]
61
                could not be parsed!
67
                  could not be parsed!
62
            [% ELSIF ( missing_critical.bad_date ) %]
68
              [% ELSIF ( missing_critical.bad_date ) %]
63
                has &quot;[% missing_critical.key %]&quot; in unrecognized format: &quot;[% missing_critical.value %]&quot;
69
                  has &quot;[% missing_critical.key %]&quot; in unrecognized format: &quot;[% missing_critical.value %]&quot;
64
            [% ELSE %]
70
              [% ELSE %]
65
                Critical field &quot;[% missing_critical.key %]&quot;
71
                  Critical field &quot;[% missing_critical.key %]&quot;
66
                [% IF ( missing_critical.branch_map ) %]has unrecognized value &quot;[% missing_critical.value %]&quot;
72
                  [% IF ( missing_critical.branch_map ) %]has unrecognized value &quot;[% missing_critical.value %]&quot;
67
                [% ELSIF ( missing_critical.category_map ) %]has unrecognized value &quot;[% missing_critical.value %]&quot;
73
                  [% ELSIF ( missing_critical.category_map ) %]has unrecognized value &quot;[% missing_critical.value %]&quot;
68
                [% ELSE %]missing
74
                  [% ELSE %]missing
69
                [% END %]
75
                  [% END %]
70
                (borrowernumber: [% missing_critical.borrowernumber %]; surname: [% missing_critical.surname %]).
76
                  (borrowernumber: [% missing_critical.borrowernumber %]; surname: [% missing_critical.surname %]).
71
            [% END %]
77
              [% END %]
72
            <br /><code>[% missing_critical.lineraw %]</code>
78
              <br /><code>[% missing_critical.lineraw %]</code>
73
        </li>
79
          </li>
74
        [% END %]
80
        [% END %]
75
    [% END %]
81
      [% END %]
76
    </ul>
82
    </ul>
83
    [% END %]
77
    </div>
84
    </div>
78
  [% END %]
85
  [% END %]
79
[% ELSE %]
86
[% ELSE %]
80
<ul>
87
<ul>
81
	<li>Select a file to import into the borrowers table</li>
88
    <li>Select a file to import into the borrowers table</li>
82
	<li>If a cardnumber exists in the table, you can choose whether to ignore the new one or overwrite the old one.</li>
89
    <li>If a cardnumber exists in the table, you can choose whether to ignore the new one or overwrite the old one.</li>
83
</ul>
90
</ul>
84
<form method="post" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
91
<form method="post" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
85
<fieldset class="rows">
92
<fieldset class="rows">
86
<legend>Import into the borrowers table</legend>
93
<legend>Import into the borrowers table</legend>
87
<ol>
94
<ol>
88
	<li>
95
    <li>
89
		<label for="uploadborrowers">Select the file to import: </label>
96
        <label for="uploadborrowers">Select the file to import: </label>
90
		<input type="file" id="uploadborrowers" name="uploadborrowers" />
97
        <input type="file" id="uploadborrowers" name="uploadborrowers" />
91
	</li>
98
    </li>
92
</ol></fieldset>
99
</ol></fieldset>
93
    <fieldset class="rows">
100
    <fieldset class="rows">
94
        <legend>Field to use for record matching</legend>
101
        <legend>Field to use for record matching</legend>
Lines 107-131 Link Here
107
<legend>Default values</legend>
114
<legend>Default values</legend>
108
<ol>
115
<ol>
109
    [% FOREACH columnkey IN columnkeys %]
116
    [% FOREACH columnkey IN columnkeys %]
110
	<li>
117
    <li>
111
        <label class="widelabel" for="[% columnkey.key %]">[% columnkey.key %]: </label>
118
        <label class="widelabel" for="[% columnkey.key %]">[% columnkey.key %]: </label>
112
		<input id="[% columnkey.key %]" name="[% columnkey.key %]" />
119
        <input id="[% columnkey.key %]" name="[% columnkey.key %]" />
113
	</li>
120
    </li>
114
    [% END %]
121
    [% END %]
115
</ol></fieldset>
122
</ol></fieldset>
116
	<fieldset class="rows">
123
    <fieldset class="rows">
117
	<legend>If matching record is already in the borrowers table:</legend>
124
    <legend>If matching record is already in the borrowers table:</legend>
118
    <ol><li class="radio">
125
    <ol><li class="radio">
119
        <input type="radio" id="overwrite_cardnumberno" name="overwrite_cardnumber" value="0" checked="checked" /><label for="overwrite_cardnumberno">Ignore this one, keep the existing one</label>
126
        <input type="radio" id="overwrite_cardnumberno" name="overwrite_cardnumber" value="0" checked="checked" /><label for="overwrite_cardnumberno">Ignore this one, keep the existing one</label>
120
        </li>
127
        </li>
121
        <li class="radio">
128
        <li class="radio">
122
		<input type="radio" id="overwrite_cardnumberyes" name="overwrite_cardnumber" value="1" /><label for="overwrite_cardnumberyes">Overwrite the existing one with this</label>
129
        <input type="radio" id="overwrite_cardnumberyes" name="overwrite_cardnumber" value="1" /><label for="overwrite_cardnumberyes">Overwrite the existing one with this</label>
123
        </li>
130
        </li>
124
    </ol>
131
    </ol>
125
    </fieldset>
132
    </fieldset>
126
    [% IF ( ExtendedPatronAttributes ) %]
133
    [% IF ( ExtendedPatronAttributes ) %]
127
	<fieldset class="rows">
134
    <fieldset class="rows">
128
	<legend>Patron Attributes</legend>
135
    <legend>Patron Attributes</legend>
129
    <ol><li class="radio">
136
    <ol><li class="radio">
130
        <input type="radio" id="ext_preserve_0" name="ext_preserve" value="0" checked="checked" /><label for="ext_preserve_0">Replace all Patron Attributes</label>
137
        <input type="radio" id="ext_preserve_0" name="ext_preserve" value="0" checked="checked" /><label for="ext_preserve_0">Replace all Patron Attributes</label>
131
        </li>
138
        </li>
Lines 135-141 Link Here
135
    </ol>
142
    </ol>
136
    </fieldset>
143
    </fieldset>
137
    [% END %]
144
    [% END %]
138
	<fieldset class="action"><input type="submit" value="Import" /></fieldset>
145
    <fieldset class="action"><input type="submit" value="Import" /></fieldset>
139
</form>
146
</form>
140
[% END %]
147
[% END %]
141
</div>
148
</div>
(-)a/tools/import_borrowers.pl (-33 / +103 lines)
Lines 1-7 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
# Copyright 2007 Liblime
3
# Copyright 2007 Liblime
4
# Parts copyright 2010 BibLibre
4
# Parts copyright 2013 BibLibre
5
#
5
#
6
# This file is part of Koha.
6
# This file is part of Koha.
7
#
7
#
Lines 34-41 Link Here
34
# dates should be in the format you have set up Koha to expect
34
# dates should be in the format you have set up Koha to expect
35
# branchcode and categorycode need to be valid
35
# branchcode and categorycode need to be valid
36
36
37
use strict;
37
use Modern::Perl;
38
use warnings;
39
38
40
use C4::Auth;
39
use C4::Auth;
41
use C4::Output;
40
use C4::Output;
Lines 46-53 use C4::Members; Link Here
46
use C4::Members::Attributes qw(:all);
45
use C4::Members::Attributes qw(:all);
47
use C4::Members::AttributeTypes;
46
use C4::Members::AttributeTypes;
48
use C4::Members::Messaging;
47
use C4::Members::Messaging;
49
48
use Koha::DateUtils;
49
use Date::Calc qw(Today_and_Now);
50
use Getopt::Long;
51
use File::Temp;
50
use Text::CSV;
52
use Text::CSV;
53
51
# Text::CSV::Unicode, even in binary mode, fails to parse lines with these diacriticals:
54
# Text::CSV::Unicode, even in binary mode, fails to parse lines with these diacriticals:
52
# ė
55
# ė
53
# č
56
# č
Lines 75-84 my ( $template, $loggedinuser, $cookie ) = get_template_and_user({ Link Here
75
        authnotrequired => 0,
78
        authnotrequired => 0,
76
        flagsrequired   => { tools => 'import_patrons' },
79
        flagsrequired   => { tools => 'import_patrons' },
77
        debug           => 1,
80
        debug           => 1,
78
});
81
    });
79
82
80
$template->param(columnkeys => $columnkeystpl);
83
$template->param(columnkeys => $columnkeystpl);
81
82
if ($input->param('sample')) {
84
if ($input->param('sample')) {
83
    print $input->header(
85
    print $input->header(
84
        -type       => 'application/vnd.sun.xml.calc', # 'application/vnd.ms-excel' ?
86
        -type       => 'application/vnd.sun.xml.calc', # 'application/vnd.ms-excel' ?
Lines 88-93 if ($input->param('sample')) { Link Here
88
    print $csv->string, "\n";
90
    print $csv->string, "\n";
89
    exit 1;
91
    exit 1;
90
}
92
}
93
94
if ($input->param('report')) {
95
    print $input->header(
96
        -type => 'text/plain',
97
        -attachment => 'import_borrowers_report.txt'
98
    );
99
    open my $fh, '<', $input->param('errors_filename');
100
    print $fh;
101
    close $fh;
102
    #TODO : We surely want to check that is it really a temp file that we are unlinking
103
    unlink $input->param('errors_filename');
104
    exit 1;
105
}
106
91
my $uploadborrowers = $input->param('uploadborrowers');
107
my $uploadborrowers = $input->param('uploadborrowers');
92
my $matchpoint      = $input->param('matchpoint');
108
my $matchpoint      = $input->param('matchpoint');
93
if ($matchpoint) {
109
if ($matchpoint) {
Lines 110-116 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
110
    my $alreadyindb = 0;
126
    my $alreadyindb = 0;
111
    my $overwritten = 0;
127
    my $overwritten = 0;
112
    my $invalid     = 0;
128
    my $invalid     = 0;
113
    my $matchpoint_attr_type; 
129
    my $matchpoint_attr_type;
114
    my %defaults = $input->Vars;
130
    my %defaults = $input->Vars;
115
131
116
    # use header line to construct key to column map
132
    # use header line to construct key to column map
Lines 121-131 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
121
    my %csvkeycol;
137
    my %csvkeycol;
122
    my $col = 0;
138
    my $col = 0;
123
    foreach my $keycol (@csvcolumns) {
139
    foreach my $keycol (@csvcolumns) {
124
    	# columnkeys don't contain whitespace, but some stupid tools add it
140
        # columnkeys don't contain whitespace, but some stupid tools add it
125
    	$keycol =~ s/ +//g;
141
        $keycol =~ s/ +//g;
126
        $csvkeycol{$keycol} = $col++;
142
        $csvkeycol{$keycol} = $col++;
127
    }
143
    }
128
    #warn($borrowerline);
144
129
    my $ext_preserve = $input->param('ext_preserve') || 0;
145
    my $ext_preserve = $input->param('ext_preserve') || 0;
130
    if ($extended) {
146
    if ($extended) {
131
        $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint);
147
        $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint);
Lines 137-142 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
137
    my @bad_dates;  # I've had a few.
153
    my @bad_dates;  # I've had a few.
138
    my $date_re = C4::Dates->new->regexp('syspref');
154
    my $date_re = C4::Dates->new->regexp('syspref');
139
    my  $iso_re = C4::Dates->new->regexp('iso');
155
    my  $iso_re = C4::Dates->new->regexp('iso');
156
    my $lastalreadyindb;
157
    my $lastinvalid;
140
    LINE: while ( my $borrowerline = <$handle> ) {
158
    LINE: while ( my $borrowerline = <$handle> ) {
141
        my %borrower;
159
        my %borrower;
142
        my @missing_criticals;
160
        my @missing_criticals;
Lines 152-174 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
152
                if ($borrower{$key} !~ /\S/) {
170
                if ($borrower{$key} !~ /\S/) {
153
                    $borrower{$key} = $defaults{$key};
171
                    $borrower{$key} = $defaults{$key};
154
                }
172
                }
155
            } 
173
            }
156
        } else {
174
        } else {
157
            # MJR: try to recover gracefully by using default values
175
            # MJR: try to recover gracefully by using default values
158
            foreach my $key (@columnkeys) {
176
            foreach my $key (@columnkeys) {
159
            	if (defined($csvkeycol{$key}) and $columns[$csvkeycol{$key}] =~ /\S/) { 
177
                if (defined($csvkeycol{$key}) and $columns[$csvkeycol{$key}] =~ /\S/) {
160
            	    $borrower{$key} = $columns[$csvkeycol{$key}];
178
                    $borrower{$key} = $columns[$csvkeycol{$key}];
161
            	} elsif ( $defaults{$key} ) {
179
                } elsif ( $defaults{$key} ) {
162
            	    $borrower{$key} = $defaults{$key};
180
                    $borrower{$key} = $defaults{$key};
163
            	} elsif ( scalar grep {$key eq $_} @criticals ) {
181
                } elsif ( scalar grep {$key eq $_} @criticals ) {
164
            	    # a critical field is undefined
182
                    # a critical field is undefined
165
            	    push @missing_criticals, {key=>$key, line=>$., lineraw=>$borrowerline};
183
                    push @missing_criticals, {key=>$key, line=>$., lineraw=>$borrowerline};
166
            	} else {
184
                } else {
167
            		$borrower{$key} = '';
185
                    $borrower{$key} = '';
168
            	}
186
                }
169
            }
187
            }
170
        }
188
        }
171
        #warn join(':',%borrower);
189
172
        if ($borrower{categorycode}) {
190
        if ($borrower{categorycode}) {
173
            push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline, value=>$borrower{categorycode}, category_map=>1}
191
            push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline, value=>$borrower{categorycode}, category_map=>1}
174
                unless GetBorrowercategory($borrower{categorycode});
192
                unless GetBorrowercategory($borrower{categorycode});
Lines 187-194 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
187
                $_->{surname}        = $borrower{surname} || 'UNDEF';
205
                $_->{surname}        = $borrower{surname} || 'UNDEF';
188
            }
206
            }
189
            $invalid++;
207
            $invalid++;
190
            (25 > scalar @errors) and push @errors, {missing_criticals=>\@missing_criticals};
208
            push @errors, {missing_criticals=>\@missing_criticals};
191
            # The first 25 errors are enough.  Keeping track of 30,000+ would destroy performance.
192
            next LINE;
209
            next LINE;
193
        }
210
        }
194
        if ($extended) {
211
        if ($extended) {
Lines 197-205 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
197
            $attr_str =~ s/\xe2\x80\x9d/"/g;
214
            $attr_str =~ s/\xe2\x80\x9d/"/g;
198
            push @feedback, {feedback=>1, name=>'attribute string', value=>$attr_str, filename=>$uploadborrowers};
215
            push @feedback, {feedback=>1, name=>'attribute string', value=>$attr_str, filename=>$uploadborrowers};
199
            delete $borrower{patron_attributes};    # not really a field in borrowers, so we don't want to pass it to ModMember.
216
            delete $borrower{patron_attributes};    # not really a field in borrowers, so we don't want to pass it to ModMember.
200
            $patron_attributes = extended_attributes_code_value_arrayref($attr_str); 
217
            $patron_attributes = extended_attributes_code_value_arrayref($attr_str);
201
        }
218
        }
202
	# Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
219
        # Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
203
        foreach (qw(dateofbirth dateenrolled dateexpiry)) {
220
        foreach (qw(dateofbirth dateenrolled dateexpiry)) {
204
            my $tempdate = $borrower{$_} or next;
221
            my $tempdate = $borrower{$_} or next;
205
            if ($tempdate =~ /$date_re/) {
222
            if ($tempdate =~ /$date_re/) {
Lines 211-218 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
211
                push @missing_criticals, {key=>$_, line=>$. , lineraw=>$borrowerline, bad_date=>1};
228
                push @missing_criticals, {key=>$_, line=>$. , lineraw=>$borrowerline, bad_date=>1};
212
            }
229
            }
213
        }
230
        }
214
	$borrower{dateenrolled} = $today_iso unless $borrower{dateenrolled};
231
        $borrower{dateenrolled} = $today_iso unless $borrower{dateenrolled};
215
	$borrower{dateexpiry} = GetExpiryDate($borrower{categorycode},$borrower{dateenrolled}) unless $borrower{dateexpiry}; 
232
        $borrower{dateexpiry} = GetExpiryDate($borrower{categorycode},$borrower{dateenrolled}) unless $borrower{dateexpiry};
216
        my $borrowernumber;
233
        my $borrowernumber;
217
        my $member;
234
        my $member;
218
        if ( ($matchpoint eq 'cardnumber') && ($borrower{'cardnumber'}) ) {
235
        if ( ($matchpoint eq 'cardnumber') && ($borrower{'cardnumber'}) ) {
Lines 231-242 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
231
                }
248
                }
232
            }
249
            }
233
        }
250
        }
234
            
251
235
        if ($borrowernumber) {
252
        if ($borrowernumber) {
236
            # borrower exists
253
            # borrower exists
237
            unless ($overwrite_cardnumber) {
254
            unless ($overwrite_cardnumber) {
238
                $alreadyindb++;
255
                $alreadyindb++;
239
                $template->param('lastalreadyindb'=>$borrower{'surname'}.' / '.$borrowernumber);
256
                $lastalreadyindb = $borrower{'surname'}.' / '.$borrowernumber;
257
                $template->param('lastalreadyindb'=>$lastalreadyindb);
240
                next LINE;
258
                next LINE;
241
            }
259
            }
242
            $borrower{'borrowernumber'} = $borrowernumber;
260
            $borrower{'borrowernumber'} = $borrowernumber;
Lines 255-261 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
255
                $invalid++;
273
                $invalid++;
256
                # untill we have better error trapping, we have no way of knowing why ModMember errored out...
274
                # untill we have better error trapping, we have no way of knowing why ModMember errored out...
257
                push @errors, {unknown_error => 1};
275
                push @errors, {unknown_error => 1};
258
                $template->param('lastinvalid'=>$borrower{'surname'}.' / '.$borrowernumber);
276
                $lastinvalid = $borrower{'surname'}.' / '.$borrowernumber;
277
                $template->param('lastinvalid'=>$lastinvalid);
259
                next LINE;
278
                next LINE;
260
            }
279
            }
261
            if ($extended) {
280
            if ($extended) {
Lines 301-306 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
301
        'total'           => $imported + $alreadyindb + $invalid + $overwritten,
320
        'total'           => $imported + $alreadyindb + $invalid + $overwritten,
302
    );
321
    );
303
322
323
    if (scalar(@errors) > 25 ) {
324
325
        my $total = $imported + $alreadyindb + $invalid + $overwritten;
326
        my $output;
327
328
        my $timestamp = output_pref( dt_from_string );
329
        $output .= "Timestamp : $timestamp\n";
330
        $output .= "Import results\n";
331
        $output .= "$imported imported records\n";
332
        $output .= "$overwritten overwritten records\n";
333
        $output .= "$alreadyindb not imported because already in borrowers table and overwrite disabled\n";
334
        $output .= "(last was $lastalreadyindb)\n" if ($lastalreadyindb);
335
        $output .= "$invalid not imported because they are not in the expected format\n";
336
        $output .= "(last was $lastinvalid)\n" if ($lastinvalid);
337
        $output .= "$total records parsed\n";
338
339
340
        $output .= "\nError analysis\n";
341
        foreach my $hash (@errors) {
342
            $output .= "Header row could not be parsed" if ($hash->{'badheader'});
343
            foreach my $array ($hash->{'missing_criticals'}) {
344
                foreach (@$array) {
345
                    $output .= "Line $_->{'line'}: ";
346
                    if ($hash->{'badparse'}) {
347
                        $output .= "could not be parsed!";
348
                    } elsif ($hash->{'bad_date'}) {
349
                        $output .= "has $_->{'key'} in unrecognized format: $_->{'value'} ";
350
                    } else {
351
                        $output .= "Critical field $_->{'key'}: ";
352
                        if ($_->{'branch_map'} || $_->{'category_map'}) {
353
                            $output .= "has unrecognized value: $_->{'value'}";
354
                        } else {
355
                            $output .= " missing";
356
                        }
357
                        $output .= " (borrowernumber: $_->{'borrowernumber'}; surname: $_->{'surname'})";
358
                    }
359
                    $output .= "\n";
360
                }
361
            }
362
        }
363
364
        if ( scalar(@errors) > 25 ) {
365
            my $tmpf = File::Temp->new(UNLINK => 0);
366
            print $tmpf $output;
367
            $template->param(
368
                download_errors => 1,
369
                errors_filename => $tmpf->filename
370
            );
371
            close $tmpf;
372
        }
373
374
    }
375
304
} else {
376
} else {
305
    if ($extended) {
377
    if ($extended) {
306
        my @matchpoints = ();
378
        my @matchpoints = ();
Lines 316-319 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
316
}
388
}
317
389
318
output_html_with_http_headers $input, $cookie, $template->output;
390
output_html_with_http_headers $input, $cookie, $template->output;
319
320
- 

Return to bug 5771