From 1bcc0e78b7398f95b074e75fa1c147e192dff4f7 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" --- Koha/Patrons/Import.pm | 10 +++++- .../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, 84 insertions(+), 13 deletions(-) diff --git a/Koha/Patrons/Import.pm b/Koha/Patrons/Import.pm index d951bf54ed..68c41bf8b6 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}; @@ -241,7 +242,7 @@ sub import_patrons { if exists $borrower{$field} and $borrower{$field} eq ""; } - if ($borrowernumber) { + if ($borrowernumber) { # borrower exists unless ($overwrite_cardnumber) { @@ -256,6 +257,13 @@ sub import_patrons { next LINE; } $borrower{'borrowernumber'} = $borrowernumber; + + if ( $preserve_fields ) { + for my $field ( @$preserve_fields ) { + delete $borrower{$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 5ed7f2b7d6..ffa0793273 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 @@ -234,6 +234,23 @@ +
+ + Preserve existing values + + + + +
If matching record is already in the borrowers table: @@ -343,6 +360,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..ee968e7520 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 @columns_to_remove; 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' => \@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 522cf1ad79..4627133412 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 => 160; +use Test::More tests => 172; use Test::Warn; use Encode qw( encode_utf8 ); use utf8; @@ -92,6 +92,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: $!"; @@ -183,6 +184,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 a0c4bfbc01..cdb39415ed 100755 --- a/tools/import_borrowers.pl +++ b/tools/import_borrowers.pl @@ -94,6 +94,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) { @@ -123,9 +125,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.24.1 (Apple Git-126)