bug 2608: let offline circ processing work in background
If an offline circulation file is large, process_koc.pl could time out before processing all of the transactions. To prevent this, the processing can now be run in the background, with an AJAX loop to check the job's status. As a consequence of the patch, the UI for uploading offline circ files has changed slightly. One must select a file, click the "upload file" button, then click the "process offline circulation file" button. Also removed the now-superfluous upload_koc.pl, added the warnings pragma, and fixed a typo in the template. Signed-off-by: Galen Charlton <galen.charlton@liblime.com>
This commit is contained in:
parent
efad22fd4d
commit
c7a3b4ede9
|
|
@ -47,7 +47,7 @@
|
|||
<div class="yui-u">
|
||||
<h5>Offline Circulation</h5>
|
||||
<ul>
|
||||
<li><a href="/cgi-bin/koha/offline_circ/upload_koc.pl">Offline Circulation File (.koc) Uploader</a></li>
|
||||
<li><a href="/cgi-bin/koha/offline_circ/process_koc.pl">Offline Circulation File (.koc) Uploader</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,56 @@
|
|||
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
|
||||
<title>Koha › Circulation › Offline Circulation File Processing</title>
|
||||
<title>Koha › Circulation › Offline Circulation File Upload</title>
|
||||
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="file-upload.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="background-job.inc" -->
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
|
||||
function CheckForm(f) {
|
||||
if (f.uploadedfileid.value == '') {
|
||||
alert('Please upload a file first.');
|
||||
} else {
|
||||
return submitBackgroundJob(f);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- TMPL_INCLUDE NAME="header.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="circ-search.inc" -->
|
||||
|
||||
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> › Offline Circulation File Uplaod</div>
|
||||
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> › Offline Circulation File Upload</div>
|
||||
|
||||
<h2>Koha Offline Circulation</h2>
|
||||
<p>Your data was processed. Here are the results.</p>
|
||||
<!-- TMPL_IF NAME="transactions_loaded" -->
|
||||
<h2>Koha Offline Circulation</h2>
|
||||
<p>Your data was processed. Here are the results.</p>
|
||||
<!-- TMPL_LOOP NAME="messages" -->
|
||||
<p><!-- TMPL_VAR NAME="message" --></p>
|
||||
<!-- /TMPL_LOOP -->
|
||||
<!-- TMPL_ELSE -->
|
||||
<h2>Upload Offline Circulation Data</h2>
|
||||
<div id="fileuploadform">
|
||||
<form method="post" action="<!-- TMPL_VAR name="SCRIPT_NAME" -->" enctype="multipart/form-data">
|
||||
<label for="fileToUpload">Choose .koc File: </label>
|
||||
<input type="file" id="fileToUpload" name="fileToUpload" /><br />
|
||||
<button class="input" onclick="return ajaxFileUpload();">Upload file</button>
|
||||
</form>
|
||||
<div id="fileuploadstatus" style="display:none">Upload progress: <span id="fileuploadprogress">0</span>%</div>
|
||||
<div id="fileuploadfailed" style="display:none"></div>
|
||||
</div>
|
||||
<form action="process_koc.pl" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
|
||||
<input type="hidden" name="runinbackground" id="runinbackground" value="" />
|
||||
<input type="hidden" name="completedJobID" id="completedJobID" value="" />
|
||||
<input type="submit" value="Process offline circulation file" onclick="return CheckForm(this.form);" id="mainformsubmit" />
|
||||
<div id="jobstatus" style="display:none">Job progress: <span id="jobprogress">0</span>%</div>
|
||||
<div id="jobfailed" style="display:none"></div>
|
||||
</form>
|
||||
<!-- /TMPL_IF -->
|
||||
|
||||
<!-- TMPL_LOOP NAME="messages" -->
|
||||
<p><!-- TMPL_VAR NAME="message" --></p>
|
||||
<!-- /TMPL_LOOP -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
|
||||
<title>Koha › Circulation › Offline Circulation File Upload</title>
|
||||
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- TMPL_INCLUDE NAME="header.inc" -->
|
||||
<!-- TMPL_INCLUDE NAME="circ-search.inc" -->
|
||||
|
||||
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> › Offline Circulation File Uplaod</div>
|
||||
|
||||
<h2>Upload Offline Circulation Data</h2>
|
||||
<form action="process_koc.pl" method="post" enctype="multipart/form-data">
|
||||
<label for="kocfile">Choose .koc File</label>
|
||||
<input type="file" id="kocfile" name="kocfile" />
|
||||
|
||||
<br />
|
||||
|
||||
<input type="submit" value="Upload File"/>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
#
|
||||
|
||||
use strict;
|
||||
require Exporter;
|
||||
use warnings;
|
||||
|
||||
use CGI;
|
||||
use C4::Output;
|
||||
|
|
@ -31,6 +31,8 @@ use C4::Accounts;
|
|||
use C4::Circulation;
|
||||
use C4::Members;
|
||||
use C4::Stats;
|
||||
use C4::UploadedFile;
|
||||
use C4::BackgroundJob;
|
||||
|
||||
use Date::Calc qw( Add_Delta_Days Date_to_Days );
|
||||
|
||||
|
|
@ -49,49 +51,107 @@ my ($template, $loggedinuser, $cookie)
|
|||
debug => 1,
|
||||
});
|
||||
|
||||
|
||||
my $fileID=$query->param('uploadedfileid');
|
||||
my $runinbackground = $query->param('runinbackground');
|
||||
my $completedJobID = $query->param('completedJobID');
|
||||
my %cookies = parse CGI::Cookie($cookie);
|
||||
my $sessionID = $cookies{'CGISESSID'}->value;
|
||||
## 'Local' globals.
|
||||
our $dbh = C4::Context->dbh();
|
||||
our @output; ## For storing messages to be displayed to the user
|
||||
|
||||
$query::POST_MAX = 1024 * 10000;
|
||||
my $file = $query->param("kocfile");
|
||||
$file=~m/^.*(\\|\/)(.*)/; # strip the remote path and keep the filename
|
||||
|
||||
my $header_line = <$file>;
|
||||
my $file_info = parse_header_line($header_line);
|
||||
if ($file_info->{'Version'} ne $FILE_VERSION) {
|
||||
push( @output, { message => "Warning: This file is version '$file_info->{'Version'}', but I only know how to import version '$FILE_VERSION'. I'll try my best." } );
|
||||
}
|
||||
our @output = (); ## For storing messages to be displayed to the user
|
||||
|
||||
|
||||
while ( my $line = <$file> ) {
|
||||
if ($completedJobID) {
|
||||
my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
|
||||
my $results = $job->results();
|
||||
$template->param(transactions_loaded => 1);
|
||||
$template->param(messages => $results->{results});
|
||||
} elsif ($fileID) {
|
||||
my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
|
||||
my $fh = $uploaded_file->fh();
|
||||
my @input_lines = <$fh>;
|
||||
|
||||
my $filename = $uploaded_file->name();
|
||||
my $job = undef;
|
||||
|
||||
# my ( $date, $time, $command, @arguments ) = parse_command_line( $line );
|
||||
my $command_line = parse_command_line($line);
|
||||
if ($runinbackground) {
|
||||
my $job_size = scalar(@input_lines);
|
||||
$job = C4::BackgroundJob->new($sessionID, $filename, $ENV{'SCRIPT_NAME'}, $job_size);
|
||||
my $jobID = $job->id();
|
||||
|
||||
# map command names in the file to subroutine names
|
||||
my %dispatch_table = (
|
||||
issue => \&kocIssueItem,
|
||||
return => \&kocReturnItem,
|
||||
payment => \&kocMakePayment,
|
||||
);
|
||||
# fork off
|
||||
if (my $pid = fork) {
|
||||
# parent
|
||||
# return job ID as JSON
|
||||
|
||||
# call the right sub name, passing the hashref of command_line to it.
|
||||
if ( exists $dispatch_table{ $command_line->{'command'} } ) {
|
||||
$dispatch_table{ $command_line->{'command'} }->($command_line);
|
||||
} else {
|
||||
warn "unknown command: '$command_line->{command}' not processed";
|
||||
# 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
|
||||
# fork failed, so exit immediately
|
||||
warn "fork failed while attempting to run $ENV{'SCRIPT_NAME'} as a background job";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# if we get here, we're a child that has detached
|
||||
# itself from Apache
|
||||
|
||||
}
|
||||
|
||||
my $header_line = shift @input_lines;
|
||||
my $file_info = parse_header_line($header_line);
|
||||
if ($file_info->{'Version'} ne $FILE_VERSION) {
|
||||
push( @output, { message => "Warning: This file is version '$file_info->{'Version'}', but I only know how to import version '$FILE_VERSION'. I'll try my best." } );
|
||||
}
|
||||
|
||||
|
||||
my $i = 0;
|
||||
foreach my $line (@input_lines) {
|
||||
|
||||
$i++;
|
||||
my $command_line = parse_command_line($line);
|
||||
|
||||
# map command names in the file to subroutine names
|
||||
my %dispatch_table = (
|
||||
issue => \&kocIssueItem,
|
||||
'return' => \&kocReturnItem,
|
||||
payment => \&kocMakePayment,
|
||||
);
|
||||
|
||||
# call the right sub name, passing the hashref of command_line to it.
|
||||
if ( exists $dispatch_table{ $command_line->{'command'} } ) {
|
||||
$dispatch_table{ $command_line->{'command'} }->($command_line);
|
||||
} else {
|
||||
warn "unknown command: '$command_line->{command}' not processed";
|
||||
}
|
||||
|
||||
if ($runinbackground) {
|
||||
$job->progress($i);
|
||||
}
|
||||
}
|
||||
|
||||
if ($runinbackground) {
|
||||
$job->finish({ results => \@output }) if defined($job);
|
||||
} else {
|
||||
$template->param(transactions_loaded => 1);
|
||||
$template->param(messages => \@output);
|
||||
}
|
||||
}
|
||||
|
||||
$template->param(
|
||||
intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
|
||||
intranetstylesheet => C4::Context->preference("intranetstylesheet"),
|
||||
IntranetNav => C4::Context->preference("IntranetNav"),
|
||||
|
||||
messages => \@output,
|
||||
);
|
||||
output_html_with_http_headers $query, $cookie, $template->output;
|
||||
|
||||
=head3 parse_header_line
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# This file is part of Koha.
|
||||
#
|
||||
# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
# Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
use strict;
|
||||
require Exporter;
|
||||
|
||||
use C4::Output;
|
||||
use C4::Auth;
|
||||
use C4::Koha;
|
||||
|
||||
use CGI;
|
||||
|
||||
my $query = new CGI;
|
||||
|
||||
my ($template, $loggedinuser, $cookie)
|
||||
= get_template_and_user({template_name => "offline_circ/upload_koc.tmpl",
|
||||
query => $query,
|
||||
type => "intranet",
|
||||
authnotrequired => 1,
|
||||
debug => 1,
|
||||
});
|
||||
|
||||
$template->param(
|
||||
intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
|
||||
intranetstylesheet => C4::Context->preference("intranetstylesheet"),
|
||||
IntranetNav => C4::Context->preference("IntranetNav"),
|
||||
);
|
||||
output_html_with_http_headers $query, $cookie, $template->output;
|
||||
Loading…
Reference in New Issue