From 58b5c1a68f5cdad77868abc2f017e180e768fd33 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Fri, 5 Mar 2021 09:13:34 -0500 Subject: [PATCH] Bug 27883: Add ability to preserve patron field from being overwritten by import Some libraries would like to be able to preserve particular fields for existing patrons when overwriting them via the patron import tool. Effectively, this means the specified columns of the CSV are used for new patrons, but ignored for existing patrons. Test Plan: 1) Create a patron CSV with one new patron, make the surname and firstname "Test1". Add a cardnumber so we can upload it again later. 2) Import the file 3) Change the firstname and surname in the CSV to "Test2" 4) Return to the patron import tool, choose to match on cardnumber, overwrite existing patrons, and preserve exiting firstnames 5) Import the file with these settings 6) Referesh the patron details for this patron, the patron's surname should still be "Test" while the firstname should now be "Test2" Signed-off-by: David Nind Signed-off-by: Martin Renvoize Signed-off-by: Jonathan Druart --- Koha/Patrons/Import.pm | 8 +++++ .../prog/en/modules/tools/import_borrowers.tt | 23 +++++++++++++ misc/import_patrons.pl | 25 +++++++++------ t/db_dependent/Koha/Patrons/Import.t | 32 ++++++++++++++++++- tools/import_borrowers.pl | 7 ++-- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/Koha/Patrons/Import.pm b/Koha/Patrons/Import.pm index 9347d03781..cd6f4aa303 100644 --- a/Koha/Patrons/Import.pm +++ b/Koha/Patrons/Import.pm @@ -70,6 +70,7 @@ sub import_patrons { my $matchpoint = $params->{matchpoint}; my $defaults = $params->{defaults}; + my $preserve_fields = $params->{preserve_fields}; my $ext_preserve = $params->{preserve_extended_attributes}; my $overwrite_cardnumber = $params->{overwrite_cardnumber}; my $overwrite_passwords = $params->{overwrite_passwords}; @@ -257,6 +258,13 @@ sub import_patrons { next LINE; } $borrower{'borrowernumber'} = $borrowernumber; + + if ( $preserve_fields ) { + for my $field ( @$preserve_fields ) { + $borrower{$field} = $patron->$field; + } + } + for my $col ( keys %borrower ) { # use values from extant patron unless our csv file includes this column or we provided a default. diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt index 4237c8fcc9..9d2aa4cdc1 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt @@ -290,6 +290,23 @@ +
+ + Preserve existing values + + + + +
If matching record is already in the borrowers table: @@ -399,6 +416,12 @@ you can supply dates in ISO format (e.g., '2010-10-28'). $(".default_values").toggle(); $(".expand_defaults").toggle(); }); + + $(".expand_preserves").click(function(e){ + e.preventDefault(); + $(".preserve_values").toggle(); + $(".expand_preserves").toggle(); + }); }); $("#overwrite_cardnumberno").click(function(){ diff --git a/misc/import_patrons.pl b/misc/import_patrons.pl index b3bbb66e87..ee0d8a92c9 100755 --- a/misc/import_patrons.pl +++ b/misc/import_patrons.pl @@ -35,17 +35,19 @@ my $ext_preserve = 0; my $confirm; my $verbose = 0; my $help; +my @preserve_fields; GetOptions( - 'c|confirm' => \$confirm, - 'f|file=s' => \$csv_file, - 'm|matchpoint=s' => \$matchpoint, - 'd|default=s' => \%defaults, - 'o|overwrite' => \$overwrite_cardnumber, - 'op|overwrite_passwords' => \$overwrite_passwords, + 'c|confirm' => \$confirm, + 'f|file=s' => \$csv_file, + 'm|matchpoint=s' => \$matchpoint, + 'd|default=s' => \%defaults, + 'o|overwrite' => \$overwrite_cardnumber, + 'op|overwrite_passwords' => \$overwrite_passwords, 'p|preserve-extended-attributes' => \$ext_preserve, - 'v|verbose+' => \$verbose, - 'h|help|?' => \$help, + 'pf|preserve-field=s' => \@preserve_fields, + 'v|verbose+' => \$verbose, + 'h|help|?' => \$help, ) or pod2usage(2); pod2usage(1) if $help; @@ -65,6 +67,7 @@ my $return = $Import->import_patrons( overwrite_cardnumber => $overwrite_cardnumber, overwrite_passwords => $overwrite_passwords, preserve_extended_attributes => $ext_preserve, + preserve_fields => \@preserve_fields, dry_run => !$confirm, } ); @@ -104,7 +107,7 @@ import_patrons.pl - CLI script to import patrons data into Koha =head1 SYNOPSIS -import_patrons.pl --file /path/to/patrons.csv --matchpoint cardnumber --confirm [--default branchcode=MPL] [--overwrite] [--preserve-extended-attributes] [--verbose] +import_patrons.pl --file /path/to/patrons.csv --matchpoint cardnumber --confirm [--default branchcode=MPL] [--overwrite] [--preserve_field ] [--preserve-extended-attributes] [--verbose] =head1 OPTIONS @@ -130,6 +133,10 @@ Field on which to match incoming patrons to existing patrons Set defaults to patron fields, repeatable e.g. --default branchcode=MPL --default categorycode=PT +=item B<-k|--preserve-field> + +Prevent specified patron fields for existing patrons from being overwritten + =item B<-o|--overwrite> Overwrite existing patrons with new data if a match is found diff --git a/t/db_dependent/Koha/Patrons/Import.t b/t/db_dependent/Koha/Patrons/Import.t index 4cdcb3b741..0d1eb8ff1e 100755 --- a/t/db_dependent/Koha/Patrons/Import.t +++ b/t/db_dependent/Koha/Patrons/Import.t @@ -18,7 +18,7 @@ # along with Koha; if not, see . use Modern::Perl; -use Test::More tests => 161; +use Test::More tests => 173; use Test::Warn; use Test::Exception; use Encode qw( encode_utf8 ); @@ -93,6 +93,7 @@ my $csv_headers = 'cardnumber,surname,firstname,title,othernames,initials,stree my $res_header = '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'; my $csv_one_line = '1000,Nancy,Jenkins,Dr,,NJ,78,Circle,Bunting,El Paso,Henderson,Texas,79984,United States,ajenkins0@sourceforge.net,7-(388)559-6763,3-(373)151-4471,8-(509)286-4001,10/16/1965,CPL,PT,12/28/2014,07/01/2015,jjenkins0,DPQILy'; my $csv_one_line_a = '1001,Nancy,Jenkins,Dr,,NJ,78,Circle,Bunting,El Paso,Henderson,Texas,79984,United States,ajenkins0@sourceforge.net,7-(388)559-6763,3-(373)151-4471,8-(509)286-4001,10/16/1965,CPL,PT,12/28/2014,07/01/2015,jjenkins0,DPQILy'; +my $csv_one_line_b = '1000,Nancy2,Jenkins2,Dr,,NJ,78,Circle,Bunting,El Paso,Henderson,Texas,79984,United States,ajenkins0@sourceforge.net,7-(388)559-6763,3-(373)151-4471,8-(509)286-4001,10/16/1965,CPL,PT,12/28/2014,07/01/2015,jjenkins0,DPQILy'; my $filename_1 = make_csv($temp_dir, $csv_headers, $csv_one_line); open(my $handle_1, "<", $filename_1) or die "cannot open < $filename_1: $!"; @@ -184,6 +185,35 @@ is($result_3a->{imported}, 0, 'Got the expected 0 imported result from import_pa is($result_3a->{invalid}, 0, 'Got the expected 0 invalid result from import_patrons'); is($result_3a->{overwritten}, 1, 'Got the expected 1 overwritten result from import_patrons that matched'); +# Given ... valid file handle, good matchpoint that matches should overwrite when set, surname is protected from +# overwrite but firstname is not +my $filename_3c = make_csv($temp_dir, $csv_headers, $csv_one_line_b); +open(my $handle_3c, "<", $filename_3c) or die "cannot open < $filename_3: $!"; +my $params_3c = { file => $handle_3c, matchpoint => 'cardnumber', overwrite_cardnumber => 1, preserve_fields => [ 'firstname' ] }; + +# When ... +my $result_3c; +warning_is { $result_3c = $patrons_import->import_patrons($params_3c) } + undef, + "No warning raised by import_patrons"; + +# Then ... +is($result_3c->{already_in_db}, 0, 'Got the expected 0 already_in_db from import_patrons when matched and overwrite set'); +is($result_3c->{errors}->[0]->{duplicate_userid}, undef, 'No duplicate userid error from import patrons with duplicate userid (it is our own)'); +is($result_3c->{errors}->[0]->{userid}, undef, 'No duplicate userid error from import patrons with duplicate userid (it is our own)'); + +is($result_3c->{feedback}->[0]->{feedback}, 1, 'Got 1 expected feedback from import_patrons that matched and overwritten'); +is($result_3c->{feedback}->[0]->{name}, 'headerrow', 'Got the expected header row name from import_patrons with duplicate userid'); +is($result_3c->{feedback}->[0]->{value}, $res_header, 'Got the expected header row value from import_patrons with duplicate userid'); + +is($result_3c->{imported}, 0, 'Got the expected 0 imported result from import_patrons'); +is($result_3c->{invalid}, 0, 'Got the expected 0 invalid result from import_patrons'); +is($result_3c->{overwritten}, 1, 'Got the expected 1 overwritten result from import_patrons that matched'); + +my $patron_3c = Koha::Patrons->find({ cardnumber => '1000' }); +is( $patron_3c->surname, "Nancy2", "Surname field is preserved from original" ); +is( $patron_3c->firstname, "Jenkins", "Firstname field is overwritten" ); + # Given ... valid file handle, good matchpoint that does not match and conflicting userid. my $filename_3b = make_csv($temp_dir, $csv_headers, $csv_one_line_a); open(my $handle_3b, "<", $filename_3b) or die "cannot open < $filename_3: $!"; diff --git a/tools/import_borrowers.pl b/tools/import_borrowers.pl index efb205ee22..9d9eedffee 100755 --- a/tools/import_borrowers.pl +++ b/tools/import_borrowers.pl @@ -93,6 +93,8 @@ if ( $input->param('sample') ) { exit 0; } +my @preserve_fields = $input->param('preserve_existing'); + my $uploadborrowers = $input->param('uploadborrowers'); my $matchpoint = $input->param('matchpoint'); if ($matchpoint) { @@ -122,9 +124,10 @@ if ( $uploadborrowers && length($uploadborrowers) > 0 ) { file => $handle, defaults => \%defaults, matchpoint => $matchpoint, - overwrite_cardnumber => scalar $input->param('overwrite_cardnumber'), + overwrite_cardnumber => scalar $input->param( 'overwrite_cardnumber' ), overwrite_passwords => $overwrite_passwords, - preserve_extended_attributes => scalar $input->param('ext_preserve') || 0, + preserve_extended_attributes => scalar $input->param( 'ext_preserve' ) || 0, + preserve_fields => \@preserve_fields, } ); -- 2.39.5