MT 2553 : Adds background job for items batch modification
Signed-off-by: Galen Charlton <gmcharlt@gmail.com>
This commit is contained in:
parent
7f3df2735d
commit
c8bf22893e
|
|
@ -66,6 +66,7 @@
|
|||
data: inputs.join('&'),
|
||||
url: f.action,
|
||||
dataType: 'json',
|
||||
type: 'post',
|
||||
success: function(json) {
|
||||
jobID = json.jobID;
|
||||
inBackgroundJobProgressTimer = false;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
|
||||
<title>Koha › Tools › Batch Deletion of Items</title>
|
||||
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="background-job.inc" -->
|
||||
<style type="text/css">
|
||||
#jobpanel,#jobstatus,#jobfailed { display : none; }
|
||||
#jobstatus { margin:.4em; }
|
||||
#jobprogress{ width:200px;height:10px;border:1px solid #666;background:url('/intranet-tmpl/prog/img/progress.png') -300px 0px no-repeat; }
|
||||
</style>
|
||||
<script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/JavaScript" language="JavaScript">
|
||||
//<![CDATA[
|
||||
|
|
@ -64,6 +70,10 @@
|
|||
|
||||
|
||||
<form name="f" action="batchMod.pl" method="post">
|
||||
<input type="hidden" name="op" value="<!-- TMPL_VAR NAME="op" -->" />
|
||||
<input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
|
||||
<input type="hidden" name="completedJobID" id="completedJobID" value="" />
|
||||
|
||||
<!-- TMPL_IF name="item_loop" -->
|
||||
<div id="cataloguing_additem_itemlist">
|
||||
<div style="overflow:auto">
|
||||
|
|
@ -115,7 +125,12 @@
|
|||
<p>This will delete <!-- TMPL_IF NAME="too_many_items" -->all the<!-- TMPL_ELSE -->the selected<!-- /TMPL_IF --> items.</p>
|
||||
<input type="hidden" name="del" value="1" />
|
||||
<fieldset class="action">
|
||||
<input type="submit" name="submit" value="Go" />
|
||||
<div id="jobpanel">
|
||||
<div id="jobstatus">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div>
|
||||
<div id="jobfailed"></div>
|
||||
</div>
|
||||
<input type="submit" name="mainformsubmit" value="Go" onclick="return submitBackgroundJob(this.form);" />
|
||||
<input type="button" value="Cancel" onclick="javascript:history.back();" />
|
||||
</fieldset>
|
||||
</div>
|
||||
<!-- /TMPL_IF -->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
|
||||
<title>Koha › Tools › Batch Modification of Items</title>
|
||||
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="background-job.inc" -->
|
||||
<style type="text/css">
|
||||
#jobpanel,#jobstatus,#jobfailed { display : none; }
|
||||
#jobstatus { margin:.4em; }
|
||||
#jobprogress{ width:200px;height:10px;border:1px solid #666;background:url('/intranet-tmpl/prog/img/progress.png') -300px 0px no-repeat; }
|
||||
</style>
|
||||
<script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/JavaScript" language="JavaScript">
|
||||
//<![CDATA[
|
||||
|
|
@ -61,6 +67,11 @@
|
|||
<!-- /TMPL_IF -->
|
||||
|
||||
<form name="f" action="batchMod.pl" method="post">
|
||||
<input type="hidden" name="op" value="<!-- TMPL_VAR NAME="op" -->" />
|
||||
<input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
|
||||
<input type="hidden" name="runinbackground" id="runinbackground" value="" />
|
||||
<input type="hidden" name="completedJobID" id="completedJobID" value="" />
|
||||
|
||||
<!-- TMPL_IF name="item_loop" -->
|
||||
<div id="cataloguing_additem_itemlist">
|
||||
<div style="overflow:auto">
|
||||
|
|
@ -108,7 +119,6 @@
|
|||
<!-- /TMPL_IF -->
|
||||
|
||||
<div id="cataloguing_additem_newitem">
|
||||
<input type="hidden" name="op" value="<!-- TMPL_VAR NAME="op" -->" />
|
||||
<h2>Edit Items</h2>
|
||||
<fieldset class="rows">
|
||||
<ol>
|
||||
|
|
@ -131,9 +141,14 @@
|
|||
<!-- /TMPL_LOOP -->
|
||||
</ol>
|
||||
</fieldset>
|
||||
<fieldset class="action">
|
||||
<input type="submit" name="submit" value="Go" />
|
||||
</fieldset>
|
||||
<fieldset class="action">
|
||||
<div id="jobpanel">
|
||||
<div id="jobstatus">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div>
|
||||
<div id="jobfailed"></div>
|
||||
</div>
|
||||
<input type="submit" name="mainformsubmit" value="Go" onclick="return submitBackgroundJob(this.form);" />
|
||||
<input type="button" value="Cancel" onclick="javascript:history.back();" />
|
||||
</fieldset>
|
||||
</div>
|
||||
<!-- TMPL_ELSE --> <!-- // ACTION -->
|
||||
<a href="javascript:window.history.back()">Go back</a>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use C4::Items;
|
|||
use C4::Context;
|
||||
use C4::Koha; # XXX subfield_is_koha_internal_p
|
||||
use C4::Branch; # XXX subfield_is_koha_internal_p
|
||||
use C4::BackgroundJob;
|
||||
use C4::ClassSource;
|
||||
use C4::Dates;
|
||||
use C4::Debug;
|
||||
|
|
@ -41,6 +42,9 @@ my $error = $input->param('error');
|
|||
my @itemnumbers = $input->param('itemnumber');
|
||||
my $op = $input->param('op');
|
||||
my $del = $input->param('del');
|
||||
my $completedJobID = $input->param('completedJobID');
|
||||
my $runinbackground = $input->param('runinbackground');
|
||||
|
||||
|
||||
my $template_name;
|
||||
my $template_flag;
|
||||
|
|
@ -77,6 +81,11 @@ my $deleted_items = 0; # Numbers of deleted items
|
|||
my $not_deleted_items = 0; # Numbers of items that could not be deleted
|
||||
my @not_deleted; # List of the itemnumbers that could not be deleted
|
||||
|
||||
my %cookies = parse CGI::Cookie($cookie);
|
||||
my $sessionID = $cookies{'CGISESSID'}->value;
|
||||
my $dbh = C4::Context->dbh;
|
||||
|
||||
|
||||
#--- ----------------------------------------------------------------------------
|
||||
if ($op eq "action") {
|
||||
#-------------------------------------------------------------------------------
|
||||
|
|
@ -90,38 +99,67 @@ if ($op eq "action") {
|
|||
# Is there something to modify ?
|
||||
# TODO : We shall use this var to warn the user in case no modification was done to the items
|
||||
my $something_to_modify = scalar(grep {!/^$/} @values);
|
||||
|
||||
foreach my $itemnumber(@itemnumbers){
|
||||
my $itemdata=GetItem($itemnumber);
|
||||
if ($input->param("del")){
|
||||
my $return = DelItemCheck(C4::Context->dbh, $itemdata->{'biblionumber'}, $itemdata->{'itemnumber'});
|
||||
if ($return == 1) {
|
||||
$deleted_items++;
|
||||
} else {
|
||||
$not_deleted_items++;
|
||||
push @not_deleted, { biblionumber => $itemdata->{'biblionumber'}, itemnumber => $itemdata->{'itemnumber'}, barcode => $itemdata->{'barcode'}, title => $itemdata->{'title'}, $return => 1 };
|
||||
}
|
||||
} else {
|
||||
if ($something_to_modify) {
|
||||
my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM');
|
||||
my $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8');
|
||||
my $localitem = TransformMarcToKoha( $dbh, $marcitem, "", 'items' );
|
||||
my $localmarcitem=Item2Marc($itemdata);
|
||||
UpdateMarcWith($marcitem,$localmarcitem);
|
||||
eval{my ($oldbiblionumber,$oldbibnum,$oldbibitemnum) = ModItemFromMarc($localmarcitem,$itemdata->{biblionumber},$itemnumber)};
|
||||
}
|
||||
}
|
||||
}
|
||||
# If we have a reasonable amount of items, we display them
|
||||
if (scalar(@itemnumbers) <= 1000) {
|
||||
$items_display_hashref=BuildItemsData(@itemnumbers);
|
||||
|
||||
# Once the job is done
|
||||
if ($completedJobID) {
|
||||
# If we have a reasonable amount of items, we display them
|
||||
if (scalar(@itemnumbers) <= 1000) {
|
||||
$items_display_hashref=BuildItemsData(@itemnumbers);
|
||||
} else {
|
||||
# Else, we only display the barcode
|
||||
my @simple_items_display = map {{ itemnumber => $_, barcode => GetBarcodeFromItemnumber($_), biblionumber => GetBiblionumberFromItemnumber($_) }} @itemnumbers;
|
||||
$template->param("simple_items_display" => \@simple_items_display);
|
||||
}
|
||||
|
||||
# Setting the job as done
|
||||
my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
|
||||
|
||||
# Calling the template
|
||||
add_saved_job_results_to_template($template, $completedJobID);
|
||||
|
||||
# While the job is getting done
|
||||
} else {
|
||||
# Else, we only display the barcode
|
||||
my @simple_items_display = map {{ itemnumber => $_, barcode => GetBarcodeFromItemnumber($_), biblionumber => GetBiblionumberFromItemnumber($_) }} @itemnumbers;
|
||||
$template->param("simple_items_display" => \@simple_items_display);
|
||||
|
||||
# Job size is the number of items we have to process
|
||||
my $job_size = scalar(@itemnumbers);
|
||||
my $job = undef;
|
||||
$dbh->{AutoCommit} = 0;
|
||||
my $callback = sub {};
|
||||
|
||||
# If we asked for background processing
|
||||
if ($runinbackground) {
|
||||
$job = put_in_background($job_size);
|
||||
$callback = progress_callback($job, $dbh);
|
||||
}
|
||||
|
||||
# For each item
|
||||
my $i = 1;
|
||||
foreach my $itemnumber(@itemnumbers){
|
||||
|
||||
$job->progress($i) if $runinbackground;
|
||||
my $itemdata=GetItem($itemnumber);
|
||||
if ($input->param("del")){
|
||||
my $return = DelItemCheck(C4::Context->dbh, $itemdata->{'biblionumber'}, $itemdata->{'itemnumber'});
|
||||
if ($return == 1) {
|
||||
$deleted_items++;
|
||||
} else {
|
||||
$not_deleted_items++;
|
||||
push @not_deleted, { biblionumber => $itemdata->{'biblionumber'}, itemnumber => $itemdata->{'itemnumber'}, barcode => $itemdata->{'barcode'}, title => $itemdata->{'title'}, $return => 1 };
|
||||
}
|
||||
} else {
|
||||
if ($something_to_modify) {
|
||||
my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM');
|
||||
my $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8');
|
||||
my $localitem = TransformMarcToKoha( $dbh, $marcitem, "", 'items' );
|
||||
my $localmarcitem=Item2Marc($itemdata);
|
||||
UpdateMarcWith($marcitem,$localmarcitem);
|
||||
eval{my ($oldbiblionumber,$oldbibnum,$oldbibitemnum) = ModItemFromMarc($localmarcitem,$itemdata->{biblionumber},$itemnumber)};
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
# build screen with existing items. and "new" one
|
||||
|
|
@ -485,5 +523,66 @@ sub find_value {
|
|||
return($indicator,$result);
|
||||
}
|
||||
|
||||
# ----------------------------
|
||||
# Background functions
|
||||
|
||||
|
||||
sub add_results_to_template {
|
||||
my $template = shift;
|
||||
my $results = shift;
|
||||
$template->param(map { $_ => $results->{$_} } keys %{ $results });
|
||||
}
|
||||
|
||||
sub add_saved_job_results_to_template {
|
||||
my $template = shift;
|
||||
my $completedJobID = shift;
|
||||
my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
|
||||
my $results = $job->results();
|
||||
add_results_to_template($template, $results);
|
||||
}
|
||||
|
||||
sub put_in_background {
|
||||
my $job_size = shift;
|
||||
|
||||
my $job = C4::BackgroundJob->new($sessionID, "test", $ENV{'SCRIPT_NAME'}, $job_size);
|
||||
my $jobID = $job->id();
|
||||
|
||||
# fork off
|
||||
if (my $pid = fork) {
|
||||
# parent
|
||||
# return job ID as JSON
|
||||
|
||||
# prevent parent exiting from
|
||||
# destroying the kid's database handle
|
||||
# FIXME: according to DBI doc, this may not work for Oracle
|
||||
$dbh->{InactiveDestroy} = 1;
|
||||
|
||||
my $reply = CGI->new("");
|
||||
print $reply->header(-type => 'text/html');
|
||||
print "{ jobID: '$jobID' }";
|
||||
exit 0;
|
||||
} elsif (defined $pid) {
|
||||
# child
|
||||
# close STDOUT to signal to Apache that
|
||||
# we're now running in the background
|
||||
close STDOUT;
|
||||
close STDERR;
|
||||
} else {
|
||||
# fork failed, so exit immediately
|
||||
warn "fork failed while attempting to run $ENV{'SCRIPT_NAME'} as a background job";
|
||||
exit 0;
|
||||
}
|
||||
return $job;
|
||||
}
|
||||
|
||||
sub progress_callback {
|
||||
my $job = shift;
|
||||
my $dbh = shift;
|
||||
return sub {
|
||||
my $progress = shift;
|
||||
$job->progress($progress);
|
||||
$dbh->commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue