- push @feedback, {feedback=>1, name=>'headerrow', value=>join(', ', @csvcolumns)};
- my $today_iso = C4::Dates->new()->output('iso');
- my @criticals = qw(surname branchcode categorycode); # there probably should be others
- my @bad_dates; # I've had a few.
- my $date_re = C4::Dates->new->regexp('syspref');
- my $iso_re = C4::Dates->new->regexp('iso');
- LINE: while ( my $borrowerline = <$handle> ) {
- my %borrower;
- my @missing_criticals;
- my $patron_attributes;
- my $status = $csv->parse($borrowerline);
- my @columns = $csv->fields();
- if (! $status) {
- push @missing_criticals, {badparse=>1, line=>$., lineraw=>$borrowerline};
- } elsif (@columns == @columnkeys) {
- @borrower{@columnkeys} = @columns;
- # MJR: try to fill blanks gracefully by using default values
- foreach my $key (@columnkeys) {
- if ($borrower{$key} !~ /\S/) {
- $borrower{$key} = $defaults{$key};
- }
- }
- } else {
- # MJR: try to recover gracefully by using default values
- foreach my $key (@columnkeys) {
- if (defined($csvkeycol{$key}) and $columns[$csvkeycol{$key}] =~ /\S/) {
- $borrower{$key} = $columns[$csvkeycol{$key}];
- } elsif ( $defaults{$key} ) {
- $borrower{$key} = $defaults{$key};
- } elsif ( scalar grep {$key eq $_} @criticals ) {
- # a critical field is undefined
- push @missing_criticals, {key=>$key, line=>$., lineraw=>$borrowerline};
- } else {
- $borrower{$key} = '';
- }
- }
- }
- #warn join(':',%borrower);
- if ($borrower{categorycode}) {
- push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline, value=>$borrower{categorycode}, category_map=>1}
- unless GetBorrowercategory($borrower{categorycode});
- } else {
- push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline};
- }
- if ($borrower{branchcode}) {
- push @missing_criticals, {key=>'branchcode', line=>$. , lineraw=>$borrowerline, value=>$borrower{branchcode}, branch_map=>1}
- unless GetBranchName($borrower{branchcode});
- } else {
- push @missing_criticals, {key=>'branchcode', line=>$. , lineraw=>$borrowerline};
- }
- if (@missing_criticals) {
- foreach (@missing_criticals) {
- $_->{borrowernumber} = $borrower{borrowernumber} || 'UNDEF';
- $_->{surname} = $borrower{surname} || 'UNDEF';
- }
- $invalid++;
- (25 > scalar @errors) and push @errors, {missing_criticals=>\@missing_criticals};
- # The first 25 errors are enough. Keeping track of 30,000+ would destroy performance.
- next LINE;
- }
- if ($extended) {
- my $attr_str = $borrower{patron_attributes};
- $attr_str =~ s/\xe2\x80\x9c/"/g; # fixup double quotes in case we are passed smart quotes
- $attr_str =~ s/\xe2\x80\x9d/"/g;
- push @feedback, {feedback=>1, name=>'attribute string', value=>$attr_str, filename=>$uploadborrowers};
- delete $borrower{patron_attributes}; # not really a field in borrowers, so we don't want to pass it to ModMember.
- $patron_attributes = extended_attributes_code_value_arrayref($attr_str);
- }
- # Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
- foreach (qw(dateofbirth dateenrolled dateexpiry)) {
- my $tempdate = $borrower{$_} or next;
- if ($tempdate =~ /$date_re/) {
- $borrower{$_} = format_date_in_iso($tempdate);
- } elsif ($tempdate =~ /$iso_re/) {
- $borrower{$_} = $tempdate;
- } else {
- $borrower{$_} = '';
- push @missing_criticals, {key=>$_, line=>$. , lineraw=>$borrowerline, bad_date=>1};
- }
- }
- $borrower{dateenrolled} = $today_iso unless $borrower{dateenrolled};
- $borrower{dateexpiry} = GetExpiryDate($borrower{categorycode},$borrower{dateenrolled}) unless $borrower{dateexpiry};
- my $borrowernumber;
- my $member;
- if ( ($matchpoint eq 'cardnumber') && ($borrower{'cardnumber'}) ) {
- $member = GetMember( 'cardnumber' => $borrower{'cardnumber'} );
- if ($member) {
- $borrowernumber = $member->{'borrowernumber'};
- }
- } elsif ($extended) {
- if (defined($matchpoint_attr_type)) {
- foreach my $attr (@$patron_attributes) {
- if ($attr->{code} eq $matchpoint and $attr->{value} ne '') {
- my @borrowernumbers = $matchpoint_attr_type->get_patrons($attr->{value});
- $borrowernumber = $borrowernumbers[0] if scalar(@borrowernumbers) == 1;
- last;
- }
- }
- }
- }
-
- if ($borrowernumber) {
- # borrower exists
- unless ($overwrite_cardnumber) {
- $alreadyindb++;
- $template->param('lastalreadyindb'=>$borrower{'surname'}.' / '.$borrowernumber);
- next LINE;
- }
- $borrower{'borrowernumber'} = $borrowernumber;
- for my $col (keys %borrower) {
- # use values from extant patron unless our csv file includes this column or we provided a default.
- # FIXME : You cannot update a field with a perl-evaluated false value using the defaults.