Koha/C4/ImportBatch.pm
Galen Charlton b69facedc4 matching enhancements -- allow matching rule to be changed on the fly
Enhancement to store the matching rule associated with an
import batch and to allow the current matching rule in
effect to be changed and the duplicate detection redone.

Signed-off-by: Chris Cormack <crc@liblime.com>
Signed-off-by: Joshua Ferraro <jmf@liblime.com>
2007-11-16 07:37:24 -06:00

1143 lines
32 KiB
Perl

package C4::ImportBatch;
# 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;
use C4::Context;
use C4::Koha;
use C4::Biblio;
require Exporter;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
$VERSION = 3.00;
=head1 NAME
C4::ImportBatch - manage batches of imported MARC records
=head1 SYNOPSIS
=over 4
use C4::ImportBatch;
=back
=head1 FUNCTIONS
=cut
@ISA = qw(Exporter);
@EXPORT = qw(
GetZ3950BatchId
GetImportRecordMarc
AddImportBatch
GetImportBatch
AddBiblioToBatch
ModBiblioInBatch
BatchStageMarcRecords
BatchFindBibDuplicates
BatchCommitBibRecords
BatchRevertBibRecords
GetAllImportBatches
GetImportBatchRangeDesc
GetNumberOfNonZ3950ImportBatches
GetImportBibliosRange
GetImportBatchStatus
SetImportBatchStatus
GetImportBatchOverlayAction
SetImportBatchOverlayAction
GetImportBatchMatcher
SetImportBatchMatcher
GetImportRecordOverlayStatus
SetImportRecordOverlayStatus
GetImportRecordStatus
SetImportRecordStatus
GetImportRecordMatches
SetImportRecordMatches
);
=head2 GetZ3950BatchId
=over 4
my $batchid = GetZ3950BatchId($z3950server);
=back
Retrieves the ID of the import batch for the Z39.50
reservoir for the given target. If necessary,
creates the import batch.
=cut
sub GetZ3950BatchId {
my ($z3950server) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT import_batch_id FROM import_batches
WHERE batch_type = 'z3950'
AND file_name = ?");
$sth->execute($z3950server);
my $rowref = $sth->fetchrow_arrayref();
$sth->finish();
if (defined $rowref) {
return $rowref->[0];
} else {
my $batch_id = AddImportBatch('create_new', 'staged', 'z3950', $z3950server, '');
return $batch_id;
}
}
=head2 GetImportRecordMarc
=over 4
my ($marcblob, $encoding) = GetImportRecordMarc($import_record_id);
=back
=cut
sub GetImportRecordMarc {
my ($import_record_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT marc, encoding FROM import_records WHERE import_record_id = ?");
$sth->execute($import_record_id);
my ($marc, $encoding) = $sth->fetchrow();
$sth->finish();
return $marc;
}
=head2 AddImportBatch
=over 4
my $batch_id = AddImportBatch($overlay_action, $import_status, $type, $file_name, $comments);
=back
=cut
sub AddImportBatch {
my ($overlay_action, $import_status, $type, $file_name, $comments) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("INSERT INTO import_batches (overlay_action, import_status, batch_type,
file_name, comments)
VALUES (?, ?, ?, ?, ?)");
$sth->execute($overlay_action, $import_status, $type, $file_name, $comments);
my $batch_id = $dbh->{'mysql_insertid'};
$sth->finish();
return $batch_id;
}
=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, $update_counts);
=back
=cut
sub AddBiblioToBatch {
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;
}
=head2 ModBiblioInBatch
=over 4
ModBiblioInBatch($import_record_id, $marc_record);
=back
=cut
sub ModBiblioInBatch {
my ($import_record_id, $marc_record) = @_;
_update_import_record_marc($import_record_id, $marc_record);
_update_biblio_fields($import_record_id, $marc_record);
}
=head2 BatchStageMarcRecords
=over 4
($batch_id, $num_records, $num_items, @invalid_records) =
BatchStageMarcRecords($marc_flavor, $marc_records, $file_name,
$comments, $branch_code, $parse_items,
$leave_as_staging,
$progress_interval, $progress_callback);
=back
=cut
sub BatchStageMarcRecords {
my $marc_flavor = shift;
my $marc_records = shift;
my $file_name = shift;
my $comments = shift;
my $branch_code = shift;
my $parse_items = shift;
my $leave_as_staging = shift;
# optional callback to monitor status
# of job
my $progress_interval = 0;
my $progress_callback = undef;
if ($#_ == 1) {
$progress_interval = shift;
$progress_callback = shift;
$progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
$progress_interval = 0 unless 'CODE' eq ref $progress_callback;
}
my $batch_id = AddImportBatch('create_new', 'staging', 'batch', $file_name, $comments);
my @invalid_records = ();
my $num_valid = 0;
my $num_items = 0;
# FIXME - for now, we're dealing only with bibs
my $rec_num = 0;
foreach my $marc_blob (split(/\x1D/, $marc_records)) {
$rec_num++;
if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
&$progress_callback($rec_num);
}
my $marc_record = FixEncoding($marc_blob, "\x1D");
my $import_record_id;
if (scalar($marc_record->fields()) == 0) {
push @invalid_records, $marc_blob;
} else {
$num_valid++;
$import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $marc_flavor, int(rand(99999)), 0);
if ($parse_items) {
my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 0);
$num_items += scalar(@import_items_ids);
}
}
}
unless ($leave_as_staging) {
SetImportBatchStatus($batch_id, 'staged');
}
# FIXME branch_code, number of bibs, number of items
_update_batch_record_counts($batch_id);
return ($batch_id, $num_valid, $num_items, @invalid_records);
}
=head2 AddItemsToImportBiblio
=over 4
my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, $update_counts);
=back
=cut
sub AddItemsToImportBiblio {
my $batch_id = shift;
my $import_record_id = shift;
my $marc_record = shift;
my $update_counts = @_ ? shift : 0;
my @import_items_ids = ();
my $dbh = C4::Context->dbh;
my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",'');
foreach my $item_field ($marc_record->field($item_tag)) {
my $item_marc = MARC::Record->new();
$item_marc->append_fields($item_field);
$marc_record->delete_field($item_field);
my $sth = $dbh->prepare_cached("INSERT INTO import_items (import_record_id, status, marcxml)
VALUES (?, ?, ?)");
$sth->bind_param(1, $import_record_id);
$sth->bind_param(2, 'staged');
$sth->bind_param(3, $item_marc->as_xml());
$sth->execute();
push @import_items_ids, $dbh->{'mysql_insertid'};
$sth->finish();
}
if ($#import_items_ids > -1) {
_update_batch_record_counts($batch_id) if $update_counts;
_update_import_record_marc($import_record_id, $marc_record);
}
return @import_items_ids;
}
=head2 BatchFindBibDuplicates
=over 4
my $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher, $max_matches, $progress_interval, $progress_callback);
=back
Goes through the records loaded in the batch and attempts to
find duplicates for each one. Sets the overlay action to
"replace" if it was "create_new", and sets the overlay status
of each record to "no_match" or "auto_match" as appropriate.
The $max_matches parameter is optional; if it is not supplied,
it defaults to 10.
The $progress_interval and $progress_callback parameters are
optional; if both are supplied, the sub referred to by
$progress_callback will be invoked every $progress_interval
records using the number of records processed as the
singular argument.
=cut
sub BatchFindBibDuplicates {
my $batch_id = shift;
my $matcher = shift;
my $max_matches = @_ ? shift : 10;
# optional callback to monitor status
# of job
my $progress_interval = 0;
my $progress_callback = undef;
if ($#_ == 1) {
$progress_interval = shift;
$progress_callback = shift;
$progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
$progress_interval = 0 unless 'CODE' eq ref $progress_callback;
}
my $dbh = C4::Context->dbh;
my $old_overlay_action = GetImportBatchOverlayAction($batch_id);
if ($old_overlay_action eq "create_new") {
SetImportBatchOverlayAction($batch_id, 'replace');
}
my $sth = $dbh->prepare("SELECT import_record_id, marc
FROM import_records
JOIN import_biblios USING (import_record_id)
WHERE import_batch_id = ?");
$sth->execute($batch_id);
my $num_with_matches = 0;
my $rec_num = 0;
while (my $rowref = $sth->fetchrow_hashref) {
$rec_num++;
if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
&$progress_callback($rec_num);
}
my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
my @matches = ();
if (defined $matcher) {
@matches = $matcher->get_matches($marc_record, $max_matches);
}
if (scalar(@matches) > 0) {
$num_with_matches++;
SetImportRecordMatches($rowref->{'import_record_id'}, @matches);
SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'auto_match');
} else {
SetImportRecordMatches($rowref->{'import_record_id'}, ());
SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'no_match');
}
}
$sth->finish();
return $num_with_matches;
}
=head2 BatchCommitBibRecords
=over 4
my ($num_added, $num_updated, $num_items_added, $num_ignored) =
BatchCommitBibRecords($batch_id, $progress_interval, $progress_callback);
=back
=cut
sub BatchCommitBibRecords {
my $batch_id = shift;
# optional callback to monitor status
# of job
my $progress_interval = 0;
my $progress_callback = undef;
if ($#_ == 1) {
$progress_interval = shift;
$progress_callback = shift;
$progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
$progress_interval = 0 unless 'CODE' eq ref $progress_callback;
}
my $num_added = 0;
my $num_updated = 0;
my $num_items_added = 0;
my $num_ignored = 0;
# commit (i.e., save, all records in the batch)
# FIXME biblio only at the moment
SetImportBatchStatus('importing');
my $overlay_action = GetImportBatchOverlayAction($batch_id);
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marc
FROM import_records
JOIN import_biblios USING (import_record_id)
WHERE import_batch_id = ?");
$sth->execute($batch_id);
my $rec_num = 0;
while (my $rowref = $sth->fetchrow_hashref) {
$rec_num++;
if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
&$progress_callback($rec_num);
}
if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'imported') {
$num_ignored++;
}
my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
if ($overlay_action eq 'create_new' or
($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();
$num_items_added += BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
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 $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();
$num_items_added += BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied');
SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
}
}
$sth->finish();
SetImportBatchStatus($batch_id, 'imported');
return ($num_added, $num_updated, $num_items_added, $num_ignored);
}
=head2 BatchCommitItems
=over 4
$num_items_added = BatchCommitItems($import_record_id, $biblionumber);
=back
=cut
sub BatchCommitItems {
my ($import_record_id, $biblionumber) = @_;
my $dbh = C4::Context->dbh;
my $num_items_added = 0;
my $sth = $dbh->prepare("SELECT import_items_id, import_items.marcxml, encoding
FROM import_items
JOIN import_records USING (import_record_id)
WHERE import_record_id = ?
ORDER BY import_items_id");
$sth->bind_param(1, $import_record_id);
$sth->execute();
while (my $row = $sth->fetchrow_hashref()) {
my $item_marc = MARC::Record->new_from_xml($row->{'marcxml'}, 'UTF-8', $row->{'encoding'});
my ($item_biblionumber, $biblionumber, $itemnumber) = AddItem($item_marc, $biblionumber);
my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, itemnumber = ? WHERE import_items_id = ?");
$updsth->bind_param(1, 'imported');
$updsth->bind_param(2, $itemnumber);
$updsth->bind_param(3, $row->{'import_items_id'});
$updsth->execute();
$updsth->finish();
$num_items_added++;
}
$sth->finish();
return $num_items_added;
}
=head2 BatchRevertBibRecords
=over 4
my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $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_items_deleted = 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')) {
$num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
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);
$num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_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_items_deleted, $num_ignored);
}
=head2 BatchRevertItems
=over 4
my $num_items_deleted = BatchRevertItems($import_record_id, $biblionumber);
=back
=cut
sub BatchRevertItems {
my ($import_record_id, $biblionumber) = @_;
my $dbh = C4::Context->dbh;
my $num_items_deleted = 0;
my $sth = $dbh->prepare_cached("SELECT import_items_id, itemnumber
FROM import_items
JOIN items USING (itemnumber)
WHERE import_record_id = ?");
$sth->bind_param(1, $import_record_id);
$sth->execute();
while (my $row = $sth->fetchrow_hashref()) {
DelItem($dbh, $biblionumber, $row->{'itemnumber'});
my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
$updsth->bind_param(1, 'reverted');
$updsth->bind_param(2, $row->{'import_items_id'});
$updsth->execute();
$updsth->finish();
$num_items_deleted++;
}
$sth->finish();
return $num_items_deleted;
}
=head2 GetAllImportBatches
=over 4
my $results = GetAllImportBatches();
=back
Returns a references to an array of hash references corresponding
to all import_batches rows (of batch_type 'batch'), sorted in
ascending order by import_batch_id.
=cut
sub GetAllImportBatches {
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
WHERE batch_type = 'batch'
ORDER BY import_batch_id ASC");
my $results = [];
$sth->execute();
while (my $row = $sth->fetchrow_hashref) {
push @$results, $row;
}
$sth->finish();
return $results;
}
=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
my $record_id = GetBestRecordMatch($import_record_id);
=back
=cut
sub GetBestRecordMatch {
my ($import_record_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT candidate_match_id
FROM import_record_matches
WHERE import_record_id = ?
ORDER BY score DESC, candidate_match_id DESC");
$sth->execute($import_record_id);
my ($record_id) = $sth->fetchrow_array();
$sth->finish();
return $record_id;
}
=head2 GetImportBatchStatus
=over 4
my $status = GetImportBatchStatus($batch_id);
=back
=cut
sub GetImportBatchStatus {
my ($batch_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT import_status FROM import_batches WHERE batch_id = ?");
$sth->execute($batch_id);
my ($status) = $sth->fetchrow_array();
$sth->finish();
return;
}
=head2 SetImportBatchStatus
=over 4
SetImportBatchStatus($batch_id, $new_status);
=back
=cut
sub SetImportBatchStatus {
my ($batch_id, $new_status) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("UPDATE import_batches SET import_status = ? WHERE import_batch_id = ?");
$sth->execute($new_status, $batch_id);
$sth->finish();
}
=head2 GetImportBatchOverlayAction
=over 4
my $overlay_action = GetImportBatchOverlayAction($batch_id);
=back
=cut
sub GetImportBatchOverlayAction {
my ($batch_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT overlay_action FROM import_batches WHERE import_batch_id = ?");
$sth->execute($batch_id);
my ($overlay_action) = $sth->fetchrow_array();
$sth->finish();
return $overlay_action;
}
=head2 SetImportBatchOverlayAction
=over 4
SetImportBatchOverlayAction($batch_id, $new_overlay_action);
=back
=cut
sub SetImportBatchOverlayAction {
my ($batch_id, $new_overlay_action) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("UPDATE import_batches SET overlay_action = ? WHERE import_batch_id = ?");
$sth->execute($new_overlay_action, $batch_id);
$sth->finish();
}
=head2 GetImportBatchMatcher
=over 4
my $matcher_id = GetImportBatchMatcher($batch_id);
=back
=cut
sub GetImportBatchMatcher {
my ($batch_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT matcher_id FROM import_batches WHERE import_batch_id = ?");
$sth->execute($batch_id);
my ($matcher_id) = $sth->fetchrow_array();
$sth->finish();
return $matcher_id;
}
=head2 SetImportBatchMatcher
=over 4
SetImportBatchMatcher($batch_id, $new_matcher_id);
=back
=cut
sub SetImportBatchMatcher {
my ($batch_id, $new_matcher_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("UPDATE import_batches SET matcher_id = ? WHERE import_batch_id = ?");
$sth->execute($new_matcher_id, $batch_id);
$sth->finish();
}
=head2 GetImportRecordOverlayStatus
=over 4
my $overlay_status = GetImportRecordOverlayStatus($import_record_id);
=back
=cut
sub GetImportRecordOverlayStatus {
my ($import_record_id) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT overlay_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 SetImportRecordOverlayStatus
=over 4
SetImportRecordOverlayStatus($import_record_id, $new_overlay_status);
=back
=cut
sub SetImportRecordOverlayStatus {
my ($import_record_id, $new_overlay_status) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("UPDATE import_records SET overlay_status = ? WHERE import_record_id = ?");
$sth->execute($new_overlay_status, $import_record_id);
$sth->finish();
}
=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
SetImportRecordMatches($import_record_id, @matches);
=back
=cut
sub SetImportRecordMatches {
my $import_record_id = shift;
my @matches = @_;
my $dbh = C4::Context->dbh;
my $delsth = $dbh->prepare("DELETE FROM import_record_matches WHERE import_record_id = ?");
$delsth->execute($import_record_id);
$delsth->finish();
my $sth = $dbh->prepare("INSERT INTO import_record_matches (import_record_id, candidate_match_id, score)
VALUES (?, ?, ?)");
foreach my $match (@matches) {
$sth->execute($import_record_id, $match->{'record_id'}, $match->{'score'});
}
}
# internal functions
sub _create_import_record {
my ($batch_id, $record_sequence, $marc_record, $record_type, $encoding, $z3950random) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("INSERT INTO import_records (import_batch_id, record_sequence, marc, marcxml,
record_type, encoding, z3950random)
VALUES (?, ?, ?, ?, ?, ?, ?)");
$sth->execute($batch_id, $record_sequence, $marc_record->as_usmarc(), $marc_record->as_xml(),
$record_type, $encoding, $z3950random);
my $import_record_id = $dbh->{'mysql_insertid'};
$sth->finish();
return $import_record_id;
}
sub _update_import_record_marc {
my ($import_record_id, $marc_record) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ?
WHERE import_record_id = ?");
$sth->execute($marc_record->as_usmarc(), $marc_record->as_xml(), $import_record_id);
$sth->finish();
}
sub _add_biblio_fields {
my ($import_record_id, $marc_record) = @_;
my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
my $dbh = C4::Context->dbh;
# FIXME no controlnumber, originalsource
# FIXME 2 - should regularize normalization of ISBN wherever it is done
$isbn =~ s/\(.*$//;
$isbn =~ tr/ -_//;
$isbn = uc $isbn;
my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn) VALUES (?, ?, ?, ?, ?)");
$sth->execute($import_record_id, $title, $author, $isbn, $issn);
$sth->finish();
}
sub _update_biblio_fields {
my ($import_record_id, $marc_record) = @_;
my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
my $dbh = C4::Context->dbh;
# FIXME no controlnumber, originalsource
# FIXME 2 - should regularize normalization of ISBN wherever it is done
$isbn =~ s/\(.*$//;
$isbn =~ tr/ -_//;
$isbn = uc $isbn;
my $sth = $dbh->prepare("UPDATE import_biblios SET title = ?, author = ?, isbn = ?, issn = ?
WHERE import_record_id = ?");
$sth->execute($title, $author, $isbn, $issn, $import_record_id);
$sth->finish();
}
sub _parse_biblio_fields {
my ($marc_record) = @_;
my $dbh = C4::Context->dbh;
my $bibliofields = TransformMarcToKoha($dbh, $marc_record, '');
return ($bibliofields->{'title'}, $bibliofields->{'author'}, $bibliofields->{'isbn'}, $bibliofields->{'issn'});
}
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();
$sth = $dbh->prepare_cached("UPDATE import_batches SET num_items = (
SELECT COUNT(*)
FROM import_records
JOIN import_items USING (import_record_id)
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
Koha Development Team <info@koha.org>
Galen Charlton <galen.charlton@liblime.com>
=cut