From 5cafd551beb9320247d3819781c260d1b6b29a13 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Mon, 12 May 2008 08:32:57 -0500 Subject: [PATCH] patron attributes - batch import When ExtendedPatronAttributes is ON, the batch patron import tool's behavior changes as follows: [1] A new (required) column is added to the input CSV format. This column should contain a list of attributes to set for the record, each value preceded by its type code. For example, if the superlibrarian has defined two types, a unique identifier INSTID and a repeatable BASEBALL, this field could contain: "INSTID:12345,BASEBALL:Cubs" This field must be wrapped in quotes if multiple values are defined. Since values can contain spaces, additional doubled-quotes may be required: "INSTID:12345,BASEBALL:Cubs,""BASEBALL:White Sox""" When replacing a patron record, any attributes specified in the input file replace all of the attribute values of any type that were previously assigned to the patron record. [2] It is possible to specify a field other than the cardnumber to use for looking for matching patrons. Specifically, any attribute marked as a unique ID can be used. The operator is asked to specify which ID type to use; if an input record has an attribute value of that type, and exactly one patron record in the database has that value, then the record will be overlaid or ignored according to the overlay setting. Signed-off-by: Joshua Ferraro --- .../en/modules/tools/import_borrowers.tmpl | 23 +++++- tools/import_borrowers.pl | 73 ++++++++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tmpl index d696449ecc..17184392f4 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tmpl @@ -40,8 +40,21 @@ +
+ Field to use for record matching +
    +
  1. + +
  2. +
+
- If cardnumber is already in the borrowers table:
  1. + If matching record is already in the borrowers table:
    1. @@ -66,8 +79,14 @@ 'debarred', 'contactname', 'contactfirstname', 'contacttitle', 'borrowernotes', 'relationship', 'ethnicity', 'ethnotes', 'sex', 'userid', 'opacnote', 'contactnote', - 'password', 'sort1', 'sort2' + 'password', 'sort1', 'sort2', 'patron_attributes'
    2. + +
    3. If loading patron attributes, the 'patron_attributes' field should contain a comma-separated list of attribute types +and values. The attribute type code and a ':' should precede each value. For example: "INSTID:12345,LANG:fr". This +means that if an input record has more than one attribute, the 'patron_attributes' field must be wrapped in double quotation marks. +
    4. +
    5. Please make sure the 'branchcode' and 'categorycode' are valid entries in your database.
    6. password should be stored in plaintext, and will be converted to a md5 hash (if your passwords are already encrypted, talk to your systems administrator about options).
    7. diff --git a/tools/import_borrowers.pl b/tools/import_borrowers.pl index db448ab0f9..a58e0da4f7 100755 --- a/tools/import_borrowers.pl +++ b/tools/import_borrowers.pl @@ -39,6 +39,8 @@ use C4::Output; use C4::Dates qw(format_date_in_iso); use C4::Context; use C4::Members; +use C4::Members::Attributes; +use C4::Members::AttributeTypes; use Text::CSV; use CGI; @@ -57,6 +59,9 @@ my @columnkeys = ( 'sex', 'userid', 'opacnote', 'contactnote', 'password', 'sort1', 'sort2' ); +if (C4::Context->preference('ExtendedPatronAttributes')) { + push @columnkeys, 'patron_attributes'; +} my $input = new CGI; @@ -72,40 +77,87 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( ); my $uploadborrowers = $input->param('uploadborrowers'); +my $matchpoint = $input->param('matchpoint'); +if ($matchpoint) { + $matchpoint =~ s/^patron_attribute_//; +} my $overwrite_cardnumber = $input->param('overwrite_cardnumber'); $template->param( SCRIPT_NAME => $ENV{'SCRIPT_NAME'} ); +if (C4::Context->preference('ExtendedPatronAttributes')) { + $template->param(ExtendedPatronAttributes => 1); +} + if ( $uploadborrowers && length($uploadborrowers) > 0 ) { my $csv = Text::CSV->new(); my $imported = 0; my $alreadyindb = 0; my $overwritten = 0; my $invalid = 0; + my $matchpoint_attr_type; + + if (C4::Context->preference('ExtendedPatronAttributes')) { + $matchpoint_attr_type = C4::Members::AttributeTypes->fetch($matchpoint); + } + while ( my $borrowerline = <$uploadborrowers> ) { my $status = $csv->parse($borrowerline); my @columns = $csv->fields(); my %borrower; + my $patron_attributes; if ( @columns == @columnkeys ) { @borrower{@columnkeys} = @columns; + my @attrs; + if (C4::Context->preference('ExtendedPatronAttributes')) { + my $attr_str = $borrower{patron_attributes}; + delete $borrower{patron_attributes}; + my $ok = $csv->parse($attr_str); + my @list = $csv->fields(); + # FIXME error handling + $patron_attributes = [ map { map { my @arr = split /:/, $_, 2; { code => $arr[0], value => $arr[1] } } $_ } @list ]; + } foreach (qw(dateofbirth dateenrolled dateexpiry)) { my $tempdate = $borrower{$_} or next; $borrower{$_} = format_date_in_iso($tempdate) || ''; } - if ( my $member = - GetMember( $borrower{'cardnumber'}, 'cardnumber' ) ) + my $borrowernumber; + if ($matchpoint eq 'cardnumber') { + my $member = GetMember( $borrower{'cardnumber'}, 'cardnumber' ); + if ($member) { + $borrowernumber = $member->{'borrowernumber'}; + } + } elsif (C4::Context->preference('ExtendedPatronAttributes')) { + 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 if ($overwrite_cardnumber) { - $borrower{'borrowernumber'} = $member->{'borrowernumber'}; + $borrower{'borrowernumber'} = $borrowernumber; ModMember(%borrower); + if (C4::Context->preference('ExtendedPatronAttributes')) { + C4::Members::Attributes::SetBorrowerAttributes($borrower{'borrowernumber'}, $patron_attributes); + } $overwritten++; } else { $alreadyindb++; } } else { - if (AddMember(%borrower)) { + if ($borrowernumber = AddMember(%borrower)) { + if (C4::Context->preference('ExtendedPatronAttributes')) { + C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $patron_attributes); + } $imported++; } else { $invalid++; # was just "$invalid", I assume incrementing was the point --atz @@ -125,6 +177,19 @@ if ( $uploadborrowers && length($uploadborrowers) > 0 ) { 'total' => $imported + $alreadyindb + $invalid + $overwritten, ); +} else { + if (C4::Context->preference('ExtendedPatronAttributes')) { + my @matchpoints = (); + my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes(); + foreach my $type (@attr_types) { + my $attr_type = C4::Members::AttributeTypes->fetch($type->{code}); + if ($attr_type->unique_id()) { + push @matchpoints, { code => "patron_attribute_" . $attr_type->code(), description => $attr_type->description() }; + } + } + $template->param(matchpoints => \@matchpoints); + } } + output_html_with_http_headers $input, $cookie, $template->output; -- 2.39.5