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 95f75deb70..6734b1ef8a 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 @@ -7,8 +7,8 @@ [% INCLUDE 'doc-head-open.inc' %] [% FILTER collapse %] - [% IF ( uploadborrowers ) %] - [% t("Results") | html %] + [% IF op == 'enqueued' %] + [% t("Job enqueued") | html %] › [% END %] [% t("Import patrons") | html %] @@ -39,12 +39,12 @@ [% WRAPPER breadcrumb_item %] <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> [% END %] - [% IF ( uploadborrowers ) %] + [% IF op == 'enqueued' %] [% WRAPPER breadcrumb_item %] <a href="/cgi-bin/koha/tools/import_borrowers.pl">Import patrons</a> [% END %] [% WRAPPER breadcrumb_item bc_active= 1 %] - <span>Results</span> + <span>Job enqueued</span> [% END %] [% ELSE %] [% WRAPPER breadcrumb_item bc_active= 1 %] @@ -57,151 +57,20 @@ [% WRAPPER 'main-container.inc' aside='tools-menu' %] <h1>Import patrons</h1> <div class="row"> - [% IF ( uploadborrowers ) %] + [% IF op == 'enqueued' %] <div class="col-sm-6"> - <h2>Import results</h2> - <ul> - <li> - [% tpx("Patron import", "{count_of_imported_records} imported records", {count_of_imported_records = imported}) | html %] - [% IF ( lastimported ) %] - [% tpx("Patron import", "(last was {last_imported_record})", {last_imported_record = lastimported}) | html %] - [% END %] - </li> - [% IF imported and patronlistname %] - <li>Patron list with imported patrons: [% patronlistname | html %]</li> - [% END %] - <li> - [% tpx("Patron import", "{count_of_overwritten_records} overwritten records", {count_of_overwritten_records = overwritten}) | html %] - [% IF ( lastoverwritten ) %] - [% tpx("Patron import", "(last was {last_overwritten_record})", {last_overwritten_record = lastoverwritten}) | html %] - [% END %] - </li> - <li> - [% tpx("Patron import", "{count_of_existing_records} not imported because they are already in borrowers table and overwrite is disabled ", {count_of_existing_records = alreadyindb}) | html %] - [% IF ( lastalreadyindb ) %] - [% tpx("Patron import", "(last was {last_existing_record})", {last_existing_record = lastalreadyindb}) | html %] - [% END %] - </li> - <li> - [% tpx("Patron import", "{count_of_invalid_records} not imported because they are not in the expected format", {count_of_invalid_records = invalid}) | html %] - [% IF ( lastinvalid ) %] - [% tpx("Patron import", "(last was {last_invalid_record})", {last_invalid_record = lastinvalid}) | html %] - [% END %] </li - ><li> [% tpx("Patron import", "{total} records parsed", {total = total}) | html %] </li> - <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a></li> - </ul> - - [% IF ( feedback ) %] - <br /><br /> - - <div> - <h2>Feedback</h2> - <ul class="feedback"> - [% FOREACH f IN feedback %] - <li> - [% IF ( f.filename ) %] - <span>Parsing upload file</span> <span class="filename">[% f.filename | html %]</span> - [% ELSIF ( f.backend ) %] - <span>Upload parsed using [% f.backend | html %]</span> - [% ELSIF ( f.headerrow ) %] - <span>These fields found: [% f.value | html %]</span> - [% ELSIF ( f.already_in_db ) %] - <span>Patron already in database: [% f.value | html %]</span> - [% ELSE %] - [% f.name | html %] - : [% f.value | html %] - [% END %] - </li> - [% END %] - </ul> - </div> - [% END %] - - [% IF ( errors ) %] - <br /><br /> - - <div> - <h2>Error analysis</h2> - <ul> - [% FOREACH e IN errors %] - [% IF ( e.badheader ) %]<li>Header row could not be parsed</li>[% END %] - - [% FOREACH missing_critical IN e.missing_criticals %] - <li class="line_error"> - Line <span class="linenumber">[% missing_critical.line | html %]</span> - - [% IF ( missing_critical.badparse ) %] - <span>could not be parsed!</span> - [% ELSIF ( missing_critical.bad_date ) %] - <span>has "[% missing_critical.key | html %]" in unrecognized format:</span> "[% missing_critical.value | html %]" - [% ELSE %] - <span>Critical field "[% missing_critical.key | html %]"</span> - - [% IF ( missing_critical.branch_map ) %] - <span>has unrecognized value "[% missing_critical.value | html %]"</span> - [% ELSIF ( missing_critical.category_map ) %] - <span>has unrecognized value "[% missing_critical.value | html %]"</span> - [% ELSE %] - <span>missing</span> - [% END %] - (<span>borrowernumber: [% missing_critical.borrowernumber | html %]</span>; <span>surname: [% missing_critical.surname | html %]</span>). - [% END %] - - <br /> - <code>[% missing_critical.lineraw | html %]</code> - </li> - [% END %] - - [% IF e.invalid_cardnumber %] - <li class="line_error"> Card number [% e.cardnumber | html %] is not a valid card number [% IF e.borrowernumber %](for patron with borrowernumber [% e.borrowernumber | html %])[% END %] </li> - [% END %] - [% IF e.duplicate_userid %] - <li class="line_error"> Userid [% e.userid | html %] is already used by another patron. </li> - [% END %] - [% IF e.passwd_too_short %] - <li class="line_error"> Password is too short for patron with borrowernumber [% e.borrowernumber | html %]. Minimum length is [% e.min_length | html %], length is [% e.length | html %] </li> - [% END %] - [% IF e.passwd_whitespace %] - <li class="line_error"> Password contains whitespace for patron with borrowernumber [% e.borrowernumber | html %]. </li> - [% END %] - [% IF e.passwd_too_weak %] - <li class="line_error"> Password is too weak for patron with borrowernumber [% e.borrowernumber | html %]. </li> - [% END %] - [% IF e.passwd_plugin_err %] - <li class="line_error"> Password plugin error for patron with borrowernumber [% e.borrowernumber | html %]. </li> - [% END %] - [% IF e.passwd_unknown_err %] - <li class="line_error"> Password error for patron with borrowernumber [% e.borrowernumber | html %]. </li> - [% END %] - [% IF e.patron_attribute_unique_id_constraint %] - <li class="line_error"> - [% IF e.borrowernumber %] - <span>Patron attribute [% e.attribute.code | html %] must be unique for patron with borrowernumber [% e.borrowernumber | html %].</span> - [% ELSE %] - <span>Patron attribute [% e.attribute.code | html %] must be unique for patron [% e.patron_id | html %].</span> - [% END %] - </li> - [% END %] - [% IF e.patron_attribute_invalid_type %] - <li class="line_error"> - [% IF e.borrowernumber %] - <span>Patron attribute [% e.attribute_type_code | html %] is invalid for patron with borrowernumber [% e.borrowernumber | html %].</span> - [% ELSE %] - <span>Patron attribute [% e.attribute_type_code | html %] is invalid for patron [% e.patron_id | html %].</span> - [% END %] - </li> - [% END %] - [% IF e.patron_attribute_non_repeatable %] - <li class="line_error"> - [% IF e.borrowernumber %] - <span>Patron attribute [% e.attribute.code | html %] is non-repeatable for patron with borrowernumber [% e.borrowernumber | html %].</span> - [% ELSE %] - <span>Patron attribute [% e.attribute.code | html %] is non-repeatable for patron [% e.patron_id | html %].</span> - [% END %] - </li> - [% END %] - [% END %] - </ul> + [% IF error == 'cannot_enqueue_job' %] + <div class="alert alert-danger">The import job could not be enqueued. Please try again.</div> + [% ELSE %] + <div class="alert alert-info"> + <h1>The patron import job has been enqueued!</h1> + <p> + <a href="/cgi-bin/koha/admin/background_jobs.pl?op=view&id=[% job_id | uri %]">View the import results</a> + | + <a href="/cgi-bin/koha/tools/import_borrowers.pl">Import more patrons</a> + | + <a href="/cgi-bin/koha/tools/tools-home.pl">Back to Tools</a> + </p> </div> [% END %] </div> diff --git a/tools/import_borrowers.pl b/tools/import_borrowers.pl index eed7265758..92c729757b 100755 --- a/tools/import_borrowers.pl +++ b/tools/import_borrowers.pl @@ -36,19 +36,16 @@ use Modern::Perl; +use Try::Tiny qw( catch try ); + use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_and_exit output_html_with_http_headers ); +use Koha::BackgroundJob::PatronImport; use Koha::Database::Columns; -use Koha::Patrons; use Koha::DateUtils qw( dt_from_string ); -use Koha::Token; -use Koha::Libraries; -use Koha::Patron::Categories; use Koha::Patron::Attribute::Types; -use Koha::List::Patron qw( AddPatronList AddPatronsToList ); - -use Koha::Patrons::Import; -my $Import = Koha::Patrons::Import->new(); +use Koha::Patron::Categories; +use Koha::Patrons; use Text::CSV; @@ -105,58 +102,48 @@ my $timestamp = $dt->ymd('-') . ' ' . $dt->hms(':'); if ( $op eq 'cud-import' && $uploadborrowers && length($uploadborrowers) > 0 ) { - my $patronlistname = $uploadborrowers . ' (' . $timestamp . ')'; - my $handle = $input->upload('uploadborrowers'); - my %defaults = $input->Vars; + my $handle = $input->upload('uploadborrowers'); + my $file_content = do { local $/; <$handle> }; + my $patronlistname = $uploadborrowers . ' (' . $timestamp . ')'; + + my %defaults; + for my $k (@columnkeys) { + my $v = scalar $input->param($k); + $defaults{$k} = $v if defined $v && length $v; + } + my $overwrite_passwords = defined $input->param('overwrite_passwords') ? 1 : 0; my $update_dateexpiry = $input->param('update_dateexpiry') // ""; - my $return = $Import->import_patrons( - { - file => $handle, - defaults => \%defaults, - matchpoint => $matchpoint, - overwrite_cardnumber => scalar $input->param('overwrite_cardnumber'), - overwrite_passwords => $overwrite_passwords, - preserve_extended_attributes => scalar $input->param('ext_preserve') || 0, - preserve_fields => \@preserve_fields, - update_dateexpiry => $update_dateexpiry ? 1 : 0, - update_dateexpiry_from_today => $update_dateexpiry eq "now" ? 1 : 0, - update_dateexpiry_from_existing => $update_dateexpiry eq "dateexpiry" ? 1 : 0, - send_welcome => $welcome_new, - } - ); - my $feedback = $return->{feedback}; - my $errors = $return->{errors}; - my $imported = $return->{imported}; - my $overwritten = $return->{overwritten}; - my $alreadyindb = $return->{already_in_db}; - my $invalid = $return->{invalid}; - my $imported_borrowers = $return->{imported_borrowers}; + try { + my $job_id = Koha::BackgroundJob::PatronImport->new->enqueue( + { + file_content => $file_content, + defaults => \%defaults, + matchpoint => $matchpoint, + overwrite_cardnumber => scalar $input->param('overwrite_cardnumber'), + overwrite_passwords => $overwrite_passwords, + preserve_extended_attributes => scalar $input->param('ext_preserve') || 0, + preserve_fields => \@preserve_fields, + update_dateexpiry => $update_dateexpiry ? 1 : 0, + update_dateexpiry_from_today => $update_dateexpiry eq "now" ? 1 : 0, + update_dateexpiry_from_existing => $update_dateexpiry eq "dateexpiry" ? 1 : 0, + send_welcome => $welcome_new, + createpatronlist => $createpatronlist, + patronlistname => $patronlistname, + } + ); - if ( $imported && $createpatronlist ) { - my $patronlist = AddPatronList( { name => $patronlistname } ); - AddPatronsToList( { list => $patronlist, borrowernumbers => $imported_borrowers } ); - $template->param( 'patronlistname' => $patronlistname ); - } - - my $uploadinfo = $input->uploadInfo($uploadborrowers); - foreach ( keys %$uploadinfo ) { - push @$feedback, { feedback => 1, name => $_, value => $uploadinfo->{$_}, $_ => $uploadinfo->{$_} }; - } - - push @$feedback, { feedback => 1, name => 'filename', value => $uploadborrowers, filename => $uploadborrowers }; - - $template->param( - uploadborrowers => 1, - errors => $errors, - feedback => $feedback, - imported => $imported, - overwritten => $overwritten, - alreadyindb => $alreadyindb, - invalid => $invalid, - total => $imported + $alreadyindb + $invalid + $overwritten, - ); + $template->param( + op => 'enqueued', + job_id => $job_id, + ); + } catch { + $template->param( + op => 'enqueued', + error => 'cannot_enqueue_job', + ); + }; } else { if ($extended) {