From 5ca53cf2bc9ed1ecf6c7fe4d1c48c0b91fac83a5 Mon Sep 17 00:00:00 2001 From: Pedro Amorim Date: Wed, 17 Jun 2026 10:22:42 +0000 Subject: [PATCH] Bug 34632: Add patron_import background job display template patron_import.inc provides the report/detail/js blocks consumed by the background job viewer: a summary of counts when finished, a live progress bar while running, and the full feedback and error analysis in the detail section. background_jobs.tt gains a patron_import entry in the job type filter dropdown. Test plan: 1) Apply patches, restart plack. 2) Navigate to the patron import tool: /cgi-bin/koha/tools/import_borrowers.pl 3) Upload the provided sample CSV file and click 'Import patrons'. 4) Confirm the page shows "The patron import job has been enqueued!" with a link to view the job. 5) Follow the link to the background job. Confirm a progress bar is shown while the job is running. 6) Once finished, confirm the report shows the correct counts (imported, overwritten, already_in_db, invalid, total). 7) Confirm the imported patrons exist under 'Patrons'. 8) Re-import the same file with 'Overwrite cardnumber' unchecked. Confirm 'already_in_db' count is 5. 9) Re-import again with 'Overwrite cardnumber' checked. Confirm 'overwritten' count is 5. 10) Visit the background jobs admin and filter by type 'Import patrons': /cgi-bin/koha/admin/background_jobs.pl 11) Confirm the jobs appear in the list. 12) Run the tests: prove t/db_dependent/Koha/BackgroundJob/PatronImport.t Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Brendan Lawlor Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim --- .../background_jobs/patron_import.inc | 153 ++++++++++++++++++ .../prog/en/modules/admin/background_jobs.tt | 4 + 2 files changed, 157 insertions(+) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/background_jobs/patron_import.inc diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/background_jobs/patron_import.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/background_jobs/patron_import.inc new file mode 100644 index 0000000000..9f5d1bf2ef --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/background_jobs/patron_import.inc @@ -0,0 +1,153 @@ +[% USE Koha %] +[% USE raw %] + +[% BLOCK report %] + [% SET job_data = job.decoded_data %] + [% IF job.status == 'finished' %] +
+
    +
  • [% job_data.imported | html %] imported records
  • + [% IF job_data.patron_list_name %] +
  • Patron list with imported patrons: [% job_data.patron_list_name | html %]
  • + [% END %] +
  • [% job_data.overwritten | html %] overwritten records
  • +
  • [% job_data.already_in_db | html %] not imported because they are already in the borrowers table and overwrite is disabled
  • +
  • [% job_data.invalid | html %] not imported because they are not in the expected format
  • +
  • [% job_data.total | html %] records parsed
  • +
+
+ [% ELSIF job.status == 'started' OR job.status == 'running' %] + [% INCLUDE "job_progress.inc" job_id=job.id %] + [% ELSIF job.status == 'cancelled' %] +
The job was cancelled before it finished.
+ [% ELSIF job.status == 'failed' %] +
The job failed.
+ [% ELSE %] + [% INCLUDE "job_progress.inc" job_id=job.id %] + [% END %] +[% END %] + +[% BLOCK detail %] + [% SET job_data = job.decoded_data %] + [% IF job_data.feedback %] +

Feedback

+ + [% END %] + + [% IF job_data.errors %] +

Error analysis

+
    + [% FOREACH e IN job_data.errors %] + [% IF e.badheader %]
  • Header row could not be parsed
  • [% END %] + + [% FOREACH missing_critical IN e.missing_criticals %] +
  • + Line [% missing_critical.line | html %] + + [% IF missing_critical.badparse %] + could not be parsed! + [% ELSIF missing_critical.bad_date %] + has "[% missing_critical.key | html %]" in unrecognized format: "[% missing_critical.value | html %]" + [% ELSE %] + Critical field "[% missing_critical.key | html %]" + + [% IF missing_critical.branch_map %] + has unrecognized value "[% missing_critical.value | html %]" + [% ELSIF missing_critical.category_map %] + has unrecognized value "[% missing_critical.value | html %]" + [% ELSE %] + missing + [% END %] + (borrowernumber: [% missing_critical.borrowernumber | html %]; surname: [% missing_critical.surname | html %]). + [% END %] + +
    + [% missing_critical.lineraw | html %] +
  • + [% END %] + + [% IF e.invalid_cardnumber %] +
  • Card number [% e.cardnumber | html %] is not a valid card number[% IF e.borrowernumber %](for patron with borrowernumber [% e.borrowernumber | html %])[% END %]
  • + [% END %] + [% IF e.duplicate_userid %] +
  • Userid [% e.userid | html %] is already used by another patron.
  • + [% END %] + [% IF e.passwd_too_short %] +
  • Password is too short for patron with borrowernumber [% e.borrowernumber | html %]. Minimum length is [% e.min_length | html %], length is [% e.length | html %].
  • + [% END %] + [% IF e.passwd_whitespace %] +
  • Password contains whitespace for patron with borrowernumber [% e.borrowernumber | html %].
  • + [% END %] + [% IF e.passwd_too_weak %] +
  • Password is too weak for patron with borrowernumber [% e.borrowernumber | html %].
  • + [% END %] + [% IF e.passwd_plugin_err %] +
  • Password plugin error for patron with borrowernumber [% e.borrowernumber | html %].
  • + [% END %] + [% IF e.passwd_unknown_err %] +
  • Password error for patron with borrowernumber [% e.borrowernumber | html %].
  • + [% END %] + [% IF e.patron_attribute_unique_id_constraint %] +
  • + [% IF e.borrowernumber %] + Patron attribute [% e.attribute.code | html %] must be unique for patron with borrowernumber [% e.borrowernumber | html %]. + [% ELSE %] + Patron attribute [% e.attribute.code | html %] must be unique for patron [% e.patron_id | html %]. + [% END %] +
  • + [% END %] + [% IF e.patron_attribute_invalid_type %] +
  • + [% IF e.borrowernumber %] + Patron attribute [% e.attribute_type_code | html %] is invalid for patron with borrowernumber [% e.borrowernumber | html %]. + [% ELSE %] + Patron attribute [% e.attribute_type_code | html %] is invalid for patron [% e.patron_id | html %]. + [% END %] +
  • + [% END %] + [% IF e.patron_attribute_non_repeatable %] +
  • + [% IF e.borrowernumber %] + Patron attribute [% e.attribute.code | html %] is non-repeatable for patron with borrowernumber [% e.borrowernumber | html %]. + [% ELSE %] + Patron attribute [% e.attribute.code | html %] is non-repeatable for patron [% e.patron_id | html %]. + [% END %] +
  • + [% END %] + [% END %] +
+ [% END %] +[% END %] + +[% BLOCK js %] + [% IF job.status != 'finished' AND job.status != 'cancelled' AND job.status != 'failed' %] + [% INCLUDE 'str/job_progress.inc' job_id=job.id %] + [% Asset.js("js/job_progress.js") | $raw %] + + [% END %] +[% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt index 79249387f7..019d36ae24 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt @@ -226,6 +226,10 @@ '_id': 'import_from_kbart_file', '_str': _("Import titles from a KBART file").escapeHtml() }, + { + '_id': 'patron_import', + '_str': _("Import patrons").escapeHtml() + }, { '_id': 'file_transport_test', '_str': _("File transport connection test")