Bugzilla – Attachment 36295 Details for
Bug 11395
Batch modifications for records
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11395: Add a batch record modification
Bug-11395-Add-a-batch-record-modification.patch (text/plain), 21.64 KB, created by
Marcel de Rooy
on 2015-03-02 13:35:08 UTC
(
hide
)
Description:
Bug 11395: Add a batch record modification
Filename:
MIME Type:
Creator:
Marcel de Rooy
Created:
2015-03-02 13:35:08 UTC
Size:
21.64 KB
patch
obsolete
>From a52be6afe4f9e83ae45681862e12e452eab93f09 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@biblibre.com> >Date: Thu, 12 Dec 2013 21:13:53 +0100 >Subject: [PATCH] Bug 11395: Add a batch record modification >Content-Type: text/plain; charset=utf-8 > >This patch offers a new tool to modify records in a batch. > >This feature adds: >- a new pl/tt files tools/batch_record_modification >- a new permission: tools > records_batchmod > >Test plan for biblios: >0/ Create a new marc modification template with some actions. >1/ Generate a list of biblionumbers you want to modify. >There are two ways to generate a list of biblionumbers: >- 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 >2/ On the "Batch record modification" tool verify: >- information is correct. >- the preview link show you the needed record. >3/ After clicking on the "Modify selected recors" button, verify >the records have been modified as you wanted. > >Test plan for authority: >0/ Create a new marc modification template with some actions. >1/ Generate a list of authid using a report: >2/ On the "Batch record modification" tool verify: >- authorities are display with the summary. >- the preview link show you the needed record. >3/ After clicking on the "Modify selected recors" button, verify >the records have been modified as you wanted. > >Catch of errors: >if an error occurs during the modification process, the tool >displays an error message. > >Signed-off-by: Brendan Gallagher <brendan@bywatersolutions.com> > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >Signed-off-by: Tomas Cohen Arazi <tomascohen@gmail.com> > >Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >--- > .../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 > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_record_modification.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_record_modification.tt >new file mode 100644 >index 0000000..2ce3481 >--- /dev/null >+++ b/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' %] >+<title>Koha › Tools › Batch record modification</title> >+[% INCLUDE 'doc-head-close.inc' %] >+[% INCLUDE 'greybox.inc' %] >+<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >+[% INCLUDE 'datatables.inc' %] >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >+<script type="text/javascript" src="[% themelang %]/js/background-job-progressbar.js"></script> >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $("#selectall").click(function(e){ >+ e.preventDefault(); >+ $(".records").checkCheckboxes(); >+ }); >+ $("#clearall").click(function(e){ >+ e.preventDefault(); >+ $(".records").unCheckCheckboxes(); >+ }); >+ $("#selectall").click(); >+ >+ $("table#biblios").dataTable($.extend(true, {}, dataTablesDefaults, { >+ "aoColumnDefs": [ >+ { "aTargets": [ 0, 3 ], "bSortable": false, "bSearchable": false }, >+ { "aTargets": [ 1 ], "sType": "num-html" } >+ ], >+ "sDom": 't', >+ "aaSorting": [], >+ "bPaginate": false >+ })); >+ >+ $("table#authorities").dataTable($.extend(true, {}, dataTablesDefaults, { >+ "aoColumnDefs": [ >+ { "aTargets": [ 0, 3 ], "bSortable": false, "bSearchable": false }, >+ { "aTargets": [ 1 ], "sType": "num-html" } >+ ], >+ "sDom": 't', >+ "aaSorting": [], >+ "bPaginate": false >+ })); >+ >+ $("#mainformsubmit").click(function(){ >+ return submitBackgroundJob(document.getElementById("process")); >+ }); >+ >+}); >+//]]> >+</script> >+</head> >+<body id="tools_batch_record_modification" class="tools"> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] >+ >+<div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> › >+ <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › >+ <a href="/cgi-bin/koha/tools/batch_record_modification.pl">Batch record modification</a> >+</div> >+ >+<div id="doc3" class="yui-t2"> >+<div id="bd"> >+<div id="yui-main"> >+<div class="yui-b"> >+ <h1>Batch record modification</h1> >+ [% FOREACH message IN messages %] >+ [% IF message.type == 'success' %] >+ <div class="dialog message"> >+ [% ELSIF message.type == 'warning' %] >+ <div class="dialog alert"> >+ [% ELSIF message.type == 'error' %] >+ <div class="dialog error" style="margin:auto;"> >+ [% END %] >+ <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber %]">[% biblio.title %]</a></td> >+ [% 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 <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% message.biblionumber %]">[% message.biblionumber %]</a> has not been modified. An error occurred on modifying it. >+ [% ELSIF message.code == 'authority_not_modified' %] >+ The authority <a href="/cgi-bin/koha/authorities/detail.pl?authid=[% message.authid %]">[% message.authid %]</a> has not been modified. An error occurred on modifying it. >+ [% ELSIF message.code == 'biblio_modified' %] >+ The biblio <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% message.biblionumber %]">[% message.biblionumber %]</a> has successfully been modified. >+ [% ELSIF message.code == 'authority_modified' %] >+ The authority <a href="/cgi-bin/koha/authorities/detail.pl?authid=[% message.authid %]">[% message.authid %]</a> has successfully been modified. >+ [% END %] >+ [% IF message.error %] >+ (The error was: [% message.error%], see the Koha logfile for more information). >+ [% END %] >+ </div> >+ [% END %] >+ [% IF view == 'form' %] >+ <form method="post" enctype="multipart/form-data" action="/cgi-bin/koha/tools/batch_record_modification.pl"> >+ <fieldset class="rows"> >+ <legend>Record type</legend> >+ <ol> >+ <li><label for="biblio_type">Biblios: </label><input type="radio" name="recordtype" value="biblio" id="biblio_type" checked="checked" /></li> >+ <li><label for="authority_type">Authorities: </label><input type="radio" name="recordtype" value="authority" id="authority_type" /></li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>Use a file</legend> >+ <ol> >+ <li><label for="uploadfile">File: </label> <input type="file" id="uploadfile" name="uploadfile" /></li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>Or enter a list of record numbers</legend> >+ <ol> >+ <li> >+ <label for="recordnumber_list">Record number list (one per line): </label> >+ <textarea rows="10" cols="30" id="recordnumber_list" name="recordnumber_list"></textarea> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>Use MARC Modification Template:</legend> >+ <ol> >+ <li> >+ <label for="marc_modification_template_id" class="required">Modify record using the following template: </label> >+ <select name="marc_modification_template_id" id="marc_modification_template_id" required="required"> >+ <option value="">Select a template</option> >+ [% FOREACH mmt IN MarcModificationTemplatesLoop %] >+ <option value="[% mmt.template_id %]">[% mmt.name %]</option> >+ [% END %] >+ </select> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="hidden" name="op" value="list" /> >+ <input type="submit" value="Continue" class="button" /> >+ <a class="cancel" href="/cgi-bin/koha/tools/tools-home.pl">Cancel</a> >+ </fieldset> >+ </form> >+ [% ELSIF view == 'list' %] >+ [% IF records %] >+ [% IF recordtype == 'biblio' %] >+ <div id="toolbar"> >+ <a id="selectall" href="#">Select All</a> >+ | <a id="clearall" href="#">Clear All</a> >+ </div> >+ <form action="/cgi-bin/koha/tools/batch_record_modification.pl" method="post" id="process"> >+ <table id="biblios" class="records"> >+ <thead> >+ <tr> >+ <th></th> >+ <th>Biblionumber</th> >+ <th>Title</th> >+ <th>Preview</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOR biblio IN records %] >+ <tr> >+ <td><input type="checkbox" name="record_id" value="[% biblio.biblionumber %]" data-items="[% biblio.itemnumbers.size %]" data-issues="[% biblio.issues_count %]" data-reserves="[% biblio.reserves.size %]" /></td> >+ <td>[% biblio.biblionumber %]</td> >+ <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblio.biblionumber %]">[% biblio.title %]</a></td> >+ <td><a href="/cgi-bin/koha/svc/records/preview?record_type=biblio&record_id=[% biblio.biblionumber %]&mmtid=[% mmtid %]" title="MARC preview" rel="gb_page_center[600,500]">Preview MARC</a> >+ >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ <div class="note">Reminder: this action will modify all selected biblios!</div> >+ [% ELSE %] >+ <div id="toolbar"> >+ <a id="selectall" href="#">Select All</a> >+ | <a id="clearall" href="#">Clear All</a> >+ </div> >+ <form action="/cgi-bin/koha/tools/batch_record_modification.pl" method="post" id="process"> >+ <table id="authorities" class="records"> >+ <thead> >+ <tr> >+ <th></th> >+ <th>Authid</th> >+ <th>Summary</th> >+ <th>Preview</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOR authority IN records %] >+ <tr> >+ <td><input type="checkbox" name="record_id" value="[% authority.authid %]" data-usage="[% authority.count_usage %]" /></td> >+ <td><a href="/cgi-bin/koha/authorities/detail.pl?authid=[% authority.authid %]">[% authority.authid %]</a></td> >+ <td>[% PROCESS authresult summary=authority.summary %]</td> >+ <td><a href="/cgi-bin/koha/svc/records/preview?record_type=authority&record_id=[% authority.authid %]&mmtid=[% mmtid %]" title="MARC preview" rel="gb_page_center[600,500]">Preview MARC</a> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ <div class="note">Reminder: this action will modify all selected authorities!</div> >+ [% END %] >+ <fieldset class="action"> >+ <input type="hidden" name="op" value="modify" /> >+ <input type="hidden" name="recordtype" value="[% recordtype %]" /> >+ <input type="button" id="mainformsubmit" value="Modify selected records" class="button" /> >+ <input type="hidden" name="runinbackground" id="runinbackground" value="" /> >+ <input type="hidden" name="completedJobID" id="completedJobID" value="" /> >+ <input type="hidden" name="marc_modification_template_id" value="[% mmtid %]" /> >+ <a class="cancel" href="/cgi-bin/koha/tools/batch_record_modification.pl">Cancel</a> >+ </fieldset> >+ <div id="jobpanel"> >+ <div id="jobstatus">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div> >+ <div id="jobfailed"></div> >+ </div> >+ </form> >+ [% 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 %] >+ <p><a href="/cgi-bin/koha/tools/batch_record_modification.pl" title="New batch record modification">New batch record modification</a></p> >+ [% ELSIF view == 'errors' %] >+ [% FOR error IN errors %] >+ [% IF error == 'no_template_defined' %] >+ No MARC modification template is defined. You have <a href="/cgi-bin/koha/tools/marc_modification_templates.pl">to create</a> at least one template for using this tool. >+ [% END %] >+ [% END %] >+ [% ELSE %] >+ No action defined for the template. >+ [% END %] >+</div> >+</div> >+<div class="yui-b"> >+ [% INCLUDE 'tools-menu.inc' %] >+</div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/tools/batch_record_modification.pl b/tools/batch_record_modification.pl >new file mode 100755 >index 0000000..bec2f9e >--- /dev/null >+++ b/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 >+# <http://www.gnu.org/licenses> >+ >+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; >-- >1.7.7.6
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 11395
:
23502
|
23503
|
23504
|
23505
|
23506
|
23507
|
23508
|
23592
|
24634
|
26072
|
26981
|
28978
|
28999
|
29000
|
29001
|
29002
|
29003
|
29004
|
29056
|
29509
|
29569
|
31344
|
32181
|
32182
|
32184
|
32239
|
32240
|
32241
|
32242
|
32243
|
32244
|
32245
|
32246
|
32247
|
32248
|
32249
|
33145
|
33146
|
33147
|
33148
|
33149
|
33150
|
33151
|
33152
|
33153
|
33154
|
33155
|
34393
|
34394
|
34395
|
34396
|
34397
|
34398
|
34399
|
34400
|
34401
|
34402
|
34552
|
34553
|
34554
|
34555
|
34556
|
34557
|
34558
|
34559
|
34560
|
34561
|
34562
|
35783
|
35784
|
35785
|
35786
|
35787
|
35788
|
35789
|
35790
|
35791
|
35792
| 36295 |
36296
|
36297
|
36298
|
36299
|
36300
|
36301
|
36302
|
36303
|
36304