batch import rework -- implement stage-commit-undo for batch import
authorGalen Charlton <galen.charlton@liblime.com>
Mon, 29 Oct 2007 21:45:14 +0000 (16:45 -0500)
committerJoshua Ferraro <jmf@liblime.com>
Mon, 29 Oct 2007 21:47:59 +0000 (16:47 -0500)
Revamps the import options on the tools menu to have two parts:

[1] Staging (load file into reservoir)
[2] Managing (review the list of staged batches, then
    choose to commit or undo a given batch.

Signed-off-by: Chris Cormack <crc@liblime.com>
Signed-off-by: Joshua Ferraro <jmf@liblime.com>
12 files changed:
C4/Breeding.pm
C4/ImportBatch.pm
koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc
koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/import.tmpl [deleted file]
koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/stage-marc-import.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/tools/import.tmpl [deleted file]
koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tmpl
tools/import.pl [deleted file]
tools/manage-marc-import.pl [new file with mode: 0755]
tools/stage-marc-import.pl [new file with mode: 0755]

index 0ec0829..dde6d3c 100644 (file)
@@ -80,7 +80,6 @@ sub ImportBreeding {
         $batch_id = GetZ3950BatchId($filename);
     } else {
         # create a new one
-        # FIXME - handle comments
         $batch_id = AddImportBatch('create_new', 'staging', 'batch', $filename, '');
     }
     my $searchisbn = $dbh->prepare("select biblioitemnumber from biblioitems where isbn=?");
index b2b77b0..84dd2ed 100644 (file)
@@ -51,12 +51,18 @@ use C4::ImportBatch;
     GetZ3950BatchId
     GetImportRecordMarc
     AddImportBatch
+    GetImportBatch
     AddBiblioToBatch
     ModBiblioInBatch
 
     BatchStageMarcRecords
     BatchFindBibDuplicates
     BatchCommitBibRecords
+    BatchRevertBibRecords
+
+    GetImportBatchRangeDesc
+    GetNumberOfNonZ3950ImportBatches
+    GetImportBibliosRange
     
     GetImportBatchStatus
     SetImportBatchStatus
@@ -64,6 +70,9 @@ use C4::ImportBatch;
     SetImportBatchOverlayAction
     GetImportRecordOverlayStatus
     SetImportRecordOverlayStatus
+    GetImportRecordStatus
+    SetImportRecordStatus
+    GetImportRecordMatches
     SetImportRecordMatches
 );
 
@@ -147,21 +156,52 @@ sub AddImportBatch {
 
 }
 
+=head2 GetImportBatch 
+
+=over 4
+
+my $row = GetImportBatch($batch_id);
+
+=back
+
+Retrieve a hashref of an import_batches row.
+
+=cut
+
+sub GetImportBatch {
+    my ($batch_id) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare_cached("SELECT * FROM import_batches WHERE import_batch_id = ?");
+    $sth->bind_param(1, $batch_id);
+    $sth->execute();
+    my $result = $sth->fetchrow_hashref;
+    $sth->finish();
+    return $result;
+
+}
+
 =head2 AddBiblioToBatch 
 
 =over 4
 
-my $import_record_id = AddBiblioToBatch($batch_id, $record_sequence, $marc_record, $encoding, $z3950random);
+my $import_record_id = AddBiblioToBatch($batch_id, $record_sequence, $marc_record, $encoding, $z3950random, $update_counts);
 
 =back
 
 =cut
 
 sub AddBiblioToBatch {
-    my ($batch_id, $record_sequence, $marc_record, $encoding, $z3950random) = @_;
+    my $batch_id = shift;
+    my $record_sequence = shift;
+    my $marc_record = shift;
+    my $encoding = shift;
+    my $z3950random = shift;
+    my $update_counts = @_ ? shift : 1;
 
     my $import_record_id = _create_import_record($batch_id, $record_sequence, $marc_record, 'biblio', $encoding, $z3950random);
     _add_biblio_fields($import_record_id, $marc_record);
+    _update_batch_record_counts($batch_id) if $update_counts;
     return $import_record_id;
 }
 
@@ -210,13 +250,14 @@ sub  BatchStageMarcRecords {
             push @invalid_records, $marc_blob;
         } else {
             $num_valid++;
-            $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $marc_flavor, int(rand(99999)));
+            $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $marc_flavor, int(rand(99999)), 0);
         }
     }
     unless ($leave_as_staging) {
         SetImportBatchStatus($batch_id, 'staged');
     }
-    # FIXME batch_code, number of bibs, number of items
+    # FIXME branch_code, number of bibs, number of items
+    _update_batch_record_counts($batch_id);
     return ($batch_id, $num_valid, @invalid_records);
 }
 
@@ -305,24 +346,175 @@ sub BatchCommitBibRecords {
             ($overlay_action eq 'replace' and $rowref->{'overlay_status'} eq 'no_match')) {
             $num_added++;
             my ($biblionumber, $biblioitemnumber) = AddBiblio($marc_record, '');
+            my $sth = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
+            $sth->execute($biblionumber, $rowref->{'import_record_id'});
+            $sth->finish();
+            SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
         } else {
             $num_updated++;
             my $biblionumber = GetBestRecordMatch($rowref->{'import_record_id'});
             my ($count, $oldbiblio) = GetBiblio($biblionumber);
             my $oldxml = GetXmlBiblio($biblionumber);
             ModBiblio($marc_record, $biblionumber, $oldbiblio->{'frameworkcode'});
-            my $dbh = C4::Context->dbh;
-            my $sth = $dbh->prepare("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?");
+            my $sth = $dbh->prepare_cached("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?");
             $sth->execute($oldxml, $rowref->{'import_record_id'});
             $sth->finish();
+            my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
+            $sth2->execute($biblionumber, $rowref->{'import_record_id'});
+            $sth2->finish();
             SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied');
+            SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
         }
     }
     $sth->finish();
-    SetImportBatchStatus('imported');
+    SetImportBatchStatus($batch_id, 'imported');
     return ($num_added, $num_updated, $num_ignored);
 }
 
