TransformHtmlToXml() now checks from UNIMARC flavour, before inserting encoding info...
[koha.git] / C4 / ImportBatch.pm
blob06d5d0769aec603dd90f2e1f27ef8772961b3a95
1 package C4::ImportBatch;
3 # Copyright (C) 2007 LibLime
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA 02111-1307 USA
20 use strict;
21 use C4::Context;
22 use C4::Koha;
23 use C4::Biblio;
24 require Exporter;
27 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
29 # set the version for version checking
30 $VERSION = 3.00;
32 =head1 NAME
34 C4::ImportBatch - manage batches of imported MARC records
36 =head1 SYNOPSIS
38 =over 4
40 use C4::ImportBatch;
42 =back
44 =head1 FUNCTIONS
46 =cut
48 @ISA = qw(Exporter);
49 @EXPORT = qw(
50 GetZ3950BatchId
51 GetImportRecordMarc
52 AddImportBatch
53 GetImportBatch
54 AddBiblioToBatch
55 ModBiblioInBatch
57 BatchStageMarcRecords
58 BatchFindBibDuplicates
59 BatchCommitBibRecords
60 BatchRevertBibRecords
62 GetAllImportBatches
63 GetImportBatchRangeDesc
64 GetNumberOfNonZ3950ImportBatches
65 GetImportBibliosRange
67 GetImportBatchStatus
68 SetImportBatchStatus
69 GetImportBatchOverlayAction
70 SetImportBatchOverlayAction
71 GetImportBatchMatcher
72 SetImportBatchMatcher
73 GetImportRecordOverlayStatus
74 SetImportRecordOverlayStatus
75 GetImportRecordStatus
76 SetImportRecordStatus
77 GetImportRecordMatches
78 SetImportRecordMatches
81 =head2 GetZ3950BatchId
83 =over 4
85 my $batchid = GetZ3950BatchId($z3950server);
87 =back
89 Retrieves the ID of the import batch for the Z39.50
90 reservoir for the given target. If necessary,
91 creates the import batch.
93 =cut
95 sub GetZ3950BatchId {
96 my ($z3950server) = @_;
98 my $dbh = C4::Context->dbh;
99 my $sth = $dbh->prepare("SELECT import_batch_id FROM import_batches
100 WHERE batch_type = 'z3950'
101 AND file_name = ?");
102 $sth->execute($z3950server);
103 my $rowref = $sth->fetchrow_arrayref();
104 $sth->finish();
105 if (defined $rowref) {
106 return $rowref->[0];
107 } else {
108 my $batch_id = AddImportBatch('create_new', 'staged', 'z3950', $z3950server, '');
109 return $batch_id;
114 =head2 GetImportRecordMarc
116 =over 4
118 my ($marcblob, $encoding) = GetImportRecordMarc($import_record_id);
120 =back
122 =cut
124 sub GetImportRecordMarc {
125 my ($import_record_id) = @_;
127 my $dbh = C4::Context->dbh;
128 my $sth = $dbh->prepare("SELECT marc, encoding FROM import_records WHERE import_record_id = ?");
129 $sth->execute($import_record_id);
130 my ($marc, $encoding) = $sth->fetchrow();
131 $sth->finish();
132 return $marc;
136 =head2 AddImportBatch
138 =over 4
140 my $batch_id = AddImportBatch($overlay_action, $import_status, $type, $file_name, $comments);
142 =back
144 =cut
146 sub AddImportBatch {
147 my ($overlay_action, $import_status, $type, $file_name, $comments) = @_;
149 my $dbh = C4::Context->dbh;
150 my $sth = $dbh->prepare("INSERT INTO import_batches (overlay_action, import_status, batch_type,
151 file_name, comments)
152 VALUES (?, ?, ?, ?, ?)");
153 $sth->execute($overlay_action, $import_status, $type, $file_name, $comments);
154 my $batch_id = $dbh->{'mysql_insertid'};
155 $sth->finish();
157 return $batch_id;
161 =head2 GetImportBatch
163 =over 4
165 my $row = GetImportBatch($batch_id);
167 =back
169 Retrieve a hashref of an import_batches row.
171 =cut
173 sub GetImportBatch {
174 my ($batch_id) = @_;
176 my $dbh = C4::Context->dbh;
177 my $sth = $dbh->prepare_cached("SELECT * FROM import_batches WHERE import_batch_id = ?");
178 $sth->bind_param(1, $batch_id);
179 $sth->execute();
180 my $result = $sth->fetchrow_hashref;
181 $sth->finish();
182 return $result;
186 =head2 AddBiblioToBatch
188 =over 4
190 my $import_record_id = AddBiblioToBatch($batch_id, $record_sequence, $marc_record, $encoding, $z3950random, $update_counts);
192 =back
194 =cut
196 sub AddBiblioToBatch {
197 my $batch_id = shift;
198 my $record_sequence = shift;
199 my $marc_record = shift;
200 my $encoding = shift;
201 my $z3950random = shift;
202 my $update_counts = @_ ? shift : 1;
204 my $import_record_id = _create_import_record($batch_id, $record_sequence, $marc_record, 'biblio', $encoding, $z3950random);
205 _add_biblio_fields($import_record_id, $marc_record);
206 _update_batch_record_counts($batch_id) if $update_counts;
207 return $import_record_id;
210 =head2 ModBiblioInBatch
212 =over 4
214 ModBiblioInBatch($import_record_id, $marc_record);
216 =back
218 =cut
220 sub ModBiblioInBatch {
221 my ($import_record_id, $marc_record) = @_;
223 _update_import_record_marc($import_record_id, $marc_record);
224 _update_biblio_fields($import_record_id, $marc_record);
228 =head2 BatchStageMarcRecords
230 =over 4
232 ($batch_id, $num_records, $num_items, @invalid_records) =
233 BatchStageMarcRecords($marc_flavor, $marc_records, $file_name,
234 $comments, $branch_code, $parse_items,
235 $leave_as_staging,
236 $progress_interval, $progress_callback);
238 =back
240 =cut
242 sub BatchStageMarcRecords {
243 my $marc_flavor = shift;
244 my $marc_records = shift;
245 my $file_name = shift;
246 my $comments = shift;
247 my $branch_code = shift;
248 my $parse_items = shift;
249 my $leave_as_staging = shift;
251 # optional callback to monitor status
252 # of job
253 my $progress_interval = 0;
254 my $progress_callback = undef;
255 if ($#_ == 1) {
256 $progress_interval = shift;
257 $progress_callback = shift;
258 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
259 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
262 my $batch_id = AddImportBatch('create_new', 'staging', 'batch', $file_name, $comments);
263 my @invalid_records = ();
264 my $num_valid = 0;
265 my $num_items = 0;
266 # FIXME - for now, we're dealing only with bibs
267 my $rec_num = 0;
268 foreach my $marc_blob (split(/\x1D/, $marc_records)) {
269 $rec_num++;
270 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
271 &$progress_callback($rec_num);
273 my $marc_record = FixEncoding($marc_blob, "\x1D");
274 my $import_record_id;
275 if (scalar($marc_record->fields()) == 0) {
276 push @invalid_records, $marc_blob;
277 } else {
278 $num_valid++;
279 $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $marc_flavor, int(rand(99999)), 0);
280 if ($parse_items) {
281 my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 0);
282 $num_items += scalar(@import_items_ids);
286 unless ($leave_as_staging) {
287 SetImportBatchStatus($batch_id, 'staged');
289 # FIXME branch_code, number of bibs, number of items
290 _update_batch_record_counts($batch_id);
291 return ($batch_id, $num_valid, $num_items, @invalid_records);
294 =head2 AddItemsToImportBiblio
296 =over 4
298 my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, $update_counts);
300 =back
302 =cut
304 sub AddItemsToImportBiblio {
305 my $batch_id = shift;
306 my $import_record_id = shift;
307 my $marc_record = shift;
308 my $update_counts = @_ ? shift : 0;
310 my @import_items_ids = ();
312 my $dbh = C4::Context->dbh;
313 my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",'');
314 foreach my $item_field ($marc_record->field($item_tag)) {
315 my $item_marc = MARC::Record->new();
316 $item_marc->append_fields($item_field);
317 $marc_record->delete_field($item_field);
318 my $sth = $dbh->prepare_cached("INSERT INTO import_items (import_record_id, status, marcxml)
319 VALUES (?, ?, ?)");
320 $sth->bind_param(1, $import_record_id);
321 $sth->bind_param(2, 'staged');
322 $sth->bind_param(3, $item_marc->as_xml());
323 $sth->execute();
324 push @import_items_ids, $dbh->{'mysql_insertid'};
325 $sth->finish();
328 if ($#import_items_ids > -1) {
329 _update_batch_record_counts($batch_id) if $update_counts;
330 _update_import_record_marc($import_record_id, $marc_record);
332 return @import_items_ids;
335 =head2 BatchFindBibDuplicates
337 =over 4
339 my $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher, $max_matches, $progress_interval, $progress_callback);
341 =back
343 Goes through the records loaded in the batch and attempts to
344 find duplicates for each one. Sets the overlay action to
345 "replace" if it was "create_new", and sets the overlay status
346 of each record to "no_match" or "auto_match" as appropriate.
348 The $max_matches parameter is optional; if it is not supplied,
349 it defaults to 10.
351 The $progress_interval and $progress_callback parameters are
352 optional; if both are supplied, the sub referred to by
353 $progress_callback will be invoked every $progress_interval
354 records using the number of records processed as the
355 singular argument.
357 =cut
359 sub BatchFindBibDuplicates {
360 my $batch_id = shift;
361 my $matcher = shift;
362 my $max_matches = @_ ? shift : 10;
364 # optional callback to monitor status
365 # of job
366 my $progress_interval = 0;
367 my $progress_callback = undef;
368 if ($#_ == 1) {
369 $progress_interval = shift;
370 $progress_callback = shift;
371 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
372 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
375 my $dbh = C4::Context->dbh;
376 my $old_overlay_action = GetImportBatchOverlayAction($batch_id);
377 if ($old_overlay_action eq "create_new") {
378 SetImportBatchOverlayAction($batch_id, 'replace');
381 my $sth = $dbh->prepare("SELECT import_record_id, marc
382 FROM import_records
383 JOIN import_biblios USING (import_record_id)
384 WHERE import_batch_id = ?");
385 $sth->execute($batch_id);
386 my $num_with_matches = 0;
387 my $rec_num = 0;
388 while (my $rowref = $sth->fetchrow_hashref) {
389 $rec_num++;
390 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
391 &$progress_callback($rec_num);
393 my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
394 my @matches = ();
395 if (defined $matcher) {
396 @matches = $matcher->get_matches($marc_record, $max_matches);
398 if (scalar(@matches) > 0) {
399 $num_with_matches++;
400 SetImportRecordMatches($rowref->{'import_record_id'}, @matches);
401 SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'auto_match');
402 } else {
403 SetImportRecordMatches($rowref->{'import_record_id'}, ());
404 SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'no_match');
407 $sth->finish();
408 return $num_with_matches;
411 =head2 BatchCommitBibRecords
413 =over 4
415 my ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored) =
416 BatchCommitBibRecords($batch_id, $progress_interval, $progress_callback);
418 =back
420 =cut
422 sub BatchCommitBibRecords {
423 my $batch_id = shift;
425 # optional callback to monitor status
426 # of job
427 my $progress_interval = 0;
428 my $progress_callback = undef;
429 if ($#_ == 1) {
430 $progress_interval = shift;
431 $progress_callback = shift;
432 $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
433 $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
436 my $num_added = 0;
437 my $num_updated = 0;
438 my $num_items_added = 0;
439 my $num_items_errored = 0;
440 my $num_ignored = 0;
441 # commit (i.e., save, all records in the batch)
442 # FIXME biblio only at the moment
443 SetImportBatchStatus('importing');
444 my $overlay_action = GetImportBatchOverlayAction($batch_id);
445 my $dbh = C4::Context->dbh;
446 my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marc, encoding
447 FROM import_records
448 JOIN import_biblios USING (import_record_id)
449 WHERE import_batch_id = ?");
450 $sth->execute($batch_id);
451 my $rec_num = 0;
452 while (my $rowref = $sth->fetchrow_hashref) {
453 $rec_num++;
454 if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
455 &$progress_callback($rec_num);
457 if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'imported') {
458 $num_ignored++;
460 my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
461 if ($overlay_action eq 'create_new' or
462 ($overlay_action eq 'replace' and $rowref->{'overlay_status'} eq 'no_match')) {
463 $num_added++;
464 my ($biblionumber, $biblioitemnumber) = AddBiblio($marc_record, '');
465 my $sth = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
466 $sth->execute($biblionumber, $rowref->{'import_record_id'});
467 $sth->finish();
468 my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
469 $num_items_added += $bib_items_added;
470 $num_items_errored += $bib_items_errored;
471 SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
472 } else {
473 $num_updated++;
474 my $biblionumber = GetBestRecordMatch($rowref->{'import_record_id'});
475 my ($count, $oldbiblio) = GetBiblio($biblionumber);
476 my $oldxml = GetXmlBiblio($biblionumber);
478 # remove item fields so that they don't get
479 # added again if record is reverted
480 my $old_marc = MARC::Record->new_from_xml($oldxml, 'UTF-8', $rowref->{'encoding'});
481 my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",'');
482 foreach my $item_field ($old_marc->field($item_tag)) {
483 $old_marc->delete_field($item_field);
486 ModBiblio($marc_record, $biblionumber, $oldbiblio->{'frameworkcode'});
487 my $sth = $dbh->prepare_cached("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?");
488 $sth->execute($old_marc->as_xml(), $rowref->{'import_record_id'});
489 $sth->finish();
490 my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
491 $sth2->execute($biblionumber, $rowref->{'import_record_id'});
492 $sth2->finish();
493 my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
494 $num_items_added += $bib_items_added;
495 $num_items_errored += $bib_items_errored;
496 SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied');
497 SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
500 $sth->finish();
501 SetImportBatchStatus($batch_id, 'imported');
502 return ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored);
505 =head2 BatchCommitItems
507 =over 4
509 ($num_items_added, $num_items_errored) = BatchCommitItems($import_record_id, $biblionumber);
511 =back
513 =cut
515 sub BatchCommitItems {
516 my ($import_record_id, $biblionumber) = @_;
518 my $dbh = C4::Context->dbh;
520 my $num_items_added = 0;
521 my $num_items_errored = 0;
522 my $sth = $dbh->prepare("SELECT import_items_id, import_items.marcxml, encoding
523 FROM import_items
524 JOIN import_records USING (import_record_id)
525 WHERE import_record_id = ?
526 ORDER BY import_items_id");
527 $sth->bind_param(1, $import_record_id);
528 $sth->execute();
529 while (my $row = $sth->fetchrow_hashref()) {
530 my $item_marc = MARC::Record->new_from_xml($row->{'marcxml'}, 'UTF-8', $row->{'encoding'});
531 # FIXME - duplicate barcode check needs to become part of AddItem()
532 my $item = TransformMarcToKoha($dbh, $item_marc);
533 my $duplicate_barcode = exists($item->{'barcode'}) && GetItemnumberFromBarcode($item->{'barcode'});
534 if ($duplicate_barcode) {
535 my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, import_error = ? WHERE import_items_id = ?");
536 $updsth->bind_param(1, 'error');
537 $updsth->bind_param(2, 'duplicate item barcode');
538 $updsth->bind_param(3, $row->{'import_items_id'});
539 $updsth->execute();
540 $num_items_errored++;
541 } else {
542 my ($item_biblionumber, $biblioitemnumber, $itemnumber) = AddItem($item_marc, $biblionumber);
543 my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, itemnumber = ? WHERE import_items_id = ?");
544 $updsth->bind_param(1, 'imported');
545 $updsth->bind_param(2, $itemnumber);
546 $updsth->bind_param(3, $row->{'import_items_id'});
547 $updsth->execute();
548 $updsth->finish();
549 $num_items_added++;
552 $sth->finish();
553 return ($num_items_added, $num_items_errored);
556 =head2 BatchRevertBibRecords
558 =over 4
560 my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored) = BatchRevertBibRecords($batch_id);
562 =back
564 =cut
566 sub BatchRevertBibRecords {
567 my $batch_id = shift;
569 my $num_deleted = 0;
570 my $num_errors = 0;
571 my $num_reverted = 0;
572 my $num_items_deleted = 0;
573 my $num_ignored = 0;
574 # commit (i.e., save, all records in the batch)
575 # FIXME biblio only at the moment
576 SetImportBatchStatus('reverting');
577 my $overlay_action = GetImportBatchOverlayAction($batch_id);
578 my $dbh = C4::Context->dbh;
579 my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marcxml_old, encoding, matched_biblionumber
580 FROM import_records
581 JOIN import_biblios USING (import_record_id)
582 WHERE import_batch_id = ?");
583 $sth->execute($batch_id);
584 while (my $rowref = $sth->fetchrow_hashref) {
585 if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'reverted') {
586 $num_ignored++;
588 if ($overlay_action eq 'create_new' or
589 ($overlay_action eq 'replace' and $rowref->{'overlay_status'} eq 'no_match')) {
590 $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
591 my $error = DelBiblio($rowref->{'matched_biblionumber'});
592 if (defined $error) {
593 $num_errors++;
594 } else {
595 $num_deleted++;
596 SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
598 } else {
599 $num_reverted++;
600 my $old_record = MARC::Record->new_from_xml($rowref->{'marcxml_old'}, 'UTF-8', $rowref->{'encoding'});
601 my $biblionumber = $rowref->{'matched_biblionumber'};
602 my ($count, $oldbiblio) = GetBiblio($biblionumber);
603 $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
604 ModBiblio($old_record, $biblionumber, $oldbiblio->{'frameworkcode'});
605 SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
608 $sth->finish();
609 SetImportBatchStatus($batch_id, 'reverted');
610 return ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored);
613 =head2 BatchRevertItems
615 =over 4
617 my $num_items_deleted = BatchRevertItems($import_record_id, $biblionumber);
619 =back
621 =cut
623 sub BatchRevertItems {
624 my ($import_record_id, $biblionumber) = @_;
626 my $dbh = C4::Context->dbh;
627 my $num_items_deleted = 0;
629 my $sth = $dbh->prepare_cached("SELECT import_items_id, itemnumber
630 FROM import_items
631 JOIN items USING (itemnumber)
632 WHERE import_record_id = ?");
633 $sth->bind_param(1, $import_record_id);
634 $sth->execute();
635 while (my $row = $sth->fetchrow_hashref()) {
636 DelItem($dbh, $biblionumber, $row->{'itemnumber'});
637 my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
638 $updsth->bind_param(1, 'reverted');
639 $updsth->bind_param(2, $row->{'import_items_id'});
640 $updsth->execute();
641 $updsth->finish();
642 $num_items_deleted++;
644 $sth->finish();
645 return $num_items_deleted;
648 =head2 GetAllImportBatches
650 =over 4
652 my $results = GetAllImportBatches();
654 =back
656 Returns a references to an array of hash references corresponding
657 to all import_batches rows (of batch_type 'batch'), sorted in
658 ascending order by import_batch_id.
660 =cut
662 sub GetAllImportBatches {
663 my $dbh = C4::Context->dbh;
664 my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
665 WHERE batch_type = 'batch'
666 ORDER BY import_batch_id ASC");
668 my $results = [];
669 $sth->execute();
670 while (my $row = $sth->fetchrow_hashref) {
671 push @$results, $row;
673 $sth->finish();
674 return $results;
677 =head2 GetImportBatchRangeDesc
679 =over 4
681 my $results = GetImportBatchRangeDesc($offset, $results_per_group);
683 =back
685 Returns a reference to an array of hash references corresponding to
686 import_batches rows (sorted in descending order by import_batch_id)
687 start at the given offset.
689 =cut
691 sub GetImportBatchRangeDesc {
692 my ($offset, $results_per_group) = @_;
694 my $dbh = C4::Context->dbh;
695 my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
696 WHERE batch_type = 'batch'
697 ORDER BY import_batch_id DESC
698 LIMIT ? OFFSET ?");
699 $sth->bind_param(1, $results_per_group);
700 $sth->bind_param(2, $offset);
702 my $results = [];
703 $sth->execute();
704 while (my $row = $sth->fetchrow_hashref) {
705 push @$results, $row;
707 $sth->finish();
708 return $results;
711 =head2 GetNumberOfImportBatches
713 =over 4
715 my $count = GetNumberOfImportBatches();
717 =back
719 =cut
721 sub GetNumberOfNonZ3950ImportBatches {
722 my $dbh = C4::Context->dbh;
723 my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type='batch'");
724 $sth->execute();
725 my ($count) = $sth->fetchrow_array();
726 $sth->finish();
727 return $count;
730 =head2 GetImportBibliosRange
732 =over 4
734 my $results = GetImportBibliosRange($batch_id, $offset, $results_per_group);
736 =back
738 Returns a reference to an array of hash references corresponding to
739 import_biblios/import_records rows for a given batch
740 starting at the given offset.
742 =cut
744 sub GetImportBibliosRange {
745 my ($batch_id, $offset, $results_per_group) = @_;
747 my $dbh = C4::Context->dbh;
748 my $sth = $dbh->prepare_cached("SELECT title, author, isbn, issn, import_record_id, record_sequence,
749 status, overlay_status
750 FROM import_records
751 JOIN import_biblios USING (import_record_id)
752 WHERE import_batch_id = ?
753 ORDER BY import_record_id LIMIT ? OFFSET ?");
754 $sth->bind_param(1, $batch_id);
755 $sth->bind_param(2, $results_per_group);
756 $sth->bind_param(3, $offset);
757 my $results = [];
758 $sth->execute();
759 while (my $row = $sth->fetchrow_hashref) {
760 push @$results, $row;
762 $sth->finish();
763 return $results;
767 =head2 GetBestRecordMatch
769 =over 4
771 my $record_id = GetBestRecordMatch($import_record_id);
773 =back
775 =cut
777 sub GetBestRecordMatch {
778 my ($import_record_id) = @_;
780 my $dbh = C4::Context->dbh;
781 my $sth = $dbh->prepare("SELECT candidate_match_id
782 FROM import_record_matches
783 WHERE import_record_id = ?
784 ORDER BY score DESC, candidate_match_id DESC");
785 $sth->execute($import_record_id);
786 my ($record_id) = $sth->fetchrow_array();
787 $sth->finish();
788 return $record_id;
791 =head2 GetImportBatchStatus
793 =over 4
795 my $status = GetImportBatchStatus($batch_id);
797 =back
799 =cut
801 sub GetImportBatchStatus {
802 my ($batch_id) = @_;
804 my $dbh = C4::Context->dbh;
805 my $sth = $dbh->prepare("SELECT import_status FROM import_batches WHERE batch_id = ?");
806 $sth->execute($batch_id);
807 my ($status) = $sth->fetchrow_array();
808 $sth->finish();
809 return;
814 =head2 SetImportBatchStatus
816 =over 4
818 SetImportBatchStatus($batch_id, $new_status);
820 =back
822 =cut
824 sub SetImportBatchStatus {
825 my ($batch_id, $new_status) = @_;
827 my $dbh = C4::Context->dbh;
828 my $sth = $dbh->prepare("UPDATE import_batches SET import_status = ? WHERE import_batch_id = ?");
829 $sth->execute($new_status, $batch_id);
830 $sth->finish();
834 =head2 GetImportBatchOverlayAction
836 =over 4
838 my $overlay_action = GetImportBatchOverlayAction($batch_id);
840 =back
842 =cut
844 sub GetImportBatchOverlayAction {
845 my ($batch_id) = @_;
847 my $dbh = C4::Context->dbh;
848 my $sth = $dbh->prepare("SELECT overlay_action FROM import_batches WHERE import_batch_id = ?");
849 $sth->execute($batch_id);
850 my ($overlay_action) = $sth->fetchrow_array();
851 $sth->finish();
852 return $overlay_action;
857 =head2 SetImportBatchOverlayAction
859 =over 4
861 SetImportBatchOverlayAction($batch_id, $new_overlay_action);
863 =back
865 =cut
867 sub SetImportBatchOverlayAction {
868 my ($batch_id, $new_overlay_action) = @_;
870 my $dbh = C4::Context->dbh;
871 my $sth = $dbh->prepare("UPDATE import_batches SET overlay_action = ? WHERE import_batch_id = ?");
872 $sth->execute($new_overlay_action, $batch_id);
873 $sth->finish();
877 =head2 GetImportBatchMatcher
879 =over 4
881 my $matcher_id = GetImportBatchMatcher($batch_id);
883 =back
885 =cut
887 sub GetImportBatchMatcher {
888 my ($batch_id) = @_;
890 my $dbh = C4::Context->dbh;
891 my $sth = $dbh->prepare("SELECT matcher_id FROM import_batches WHERE import_batch_id = ?");
892 $sth->execute($batch_id);
893 my ($matcher_id) = $sth->fetchrow_array();
894 $sth->finish();
895 return $matcher_id;
900 =head2 SetImportBatchMatcher
902 =over 4
904 SetImportBatchMatcher($batch_id, $new_matcher_id);
906 =back
908 =cut
910 sub SetImportBatchMatcher {
911 my ($batch_id, $new_matcher_id) = @_;
913 my $dbh = C4::Context->dbh;
914 my $sth = $dbh->prepare("UPDATE import_batches SET matcher_id = ? WHERE import_batch_id = ?");
915 $sth->execute($new_matcher_id, $batch_id);
916 $sth->finish();
920 =head2 GetImportRecordOverlayStatus
922 =over 4
924 my $overlay_status = GetImportRecordOverlayStatus($import_record_id);
926 =back
928 =cut
930 sub GetImportRecordOverlayStatus {
931 my ($import_record_id) = @_;
933 my $dbh = C4::Context->dbh;
934 my $sth = $dbh->prepare("SELECT overlay_status FROM import_records WHERE import_record_id = ?");
935 $sth->execute($import_record_id);
936 my ($overlay_status) = $sth->fetchrow_array();
937 $sth->finish();
938 return $overlay_status;
943 =head2 SetImportRecordOverlayStatus
945 =over 4
947 SetImportRecordOverlayStatus($import_record_id, $new_overlay_status);
949 =back
951 =cut
953 sub SetImportRecordOverlayStatus {
954 my ($import_record_id, $new_overlay_status) = @_;
956 my $dbh = C4::Context->dbh;
957 my $sth = $dbh->prepare("UPDATE import_records SET overlay_status = ? WHERE import_record_id = ?");
958 $sth->execute($new_overlay_status, $import_record_id);
959 $sth->finish();
963 =head2 GetImportRecordStatus
965 =over 4
967 my $overlay_status = GetImportRecordStatus($import_record_id);
969 =back
971 =cut
973 sub GetImportRecordStatus {
974 my ($import_record_id) = @_;
976 my $dbh = C4::Context->dbh;
977 my $sth = $dbh->prepare("SELECT status FROM import_records WHERE import_record_id = ?");
978 $sth->execute($import_record_id);
979 my ($overlay_status) = $sth->fetchrow_array();
980 $sth->finish();
981 return $overlay_status;
986 =head2 SetImportRecordStatus
988 =over 4
990 SetImportRecordStatus($import_record_id, $new_overlay_status);
992 =back
994 =cut
996 sub SetImportRecordStatus {
997 my ($import_record_id, $new_overlay_status) = @_;
999 my $dbh = C4::Context->dbh;
1000 my $sth = $dbh->prepare("UPDATE import_records SET status = ? WHERE import_record_id = ?");
1001 $sth->execute($new_overlay_status, $import_record_id);
1002 $sth->finish();
1006 =head2 GetImportRecordMatches
1008 =over 4
1010 my $results = GetImportRecordMatches($import_record_id, $best_only);
1012 =back
1014 =cut
1016 sub GetImportRecordMatches {
1017 my $import_record_id = shift;
1018 my $best_only = @_ ? shift : 0;
1020 my $dbh = C4::Context->dbh;
1021 # FIXME currently biblio only
1022 my $sth = $dbh->prepare_cached("SELECT title, author, biblionumber, score
1023 FROM import_records
1024 JOIN import_record_matches USING (import_record_id)
1025 JOIN biblio ON (biblionumber = candidate_match_id)
1026 WHERE import_record_id = ?
1027 ORDER BY score DESC, biblionumber DESC");
1028 $sth->bind_param(1, $import_record_id);
1029 my $results = [];
1030 $sth->execute();
1031 while (my $row = $sth->fetchrow_hashref) {
1032 push @$results, $row;
1033 last if $best_only;
1035 $sth->finish();
1037 return $results;
1042 =head2 SetImportRecordMatches
1044 =over 4
1046 SetImportRecordMatches($import_record_id, @matches);
1048 =back
1050 =cut
1052 sub SetImportRecordMatches {
1053 my $import_record_id = shift;
1054 my @matches = @_;
1056 my $dbh = C4::Context->dbh;
1057 my $delsth = $dbh->prepare("DELETE FROM import_record_matches WHERE import_record_id = ?");
1058 $delsth->execute($import_record_id);
1059 $delsth->finish();
1061 my $sth = $dbh->prepare("INSERT INTO import_record_matches (import_record_id, candidate_match_id, score)
1062 VALUES (?, ?, ?)");
1063 foreach my $match (@matches) {
1064 $sth->execute($import_record_id, $match->{'record_id'}, $match->{'score'});
1069 # internal functions
1071 sub _create_import_record {
1072 my ($batch_id, $record_sequence, $marc_record, $record_type, $encoding, $z3950random) = @_;
1074 my $dbh = C4::Context->dbh;
1075 my $sth = $dbh->prepare("INSERT INTO import_records (import_batch_id, record_sequence, marc, marcxml,
1076 record_type, encoding, z3950random)
1077 VALUES (?, ?, ?, ?, ?, ?, ?)");
1078 $sth->execute($batch_id, $record_sequence, $marc_record->as_usmarc(), $marc_record->as_xml(),
1079 $record_type, $encoding, $z3950random);
1080 my $import_record_id = $dbh->{'mysql_insertid'};
1081 $sth->finish();
1082 return $import_record_id;
1085 sub _update_import_record_marc {
1086 my ($import_record_id, $marc_record) = @_;
1088 my $dbh = C4::Context->dbh;
1089 my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ?
1090 WHERE import_record_id = ?");
1091 $sth->execute($marc_record->as_usmarc(), $marc_record->as_xml(), $import_record_id);
1092 $sth->finish();
1095 sub _add_biblio_fields {
1096 my ($import_record_id, $marc_record) = @_;
1098 my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
1099 my $dbh = C4::Context->dbh;
1100 # FIXME no controlnumber, originalsource
1101 # FIXME 2 - should regularize normalization of ISBN wherever it is done
1102 $isbn =~ s/\(.*$//;
1103 $isbn =~ tr/ -_//;
1104 $isbn = uc $isbn;
1105 my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn) VALUES (?, ?, ?, ?, ?)");
1106 $sth->execute($import_record_id, $title, $author, $isbn, $issn);
1107 $sth->finish();
1111 sub _update_biblio_fields {
1112 my ($import_record_id, $marc_record) = @_;
1114 my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
1115 my $dbh = C4::Context->dbh;
1116 # FIXME no controlnumber, originalsource
1117 # FIXME 2 - should regularize normalization of ISBN wherever it is done
1118 $isbn =~ s/\(.*$//;
1119 $isbn =~ tr/ -_//;
1120 $isbn = uc $isbn;
1121 my $sth = $dbh->prepare("UPDATE import_biblios SET title = ?, author = ?, isbn = ?, issn = ?
1122 WHERE import_record_id = ?");
1123 $sth->execute($title, $author, $isbn, $issn, $import_record_id);
1124 $sth->finish();
1127 sub _parse_biblio_fields {
1128 my ($marc_record) = @_;
1130 my $dbh = C4::Context->dbh;
1131 my $bibliofields = TransformMarcToKoha($dbh, $marc_record, '');
1132 return ($bibliofields->{'title'}, $bibliofields->{'author'}, $bibliofields->{'isbn'}, $bibliofields->{'issn'});
1136 sub _update_batch_record_counts {
1137 my ($batch_id) = @_;
1139 my $dbh = C4::Context->dbh;
1140 my $sth = $dbh->prepare_cached("UPDATE import_batches SET num_biblios = (
1141 SELECT COUNT(*)
1142 FROM import_records
1143 WHERE import_batch_id = import_batches.import_batch_id
1144 AND record_type = 'biblio')
1145 WHERE import_batch_id = ?");
1146 $sth->bind_param(1, $batch_id);
1147 $sth->execute();
1148 $sth->finish();
1149 $sth = $dbh->prepare_cached("UPDATE import_batches SET num_items = (
1150 SELECT COUNT(*)
1151 FROM import_records
1152 JOIN import_items USING (import_record_id)
1153 WHERE import_batch_id = import_batches.import_batch_id
1154 AND record_type = 'biblio')
1155 WHERE import_batch_id = ?");
1156 $sth->bind_param(1, $batch_id);
1157 $sth->execute();
1158 $sth->finish();
1164 =head1 AUTHOR
1166 Koha Development Team <info@koha.org>
1168 Galen Charlton <galen.charlton@liblime.com>
1170 =cut