@@ -, +, @@
- a new pl/tt files tools/batch_record_modification
- a new permission: tools > records_batchmod
- using the basket: do a search, add some biblio to your basket, open
the basket and click on the "Action" button > "Modify"
- generating a list from a report
- information is correct.
- the preview link show you the needed record.
- authorities are display with the summary.
- the preview link show you the needed record.
---
.../en/modules/tools/batch_record_modification.tt | 237 ++++++++++++++++++
tools/batch_record_modification.pl | 261 ++++++++++++++++++++
2 files changed, 498 insertions(+), 0 deletions(-)
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_record_modification.tt
create mode 100755 tools/batch_record_modification.pl
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_record_modification.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_record_modification.tt
@@ -0,0 +1,237 @@
+[% PROCESS 'authorities-search-results.inc' %]
+[% INCLUDE 'doc-head-open.inc' %]
+
Koha › Tools › Batch record modification
+[% INCLUDE 'doc-head-close.inc' %]
+[% INCLUDE 'greybox.inc' %]
+
+[% INCLUDE 'datatables.inc' %]
+
+
+
+
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+
+
+ [% IF message.code == 'no_action_defined_for_the_template' %]
+ The selected template (id=[% message.mmtid%]) does not exist or no action is defined.
+ [% ELSIF message.code == 'biblio_not_exists' %]
+ The biblionumber [% message.biblionumber %] does not exist in the database.
+ [% ELSIF message.code == 'authority_not_exists' %]
+ The authority id [% message.authid %] does not exist in the database.
+ [% ELSIF message.code == 'biblio_not_modified' %]
+ The biblio [% message.biblionumber %] has not been modified. An error occurred on modifying it.
+ [% ELSIF message.code == 'authority_not_modified' %]
+ The authority [% message.authid %] has not been modified. An error occurred on modifying it.
+ [% ELSIF message.code == 'biblio_modified' %]
+ The biblio [% message.biblionumber %] has successfully been modified.
+ [% ELSIF message.code == 'authority_modified' %]
+ The authority [% message.authid %] has successfully been modified.
+ [% END %]
+ [% IF message.error %]
+ (The error was: [% message.error%], see the Koha logfile for more information).
+ [% END %]
+
+ [% END %]
+ [% IF view == 'form' %]
+
+ [% ELSIF view == 'list' %]
+ [% IF records %]
+ [% IF recordtype == 'biblio' %]
+
+
+ [% ELSE %]
+ There is no record ids defined.
+ [% END %]
+ [% ELSIF view == 'report' %]
+ [% IF report.total_records == report.total_success %]
+ All records have successfully been modified!
+ [% ELSE %]
+ [% report.total_success %] / [% report.total_records %] records have successfully been modified.
+ Some errors occurred.
+ [% END %]
+
+ [% ELSIF view == 'errors' %]
+ [% FOR error IN errors %]
+ [% IF error == 'no_template_defined' %]
+ No MARC modification template is defined. You have to create at least one template for using this tool.
+ [% END %]
+ [% END %]
+ [% ELSE %]
+ No action defined for the template.
+ [% END %]
+
+
+
+ [% INCLUDE 'tools-menu.inc' %]
+
+
+[% INCLUDE 'intranet-bottom.inc' %]
--- a/tools/batch_record_modification.pl
+++ a/tools/batch_record_modification.pl
@@ -0,0 +1,261 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Copyright 2013 BibLibre
+#
+# Koha is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3
+# of the License, or (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General
+# Public License along with Koha; if not, see
+#
+
+use Modern::Perl;
+
+use CGI;
+use List::MoreUtils qw( uniq );
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+use C4::AuthoritiesMarc qw( BuildSummary GetAuthTypeCode ModAuthority );
+use C4::BackgroundJob;
+use C4::Biblio qw( GetMarcBiblio ModBiblio );
+use C4::MarcModificationTemplates qw( GetModificationTemplateActions GetModificationTemplates ModifyRecordWithTemplate );
+use Koha::Authority;
+
+my $input = new CGI;
+our $dbh = C4::Context->dbh;
+my $op = $input->param('op') // q|form|;
+my $recordtype = $input->param('recordtype') // 'biblio';
+my $mmtid = $input->param('marc_modification_template_id');
+
+my ( @messages );
+
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+ template_name => 'tools/batch_record_modification.tt',
+ query => $input,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { tools => 'biblio_batchmod' },
+});
+
+
+my $sessionID = $input->cookie("CGISESSID");
+
+my $runinbackground = $input->param('runinbackground');
+my $completedJobID = $input->param('completedJobID');
+if ( $completedJobID ) {
+ my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
+ my $report = $job->get('report');
+ my $messages = $job->get('messages');
+ $template->param(
+ report => $report,
+ messages => $messages,
+ view => 'report',
+ );
+ output_html_with_http_headers $input, $cookie, $template->output;
+ exit;
+}
+
+my @templates = GetModificationTemplates();
+unless ( @templates ) {
+ $op = 'error';
+ $template->param(
+ view => 'errors',
+ errors => ['no_template_defined'],
+ );
+ output_html_with_http_headers $input, $cookie, $template->output;
+}
+
+if ( $mmtid ) {
+ my @actions = GetModificationTemplateActions( $mmtid );
+ unless ( @actions ) {
+ $op = 'form';
+ push @messages, {
+ type => 'error',
+ code => 'no_action_defined_for_the_template',
+ mmtid => $mmtid,
+ };
+ }
+}
+
+if ( $op eq 'form' ) {
+ # Display the form
+ $template->param(
+ view => 'form',
+ MarcModificationTemplatesLoop => \@templates,
+ );
+} elsif ( $op eq 'list' ) {
+ # List all records to process
+ my ( @records, @record_ids );
+ if ( my $bib_list = $input->param('bib_list') ) {
+ # Come from the basket
+ @record_ids = split /\//, $bib_list;
+ $recordtype = 'biblio';
+ } elsif ( my $uploadfile = $input->param('uploadfile') ) {
+ # A file of id is given
+ while ( my $content = <$uploadfile> ) {
+ next unless $content;
+ $content =~ s/[\r\n]*$//;
+ push @record_ids, $content if $content;
+ }
+ } else {
+ # The user enters manually the list of id
+ push @record_ids, split( /\s\n/, $input->param('recordnumber_list') );
+ }
+
+ for my $record_id ( uniq @record_ids ) {
+ if ( $recordtype eq 'biblio' ) {
+ # Retrieve biblio information
+ my $biblio = C4::Biblio::GetBiblio( $record_id );
+ unless ( $biblio ) {
+ push @messages, {
+ type => 'warning',
+ code => 'biblio_not_exists',
+ biblionumber => $record_id,
+ };
+ next;
+ }
+ push @records, $biblio;
+ } else {
+ # Retrieve authority information
+ my $authority = Koha::Authority->get_from_authid( $record_id );
+ unless ( $authority ) {
+ push @messages, {
+ type => 'warning',
+ code => 'authority_not_exists',
+ authid => $record_id,
+ };
+ next;
+ }
+
+ push @records, {
+ authid => $record_id,
+ summary => C4::AuthoritiesMarc::BuildSummary( $authority->record, $record_id ),
+ };
+ }
+ }
+ $template->param(
+ records => \@records,
+ mmtid => $mmtid,
+ view => 'list',
+ );
+} elsif ( $op eq 'modify' ) {
+ # We want to modify selected records!
+ my @record_ids = $input->param('record_id');
+
+ my ( $job );
+ if ( $runinbackground ) {
+ my $job_size = scalar( @record_ids );
+ $job = C4::BackgroundJob->new( $sessionID, "FIXME", $ENV{SCRIPT_NAME}, $job_size );
+ my $job_id = $job->id;
+ if (my $pid = fork) {
+ $dbh->{InactiveDestroy} = 1;
+
+ my $reply = CGI->new("");
+ print $reply->header(-type => 'text/html');
+ print '{"jobID":"' . $job_id . '"}';
+ exit 0;
+ } elsif (defined $pid) {
+ close STDOUT;
+ close STDERR;
+ } else {
+ warn "fork failed while attempting to run $ENV{'SCRIPT_NAME'} as a background job";
+ exit 0;
+ }
+ }
+
+ my $report = {
+ total_records => 0,
+ total_success => 0,
+ };
+ my $progress = 0;
+ $dbh->{RaiseError} = 1;
+ RECORD_IDS: for my $record_id ( sort { $a <=> $b } @record_ids ) {
+ $report->{total_records}++;
+ next unless $record_id;
+
+ if ( $recordtype eq 'biblio' ) {
+ # Biblios
+ my $biblionumber = $record_id;
+
+ # Finally, modify the biblio
+ my $error = eval {
+ my $record = GetMarcBiblio( $biblionumber );
+ ModifyRecordWithTemplate( $mmtid, $record );
+ ModBiblio( $record, $biblionumber );
+ };
+ if ( $error and $error != 1 or $@ ) { # ModBiblio returns 1 if everything as gone well
+ push @messages, {
+ type => 'error',
+ code => 'biblio_not_modified',
+ biblionumber => $biblionumber,
+ error => ($@ ? $@ : $error),
+ };
+ } else {
+ push @messages, {
+ type => 'success',
+ code => 'biblio_modified',
+ biblionumber => $biblionumber,
+ };
+ $report->{total_success}++;
+ }
+ } else {
+ # Authorities
+ my $authid = $record_id;
+ my $error = eval {
+ my $authority = Koha::Authority->get_from_authid( $authid );
+ my $record = $authority->record;
+ ModifyRecordWithTemplate( $mmtid, $record );
+ ModAuthority( $authid, $record, GetAuthTypeCode( $authid ) );
+ };
+ if ( $error and $error != $authid or $@ ) {
+ push @messages, {
+ type => 'error',
+ code => 'authority_not_modified',
+ authid => $authid,
+ error => ($@ ? $@ : 0),
+ };
+ } else {
+ push @messages, {
+ type => 'success',
+ code => 'authority_modified',
+ authid => $authid,
+ };
+ $report->{total_success}++;
+ }
+ }
+
+ $job->set({
+ view => 'report',
+ report => $report,
+ messages => \@messages,
+ });
+ $job->progress( ++$progress ) if $runinbackground;
+ }
+
+ if ($runinbackground) {
+ $job->finish if defined $job;
+ } else {
+ $template->param(
+ view => 'report',
+ report => $report,
+ messages => \@messages,
+ );
+ }
+}
+
+$template->param(
+ messages => \@messages,
+ recordtype => $recordtype,
+);
+
+output_html_with_http_headers $input, $cookie, $template->output;
--