1 package C4
::ImportBatch
;
3 # Copyright (C) 2007 LibLime, 2012 C & P Bibliography Services
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
28 use C4
::AuthoritiesMarc
;
29 use C4
::MarcModificationTemplates
;
30 use Koha
::Plugins
::Handler
;
33 use vars
qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
42 GetImportRecordMarcXML
47 AddItemsToImportBiblio
59 GetStagedWebserviceBatches
60 GetImportBatchRangeDesc
61 GetNumberOfNonZ3950ImportBatches
64 GetItemNumbersFromImportBatch
68 GetImportBatchOverlayAction
69 SetImportBatchOverlayAction
70 GetImportBatchNoMatchAction
71 SetImportBatchNoMatchAction
72 GetImportBatchItemAction
73 SetImportBatchItemAction
76 GetImportRecordOverlayStatus
77 SetImportRecordOverlayStatus
80 GetImportRecordMatches
81 SetImportRecordMatches
85 our $logger = Koha
::Logger
->get( { category
=> 'C4.ImportBatch' } );
89 C4::ImportBatch - manage batches of imported MARC records
97 =head2 GetZ3950BatchId
99 my $batchid = GetZ3950BatchId($z3950server);
101 Retrieves the ID of the import batch for the Z39.50
102 reservoir for the given target. If necessary,
103 creates the import batch.
107 sub GetZ3950BatchId
{
108 my ($z3950server) = @_;
110 my $dbh = C4
::Context
->dbh;
111 my $sth = $dbh->prepare("SELECT import_batch_id FROM import_batches
112 WHERE batch_type = 'z3950'
114 $sth->execute($z3950server);
115 my $rowref = $sth->fetchrow_arrayref();
117 if (defined $rowref) {
120 my $batch_id = AddImportBatch
( {
121 overlay_action
=> 'create_new',
122 import_status
=> 'staged',
123 batch_type
=> 'z3950',
124 file_name
=> $z3950server,
131 =head2 GetWebserviceBatchId
133 my $batchid = GetWebserviceBatchId();
135 Retrieves the ID of the import batch for webservice.
136 If necessary, creates the import batch.
140 my $WEBSERVICE_BASE_QRY = <<EOQ;
141 SELECT import_batch_id FROM import_batches
142 WHERE batch_type = 'webservice'
143 AND import_status = 'staged'
145 sub GetWebserviceBatchId
{
148 my $dbh = C4
::Context
->dbh;
149 my $sql = $WEBSERVICE_BASE_QRY;
151 foreach my $field (qw(matcher_id overlay_action nomatch_action item_action)) {
152 if (my $val = $params->{$field}) {
153 $sql .= " AND $field = ?";
157 my $id = $dbh->selectrow_array($sql, undef, @args);
160 $params->{batch_type
} = 'webservice';
161 $params->{import_status
} = 'staged';
162 return AddImportBatch
($params);
165 =head2 GetImportRecordMarc
167 my ($marcblob, $encoding) = GetImportRecordMarc($import_record_id);
171 sub GetImportRecordMarc
{
172 my ($import_record_id) = @_;
174 my $dbh = C4
::Context
->dbh;
175 my ( $marc, $encoding ) = $dbh->selectrow_array(q
|
176 SELECT marc
, encoding
178 WHERE import_record_id
= ?
179 |, undef, $import_record_id );
181 return $marc, $encoding;
184 sub GetRecordFromImportBiblio
{
185 my ( $import_record_id, $embed_items ) = @_;
187 my ($marc) = GetImportRecordMarc
($import_record_id);
188 my $record = MARC
::Record
->new_from_usmarc($marc);
190 EmbedItemsInImportBiblio
( $record, $import_record_id ) if $embed_items;
195 sub EmbedItemsInImportBiblio
{
196 my ( $record, $import_record_id ) = @_;
197 my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField
("items.itemnumber", '');
198 my $dbh = C4
::Context
->dbh;
199 my $import_items = $dbh->selectall_arrayref(q
|
200 SELECT import_items
.marcxml
202 WHERE import_record_id
= ?
203 |, { Slice
=> {} }, $import_record_id );
205 for my $import_item ( @
$import_items ) {
206 my $item_marc = MARC
::Record
::new_from_xml
($import_item->{marcxml
});
207 push @item_fields, $item_marc->field($itemtag);
209 $record->append_fields(@item_fields);
213 =head2 GetImportRecordMarcXML
215 my $marcxml = GetImportRecordMarcXML($import_record_id);
219 sub GetImportRecordMarcXML
{
220 my ($import_record_id) = @_;
222 my $dbh = C4
::Context
->dbh;
223 my $sth = $dbh->prepare("SELECT marcxml FROM import_records WHERE import_record_id = ?");
224 $sth->execute($import_record_id);
225 my ($marcxml) = $sth->fetchrow();
231 =head2 AddImportBatch
233 my $batch_id = AddImportBatch($params_hash);
241 foreach (qw( matcher_id template_id branchcode
242 overlay_action nomatch_action item_action
243 import_status batch_type file_name comments record_type )) {
244 if (exists $params->{$_}) {
246 push @vals, $params->{$_};
249 my $dbh = C4
::Context
->dbh;
250 $dbh->do("INSERT INTO import_batches (".join( ',', @fields).")
251 VALUES (".join( ',', map '?', @fields).")",
254 return $dbh->{'mysql_insertid'};
257 =head2 GetImportBatch
259 my $row = GetImportBatch($batch_id);
261 Retrieve a hashref of an import_batches row.
268 my $dbh = C4
::Context
->dbh;
269 my $sth = $dbh->prepare_cached("SELECT * FROM import_batches WHERE import_batch_id = ?");
270 $sth->bind_param(1, $batch_id);
272 my $result = $sth->fetchrow_hashref;
278 =head2 AddBiblioToBatch
280 my $import_record_id = AddBiblioToBatch($batch_id, $record_sequence,
281 $marc_record, $encoding, $z3950random, $update_counts);
285 sub AddBiblioToBatch
{
286 my $batch_id = shift;
287 my $record_sequence = shift;
288 my $marc_record = shift;
289 my $encoding = shift;
290 my $z3950random = shift;
291 my $update_counts = @_ ?
shift : 1;
293 my $import_record_id = _create_import_record
($batch_id, $record_sequence, $marc_record, 'biblio', $encoding, $z3950random, C4
::Context
->preference('marcflavour'));
294 _add_biblio_fields
($import_record_id, $marc_record);
295 _update_batch_record_counts
($batch_id) if $update_counts;
296 return $import_record_id;
299 =head2 ModBiblioInBatch
301 ModBiblioInBatch($import_record_id, $marc_record);
305 sub ModBiblioInBatch
{
306 my ($import_record_id, $marc_record) = @_;
308 _update_import_record_marc
($import_record_id, $marc_record, C4
::Context
->preference('marcflavour'));
309 _update_biblio_fields
($import_record_id, $marc_record);
313 =head2 AddAuthToBatch
315 my $import_record_id = AddAuthToBatch($batch_id, $record_sequence,
316 $marc_record, $encoding, $z3950random, $update_counts, [$marc_type]);
321 my $batch_id = shift;
322 my $record_sequence = shift;
323 my $marc_record = shift;
324 my $encoding = shift;
325 my $z3950random = shift;
326 my $update_counts = @_ ?
shift : 1;
327 my $marc_type = shift || C4
::Context
->preference('marcflavour');
329 $marc_type = 'UNIMARCAUTH' if $marc_type eq 'UNIMARC';
331 my $import_record_id = _create_import_record
($batch_id, $record_sequence, $marc_record, 'auth', $encoding, $z3950random, $marc_type);
332 _add_auth_fields
($import_record_id, $marc_record);
333 _update_batch_record_counts
($batch_id) if $update_counts;
334 return $import_record_id;
337 =head2 ModAuthInBatch
339 ModAuthInBatch($import_record_id, $marc_record);
344 my ($import_record_id, $marc_record) = @_;
346 my $marcflavour = C4
::Context
->preference('marcflavour');
347 _update_import_record_marc
($import_record_id, $marc_record, $marcflavour eq 'UNIMARC' ?
'UNIMARCAUTH' : 'USMARC');
351 =head2 BatchStageMarcRecords
353 ( $batch_id, $num_records, $num_items, @invalid_records ) =
354 BatchStageMarcRecords(
355 $record_type, $encoding,
356 $marc_records, $file_name,
357 $marc_modification_template, $comments,
358 $branch_code, $parse_items,
359 $leave_as_staging, $progress_interval,
365 sub BatchStageMarcRecords
{
366 my $record_type = shift;
367 my $encoding = shift;
368 my $marc_records = shift;
369 my $file_name = shift;
370 my $marc_modification_template = shift;
371 my $comments = shift;
372 my $branch_code = shift;
373 my $parse_items = shift;
374 my $leave_as_staging = shift;
376 # optional callback to monitor status
378 my $progress_interval = 0;
379 my $progress_callback = undef;
381 $progress_interval = shift;
382 $progress_callback = shift;
383 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
384 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
387 my $batch_id = AddImportBatch
( {
388 overlay_action
=> 'create_new',
389 import_status
=> 'staging',
390 batch_type
=> 'batch',
391 file_name
=> $file_name,
392 comments
=> $comments,
393 record_type
=> $record_type,
396 SetImportBatchItemAction
($batch_id, 'always_add');
398 SetImportBatchItemAction
($batch_id, 'ignore');
402 my $marc_type = C4
::Context
->preference('marcflavour');
403 $marc_type .= 'AUTH' if ($marc_type eq 'UNIMARC' && $record_type eq 'auth');
404 my @invalid_records = ();
407 # FIXME - for now, we're dealing only with bibs
409 foreach my $marc_record (@
$marc_records) {
411 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
412 &$progress_callback($rec_num);
415 ModifyRecordWithTemplate
( $marc_modification_template, $marc_record ) if ( $marc_modification_template );
417 my $import_record_id;
418 if (scalar($marc_record->fields()) == 0) {
419 push @invalid_records, $marc_record;
422 # Normalize the record so it doesn't have separated diacritics
423 SetUTF8Flag
($marc_record);
426 if ($record_type eq 'biblio') {
427 $import_record_id = AddBiblioToBatch
($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0);
429 my @import_items_ids = AddItemsToImportBiblio
($batch_id, $import_record_id, $marc_record, 0);
430 $num_items += scalar(@import_items_ids);
432 } elsif ($record_type eq 'auth') {
433 $import_record_id = AddAuthToBatch
($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0, $marc_type);
437 unless ($leave_as_staging) {
438 SetImportBatchStatus
($batch_id, 'staged');
440 # FIXME branch_code, number of bibs, number of items
441 _update_batch_record_counts
($batch_id);
442 return ($batch_id, $num_valid, $num_items, @invalid_records);
445 =head2 AddItemsToImportBiblio
447 my @import_items_ids = AddItemsToImportBiblio($batch_id,
448 $import_record_id, $marc_record, $update_counts);
452 sub AddItemsToImportBiblio
{
453 my $batch_id = shift;
454 my $import_record_id = shift;
455 my $marc_record = shift;
456 my $update_counts = @_ ?
shift : 0;
458 my @import_items_ids = ();
460 my $dbh = C4
::Context
->dbh;
461 my ($item_tag,$item_subfield) = &GetMarcFromKohaField
("items.itemnumber",'');
462 foreach my $item_field ($marc_record->field($item_tag)) {
463 my $item_marc = MARC
::Record
->new();
464 $item_marc->leader("00000 a "); # must set Leader/09 to 'a'
465 $item_marc->append_fields($item_field);
466 $marc_record->delete_field($item_field);
467 my $sth = $dbh->prepare_cached("INSERT INTO import_items (import_record_id, status, marcxml)
469 $sth->bind_param(1, $import_record_id);
470 $sth->bind_param(2, 'staged');
471 $sth->bind_param(3, $item_marc->as_xml());
473 push @import_items_ids, $dbh->{'mysql_insertid'};
477 if ($#import_items_ids > -1) {
478 _update_batch_record_counts
($batch_id) if $update_counts;
479 _update_import_record_marc
($import_record_id, $marc_record, C4
::Context
->preference('marcflavour'));
481 return @import_items_ids;
484 =head2 BatchFindDuplicates
486 my $num_with_matches = BatchFindDuplicates($batch_id, $matcher,
487 $max_matches, $progress_interval, $progress_callback);
489 Goes through the records loaded in the batch and attempts to
490 find duplicates for each one. Sets the matching status
491 of each record to "no_match" or "auto_match" as appropriate.
493 The $max_matches parameter is optional; if it is not supplied,
496 The $progress_interval and $progress_callback parameters are
497 optional; if both are supplied, the sub referred to by
498 $progress_callback will be invoked every $progress_interval
499 records using the number of records processed as the
504 sub BatchFindDuplicates
{
505 my $batch_id = shift;
507 my $max_matches = @_ ?
shift : 10;
509 # optional callback to monitor status
511 my $progress_interval = 0;
512 my $progress_callback = undef;
514 $progress_interval = shift;
515 $progress_callback = shift;
516 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
517 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
520 my $dbh = C4
::Context
->dbh;
522 my $sth = $dbh->prepare("SELECT import_record_id, record_type, marc
524 WHERE import_batch_id = ?");
525 $sth->execute($batch_id);
526 my $num_with_matches = 0;
528 while (my $rowref = $sth->fetchrow_hashref) {
530 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
531 &$progress_callback($rec_num);
533 my $marc_record = MARC
::Record
->new_from_usmarc($rowref->{'marc'});
535 if (defined $matcher) {
536 @matches = $matcher->get_matches($marc_record, $max_matches);
538 if (scalar(@matches) > 0) {
540 SetImportRecordMatches
($rowref->{'import_record_id'}, @matches);
541 SetImportRecordOverlayStatus
($rowref->{'import_record_id'}, 'auto_match');
543 SetImportRecordMatches
($rowref->{'import_record_id'}, ());
544 SetImportRecordOverlayStatus
($rowref->{'import_record_id'}, 'no_match');
548 return $num_with_matches;
551 =head2 BatchCommitRecords
553 my ($num_added, $num_updated, $num_items_added, $num_items_replaced, $num_items_errored, $num_ignored) =
554 BatchCommitRecords($batch_id, $framework,
555 $progress_interval, $progress_callback);
559 sub BatchCommitRecords
{
560 my $batch_id = shift;
561 my $framework = shift;
563 # optional callback to monitor status
565 my $progress_interval = 0;
566 my $progress_callback = undef;
568 $progress_interval = shift;
569 $progress_callback = shift;
570 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
571 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
577 my $num_items_added = 0;
578 my $num_items_replaced = 0;
579 my $num_items_errored = 0;
581 # commit (i.e., save, all records in the batch)
582 SetImportBatchStatus
('importing');
583 my $overlay_action = GetImportBatchOverlayAction
($batch_id);
584 my $nomatch_action = GetImportBatchNoMatchAction
($batch_id);
585 my $item_action = GetImportBatchItemAction
($batch_id);
588 my $dbh = C4
::Context
->dbh;
589 my $sth = $dbh->prepare("SELECT import_records.import_record_id, record_type, status, overlay_status, marc, encoding
591 LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id)
592 LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id)
593 WHERE import_batch_id = ?");
594 $sth->execute($batch_id);
595 my $marcflavour = C4
::Context
->preference('marcflavour');
597 while (my $rowref = $sth->fetchrow_hashref) {
598 $record_type = $rowref->{'record_type'};
600 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
601 &$progress_callback($rec_num);
603 if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'imported') {
609 if ($marcflavour eq 'UNIMARC' && $record_type eq 'auth') {
610 $marc_type = 'UNIMARCAUTH';
611 } elsif ($marcflavour eq 'UNIMARC') {
612 $marc_type = 'UNIMARC';
614 $marc_type = 'USMARC';
616 my $marc_record = MARC
::Record
->new_from_usmarc($rowref->{'marc'});
618 if ($record_type eq 'biblio') {
619 # remove any item tags - rely on BatchCommitItems
620 ($item_tag,$item_subfield) = &GetMarcFromKohaField
("items.itemnumber",'');
621 foreach my $item_field ($marc_record->field($item_tag)) {
622 $marc_record->delete_field($item_field);
626 my ($record_result, $item_result, $record_match) =
627 _get_commit_action
($overlay_action, $nomatch_action, $item_action,
628 $rowref->{'overlay_status'}, $rowref->{'import_record_id'}, $record_type);
632 if ($record_result eq 'create_new') {
634 if ($record_type eq 'biblio') {
635 my $biblioitemnumber;
636 ($recordid, $biblioitemnumber) = AddBiblio
($marc_record, $framework);
637 $query = "UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?";
638 if ($item_result eq 'create_new' || $item_result eq 'replace') {
639 my ($bib_items_added, $bib_items_replaced, $bib_items_errored) = BatchCommitItems
($rowref->{'import_record_id'}, $recordid, $item_result);
640 $num_items_added += $bib_items_added;
641 $num_items_replaced += $bib_items_replaced;
642 $num_items_errored += $bib_items_errored;
645 $recordid = AddAuthority
($marc_record, undef, GuessAuthTypeCode
($marc_record));
646 $query = "UPDATE import_auths SET matched_authid = ? WHERE import_record_id = ?";
648 my $sth = $dbh->prepare_cached($query);
649 $sth->execute($recordid, $rowref->{'import_record_id'});
651 SetImportRecordStatus
($rowref->{'import_record_id'}, 'imported');
652 } elsif ($record_result eq 'replace') {
654 $recordid = $record_match;
656 if ($record_type eq 'biblio') {
657 my $oldbiblio = Koha
::Biblios
->find( $recordid );
658 $oldxml = GetXmlBiblio
($recordid);
660 # remove item fields so that they don't get
661 # added again if record is reverted
662 # FIXME: GetXmlBiblio output should not contain item info any more! So the next foreach should not be needed. Does not hurt either; may remove old 952s that should not have been there anymore.
663 my $old_marc = MARC
::Record
->new_from_xml(StripNonXmlChars
($oldxml), 'UTF-8', $rowref->{'encoding'}, $marc_type);
664 foreach my $item_field ($old_marc->field($item_tag)) {
665 $old_marc->delete_field($item_field);
667 $oldxml = $old_marc->as_xml($marc_type);
669 ModBiblio
($marc_record, $recordid, $oldbiblio->frameworkcode);
670 $query = "UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?";
672 if ($item_result eq 'create_new' || $item_result eq 'replace') {
673 my ($bib_items_added, $bib_items_replaced, $bib_items_errored) = BatchCommitItems
($rowref->{'import_record_id'}, $recordid, $item_result);
674 $num_items_added += $bib_items_added;
675 $num_items_replaced += $bib_items_replaced;
676 $num_items_errored += $bib_items_errored;
679 $oldxml = GetAuthorityXML
($recordid);
681 ModAuthority
($recordid, $marc_record, GuessAuthTypeCode
($marc_record));
682 $query = "UPDATE import_auths SET matched_authid = ? WHERE import_record_id = ?";
684 my $sth = $dbh->prepare_cached("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?");
685 $sth->execute($oldxml, $rowref->{'import_record_id'});
687 my $sth2 = $dbh->prepare_cached($query);
688 $sth2->execute($recordid, $rowref->{'import_record_id'});
690 SetImportRecordOverlayStatus
($rowref->{'import_record_id'}, 'match_applied');
691 SetImportRecordStatus
($rowref->{'import_record_id'}, 'imported');
692 } elsif ($record_result eq 'ignore') {
693 $recordid = $record_match;
695 $recordid = $record_match;
696 if ($record_type eq 'biblio' and defined $recordid and ( $item_result eq 'create_new' || $item_result eq 'replace' ) ) {
697 my ($bib_items_added, $bib_items_replaced, $bib_items_errored) = BatchCommitItems
($rowref->{'import_record_id'}, $recordid, $item_result);
698 $num_items_added += $bib_items_added;
699 $num_items_replaced += $bib_items_replaced;
700 $num_items_errored += $bib_items_errored;
701 # still need to record the matched biblionumber so that the
702 # items can be reverted
703 my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
704 $sth2->execute($recordid, $rowref->{'import_record_id'});
705 SetImportRecordOverlayStatus
($rowref->{'import_record_id'}, 'match_applied');
707 SetImportRecordStatus
($rowref->{'import_record_id'}, 'ignored');
711 SetImportBatchStatus
($batch_id, 'imported');
712 return ($num_added, $num_updated, $num_items_added, $num_items_replaced, $num_items_errored, $num_ignored);
715 =head2 BatchCommitItems
717 ($num_items_added, $num_items_errored) =
718 BatchCommitItems($import_record_id, $biblionumber);
722 sub BatchCommitItems
{
723 my ( $import_record_id, $biblionumber, $action ) = @_;
725 my $dbh = C4
::Context
->dbh;
727 my $num_items_added = 0;
728 my $num_items_errored = 0;
729 my $num_items_replaced = 0;
731 my $sth = $dbh->prepare( "
732 SELECT import_items_id, import_items.marcxml, encoding
734 JOIN import_records USING (import_record_id)
735 WHERE import_record_id = ?
736 ORDER BY import_items_id
738 $sth->bind_param( 1, $import_record_id );
741 while ( my $row = $sth->fetchrow_hashref() ) {
742 my $item_marc = MARC
::Record
->new_from_xml( StripNonXmlChars
( $row->{'marcxml'} ), 'UTF-8', $row->{'encoding'} );
744 # Delete date_due subfield as to not accidentally delete item checkout due dates
745 my ( $MARCfield, $MARCsubfield ) = GetMarcFromKohaField
( 'items.onloan', GetFrameworkCode
($biblionumber) );
746 $item_marc->field($MARCfield)->delete_subfield( code
=> $MARCsubfield );
748 my $item = TransformMarcToKoha
( $item_marc );
750 my $duplicate_barcode = exists( $item->{'barcode'} ) && GetItemnumberFromBarcode
( $item->{'barcode'} );
751 my $duplicate_itemnumber = exists( $item->{'itemnumber'} );
753 my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, itemnumber = ? WHERE import_items_id = ?");
754 if ( $action eq "replace" && $duplicate_itemnumber ) {
755 # Duplicate itemnumbers have precedence, that way we can update barcodes by overlaying
756 ModItemFromMarc
( $item_marc, $biblionumber, $item->{itemnumber
} );
757 $updsth->bind_param( 1, 'imported' );
758 $updsth->bind_param( 2, $item->{itemnumber
} );
759 $updsth->bind_param( 3, $row->{'import_items_id'} );
762 $num_items_replaced++;
763 } elsif ( $action eq "replace" && $duplicate_barcode ) {
764 my $itemnumber = GetItemnumberFromBarcode
( $item->{'barcode'} );
765 ModItemFromMarc
( $item_marc, $biblionumber, $itemnumber );
766 $updsth->bind_param( 1, 'imported' );
767 $updsth->bind_param( 2, $item->{itemnumber
} );
768 $updsth->bind_param( 3, $row->{'import_items_id'} );
771 $num_items_replaced++;
772 } elsif ($duplicate_barcode) {
773 $updsth->bind_param( 1, 'error' );
774 $updsth->bind_param( 2, 'duplicate item barcode' );
775 $updsth->bind_param( 3, $row->{'import_items_id'} );
777 $num_items_errored++;
779 my ( $item_biblionumber, $biblioitemnumber, $itemnumber ) = AddItemFromMarc
( $item_marc, $biblionumber );
781 $updsth->bind_param( 1, 'imported' );
782 $updsth->bind_param( 2, $itemnumber );
783 $updsth->bind_param( 3, $row->{'import_items_id'} );
791 return ( $num_items_added, $num_items_replaced, $num_items_errored );
794 =head2 BatchRevertRecords
796 my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted,
797 $num_ignored) = BatchRevertRecords($batch_id);
801 sub BatchRevertRecords
{
802 my $batch_id = shift;
804 $logger->trace("C4::ImportBatch::BatchRevertRecords( $batch_id )");
809 my $num_reverted = 0;
811 my $num_items_deleted = 0;
812 # commit (i.e., save, all records in the batch)
813 SetImportBatchStatus
('reverting');
814 my $overlay_action = GetImportBatchOverlayAction
($batch_id);
815 my $nomatch_action = GetImportBatchNoMatchAction
($batch_id);
816 my $dbh = C4
::Context
->dbh;
817 my $sth = $dbh->prepare("SELECT import_records.import_record_id, record_type, status, overlay_status, marcxml_old, encoding, matched_biblionumber, matched_authid
819 LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id)
820 LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id)
821 WHERE import_batch_id = ?");
822 $sth->execute($batch_id);
824 my $marcflavour = C4
::Context
->preference('marcflavour');
825 while (my $rowref = $sth->fetchrow_hashref) {
826 $record_type = $rowref->{'record_type'};
827 if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'reverted') {
831 if ($marcflavour eq 'UNIMARC' && $record_type eq 'auth') {
832 $marc_type = 'UNIMARCAUTH';
833 } elsif ($marcflavour eq 'UNIMARC') {
834 $marc_type = 'UNIMARC';
836 $marc_type = 'USMARC';
839 my $record_result = _get_revert_action
($overlay_action, $rowref->{'overlay_status'}, $rowref->{'status'});
841 if ($record_result eq 'delete') {
843 if ($record_type eq 'biblio') {
844 $num_items_deleted += BatchRevertItems
($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
845 $error = DelBiblio
($rowref->{'matched_biblionumber'});
847 DelAuthority
({ authid
=> $rowref->{'matched_authid'} });
849 if (defined $error) {
853 SetImportRecordStatus
($rowref->{'import_record_id'}, 'reverted');
855 } elsif ($record_result eq 'restore') {
857 my $old_record = MARC
::Record
->new_from_xml(StripNonXmlChars
($rowref->{'marcxml_old'}), 'UTF-8', $rowref->{'encoding'}, $marc_type);
858 if ($record_type eq 'biblio') {
859 my $biblionumber = $rowref->{'matched_biblionumber'};
860 my $oldbiblio = Koha
::Biblios
->find( $biblionumber );
862 $logger->info("C4::ImportBatch::BatchRevertRecords: Biblio record $biblionumber does not exist, restoration of this record was skipped") unless $oldbiblio;
863 next unless $oldbiblio; # Record has since been deleted. Deleted records should stay deleted.
865 $num_items_deleted += BatchRevertItems
($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
866 ModBiblio
($old_record, $biblionumber, $oldbiblio->frameworkcode);
868 my $authid = $rowref->{'matched_authid'};
869 ModAuthority
($authid, $old_record, GuessAuthTypeCode
($old_record));
871 SetImportRecordStatus
($rowref->{'import_record_id'}, 'reverted');
872 } elsif ($record_result eq 'ignore') {
873 if ($record_type eq 'biblio') {
874 $num_items_deleted += BatchRevertItems
($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
876 SetImportRecordStatus
($rowref->{'import_record_id'}, 'reverted');
879 if ($record_type eq 'biblio') {
880 # remove matched_biblionumber only if there is no 'imported' item left
881 $query = "UPDATE import_biblios SET matched_biblionumber = NULL WHERE import_record_id = ?";
882 $query = "UPDATE import_biblios SET matched_biblionumber = NULL WHERE import_record_id = ? AND NOT EXISTS (SELECT * FROM import_items WHERE import_items.import_record_id=import_biblios.import_record_id and status='imported')";
884 $query = "UPDATE import_auths SET matched_authid = NULL WHERE import_record_id = ?";
886 my $sth2 = $dbh->prepare_cached($query);
887 $sth2->execute($rowref->{'import_record_id'});
891 SetImportBatchStatus
($batch_id, 'reverted');
892 return ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored);
895 =head2 BatchRevertItems
897 my $num_items_deleted = BatchRevertItems($import_record_id, $biblionumber);
901 sub BatchRevertItems
{
902 my ($import_record_id, $biblionumber) = @_;
904 my $dbh = C4
::Context
->dbh;
905 my $num_items_deleted = 0;
907 my $sth = $dbh->prepare_cached("SELECT import_items_id, itemnumber
909 JOIN items USING (itemnumber)
910 WHERE import_record_id = ?");
911 $sth->bind_param(1, $import_record_id);
913 while (my $row = $sth->fetchrow_hashref()) {
914 my $error = DelItemCheck
( $biblionumber, $row->{'itemnumber'});
916 my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
917 $updsth->bind_param(1, 'reverted');
918 $updsth->bind_param(2, $row->{'import_items_id'});
921 $num_items_deleted++;
928 return $num_items_deleted;
933 CleanBatch($batch_id)
935 Deletes all staged records from the import batch
936 and sets the status of the batch to 'cleaned'. Note
937 that deleting a stage record does *not* affect
938 any record that has been committed to the database.
943 my $batch_id = shift;
944 return unless defined $batch_id;
946 C4
::Context
->dbh->do('DELETE FROM import_records WHERE import_batch_id = ?', {}, $batch_id);
947 SetImportBatchStatus
($batch_id, 'cleaned');
952 DeleteBatch($batch_id)
954 Deletes the record from the database. This can only be done
955 once the batch has been cleaned.
960 my $batch_id = shift;
961 return unless defined $batch_id;
963 my $dbh = C4
::Context
->dbh;
964 my $sth = $dbh->prepare('DELETE FROM import_batches WHERE import_batch_id = ?');
965 $sth->execute( $batch_id );
968 =head2 GetAllImportBatches
970 my $results = GetAllImportBatches();
972 Returns a references to an array of hash references corresponding
973 to all import_batches rows (of batch_type 'batch'), sorted in
974 ascending order by import_batch_id.
978 sub GetAllImportBatches
{
979 my $dbh = C4
::Context
->dbh;
980 my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
981 WHERE batch_type IN ('batch', 'webservice')
982 ORDER BY import_batch_id ASC");
986 while (my $row = $sth->fetchrow_hashref) {
987 push @
$results, $row;
993 =head2 GetStagedWebserviceBatches
995 my $batch_ids = GetStagedWebserviceBatches();
997 Returns a references to an array of batch id's
998 of batch_type 'webservice' that are not imported
1002 my $PENDING_WEBSERVICE_BATCHES_QRY = <<EOQ;
1003 SELECT import_batch_id FROM import_batches
1004 WHERE batch_type = 'webservice'
1005 AND import_status = 'staged'
1007 sub GetStagedWebserviceBatches
{
1008 my $dbh = C4
::Context
->dbh;
1009 return $dbh->selectcol_arrayref($PENDING_WEBSERVICE_BATCHES_QRY);
1012 =head2 GetImportBatchRangeDesc
1014 my $results = GetImportBatchRangeDesc($offset, $results_per_group);
1016 Returns a reference to an array of hash references corresponding to
1017 import_batches rows (sorted in descending order by import_batch_id)
1018 start at the given offset.
1022 sub GetImportBatchRangeDesc
{
1023 my ($offset, $results_per_group) = @_;
1025 my $dbh = C4
::Context
->dbh;
1026 my $query = "SELECT * FROM import_batches
1027 WHERE batch_type IN ('batch', 'webservice')
1028 ORDER BY import_batch_id DESC";
1030 if ($results_per_group){
1031 $query .= " LIMIT ?";
1032 push(@params, $results_per_group);
1035 $query .= " OFFSET ?";
1036 push(@params, $offset);
1038 my $sth = $dbh->prepare_cached($query);
1039 $sth->execute(@params);
1040 my $results = $sth->fetchall_arrayref({});
1045 =head2 GetItemNumbersFromImportBatch
1047 my @itemsnos = GetItemNumbersFromImportBatch($batch_id);
1051 sub GetItemNumbersFromImportBatch
{
1052 my ($batch_id) = @_;
1053 my $dbh = C4
::Context
->dbh;
1055 SELECT itemnumber FROM import_items
1056 INNER JOIN items USING
(itemnumber
)
1057 INNER JOIN import_records USING
(import_record_id
)
1058 WHERE import_batch_id
= ?
|;
1059 my $sth = $dbh->prepare( $sql );
1060 $sth->execute($batch_id);
1062 while ( my ($itm) = $sth->fetchrow_array ) {
1068 =head2 GetNumberOfImportBatches
1070 my $count = GetNumberOfImportBatches();
1074 sub GetNumberOfNonZ3950ImportBatches
{
1075 my $dbh = C4
::Context
->dbh;
1076 my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type != 'z3950'");
1078 my ($count) = $sth->fetchrow_array();
1083 =head2 GetImportBiblios
1085 my $results = GetImportBiblios($importid);
1089 sub GetImportBiblios
{
1090 my ($import_record_id) = @_;
1092 my $dbh = C4
::Context
->dbh;
1093 my $query = "SELECT * FROM import_biblios WHERE import_record_id = ?";
1094 return $dbh->selectall_arrayref(
1102 =head2 GetImportRecordsRange
1104 my $results = GetImportRecordsRange($batch_id, $offset, $results_per_group);
1106 Returns a reference to an array of hash references corresponding to
1107 import_biblios/import_auths/import_records rows for a given batch
1108 starting at the given offset.
1112 sub GetImportRecordsRange
{
1113 my ( $batch_id, $offset, $results_per_group, $status, $parameters ) = @_;
1115 my $dbh = C4
::Context
->dbh;
1117 my $order_by = $parameters->{order_by
} || 'import_record_id';
1118 ( $order_by ) = grep( /^$order_by$/, qw( import_record_id title status overlay_status ) ) ?
$order_by : 'import_record_id';
1120 my $order_by_direction =
1121 uc( $parameters->{order_by_direction
} ) eq 'DESC' ?
'DESC' : 'ASC';
1123 $order_by .= " $order_by_direction, authorized_heading" if $order_by eq 'title';
1125 my $query = "SELECT title, author, isbn, issn, authorized_heading, import_records.import_record_id,
1126 record_sequence, status, overlay_status,
1127 matched_biblionumber, matched_authid, record_type
1129 LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id)
1130 LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id)
1131 WHERE import_batch_id = ?";
1133 push(@params, $batch_id);
1135 $query .= " AND status=?";
1136 push(@params,$status);
1139 $query.=" ORDER BY $order_by $order_by_direction";
1141 if($results_per_group){
1142 $query .= " LIMIT ?";
1143 push(@params, $results_per_group);
1146 $query .= " OFFSET ?";
1147 push(@params, $offset);
1149 my $sth = $dbh->prepare_cached($query);
1150 $sth->execute(@params);
1151 my $results = $sth->fetchall_arrayref({});
1157 =head2 GetBestRecordMatch
1159 my $record_id = GetBestRecordMatch($import_record_id);
1163 sub GetBestRecordMatch
{
1164 my ($import_record_id) = @_;
1166 my $dbh = C4
::Context
->dbh;
1167 my $sth = $dbh->prepare("SELECT candidate_match_id
1168 FROM import_record_matches
1169 JOIN import_records ON ( import_record_matches.import_record_id = import_records.import_record_id )
1170 LEFT JOIN biblio ON ( candidate_match_id = biblio.biblionumber )
1171 LEFT JOIN auth_header ON ( candidate_match_id = auth_header.authid )
1172 WHERE import_record_matches.import_record_id = ? AND
1173 ( (import_records.record_type = 'biblio' AND biblio.biblionumber IS NOT NULL) OR
1174 (import_records.record_type = 'auth' AND auth_header.authid IS NOT NULL) )
1175 ORDER BY score DESC, candidate_match_id DESC");
1176 $sth->execute($import_record_id);
1177 my ($record_id) = $sth->fetchrow_array();
1182 =head2 GetImportBatchStatus
1184 my $status = GetImportBatchStatus($batch_id);
1188 sub GetImportBatchStatus
{
1189 my ($batch_id) = @_;
1191 my $dbh = C4
::Context
->dbh;
1192 my $sth = $dbh->prepare("SELECT import_status FROM import_batches WHERE import_batch_id = ?");
1193 $sth->execute($batch_id);
1194 my ($status) = $sth->fetchrow_array();
1200 =head2 SetImportBatchStatus
1202 SetImportBatchStatus($batch_id, $new_status);
1206 sub SetImportBatchStatus
{
1207 my ($batch_id, $new_status) = @_;
1209 my $dbh = C4
::Context
->dbh;
1210 my $sth = $dbh->prepare("UPDATE import_batches SET import_status = ? WHERE import_batch_id = ?");
1211 $sth->execute($new_status, $batch_id);
1216 =head2 GetImportBatchOverlayAction
1218 my $overlay_action = GetImportBatchOverlayAction($batch_id);
1222 sub GetImportBatchOverlayAction
{
1223 my ($batch_id) = @_;
1225 my $dbh = C4
::Context
->dbh;
1226 my $sth = $dbh->prepare("SELECT overlay_action FROM import_batches WHERE import_batch_id = ?");
1227 $sth->execute($batch_id);
1228 my ($overlay_action) = $sth->fetchrow_array();
1230 return $overlay_action;
1235 =head2 SetImportBatchOverlayAction
1237 SetImportBatchOverlayAction($batch_id, $new_overlay_action);
1241 sub SetImportBatchOverlayAction
{
1242 my ($batch_id, $new_overlay_action) = @_;
1244 my $dbh = C4
::Context
->dbh;
1245 my $sth = $dbh->prepare("UPDATE import_batches SET overlay_action = ? WHERE import_batch_id = ?");
1246 $sth->execute($new_overlay_action, $batch_id);
1251 =head2 GetImportBatchNoMatchAction
1253 my $nomatch_action = GetImportBatchNoMatchAction($batch_id);
1257 sub GetImportBatchNoMatchAction
{
1258 my ($batch_id) = @_;
1260 my $dbh = C4
::Context
->dbh;
1261 my $sth = $dbh->prepare("SELECT nomatch_action FROM import_batches WHERE import_batch_id = ?");
1262 $sth->execute($batch_id);
1263 my ($nomatch_action) = $sth->fetchrow_array();
1265 return $nomatch_action;
1270 =head2 SetImportBatchNoMatchAction
1272 SetImportBatchNoMatchAction($batch_id, $new_nomatch_action);
1276 sub SetImportBatchNoMatchAction
{
1277 my ($batch_id, $new_nomatch_action) = @_;
1279 my $dbh = C4
::Context
->dbh;
1280 my $sth = $dbh->prepare("UPDATE import_batches SET nomatch_action = ? WHERE import_batch_id = ?");
1281 $sth->execute($new_nomatch_action, $batch_id);
1286 =head2 GetImportBatchItemAction
1288 my $item_action = GetImportBatchItemAction($batch_id);
1292 sub GetImportBatchItemAction
{
1293 my ($batch_id) = @_;
1295 my $dbh = C4
::Context
->dbh;
1296 my $sth = $dbh->prepare("SELECT item_action FROM import_batches WHERE import_batch_id = ?");
1297 $sth->execute($batch_id);
1298 my ($item_action) = $sth->fetchrow_array();
1300 return $item_action;
1305 =head2 SetImportBatchItemAction
1307 SetImportBatchItemAction($batch_id, $new_item_action);
1311 sub SetImportBatchItemAction
{
1312 my ($batch_id, $new_item_action) = @_;
1314 my $dbh = C4
::Context
->dbh;
1315 my $sth = $dbh->prepare("UPDATE import_batches SET item_action = ? WHERE import_batch_id = ?");
1316 $sth->execute($new_item_action, $batch_id);
1321 =head2 GetImportBatchMatcher
1323 my $matcher_id = GetImportBatchMatcher($batch_id);
1327 sub GetImportBatchMatcher
{
1328 my ($batch_id) = @_;
1330 my $dbh = C4
::Context
->dbh;
1331 my $sth = $dbh->prepare("SELECT matcher_id FROM import_batches WHERE import_batch_id = ?");
1332 $sth->execute($batch_id);
1333 my ($matcher_id) = $sth->fetchrow_array();
1340 =head2 SetImportBatchMatcher
1342 SetImportBatchMatcher($batch_id, $new_matcher_id);
1346 sub SetImportBatchMatcher
{
1347 my ($batch_id, $new_matcher_id) = @_;
1349 my $dbh = C4
::Context
->dbh;
1350 my $sth = $dbh->prepare("UPDATE import_batches SET matcher_id = ? WHERE import_batch_id = ?");
1351 $sth->execute($new_matcher_id, $batch_id);
1356 =head2 GetImportRecordOverlayStatus
1358 my $overlay_status = GetImportRecordOverlayStatus($import_record_id);
1362 sub GetImportRecordOverlayStatus
{
1363 my ($import_record_id) = @_;
1365 my $dbh = C4
::Context
->dbh;
1366 my $sth = $dbh->prepare("SELECT overlay_status FROM import_records WHERE import_record_id = ?");
1367 $sth->execute($import_record_id);
1368 my ($overlay_status) = $sth->fetchrow_array();
1370 return $overlay_status;
1375 =head2 SetImportRecordOverlayStatus
1377 SetImportRecordOverlayStatus($import_record_id, $new_overlay_status);
1381 sub SetImportRecordOverlayStatus
{
1382 my ($import_record_id, $new_overlay_status) = @_;
1384 my $dbh = C4
::Context
->dbh;
1385 my $sth = $dbh->prepare("UPDATE import_records SET overlay_status = ? WHERE import_record_id = ?");
1386 $sth->execute($new_overlay_status, $import_record_id);
1391 =head2 GetImportRecordStatus
1393 my $status = GetImportRecordStatus($import_record_id);
1397 sub GetImportRecordStatus
{
1398 my ($import_record_id) = @_;
1400 my $dbh = C4
::Context
->dbh;
1401 my $sth = $dbh->prepare("SELECT status FROM import_records WHERE import_record_id = ?");
1402 $sth->execute($import_record_id);
1403 my ($status) = $sth->fetchrow_array();
1410 =head2 SetImportRecordStatus
1412 SetImportRecordStatus($import_record_id, $new_status);
1416 sub SetImportRecordStatus
{
1417 my ($import_record_id, $new_status) = @_;
1419 my $dbh = C4
::Context
->dbh;
1420 my $sth = $dbh->prepare("UPDATE import_records SET status = ? WHERE import_record_id = ?");
1421 $sth->execute($new_status, $import_record_id);
1426 =head2 GetImportRecordMatches
1428 my $results = GetImportRecordMatches($import_record_id, $best_only);
1432 sub GetImportRecordMatches
{
1433 my $import_record_id = shift;
1434 my $best_only = @_ ?
shift : 0;
1436 my $dbh = C4
::Context
->dbh;
1437 # FIXME currently biblio only
1438 my $sth = $dbh->prepare_cached("SELECT title, author, biblionumber,
1439 candidate_match_id, score, record_type
1441 JOIN import_record_matches USING (import_record_id)
1442 LEFT JOIN biblio ON (biblionumber = candidate_match_id)
1443 WHERE import_record_id = ?
1444 ORDER BY score DESC, biblionumber DESC");
1445 $sth->bind_param(1, $import_record_id);
1448 while (my $row = $sth->fetchrow_hashref) {
1449 if ($row->{'record_type'} eq 'auth') {
1450 $row->{'authorized_heading'} = C4
::AuthoritiesMarc
::GetAuthorizedHeading
( { authid
=> $row->{'candidate_match_id'} } );
1452 next if ($row->{'record_type'} eq 'biblio' && not $row->{'biblionumber'});
1453 push @
$results, $row;
1462 =head2 SetImportRecordMatches
1464 SetImportRecordMatches($import_record_id, @matches);
1468 sub SetImportRecordMatches
{
1469 my $import_record_id = shift;
1472 my $dbh = C4
::Context
->dbh;
1473 my $delsth = $dbh->prepare("DELETE FROM import_record_matches WHERE import_record_id = ?");
1474 $delsth->execute($import_record_id);
1477 my $sth = $dbh->prepare("INSERT INTO import_record_matches (import_record_id, candidate_match_id, score)
1479 foreach my $match (@matches) {
1480 $sth->execute($import_record_id, $match->{'record_id'}, $match->{'score'});
1484 =head2 RecordsFromISO2709File
1486 my ($errors, $records) = C4::ImportBatch::RecordsFromISO2709File($input_file, $record_type, $encoding);
1488 Reads ISO2709 binary porridge from the given file and creates MARC::Record-objects out of it.
1490 @PARAM1, String, absolute path to the ISO2709 file.
1491 @PARAM2, String, see stage_file.pl
1492 @PARAM3, String, should be utf8
1494 Returns two array refs.
1498 sub RecordsFromISO2709File
{
1499 my ($input_file, $record_type, $encoding) = @_;
1502 my $marc_type = C4
::Context
->preference('marcflavour');
1503 $marc_type .= 'AUTH' if ($marc_type eq 'UNIMARC' && $record_type eq 'auth');
1505 open IN
, "<$input_file" or die "$0: cannot open input file $input_file: $!\n";
1511 next unless $_; # skip if record has only whitespace, as might occur
1512 # if file includes newlines between each MARC record
1513 my ($marc_record, $charset_guessed, $char_errors) = MarcToUTF8Record
($_, $marc_type, $encoding);
1514 push @marc_records, $marc_record;
1515 if ($charset_guessed ne $encoding) {
1517 "Unexpected charset $charset_guessed, expecting $encoding";
1521 return ( \
@errors, \
@marc_records );
1524 =head2 RecordsFromMARCXMLFile
1526 my ($errors, $records) = C4::ImportBatch::RecordsFromMARCXMLFile($input_file, $encoding);
1528 Creates MARC::Record-objects out of the given MARCXML-file.
1530 @PARAM1, String, absolute path to the ISO2709 file.
1531 @PARAM2, String, should be utf8
1533 Returns two array refs.
1537 sub RecordsFromMARCXMLFile
{
1538 my ( $filename, $encoding ) = @_;
1539 my $batch = MARC
::File
::XML
->in( $filename );
1540 my ( @marcRecords, @errors, $record );
1542 eval { $record = $batch->next( $encoding ); };
1546 push @marcRecords, $record if $record;
1548 return (\
@errors, \
@marcRecords);
1551 =head2 RecordsFromMarcPlugin
1553 Converts text of input_file into array of MARC records with to_marc plugin
1557 sub RecordsFromMarcPlugin
{
1558 my ($input_file, $plugin_class, $encoding) = @_;
1561 open IN
, "<$input_file" or die "$0: cannot open input file $input_file: $!\n";
1562 my ( $text, $marc, @return );
1572 # Convert to large MARC blob with plugin
1573 $text = Koha
::Plugins
::Handler
->run({
1574 class => $plugin_class,
1575 method
=> 'to_marc',
1576 params
=> { data
=> $text },
1579 # Convert to array of MARC records
1580 my $marc_type = C4
::Context
->preference('marcflavour');
1581 foreach my $blob ( split(/\x1D/, $text) ) {
1582 next if $blob =~ /^\s*$/;
1583 my ($marcrecord) = MarcToUTF8Record
($blob, $marc_type, $encoding);
1584 push @return, $marcrecord;
1589 # internal functions
1591 sub _create_import_record
{
1592 my ($batch_id, $record_sequence, $marc_record, $record_type, $encoding, $z3950random, $marc_type) = @_;
1594 my $dbh = C4
::Context
->dbh;
1595 my $sth = $dbh->prepare("INSERT INTO import_records (import_batch_id, record_sequence, marc, marcxml,
1596 record_type, encoding, z3950random)
1597 VALUES (?, ?, ?, ?, ?, ?, ?)");
1598 $sth->execute($batch_id, $record_sequence, $marc_record->as_usmarc(), $marc_record->as_xml($marc_type),
1599 $record_type, $encoding, $z3950random);
1600 my $import_record_id = $dbh->{'mysql_insertid'};
1602 return $import_record_id;
1605 sub _update_import_record_marc
{
1606 my ($import_record_id, $marc_record, $marc_type) = @_;
1608 my $dbh = C4
::Context
->dbh;
1609 my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ?
1610 WHERE import_record_id = ?");
1611 $sth->execute($marc_record->as_usmarc(), $marc_record->as_xml($marc_type), $import_record_id);
1615 sub _add_auth_fields
{
1616 my ($import_record_id, $marc_record) = @_;
1619 if ($marc_record->field('001')) {
1620 $controlnumber = $marc_record->field('001')->data();
1622 my $authorized_heading = C4
::AuthoritiesMarc
::GetAuthorizedHeading
({ record
=> $marc_record });
1623 my $dbh = C4
::Context
->dbh;
1624 my $sth = $dbh->prepare("INSERT INTO import_auths (import_record_id, control_number, authorized_heading) VALUES (?, ?, ?)");
1625 $sth->execute($import_record_id, $controlnumber, $authorized_heading);
1629 sub _add_biblio_fields
{
1630 my ($import_record_id, $marc_record) = @_;
1632 my ($title, $author, $isbn, $issn) = _parse_biblio_fields
($marc_record);
1633 my $dbh = C4
::Context
->dbh;
1634 # FIXME no controlnumber, originalsource
1635 $isbn = C4
::Koha
::GetNormalizedISBN
($isbn);
1636 my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn) VALUES (?, ?, ?, ?, ?)");
1637 $sth->execute($import_record_id, $title, $author, $isbn, $issn);
1642 sub _update_biblio_fields
{
1643 my ($import_record_id, $marc_record) = @_;
1645 my ($title, $author, $isbn, $issn) = _parse_biblio_fields
($marc_record);
1646 my $dbh = C4
::Context
->dbh;
1647 # FIXME no controlnumber, originalsource
1648 # FIXME 2 - should regularize normalization of ISBN wherever it is done
1652 my $sth = $dbh->prepare("UPDATE import_biblios SET title = ?, author = ?, isbn = ?, issn = ?
1653 WHERE import_record_id = ?");
1654 $sth->execute($title, $author, $isbn, $issn, $import_record_id);
1658 sub _parse_biblio_fields
{
1659 my ($marc_record) = @_;
1661 my $dbh = C4
::Context
->dbh;
1662 my $bibliofields = TransformMarcToKoha
($marc_record, '');
1663 return ($bibliofields->{'title'}, $bibliofields->{'author'}, $bibliofields->{'isbn'}, $bibliofields->{'issn'});
1667 sub _update_batch_record_counts
{
1668 my ($batch_id) = @_;
1670 my $dbh = C4
::Context
->dbh;
1671 my $sth = $dbh->prepare_cached("UPDATE import_batches SET
1675 WHERE import_batch_id = import_batches.import_batch_id),
1679 JOIN import_items USING (import_record_id)
1680 WHERE import_batch_id = import_batches.import_batch_id
1681 AND record_type = 'biblio')
1682 WHERE import_batch_id = ?");
1683 $sth->bind_param(1, $batch_id);
1688 sub _get_commit_action
{
1689 my ($overlay_action, $nomatch_action, $item_action, $overlay_status, $import_record_id, $record_type) = @_;
1691 if ($record_type eq 'biblio') {
1692 my ($bib_result, $bib_match, $item_result);
1694 if ($overlay_status ne 'no_match') {
1695 $bib_match = GetBestRecordMatch
($import_record_id);
1696 if ($overlay_action eq 'replace') {
1697 $bib_result = defined($bib_match) ?
'replace' : 'create_new';
1698 } elsif ($overlay_action eq 'create_new') {
1699 $bib_result = 'create_new';
1700 } elsif ($overlay_action eq 'ignore') {
1701 $bib_result = 'ignore';
1703 if($item_action eq 'always_add' or $item_action eq 'add_only_for_matches'){
1704 $item_result = 'create_new';
1706 elsif($item_action eq 'replace'){
1707 $item_result = 'replace';
1710 $item_result = 'ignore';
1713 $bib_result = $nomatch_action;
1714 $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_new') ?
'create_new' : 'ignore';
1716 return ($bib_result, $item_result, $bib_match);
1717 } else { # must be auths
1718 my ($auth_result, $auth_match);
1720 if ($overlay_status ne 'no_match') {
1721 $auth_match = GetBestRecordMatch
($import_record_id);
1722 if ($overlay_action eq 'replace') {
1723 $auth_result = defined($auth_match) ?
'replace' : 'create_new';
1724 } elsif ($overlay_action eq 'create_new') {
1725 $auth_result = 'create_new';
1726 } elsif ($overlay_action eq 'ignore') {
1727 $auth_result = 'ignore';
1730 $auth_result = $nomatch_action;
1733 return ($auth_result, undef, $auth_match);
1738 sub _get_revert_action
{
1739 my ($overlay_action, $overlay_status, $status) = @_;
1743 if ($status eq 'ignored') {
1744 $bib_result = 'ignore';
1746 if ($overlay_action eq 'create_new') {
1747 $bib_result = 'delete';
1749 $bib_result = ($overlay_status eq 'match_applied') ?
'restore' : 'delete';
1760 Koha Development Team <http://koha-community.org/>
1762 Galen Charlton <galen.charlton@liblime.com>