+=head2 BatchRevertBibRecords
+
+=over 4
+
+my ($num_deleted, $num_errors, $num_reverted, $num_ignored) = BatchRevertBibRecords($batch_id);
+
+=back
+
+=cut
+
+sub BatchRevertBibRecords {
+    my $batch_id = shift;
+
+    my $num_deleted = 0;
+    my $num_errors = 0;
+    my $num_reverted = 0;
+    my $num_ignored = 0;
+    # commit (i.e., save, all records in the batch)
+    # FIXME biblio only at the moment
+    SetImportBatchStatus('reverting');
+    my $overlay_action = GetImportBatchOverlayAction($batch_id);
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marcxml_old, encoding, matched_biblionumber
+                             FROM import_records
+                             JOIN import_biblios USING (import_record_id)
+                             WHERE import_batch_id = ?");
+    $sth->execute($batch_id);
+    while (my $rowref = $sth->fetchrow_hashref) {
+        if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'reverted') {
+            $num_ignored++;
+        }
+        if ($overlay_action eq 'create_new' or
+            ($overlay_action eq 'replace' and $rowref->{'overlay_status'} eq 'no_match')) {
+            my $error = DelBiblio($rowref->{'matched_biblionumber'});
+            if (defined $error) {
+                $num_errors++;
+            } else {
+                $num_deleted++;
+                SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
+            }
+        } else {
+            $num_reverted++;
+            my $old_record = MARC::Record->new_from_xml($rowref->{'marcxml_old'}, 'UTF-8', $rowref->{'encoding'});
+            my $biblionumber = $rowref->{'matched_biblionumber'};
+            my ($count, $oldbiblio) = GetBiblio($biblionumber);
+            ModBiblio($old_record, $biblionumber, $oldbiblio->{'frameworkcode'});
+            SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
+        }
+    }
+    $sth->finish();
+    SetImportBatchStatus($batch_id, 'reverted');
+    return ($num_deleted, $num_errors, $num_reverted, $num_ignored);
+}
+
+=head2 GetImportBatchRangeDesc
+
+=over 4
+
+my $results = GetImportBatchRangeDesc($offset, $results_per_group);
+
+=back
+
+Returns a reference to an array of hash references corresponding to
+import_batches rows (sorted in descending order by import_batch_id)
+start at the given offset.
+
+=cut
+
+sub GetImportBatchRangeDesc {
+    my ($offset, $results_per_group) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
+                                    WHERE batch_type = 'batch'
+                                    ORDER BY import_batch_id DESC
+                                    LIMIT ? OFFSET ?");
+    $sth->bind_param(1, $results_per_group);
+    $sth->bind_param(2, $offset);
+
+    my $results = [];
+    $sth->execute();
+    while (my $row = $sth->fetchrow_hashref) {
+        push @$results, $row;
+    }
+    $sth->finish();
+    return $results;
+}
+
+=head2 GetNumberOfImportBatches 
+
+=over 4
+
+my $count = GetNumberOfImportBatches();
+
+=back
+
+=cut
+
+sub GetNumberOfNonZ3950ImportBatches {
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type='batch'");
+    $sth->execute();
+    my ($count) = $sth->fetchrow_array();
+    $sth->finish();
+    return $count;
+}
+
+=head2 GetImportBibliosRange
+
+=over 4
+
+my $results = GetImportBibliosRange($batch_id, $offset, $results_per_group);
+
+=back
+
+Returns a reference to an array of hash references corresponding to
+import_biblios/import_records rows for a given batch
+starting at the given offset.
+
+=cut
+
+sub GetImportBibliosRange {
+    my ($batch_id, $offset, $results_per_group) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare_cached("SELECT title, author, isbn, issn, import_record_id, record_sequence,
+                                           status, overlay_status
+                                    FROM   import_records
+                                    JOIN   import_biblios USING (import_record_id)
+                                    WHERE  import_batch_id = ?
+                                    ORDER BY import_record_id LIMIT ? OFFSET ?");
+    $sth->bind_param(1, $batch_id);
+    $sth->bind_param(2, $results_per_group);
+    $sth->bind_param(3, $offset);
+    my $results = [];
+    $sth->execute();
+    while (my $row = $sth->fetchrow_hashref) {
+        push @$results, $row;
+    }
+    $sth->finish();
+    return $results;
+
+}
+
 =head2 GetBestRecordMatch
 
 =over 4
@@ -476,6 +668,85 @@ sub SetImportRecordOverlayStatus {
 
 }
 
+=head2 GetImportRecordStatus
+
+=over 4
+
+my $overlay_status = GetImportRecordStatus($import_record_id);
+
+=back
+
+=cut
+
+sub GetImportRecordStatus {
+    my ($import_record_id) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("SELECT status FROM import_records WHERE import_record_id = ?");
+    $sth->execute($import_record_id);
+    my ($overlay_status) = $sth->fetchrow_array();
+    $sth->finish();
+    return $overlay_status;
+
+}
+
+
+=head2 SetImportRecordStatus
+
+=over 4
+
+SetImportRecordStatus($import_record_id, $new_overlay_status);
+
+=back
+
+=cut
+
+sub SetImportRecordStatus {
+    my ($import_record_id, $new_overlay_status) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("UPDATE import_records SET status = ? WHERE import_record_id = ?");
+    $sth->execute($new_overlay_status, $import_record_id);
+    $sth->finish();
+
+}
+
+=head2 GetImportRecordMatches
+
+=over 4
+
+my $results = GetImportRecordMatches($import_record_id, $best_only);
+
+=back
+
+=cut
+
+sub GetImportRecordMatches {
+    my $import_record_id = shift;
+    my $best_only = @_ ? shift : 0;
+
+    my $dbh = C4::Context->dbh;
+    # FIXME currently biblio only
+    my $sth = $dbh->prepare_cached("SELECT title, author, biblionumber, score
+                                    FROM import_records
+                                    JOIN import_record_matches USING (import_record_id)
+                                    JOIN biblio ON (biblionumber = candidate_match_id)
+                                    WHERE import_record_id = ?
+                                    ORDER BY score DESC, biblionumber DESC");
+    $sth->bind_param(1, $import_record_id);
+    my $results = [];
+    $sth->execute();
+    while (my $row = $sth->fetchrow_hashref) {
+        push @$results, $row;
+        last if $best_only;
+    }
+    $sth->finish();
+
+    return $results;
+    
+}
+
+
 =head2 SetImportRecordMatches
 
 =over 4
@@ -570,6 +841,22 @@ sub _parse_biblio_fields {
 
 }
 
+sub _update_batch_record_counts {
+    my ($batch_id) = @_;
+
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare_cached("UPDATE import_batches SET num_biblios = (
+                                    SELECT COUNT(*)
+                                    FROM import_records
+                                    WHERE import_batch_id = import_batches.import_batch_id
+                                    AND record_type = 'biblio')
+                                    WHERE import_batch_id = ?");
+    $sth->bind_param(1, $batch_id);
+    $sth->execute();
+    $sth->finish();
+
+}
+
 1;
 
 =head1 AUTHOR
index 56c8804..b32ce96 100644 (file)
@@ -1,10 +1,14 @@
 <ul>
        <li><a href="/cgi-bin/koha/tools/tools-home.pl">Tools Home</a></li>
        <li><a href="/cgi-bin/koha/tools/koha-news.pl">News</a></li>
-       <li><a href="/cgi-bin/koha/labels/label-home.pl">Labels (spine and barcode)</a></li>
-       <li><a href="/cgi-bin/koha/tools/holidays.pl">Holidays</a></li>
+       <li><a href="/cgi-bin/koha/tools/inventory.pl">Inventory/stocktaking</a></li>
+       <li><a href="/cgi-bin/koha/tools/cleanborrowers.pl">Clean borrowers</a></li>
+       <li><a href="/cgi-bin/koha/tools/export.pl">Export</a></li>
+       <li><a href="/cgi-bin/koha/tools/stage-marc-import.pl">MARC Import (staging)</a></li>
+       <li><a href="/cgi-bin/koha/tools/manage-marc-import.pl">MARC Import (managing batches)</a></li>
        <li><a href="/cgi-bin/koha/tools/letter.pl">Notices</a></li>
        <li><a href="/cgi-bin/koha/tools/overduerules.pl">Notice/status triggers</a></li>
+       <li><a href="/cgi-bin/koha/labels/label-home.pl">Labels</a></li>
        <li><a href="/cgi-bin/koha/tools/viewlog.pl">Log viewer</a></li>
        <li><a href="/cgi-bin/koha/tools/inventory.pl">Inventory/stocktaking</a></li>
        <li><a href="/cgi-bin/koha/tools/export.pl">Export bibs/holdings</a></li>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/import.tmpl
deleted file mode 100644 (file)
index f37124c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
-<title>Online Help &rsaquo; MARC Import</title>
-<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
-</head>
-<body>
-
-
-<h1>MARC Import</h1>
-<p>This is one of the screens you will see frequently if you are starting from scratch.</p>
-
-<p>It is useful to import a bunch of ISO 2709 biblios that can be used later for a quick cataloguing</p>
-
-<p>First, you need to browse your computer to find the MARC record that you grabbed for your item. Click on</p>
-
-<p>Choose File to browse.</p>
-
-<p>If you aren't sure if you've already imported a record, keep the radio button set to</p>
-
-<p>Ignore this one, keep the existing one.</p>
-
-<p>You can "name" the import to help you when you need to choose between more than 1 imported biblio (or just want to keep trace on where the biblios comes from)</p>
-
-<p>You can also change char encoding between MARC21 and UNIMARC</p>
-
-<p>You don't need to actually name every import, so you don't need to fill in this box if you don't want to. It is useful for telling imports apart if you've more than one of the same record.</p>
-
-<p><b>IMPORTANT : This tool is NOT intended to import ISO 2709 in your ACTIVE database. If you need to migrate data from another ILS, then you must consider $kohaInstall/scripts/misc/bulkmarcimport.pl</b></p>
-
-<!-- TMPL_INCLUDE name="intranet-bottom.inc" -->
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/stage-marc-import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/stage-marc-import.tmpl
new file mode 100644 (file)
index 0000000..f37124c
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
+<title>Online Help &rsaquo; MARC Import</title>
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+</head>
+<body>
+
+
+<h1>MARC Import</h1>
+<p>This is one of the screens you will see frequently if you are starting from scratch.</p>
+
+<p>It is useful to import a bunch of ISO 2709 biblios that can be used later for a quick cataloguing</p>
+
+<p>First, you need to browse your computer to find the MARC record that you grabbed for your item. Click on</p>
+
+<p>Choose File to browse.</p>
+
+<p>If you aren't sure if you've already imported a record, keep the radio button set to</p>
+
+<p>Ignore this one, keep the existing one.</p>
+
+<p>You can "name" the import to help you when you need to choose between more than 1 imported biblio (or just want to keep trace on where the biblios comes from)</p>
+
+<p>You can also change char encoding between MARC21 and UNIMARC</p>
+
+<p>You don't need to actually name every import, so you don't need to fill in this box if you don't want to. It is useful for telling imports apart if you've more than one of the same record.</p>
+
+<p><b>IMPORTANT : This tool is NOT intended to import ISO 2709 in your ACTIVE database. If you need to migrate data from another ILS, then you must consider $kohaInstall/scripts/misc/bulkmarcimport.pl</b></p>
+
+<!-- TMPL_INCLUDE name="intranet-bottom.inc" -->
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import.tmpl
deleted file mode 100644 (file)
index ada3c46..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
-<title>Koha &rsaquo; Tools &rsaquo; MARC Import</title>
-<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
-</head>
-<body>
-<!-- TMPL_INCLUDE NAME="header.inc" -->
-<!-- TMPL_INCLUDE NAME="cat-search.inc" -->
-
-<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; MARC Import</div>
-
-<div id="doc3" class="yui-t2">
-   
-   <div id="bd">
-       <div id="yui-main">
-       <div class="yui-b">
-
-<h1>MARC acquisition system</h1>
-
-<!-- TMPL_IF name="uploadmarc" -->
-<p>Import results :</p>
-<ul>
-       <li><!-- TMPL_VAR name="imported" --> imported records</li>
-       <li><!-- TMPL_VAR name="alreadyindb" --> not imported because already in catalog</li>
-       <li><!-- TMPL_VAR name="alreadyinfarm" --> not imported because already in the reservoir</li>
-       <li><!-- TMPL_VAR name="notmarcrecord" --> not imported because they seem not to be in MARC format (or ISBN/ISSN missing) !</li>
-       <li><!-- TMPL_VAR name="total" -->  records parsed</li>
-       <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back</a></li>
-</ul>
-<!-- TMPL_ELSE -->
-<ul>
-       <li>Select a file to import into the reservoir. It will be parsed, and for each ISBN found, a new baby will be created in the reservoir.</li>
-       <li>If an ISBN already exists in the reservoir, you can choose whether to ignore the new one or overwrite the old one.</li>
-       <li>You can enter a name for this import. It may be useful, when creating a biblio, to remember where the suggested MARC data comes from!</li>
-       <li>Of course, if the ISBN already exists in the active DB, the biblio will be ignored.</li>
-</ul>
-<form method="post" action="<!-- TMPL_VAR name="SCRIPT_NAME" -->" enctype="multipart/form-data">
-<fieldset class="rows">
-<legend>Import into the reservoir</legend><ol>
-       <li>
-               <label for="uploadmarc">Select the file to import: </label>
-               
-                       <input type="file" id="uploadmarc" name="uploadmarc" /><br />
-               
-       </li>
-       <li>
-               <label for="comments">Notes about this import: </label>
-               
-                       <input type="text" id="comments" name="comments" />
-               
-       </li>
-       <li>
-               <label for="syntax">Character encoding: </label>
-               
-                       <select name="syntax" id="syntax"><option value="MARC21">MARC21</option><option value="UNIMARC">UNIMARC</option></select>
-               
-       </li>
-</ol></fieldset>
-       <fieldset class="rows">
-       <legend>If ISBN is already in the reservoir:</legend><ol><li class="radio">
-                
-               <input type="radio" id="overwrite_bibliono" name="overwrite_biblio" value="0" checked="checked" /><label for="overwrite_bibliono">Ignore this one, keep the existing one</label></li>
-<li class="radio">
-                       <input type="radio" id="overwrite_biblioyes" name="overwrite_biblio" value="1" /><label for="overwrite_biblioyes">Overwrite the existing one with this</label>
-       </li></ol></fieldset><input type="submit" value="Import" />
-</form>
-<!-- /TMPL_IF -->
-
-</div>
-</div>
-<div class="yui-b">
-<!-- TMPL_INCLUDE NAME="tools-menu.inc" -->
-</div>
-</div>
-<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl
new file mode 100644 (file)
index 0000000..9b97ddb
--- /dev/null
@@ -0,0 +1,180 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
+<title>Koha &rsaquo; Tools &rsaquo; Manage Staged MARC Records
+<!-- TMPL_IF name="import_batch_id" -->
+ &rsaquo; Batch <!-- TMPL_VAR name="import_batch_id" -->
+<!-- /TMPL_IF -->
+</title>
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+</head>
+<body>
+<!-- TMPL_INCLUDE NAME="header.inc" -->
+<!-- TMPL_INCLUDE NAME="cat-search.inc" -->
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> 
+<!-- TMPL_IF name="import_batch_id" -->
+ &rsaquo;
+ <a href="<!-- TMPL_VAR name="script_name"-->">Manage Staged MARC Records</a>
+ &rsaquo; Batch <!-- TMPL_VAR name="import_batch_id" -->
+<!-- TMPL_ELSE -->
+ &rsaquo; Manage Staged MARC Records
+<!-- /TMPL_IF -->
+</div>
+
+<div id="doc3" class="yui-t2">
+   
+   <div id="bd">
+       <div id="yui-main">
+       <div class="yui-b">
+
+<h1>Manage Staged MARC Records
+<!-- TMPL_IF name="import_batch_id" -->
+ &rsaquo; Batch <!-- TMPL_VAR name="import_batch_id" -->
+<!-- /TMPL_IF -->
+</h1>
+
+<!-- TMPL_IF name="batch_info" -->
+<p><label>File name</label> <!-- TMPL_VAR name="file_name" --></p>
+<p><label>Comments</label> <!-- TMPL_VAR name="comments" --></p>
+<p><label>Staged</label> <!-- TMPL_VAR name="upload_timestamp" --></p>
+<p><label>Status</label> <!-- TMPL_VAR name="import_status" --></p>
+<p>
+  <!-- TMPL_IF name="can_commit" -->
+  <form action="<!-- TMPL_VAR name="script_name" -->" method="post">
+    <input type="hidden" name="op" value="commit-batch" />
+    <input type="hidden" name="import_batch_id" value="<!-- TMPL_VAR name="import_batch_id" -->" />
+    <input type="submit" class="button" value="Complete import" />
+  </form>
+  <!-- /TMPL_IF -->
+  <!-- TMPL_IF name="can_revert" -->
+  <form action="<!-- TMPL_VAR name="script_name" -->" method="post">
+    <input type="hidden" name="op" value="revert-batch" />
+    <input type="hidden" name="import_batch_id" value="<!-- TMPL_VAR name="import_batch_id" -->" />
+    <input type="submit" class="button" value="Undo import" />
+  </form>
+  <!-- /TMPL_IF -->
+</p>
+  <!-- TMPL_IF name="did_commit" -->
+  <p><span class="problem">Completed import of records</span></p>
+  <table>
+  <tr><td>Number of records added</td><td><!-- TMPL_VAR name="num_added" --></td></tr>
+  <tr><td>Number of records updated</td><td><!-- TMPL_VAR name="num_updated" --></td></tr>
+  <tr><td>Number of records ignored</td><td><!-- TMPL_VAR name="num_ignored" --></td></tr>
+  </table>
+  <!-- /TMPL_IF -->
+  <!-- TMPL_IF name="did_revert" -->
+  <p><span class="problem">Undid import of records</span></p>
+  <table>
+  <tr><td>Number of records deleted</td><td><!-- TMPL_VAR name="num_deleted" --></td></tr>
+  <tr><td>Number of records not deleted due to items on loan</td><td><!-- TMPL_VAR name="num_errors" --></td></tr>
+  <tr><td>Number of records changed back</td><td><!-- TMPL_VAR name="num_reverted" --></td></tr>
+  <tr><td>Number of records ignored</td><td><!-- TMPL_VAR name="num_ignored" --></td></tr>
+  </table>
+  <!-- /TMPL_IF -->
+<!-- /TMPL_IF -->
+<br />
+
+<!-- TMPL_IF name="batch_list" -->
+  <!-- TMPL_IF name="pages" -->
+<div class="pages">
+Page 
+    <!-- TMPL_LOOP name="pages" -->
+      <!-- TMPL_IF name="current_page" -->
+      <span class="current"><!-- TMPL_VAR name="page_number" --></span>
+      <!-- TMPL_ELSE -->
+      <a class="nav" href="<!-- TMPL_VAR name="script_name" -->?offset=<!-- TMPL_VAR name="offset" -->"><!-- TMPL_VAR name="page_number" --></a>
+      <!-- /TMPL_IF -->
+    <!-- /TMPL_LOOP -->
+</div>
+  <!-- /TMPL_IF -->
+<table>
+  <tr>
+    <th>#</th>
+    <th>File name</th>
+    <th>Comments</th>
+    <th>Status</th>
+    <th>Staged</th>
+    <th># Bibs</th.
+    <th># Items</th>
+  </tr>
+  <!-- TMPL_LOOP name="batch_list" -->
+  <tr>
+    <td><a href="<!-- TMPL_VAR name="script_name" -->?import_batch_id=<!-- TMPL_VAR name="import_batch_id" -->"><!-- TMPL_VAR name="import_batch_id" --></a></td>
+    <td><!-- TMPL_VAR name="file_name" --></td>
+    <td><!-- TMPL_VAR name="comments" --></td>
+    <td><!-- TMPL_VAR name="import_status" --></td>
+    <td><!-- TMPL_VAR name="upload_timestamp" --></td>
+    <td><!-- TMPL_VAR name="num_biblios" --></td>
+    <td><!-- TMPL_VAR name="num_items" --></td>
+  </tr>
+  <!-- /TMPL_LOOP -->
+</table>
+  <!-- TMPL_IF name="pages" -->
+<div class="pages">
+Page 
+    <!-- TMPL_LOOP name="pages" -->
+      <!-- TMPL_IF name="current_page" -->
+      <span class="current"><!-- TMPL_VAR name="page_number" --></span>
+      <!-- TMPL_ELSE -->
+      <a class="nav" href="<!-- TMPL_VAR name="script_name" -->?offset=<!-- TMPL_VAR name="offset" -->"><!-- TMPL_VAR name="page_number" --></a>
+      <!-- /TMPL_IF -->
+    <!-- /TMPL_LOOP -->
+</div>
+  <!-- /TMPL_IF -->
+<!-- /TMPL_IF -->
+
+<!-- TMPL_IF name="biblio_list" -->
+  <!-- TMPL_IF name="pages" -->
+<div class="pages">
+Page 
+    <!-- TMPL_LOOP name="pages" -->
+      <!-- TMPL_IF name="current_page" -->
+      <span class="current"><!-- TMPL_VAR name="page_number" --></span>
+      <!-- TMPL_ELSE -->
+      <a class="nav" href="<!-- TMPL_VAR name="script_name" -->?import_batch_id=<!-- TMPL_VAR name="import_batch_id" -->&offset=<!-- TMPL_VAR name="offset" -->"><!-- TMPL_VAR name="page_number" --></a>
+      <!-- /TMPL_IF -->
+    <!-- /TMPL_LOOP -->
+</div>
+  <!-- /TMPL_IF -->
+<table>
+  <tr>
+    <th>#</th>
+    <th>Citation</th>
+    <th>Status</th>
+    <th>Overlay?</th>
+  </tr>
+  <!-- TMPL_LOOP name="biblio_list" -->
+  <tr>
+    <td><!-- TMPL_VAR name="record_sequence"--></td>
+    <td><!-- TMPL_VAR name="citation"--></td>
+    <td><!-- TMPL_VAR name="status"--></td>
+    <td><!-- TMPL_VAR name="overlay_status"--></td>
+  </tr>
+    <!-- TMPL_IF name="match_biblionumber" -->
+    <tr>
+      <td />
+      <td class="highlight" colspan="3">Matches biblio <!-- TMPL_VAR name="match_biblionumber" --> (score = <!-- TMPL_VAR name="match_score" -->): <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR name="match_biblionumber" -->"><!-- TMPL_VAR name="match_citation" --></a></td>
+    </tr>
+    <!-- /TMPL_IF -->
+  <!-- /TMPL_LOOP -->
+</table>
+  <!-- TMPL_IF name="pages" -->
+<div class="pages">
+Page 
+    <!-- TMPL_LOOP name="pages" -->
+      <!-- TMPL_IF name="current_page" -->
+      <span class="current"><!-- TMPL_VAR name="page_number" --></span>
+      <!-- TMPL_ELSE -->
+      <a class="nav" href="<!-- TMPL_VAR name="script_name" -->?import_batch_id=<!-- TMPL_VAR name="import_batch_id" -->&offset=<!-- TMPL_VAR name="offset" -->"><!-- TMPL_VAR name="page_number" --></a>
+      <!-- /TMPL_IF -->
+    <!-- /TMPL_LOOP -->
+</div>
+  <!-- /TMPL_IF -->
+<!-- /TMPL_IF -->
+
+</div>
+</div>
+<div class="yui-b">
+<!-- TMPL_INCLUDE NAME="tools-menu.inc" -->
+</div>
+</div>
+<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stage-marc-import.tmpl
new file mode 100644 (file)
index 0000000..1f063fb
--- /dev/null
@@ -0,0 +1,76 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
+<title>Koha &rsaquo; Tools &rsaquo; Stage MARC Records For Import</title>
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+</head>
+<body>
+<!-- TMPL_INCLUDE NAME="header.inc" -->
+<!-- TMPL_INCLUDE NAME="cat-search.inc" -->
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; Stage MARC Records For Import</div>
+
+<div id="doc3" class="yui-t2">
+   
+   <div id="bd">
+       <div id="yui-main">
+       <div class="yui-b">
+
+<h1>Stage MARC Records For Import</h1>
+
+<!-- TMPL_IF name="uploadmarc" -->
+<p>MARC Staging results :</p>
+<ul>
+       <li><!-- TMPL_VAR name="total" -->  records in file</li>
+       <li><!-- TMPL_VAR name="import_errors" --> records not staged because of MARC error</li>
+       <li><!-- TMPL_VAR name="staged" --> records staged</li>
+    <!-- TMPL_IF name="checked_matches" -->
+       <li><!-- TMPL_VAR name="matched" --> records with at least one match in catalogue</li>
+    <!-- TMPL_ELSE -->
+    <li>Did not check for matches with existing records in catalogue</li>
+    <!-- /TMPL_IF -->
+    <li><a href="/cgi-bin/koha/tools/manage-marc-import.pl?import_batch_id=<!-- TMPL_VAR name="import_batch_id" -->">Manage staged records</a></li>
+       <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back</a></li>
+</ul>
+<!-- TMPL_ELSE -->
+<ul>
+       <li>Select a MARC file to stage in the import reservoir.  It will be parsed, and each valid record staged for later import into the catalogue.</li>
+       <li>You can enter a name for this import. It may be useful, when creating a biblio, to remember where the suggested MARC data comes from!</li>
+</ul>
+<form method="post" action="<!-- TMPL_VAR name="SCRIPT_NAME" -->" enctype="multipart/form-data">
+<fieldset class="rows">
+<legend>Stage records into the reservoir</legend><ol>
+       <li>
+               <label for="uploadmarc">Select the file to stage: </label>
+               
+                       <input type="file" id="uploadmarc" name="uploadmarc" /><br />
+               
+       </li>
+       <li>
+               <label for="comments">Notes about this file: </label>
+               
+                       <input type="text" id="comments" name="comments" />
+               
+       </li>
+       <li>
+               <label for="syntax">Character encoding: </label>
+               
+                       <select name="syntax" id="syntax"><option value="MARC21">MARC21</option><option value="UNIMARC">UNIMARC</option></select>
+               
+       </li>
+</ol></fieldset>
+       <fieldset class="rows">
+       <legend>Look for existing records in catalogue?</legend><ol><li class="radio">
+                
+               <input type="radio" id="check_for_matchesno" name="check_for_matches" value="0" checked="checked" /><label for="check_for_matchesno">Do not look for matching records (using ISBN)</label></li>
+<li class="radio">
+                       <input type="radio" id="check_for_matchesyes" name="check_for_matches" value="1" /><label for="check_for_matchesyes">Look for matching records</label>
+       </li></ol></fieldset><input type="submit" value="Import" />
+</form>
+<!-- /TMPL_IF -->
+
+</div>
+</div>
+<div class="yui-b">
+<!-- TMPL_INCLUDE NAME="tools-menu.inc" -->
+</div>
+</div>
+<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
index 73ee399..7087859 100644 (file)
 
     <dt><a href="/cgi-bin/koha/tools/inventory.pl">Inventory/stocktaking</a></dt>
     <dd>Perform inventory (stocktaking) of your catalogue</dd>
+       <dt><a href="/cgi-bin/koha/tools/import_borrowers.pl">Import Borrowers</a></dt>
+    <dd>Import borrowers data.</dd>
+       
+    <dt><a href="/cgi-bin/koha/tools/stage-marc-import.pl">Stage MARC Records For Import</a></dt>
+    <dd>Stage MARC records into the reservoir.</dd>
 
+    <dt><a href="/cgi-bin/koha/tools/manage-marc-import.pl">Manage Staged MARC Records</a></dt>
+    <dd>Managed staged MARC records, including completing and reversing imports.</dd>
        </dl>
 </div>
 <div class="yui-u">
diff --git a/tools/import.pl b/tools/import.pl
deleted file mode 100755 (executable)
index 9932f1b..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/perl
-
-# Script for handling import of MARC data into Koha db
-#   and Z39.50 lookups
-
-# Koha library project  www.koha.org
-
-# Licensed under the GPL
-
-# Copyright 2000-2002 Katipo Communications
-#
-# 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;
-
-# standard or CPAN modules used
-use CGI;
-use MARC::File::USMARC;
-
-# Koha modules used
-use C4::Context;
-use C4::Auth;
-use C4::Input;
-use C4::Output;
-use C4::Biblio;
-use C4::Breeding;
-use C4::ImportBatch;
-use C4::Matcher;
-
-#------------------
-# Constants
-
-my $includes = C4::Context->config('includes') ||
-       "/usr/local/www/hdl/htdocs/includes";
-
-# HTML colors for alternating lines
-my $lc1='#dddddd';
-my $lc2='#ddaaaa';
-
-#-------------
-#-------------
-# Initialize
-
-my $userid=$ENV{'REMOTE_USER'};
-
-my $input = new CGI;
-my $dbh = C4::Context->dbh;
-
-my $uploadmarc=$input->param('uploadmarc');
-my $overwrite_biblio = $input->param('overwrite_biblio');
-my $comments = $input->param('comments');
-my $syntax = $input->param('syntax');
-my ($template, $loggedinuser, $cookie)
-       = get_template_and_user({template_name => "tools/import.tmpl",
-                                       query => $input,
-                                       type => "intranet",
-                                       authnotrequired => 0,
-                                       flagsrequired => {tools => 1},
-                                       debug => 1,
-                                       });
-
-$template->param(SCRIPT_NAME => $ENV{'SCRIPT_NAME'},
-                                               uploadmarc => $uploadmarc);
-my $filename = $uploadmarc;
-if ($uploadmarc && length($uploadmarc)>0) {
-       my $marcrecord='';
-       while (<$uploadmarc>) {
-               $marcrecord.=$_;
-       }
-       #my ($notmarcrecord,$alreadyindb,$alreadyinfarm,$imported) = ImportBreeding($marcrecord,$overwrite_biblio,$filename,$syntax,int(rand(99999)), 'batch');
-
-    # FIXME branch code
-    my ($batch_id, $num_valid, @import_errors) = BatchStageMarcRecords($syntax, $marcrecord, $filename, $comments, '', 1);
-    my $matcher = C4::Matcher->new('biblio');
-    $matcher->add_matchpoint("020", "a", '', 'isbn', 1000);
-    my $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher);
-    my ($num_added, $num_updated, $num_ignored) = BatchCommitBibRecords($batch_id);
-
-       $template->param(imported => $num_valid,
-                                                       alreadyindb => $num_with_matches,
-                                                       alreadyinfarm => 0,
-                                                       notmarcrecord => scalar(@import_errors),
-                                                       total => $num_valid + scalar(@import_errors)
-                                                       );
-
-}
-
-output_html_with_http_headers $input, $cookie, $template->output;
-
-
-#---------------
-# log cleared, as marcimport is (almost) rewritten from scratch.
-#
-# Revision 1.5  2007/04/24 13:54:30  hdl
-# functions that were in C4::Interface::CGI::Output are now in C4::Output.
-# So this implies quite a change for files.
-# Sorry about conflicts which will be caused.
-# directory Interface::CGI should now be dropped.
-# I noticed that many scripts (reports ones, but also some circ/stats.pl or opac-topissues) still use Date::Manip.
-#
-# Revision 1.4  2007/03/09 15:14:47  tipaul
-# rel_3_0 moved to HEAD
-#
-# Revision 1.1.2.4  2006/12/22 17:13:49  tipaul
-# removing "management" permission, that is useless (replaced by tools & admin)
-#
-# Revision 1.1.2.3  2006/12/18 16:35:20  toins
-# removing use HTML::Template from *.pl.
-#
-# Revision 1.1.2.2  2006/10/03 12:27:32  toins
-# the script was written twice into the file !
-#
-# Revision 1.1.2.1  2006/09/26 13:42:54  toins
-# fix wrong link to breeding.tmpl
-#
-# Revision 1.1  2006/02/24 11:52:38  hdl
-# Adding tools directory template and scripts
-# Changing barcodes, export and import and letters directory.
-# Changing export script name (marc.pl) to export.pl
-# Changing import script name (breeding.pl) to import.pl
-#
-# Revision 1.4  2005/05/04 08:52:13  tipaul
-# synch'ing 2.2 and head
-#
-# Revision 1.3  2005/03/23 09:57:47  doxulting
-# Adding a parameter to allow acces to people with management/tools flags
diff --git a/tools/manage-marc-import.pl b/tools/manage-marc-import.pl
new file mode 100755 (executable)
index 0000000..2072368
--- /dev/null
@@ -0,0 +1,196 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2007 LibLime
+#
+# 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;
+
+# standard or CPAN modules used
+use CGI;
+use MARC::File::USMARC;
+
+# Koha modules used
+use C4::Context;
+use C4::Auth;
+use C4::Input;
+use C4::Output;
+use C4::Biblio;
+use C4::ImportBatch;
+use C4::Matcher;
+
+my $script_name = "/cgi-bin/koha/tools/manage-marc-import.pl";
+
+my $input = new CGI;
+my $op = $input->param('op');
+my $import_batch_id = $input->param('import_batch_id');
+
+# record list displays
+my $offset = $input->param('offset') || 0;
+my $results_per_page = $input->param('results_per_page') || 10; 
+
+my ($template, $loggedinuser, $cookie)
+    = get_template_and_user({template_name => "tools/manage-marc-import.tmpl",
+                 query => $input,
+                 type => "intranet",
+                 authnotrequired => 0,
+                 flagsrequired => {parameters => 1},
+                 debug => 1,
+                 });
+
+if ($op) {
+    $template->param(script_name => $script_name, $op => 1);
+} else {
+    $template->param(script_name => $script_name);
+}
+
+if ($op eq "") {
+    # displaying a list
+    if ($import_batch_id eq "") {
+        import_batches_list($template, $offset, $results_per_page);
+    } else {
+        import_biblios_list($template, $import_batch_id, $offset, $results_per_page);
+    }
+} elsif ($op eq "commit-batch") {
+    commit_batch($template, $import_batch_id);
+    import_biblios_list($template, $import_batch_id, $offset, $results_per_page);
+} elsif ($op eq "revert-batch") {
+    revert_batch($template, $import_batch_id);
+    import_biblios_list($template, $import_batch_id, $offset, $results_per_page);
+} elsif ($op eq "clean-batch") {
+    ;
+}
+
+output_html_with_http_headers $input, $cookie, $template->output;
+
+exit 0;
+
+sub import_batches_list {
+    my ($template, $offset, $results_per_page) = @_;
+    my $batches = GetImportBatchRangeDesc($offset, $results_per_page);
+
+    my @list = ();
+    foreach my $batch (@$batches) {
+        push @list, {
+            import_batch_id => $batch->{'import_batch_id'},
+            num_biblios => $batch->{'num_biblios'},
+            num_items => $batch->{'num_items'},
+            upload_timestamp => $batch->{'upload_timestamp'},
+            import_status => $batch->{'import_status'},
+            file_name => $batch->{'file_name'},
+            comments => $batch->{'comments'}
+        };
+    }
+    $template->param(batch_list => \@list); 
+    my $num_batches = GetNumberOfNonZ3950ImportBatches();
+    add_page_numbers($template, $offset, $results_per_page, $num_batches);
+    $template->param(offset => $offset);
+    $template->param(range_top => $offset + $results_per_page - 1);
+    $template->param(num_results => $num_batches);
+    $template->param(results_per_page => $results_per_page);
+
+}
+
+sub commit_batch {
+    my ($template, $import_batch_id) = @_;
+    my ($num_added, $num_updated, $num_ignored) = BatchCommitBibRecords($import_batch_id);
+    $template->param(did_commit => 1);
+    $template->param(num_added => $num_added);
+    $template->param(num_updated => $num_updated);
+    $template->param(num_ignored => $num_ignored);
+}
+
+sub revert_batch {
+    my ($template, $import_batch_id) = @_;
+    my ($num_deleted, $num_errors, $num_reverted, $num_ignored) = BatchRevertBibRecords($import_batch_id);
+    $template->param(did_revert => 1);
+    $template->param(num_deleted => $num_deleted);
+    $template->param(num_errors => $num_errors);
+    $template->param(num_reverted => $num_reverted);
+    $template->param(num_ignored => $num_ignored);
+}
+
+sub import_biblios_list {
+    my ($template, $import_batch_id, $offset, $results_per_page) = @_;
+
+    my $batch = GetImportBatch($import_batch_id);
+    my $biblios = GetImportBibliosRange($import_batch_id, $offset, $results_per_page);
+    my @list = ();
+    foreach my $biblio (@$biblios) {
+        my $citation = $biblio->{'title'};
+        $citation .= " $biblio->{'author'}" if $biblio->{'author'};
+        $citation .= " (" if $biblio->{'issn'} or $biblio->{'isbn'};
+        $citation .= $biblio->{'isbn'} if $biblio->{'isbn'};
+        $citation .= ", " if $biblio->{'issn'} and $biblio->{'isbn'};
+        $citation .= $biblio->{'issn'} if $biblio->{'issn'};
+        $citation .= ")" if $biblio->{'issn'} or $biblio->{'isbn'};
+        my $match = GetImportRecordMatches($biblio->{'import_record_id'}, 1);
+        push @list, {
+            import_record_id => $biblio->{'import_record_id'},
+            citation => $citation,
+            status => $biblio->{'status'},
+            record_sequence => $biblio->{'record_sequence'},
+            overlay_status => $biblio->{'overlay_status'},
+            match_biblionumber => $#$match > -1 ? $match->[0]->{'biblionumber'} : 0,
+            match_citation => $#$match > -1 ? $match->[0]->{'title'} . ' ' . $match->[0]->{'author'} : '',
+            match_score => $#$match > -1 ? $match->[0]->{'score'} : 0,
+        };
+    }
+    my $num_biblios = $batch->{'num_biblios'};
+    $template->param(biblio_list => \@list); 
+    add_page_numbers($template, $offset, $results_per_page, $num_biblios);
+    $template->param(offset => $offset);
+    $template->param(range_top => $offset + $results_per_page - 1);
+    $template->param(num_results => $num_biblios);
+    $template->param(results_per_page => $results_per_page);
+    $template->param(import_batch_id => $import_batch_id);
+    batch_info($template, $batch);
+    
+}
+
+sub batch_info {
+    my ($template, $batch) = @_;
+    $template->param(batch_info => 1);
+    $template->param(file_name => $batch->{'file_name'});
+    $template->param(comments => $batch->{'comments'});
+    $template->param(import_status => $batch->{'import_status'});
+    $template->param(upload_timestamp => $batch->{'upload_timestamp'});
+    $template->param(num_biblios => $batch->{'num_biblios'});
+    $template->param(num_items => $batch->{'num_biblios'});
+    if ($batch->{'import_status'} eq 'staged' or $batch->{'import_status'} eq 'reverted') {
+        $template->param(can_commit => 1);
+    }
+    if ($batch->{'import_status'} eq 'imported') {
+        $template->param(can_revert => 1);
+    }
+}
+
+sub add_page_numbers {
+    my ($template, $offset, $results_per_page, $total_results) = @_;
+    my $max_pages = POSIX::ceil($total_results / $results_per_page);
+    return if $max_pages < 2;
+    my $current_page = int($offset / $results_per_page) + 1;
+    my @pages = ();
+    for (my $i = 1; $i <= $max_pages; $i++) {
+        push @pages, {
+            page_number => $i,
+            current_page => ($current_page == $i) ? 1 : 0,
+            offset => ($i - 1) * $results_per_page
+        }
+    }
+    $template->param(pages => \@pages);
+}
+
diff --git a/tools/stage-marc-import.pl b/tools/stage-marc-import.pl
new file mode 100755 (executable)
index 0000000..b3b2aa4
--- /dev/null
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+
+# Script for handling import of MARC data into Koha db
+#   and Z39.50 lookups
+
+# Koha library project  www.koha.org
+
+# Licensed under the GPL
+
+# Copyright 2000-2002 Katipo Communications
+#
+# 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;
+
+# standard or CPAN modules used
+use CGI;
+use MARC::File::USMARC;
+
+# Koha modules used
+use C4::Context;
+use C4::Auth;
+use C4::Input;
+use C4::Output;
+use C4::Biblio;
+use C4::ImportBatch;
+use C4::Matcher;
+
+#------------------
+# Constants
+
+my $includes = C4::Context->config('includes') ||
+       "/usr/local/www/hdl/htdocs/includes";
+
+# HTML colors for alternating lines
+my $lc1='#dddddd';
+my $lc2='#ddaaaa';
+
+#-------------
+#-------------
+# Initialize
+
+my $userid=$ENV{'REMOTE_USER'};
+
+my $input = new CGI;
+my $dbh = C4::Context->dbh;
+
+my $uploadmarc=$input->param('uploadmarc');
+my $check_for_matches = $input->param('check_for_matches');
+my $comments = $input->param('comments');
+my $syntax = $input->param('syntax');
+my ($template, $loggedinuser, $cookie)
+       = get_template_and_user({template_name => "tools/stage-marc-import.tmpl",
+                                       query => $input,
+                                       type => "intranet",
+                                       authnotrequired => 0,
+                                       flagsrequired => {tools => 1},
+                                       debug => 1,
+                                       });
+
+$template->param(SCRIPT_NAME => $ENV{'SCRIPT_NAME'},
+                                               uploadmarc => $uploadmarc);
+my $filename = $uploadmarc;
+if ($uploadmarc && length($uploadmarc)>0) {
+       my $marcrecord='';
+       while (<$uploadmarc>) {
+               $marcrecord.=$_;
+       }
+
+    # FIXME branch code
+    my ($batch_id, $num_valid, @import_errors) = BatchStageMarcRecords($syntax, $marcrecord, $filename, $comments, '', 0);
+    my $matcher = C4::Matcher->new('biblio');
+    $matcher->add_matchpoint("020", "a", '', 'isbn', 1000);
+    my $num_with_matches = 0;
+    my $checked_matches = 0;
+    if ($check_for_matches) {
+        $checked_matches = 1;
+        $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher);
+    }
+    # FIXME we're not committing now
+    # my ($num_added, $num_updated, $num_ignored) = BatchCommitBibRecords($batch_id);
+
+       $template->param(staged => $num_valid,
+                        matched => $num_with_matches,
+                     import_errors => scalar(@import_errors),
+                     total => $num_valid + scalar(@import_errors),
+                     checked_matches => $checked_matches,
+                     import_batch_id => $batch_id
+                    );
+
+}
+
+output_html_with_http_headers $input, $cookie, $template->output;
+