Bug 7936: Label Help Files
[koha.git] / C4 / ImportBatch.pm
1 package C4::ImportBatch;
2
3 # Copyright (C) 2007 LibLime
4 #
5 # This file is part of Koha.
6 #
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.
11 #
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.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 use strict;
21 use warnings;
22
23 use C4::Context;
24 use C4::Koha;
25 use C4::Biblio;
26 use C4::Items;
27 use C4::Charset;
28
29 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
30
31 BEGIN {
32         # set the version for version checking
33         $VERSION = 3.01;
34         require Exporter;
35         @ISA    = qw(Exporter);
36         @EXPORT = qw(
37     GetZ3950BatchId
38     GetWebserviceBatchId
39     GetImportRecordMarc
40     GetImportRecordMarcXML
41     AddImportBatch
42     GetImportBatch
43     AddBiblioToBatch
44     AddItemsToImportBiblio
45     ModBiblioInBatch
46
47     BatchStageMarcRecords
48     BatchFindBibDuplicates
49     BatchCommitBibRecords
50     BatchRevertBibRecords
51     CleanBatch
52
53     GetAllImportBatches
54     GetStagedWebserviceBatches
55     GetImportBatchRangeDesc
56     GetNumberOfNonZ3950ImportBatches
57     GetImportBibliosRange
58         GetItemNumbersFromImportBatch
59     
60     GetImportBatchStatus
61     SetImportBatchStatus
62     GetImportBatchOverlayAction
63     SetImportBatchOverlayAction
64     GetImportBatchNoMatchAction
65     SetImportBatchNoMatchAction
66     GetImportBatchItemAction
67     SetImportBatchItemAction
68     GetImportBatchMatcher
69     SetImportBatchMatcher
70     GetImportRecordOverlayStatus
71     SetImportRecordOverlayStatus
72     GetImportRecordStatus
73     SetImportRecordStatus
74     GetImportRecordMatches
75     SetImportRecordMatches
76         );
77 }
78
79 =head1 NAME
80
81 C4::ImportBatch - manage batches of imported MARC records
82
83 =head1 SYNOPSIS
84
85 use C4::ImportBatch;
86
87 =head1 FUNCTIONS
88
89 =head2 GetZ3950BatchId
90
91   my $batchid = GetZ3950BatchId($z3950server);
92
93 Retrieves the ID of the import batch for the Z39.50
94 reservoir for the given target.  If necessary,
95 creates the import batch.
96
97 =cut
98
99 sub GetZ3950BatchId {
100     my ($z3950server) = @_;
101
102     my $dbh = C4::Context->dbh;
103     my $sth = $dbh->prepare("SELECT import_batch_id FROM import_batches
104                              WHERE  batch_type = 'z3950'
105                              AND    file_name = ?");
106     $sth->execute($z3950server);
107     my $rowref = $sth->fetchrow_arrayref();
108     $sth->finish();
109     if (defined $rowref) {
110         return $rowref->[0];
111     } else {
112         my $batch_id = AddImportBatch( {
113                 overlay_action => 'create_new',
114                 import_status => 'staged',
115                 batch_type => 'z3950',
116                 file_name => $z3950server,
117             } );
118         return $batch_id;
119     }
120     
121 }
122
123 =head2 GetWebserviceBatchId
124
125   my $batchid = GetWebserviceBatchId();
126
127 Retrieves the ID of the import batch for webservice.
128 If necessary, creates the import batch.
129
130 =cut
131
132 my $WEBSERVICE_BASE_QRY = <<EOQ;
133 SELECT import_batch_id FROM import_batches
134 WHERE  batch_type = 'webservice'
135 AND    import_status = 'staged'
136 EOQ
137 sub GetWebserviceBatchId {
138     my ($params) = @_;
139
140     my $dbh = C4::Context->dbh;
141     my $sql = $WEBSERVICE_BASE_QRY;
142     my @args;
143     foreach my $field (qw(matcher_id overlay_action nomatch_action item_action)) {
144         if (my $val = $params->{$field}) {
145             $sql .= " AND $field = ?";
146             push @args, $val;
147         }
148     }
149     my $id = $dbh->selectrow_array($sql, undef, @args);
150     return $id if $id;
151
152     $params->{batch_type} = 'webservice';
153     $params->{import_status} = 'staged';
154     return AddImportBatch($params);
155 }
156
157 =head2 GetImportRecordMarc
158
159   my ($marcblob, $encoding) = GetImportRecordMarc($import_record_id);
160
161 =cut
162
163 sub GetImportRecordMarc {
164     my ($import_record_id) = @_;
165
166     my $dbh = C4::Context->dbh;
167     my $sth = $dbh->prepare("SELECT marc, encoding FROM import_records WHERE import_record_id = ?");
168     $sth->execute($import_record_id);
169     my ($marc, $encoding) = $sth->fetchrow();
170     $sth->finish();
171     return $marc, $encoding;
172
173 }
174
175 =head2 GetImportRecordMarcXML
176
177   my $marcxml = GetImportRecordMarcXML($import_record_id);
178
179 =cut
180
181 sub GetImportRecordMarcXML {
182     my ($import_record_id) = @_;
183
184     my $dbh = C4::Context->dbh;
185     my $sth = $dbh->prepare("SELECT marcxml FROM import_records WHERE import_record_id = ?");
186     $sth->execute($import_record_id);
187     my ($marcxml) = $sth->fetchrow();
188     $sth->finish();
189     return $marcxml;
190
191 }
192
193 =head2 AddImportBatch
194
195   my $batch_id = AddImportBatch($params_hash);
196
197 =cut
198
199 sub AddImportBatch {
200     my ($params) = @_;
201
202     my (@fields, @vals);
203     foreach (qw( matcher_id template_id branchcode
204                  overlay_action nomatch_action item_action
205                  import_status batch_type file_name comments )) {
206         if (exists $params->{$_}) {
207             push @fields, $_;
208             push @vals, $params->{$_};
209         }
210     }
211     my $dbh = C4::Context->dbh;
212     $dbh->do("INSERT INTO import_batches (".join( ',', @fields).")
213                                   VALUES (".join( ',', map '?', @fields).")",
214              undef,
215              @vals);
216     return $dbh->{'mysql_insertid'};
217 }
218
219 =head2 GetImportBatch 
220
221   my $row = GetImportBatch($batch_id);
222
223 Retrieve a hashref of an import_batches row.
224
225 =cut
226
227 sub GetImportBatch {
228     my ($batch_id) = @_;
229
230     my $dbh = C4::Context->dbh;
231     my $sth = $dbh->prepare_cached("SELECT * FROM import_batches WHERE import_batch_id = ?");
232     $sth->bind_param(1, $batch_id);
233     $sth->execute();
234     my $result = $sth->fetchrow_hashref;
235     $sth->finish();
236     return $result;
237
238 }
239
240 =head2 AddBiblioToBatch 
241
242   my $import_record_id = AddBiblioToBatch($batch_id, $record_sequence, 
243                 $marc_record, $encoding, $z3950random, $update_counts);
244
245 =cut
246
247 sub AddBiblioToBatch {
248     my $batch_id = shift;
249     my $record_sequence = shift;
250     my $marc_record = shift;
251     my $encoding = shift;
252     my $z3950random = shift;
253     my $update_counts = @_ ? shift : 1;
254
255     my $import_record_id = _create_import_record($batch_id, $record_sequence, $marc_record, 'biblio', $encoding, $z3950random);
256     _add_biblio_fields($import_record_id, $marc_record);
257     _update_batch_record_counts($batch_id) if $update_counts;
258     return $import_record_id;
259 }
260
261 =head2 ModBiblioInBatch
262
263   ModBiblioInBatch($import_record_id, $marc_record);
264
265 =cut
266
267 sub ModBiblioInBatch {
268     my ($import_record_id, $marc_record) = @_;
269
270     _update_import_record_marc($import_record_id, $marc_record);
271     _update_biblio_fields($import_record_id, $marc_record);
272
273 }
274
275 =head2 BatchStageMarcRecords
276
277   ($batch_id, $num_records, $num_items, @invalid_records) = 
278     BatchStageMarcRecords($encoding, $marc_records, $file_name, 
279                           $comments, $branch_code, $parse_items,
280                           $leave_as_staging, 
281                           $progress_interval, $progress_callback);
282
283 =cut
284
285 sub  BatchStageMarcRecords {
286     my $encoding = shift;
287     my $marc_records = shift;
288     my $file_name = shift;
289     my $comments = shift;
290     my $branch_code = shift;
291     my $parse_items = shift;
292     my $leave_as_staging = shift;
293    
294     # optional callback to monitor status 
295     # of job
296     my $progress_interval = 0;
297     my $progress_callback = undef;
298     if ($#_ == 1) {
299         $progress_interval = shift;
300         $progress_callback = shift;
301         $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
302         $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
303     } 
304     
305     my $batch_id = AddImportBatch( {
306             overlay_action => 'create_new',
307             import_status => 'staging',
308             batch_type => 'batch',
309             file_name => $file_name,
310             comments => $comments,
311         } );
312     if ($parse_items) {
313         SetImportBatchItemAction($batch_id, 'always_add');
314     } else {
315         SetImportBatchItemAction($batch_id, 'ignore');
316     }
317
318     my @invalid_records = ();
319     my $num_valid = 0;
320     my $num_items = 0;
321     # FIXME - for now, we're dealing only with bibs
322     my $rec_num = 0;
323     foreach my $marc_blob (split(/\x1D/, $marc_records)) {
324         $marc_blob =~ s/^\s+//g;
325         $marc_blob =~ s/\s+$//g;
326         next unless $marc_blob;
327         $rec_num++;
328         if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
329             &$progress_callback($rec_num);
330         }
331         my ($marc_record, $charset_guessed, $char_errors) =
332             MarcToUTF8Record($marc_blob, C4::Context->preference("marcflavour"), $encoding);
333
334         $encoding = $charset_guessed unless $encoding;
335
336         my $import_record_id;
337         if (scalar($marc_record->fields()) == 0) {
338             push @invalid_records, $marc_blob;
339         } else {
340             $num_valid++;
341             $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0);
342             if ($parse_items) {
343                 my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 0);
344                 $num_items += scalar(@import_items_ids);
345             }
346         }
347     }
348     unless ($leave_as_staging) {
349         SetImportBatchStatus($batch_id, 'staged');
350     }
351     # FIXME branch_code, number of bibs, number of items
352     _update_batch_record_counts($batch_id);
353     return ($batch_id, $num_valid, $num_items, @invalid_records);
354 }
355
356 =head2 AddItemsToImportBiblio
357
358   my @import_items_ids = AddItemsToImportBiblio($batch_id, 
359                 $import_record_id, $marc_record, $update_counts);
360
361 =cut
362
363 sub AddItemsToImportBiblio {
364     my $batch_id = shift;
365     my $import_record_id = shift;
366     my $marc_record = shift;
367     my $update_counts = @_ ? shift : 0;
368
369     my @import_items_ids = ();
370    
371     my $dbh = C4::Context->dbh; 
372     my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",'');
373     foreach my $item_field ($marc_record->field($item_tag)) {
374         my $item_marc = MARC::Record->new();
375         $item_marc->leader("00000    a              "); # must set Leader/09 to 'a'
376         $item_marc->append_fields($item_field);
377         $marc_record->delete_field($item_field);
378         my $sth = $dbh->prepare_cached("INSERT INTO import_items (import_record_id, status, marcxml)
379                                         VALUES (?, ?, ?)");
380         $sth->bind_param(1, $import_record_id);
381         $sth->bind_param(2, 'staged');
382         $sth->bind_param(3, $item_marc->as_xml());
383         $sth->execute();
384         push @import_items_ids, $dbh->{'mysql_insertid'};
385         $sth->finish();
386     }
387
388     if ($#import_items_ids > -1) {
389         _update_batch_record_counts($batch_id) if $update_counts;
390         _update_import_record_marc($import_record_id, $marc_record);
391     }
392     return @import_items_ids;
393 }
394
395 =head2 BatchFindBibDuplicates
396
397   my $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher, 
398              $max_matches, $progress_interval, $progress_callback);
399
400 Goes through the records loaded in the batch and attempts to 
401 find duplicates for each one.  Sets the matching status 
402 of each record to "no_match" or "auto_match" as appropriate.
403
404 The $max_matches parameter is optional; if it is not supplied,
405 it defaults to 10.
406
407 The $progress_interval and $progress_callback parameters are 
408 optional; if both are supplied, the sub referred to by
409 $progress_callback will be invoked every $progress_interval
410 records using the number of records processed as the 
411 singular argument.
412
413 =cut
414
415 sub BatchFindBibDuplicates {
416     my $batch_id = shift;
417     my $matcher = shift;
418     my $max_matches = @_ ? shift : 10;
419
420     # optional callback to monitor status 
421     # of job
422     my $progress_interval = 0;
423     my $progress_callback = undef;
424     if ($#_ == 1) {
425         $progress_interval = shift;
426         $progress_callback = shift;
427         $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
428         $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
429     }
430
431     my $dbh = C4::Context->dbh;
432
433     my $sth = $dbh->prepare("SELECT import_record_id, marc
434                              FROM import_records
435                              JOIN import_biblios USING (import_record_id)
436                              WHERE import_batch_id = ?");
437     $sth->execute($batch_id);
438     my $num_with_matches = 0;
439     my $rec_num = 0;
440     while (my $rowref = $sth->fetchrow_hashref) {
441         $rec_num++;
442         if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
443             &$progress_callback($rec_num);
444         }
445         my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
446         my @matches = ();
447         if (defined $matcher) {
448             @matches = $matcher->get_matches($marc_record, $max_matches);
449         }
450         if (scalar(@matches) > 0) {
451             $num_with_matches++;
452             SetImportRecordMatches($rowref->{'import_record_id'}, @matches);
453             SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'auto_match');
454         } else {
455             SetImportRecordMatches($rowref->{'import_record_id'}, ());
456             SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'no_match');
457         }
458     }
459     $sth->finish();
460     return $num_with_matches;
461 }
462
463 =head2 BatchCommitBibRecords
464
465   my ($num_added, $num_updated, $num_items_added, $num_items_errored, 
466       $num_ignored) = BatchCommitBibRecords($batch_id, $framework,
467                       $progress_interval, $progress_callback);
468
469 =cut
470
471 sub BatchCommitBibRecords {
472     my $batch_id = shift;
473     my $framework = shift;
474
475     # optional callback to monitor status 
476     # of job
477     my $progress_interval = 0;
478     my $progress_callback = undef;
479     if ($#_ == 1) {
480         $progress_interval = shift;
481         $progress_callback = shift;
482         $progress_interval = 0 unless $progress_interval =~ /^\d+$/ and $progress_interval > 0;
483         $progress_interval = 0 unless 'CODE' eq ref $progress_callback;
484     }
485
486     my $num_added = 0;
487     my $num_updated = 0;
488     my $num_items_added = 0;
489     my $num_items_errored = 0;
490     my $num_ignored = 0;
491     # commit (i.e., save, all records in the batch)
492     # FIXME biblio only at the moment
493     SetImportBatchStatus('importing');
494     my $overlay_action = GetImportBatchOverlayAction($batch_id);
495     my $nomatch_action = GetImportBatchNoMatchAction($batch_id);
496     my $item_action = GetImportBatchItemAction($batch_id);
497     my $dbh = C4::Context->dbh;
498     my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marc, encoding
499                              FROM import_records
500                              JOIN import_biblios USING (import_record_id)
501                              WHERE import_batch_id = ?");
502     $sth->execute($batch_id);
503     my $rec_num = 0;
504     while (my $rowref = $sth->fetchrow_hashref) {
505         $rec_num++;
506         if ($progress_interval and (0 == ($rec_num % $progress_interval))) {
507             &$progress_callback($rec_num);
508         }
509         if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'imported') {
510             $num_ignored++;
511             next;
512         }
513
514         my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'});
515
516         # remove any item tags - rely on BatchCommitItems
517         my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",'');
518         foreach my $item_field ($marc_record->field($item_tag)) {
519             $marc_record->delete_field($item_field);
520         }
521
522         # decide what what to do with the bib and item records
523         my ($bib_result, $item_result, $bib_match) = 
524             _get_commit_action($overlay_action, $nomatch_action, $item_action, 
525                                $rowref->{'overlay_status'}, $rowref->{'import_record_id'});
526
527         if ($bib_result eq 'create_new') {
528             $num_added++;
529             my ($biblionumber, $biblioitemnumber) = AddBiblio($marc_record, $framework);
530             my $sth = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
531             $sth->execute($biblionumber, $rowref->{'import_record_id'});
532             $sth->finish();
533             if ($item_result eq 'create_new') {
534                 my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
535                 $num_items_added += $bib_items_added;
536                 $num_items_errored += $bib_items_errored;
537             }
538             SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
539         } elsif ($bib_result eq 'replace') {
540             $num_updated++;
541             my $biblionumber = $bib_match;
542             my ($count, $oldbiblio) = GetBiblio($biblionumber);
543             my $oldxml = GetXmlBiblio($biblionumber);
544
545             # remove item fields so that they don't get
546             # added again if record is reverted
547             my $old_marc = MARC::Record->new_from_xml(StripNonXmlChars($oldxml), 'UTF-8', $rowref->{'encoding'});
548             foreach my $item_field ($old_marc->field($item_tag)) {
549                 $old_marc->delete_field($item_field);
550             }
551
552             ModBiblio($marc_record, $biblionumber, $oldbiblio->{'frameworkcode'});
553             my $sth = $dbh->prepare_cached("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?");
554             $sth->execute($old_marc->as_xml(), $rowref->{'import_record_id'});
555             $sth->finish();
556             my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
557             $sth2->execute($biblionumber, $rowref->{'import_record_id'});
558             $sth2->finish();
559             if ($item_result eq 'create_new') {
560                 my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
561                 $num_items_added += $bib_items_added;
562                 $num_items_errored += $bib_items_errored;
563             }
564             SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied');
565             SetImportRecordStatus($rowref->{'import_record_id'}, 'imported');
566         } elsif ($bib_result eq 'ignore') {
567             $num_ignored++;
568             my $biblionumber = $bib_match;
569             if (defined $biblionumber and $item_result eq 'create_new') {
570                 my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber);
571                 $num_items_added += $bib_items_added;
572                 $num_items_errored += $bib_items_errored;
573                 # still need to record the matched biblionumber so that the
574                 # items can be reverted
575                 my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?");
576                 $sth2->execute($biblionumber, $rowref->{'import_record_id'});
577                 SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied');
578             }
579             SetImportRecordStatus($rowref->{'import_record_id'}, 'ignored');
580         }
581     }
582     $sth->finish();
583     SetImportBatchStatus($batch_id, 'imported');
584     return ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored);
585 }
586
587 =head2 BatchCommitItems
588
589   ($num_items_added, $num_items_errored) = 
590          BatchCommitItems($import_record_id, $biblionumber);
591
592 =cut
593
594 sub BatchCommitItems {
595     my ($import_record_id, $biblionumber) = @_;
596
597     my $dbh = C4::Context->dbh;
598
599     my $num_items_added = 0;
600     my $num_items_errored = 0;
601     my $sth = $dbh->prepare("SELECT import_items_id, import_items.marcxml, encoding
602                              FROM import_items
603                              JOIN import_records USING (import_record_id)
604                              WHERE import_record_id = ?
605                              ORDER BY import_items_id");
606     $sth->bind_param(1, $import_record_id);
607     $sth->execute();
608     while (my $row = $sth->fetchrow_hashref()) {
609         my $item_marc = MARC::Record->new_from_xml(StripNonXmlChars($row->{'marcxml'}), 'UTF-8', $row->{'encoding'});
610         # FIXME - duplicate barcode check needs to become part of AddItemFromMarc()
611         my $item = TransformMarcToKoha($dbh, $item_marc);
612         my $duplicate_barcode = exists($item->{'barcode'}) && GetItemnumberFromBarcode($item->{'barcode'});
613         if ($duplicate_barcode) {
614             my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, import_error = ? WHERE import_items_id = ?");
615             $updsth->bind_param(1, 'error');
616             $updsth->bind_param(2, 'duplicate item barcode');
617             $updsth->bind_param(3, $row->{'import_items_id'});
618             $updsth->execute();
619             $num_items_errored++;
620         } else {
621             my ($item_biblionumber, $biblioitemnumber, $itemnumber) = AddItemFromMarc($item_marc, $biblionumber);
622             my $updsth = $dbh->prepare("UPDATE import_items SET status = ?, itemnumber = ? WHERE import_items_id = ?");
623             $updsth->bind_param(1, 'imported');
624             $updsth->bind_param(2, $itemnumber);
625             $updsth->bind_param(3, $row->{'import_items_id'});
626             $updsth->execute();
627             $updsth->finish();
628             $num_items_added++;
629         }
630     }
631     $sth->finish();
632     return ($num_items_added, $num_items_errored);
633 }
634
635 =head2 BatchRevertBibRecords
636
637   my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, 
638       $num_ignored) = BatchRevertBibRecords($batch_id);
639
640 =cut
641
642 sub BatchRevertBibRecords {
643     my $batch_id = shift;
644
645     my $num_deleted = 0;
646     my $num_errors = 0;
647     my $num_reverted = 0;
648     my $num_items_deleted = 0;
649     my $num_ignored = 0;
650     # commit (i.e., save, all records in the batch)
651     # FIXME biblio only at the moment
652     SetImportBatchStatus('reverting');
653     my $overlay_action = GetImportBatchOverlayAction($batch_id);
654     my $nomatch_action = GetImportBatchNoMatchAction($batch_id);
655     my $dbh = C4::Context->dbh;
656     my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marcxml_old, encoding, matched_biblionumber
657                              FROM import_records
658                              JOIN import_biblios USING (import_record_id)
659                              WHERE import_batch_id = ?");
660     $sth->execute($batch_id);
661     while (my $rowref = $sth->fetchrow_hashref) {
662         if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'reverted') {
663             $num_ignored++;
664             next;
665         }
666
667         my $bib_result = _get_revert_action($overlay_action, $rowref->{'overlay_status'}, $rowref->{'status'});
668
669         if ($bib_result eq 'delete') {
670             $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
671             my $error = DelBiblio($rowref->{'matched_biblionumber'});
672             if (defined $error) {
673                 $num_errors++;
674             } else {
675                 $num_deleted++;
676                 SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
677             }
678         } elsif ($bib_result eq 'restore') {
679             $num_reverted++;
680             my $old_record = MARC::Record->new_from_xml(StripNonXmlChars($rowref->{'marcxml_old'}), 'UTF-8', $rowref->{'encoding'});
681             my $biblionumber = $rowref->{'matched_biblionumber'};
682             my ($count, $oldbiblio) = GetBiblio($biblionumber);
683             $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
684             ModBiblio($old_record, $biblionumber, $oldbiblio->{'frameworkcode'});
685             SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
686         } elsif ($bib_result eq 'ignore') {
687             $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'});
688             SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted');
689         }
690         my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = NULL WHERE import_record_id = ?");
691         $sth2->execute($rowref->{'import_record_id'});
692     }
693
694     $sth->finish();
695     SetImportBatchStatus($batch_id, 'reverted');
696     return ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored);
697 }
698
699 =head2 BatchRevertItems
700
701   my $num_items_deleted = BatchRevertItems($import_record_id, $biblionumber);
702
703 =cut
704
705 sub BatchRevertItems {
706     my ($import_record_id, $biblionumber) = @_;
707
708     my $dbh = C4::Context->dbh;
709     my $num_items_deleted = 0;
710
711     my $sth = $dbh->prepare_cached("SELECT import_items_id, itemnumber
712                                    FROM import_items
713                                    JOIN items USING (itemnumber)
714                                    WHERE import_record_id = ?");
715     $sth->bind_param(1, $import_record_id);
716     $sth->execute();
717     while (my $row = $sth->fetchrow_hashref()) {
718         DelItem($dbh, $biblionumber, $row->{'itemnumber'});
719         my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
720         $updsth->bind_param(1, 'reverted');
721         $updsth->bind_param(2, $row->{'import_items_id'});
722         $updsth->execute();
723         $updsth->finish();
724         $num_items_deleted++;
725     }
726     $sth->finish();
727     return $num_items_deleted;
728 }
729
730 =head2 CleanBatch
731
732   CleanBatch($batch_id)
733
734 Deletes all staged records from the import batch
735 and sets the status of the batch to 'cleaned'.  Note
736 that deleting a stage record does *not* affect
737 any record that has been committed to the database.
738
739 =cut
740
741 sub CleanBatch {
742     my $batch_id = shift;
743     return unless defined $batch_id;
744
745     C4::Context->dbh->do('DELETE FROM import_records WHERE import_batch_id = ?', {}, $batch_id);
746     SetImportBatchStatus($batch_id, 'cleaned');
747 }
748
749 =head2 GetAllImportBatches
750
751   my $results = GetAllImportBatches();
752
753 Returns a references to an array of hash references corresponding
754 to all import_batches rows (of batch_type 'batch'), sorted in 
755 ascending order by import_batch_id.
756
757 =cut
758
759 sub  GetAllImportBatches {
760     my $dbh = C4::Context->dbh;
761     my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
762                                     WHERE batch_type IN ('batch', 'webservice')
763                                     ORDER BY import_batch_id ASC");
764
765     my $results = [];
766     $sth->execute();
767     while (my $row = $sth->fetchrow_hashref) {
768         push @$results, $row;
769     }
770     $sth->finish();
771     return $results;
772 }
773
774 =head2 GetStagedWebserviceBatches
775
776   my $batch_ids = GetStagedWebserviceBatches();
777
778 Returns a references to an array of batch id's
779 of batch_type 'webservice' that are not imported
780
781 =cut
782
783 my $PENDING_WEBSERVICE_BATCHES_QRY = <<EOQ;
784 SELECT import_batch_id FROM import_batches
785 WHERE batch_type = 'webservice'
786 AND import_status = 'staged'
787 EOQ
788 sub  GetStagedWebserviceBatches {
789     my $dbh = C4::Context->dbh;
790     return $dbh->selectcol_arrayref($PENDING_WEBSERVICE_BATCHES_QRY);
791 }
792
793 =head2 GetImportBatchRangeDesc
794
795   my $results = GetImportBatchRangeDesc($offset, $results_per_group);
796
797 Returns a reference to an array of hash references corresponding to
798 import_batches rows (sorted in descending order by import_batch_id)
799 start at the given offset.
800
801 =cut
802
803 sub GetImportBatchRangeDesc {
804     my ($offset, $results_per_group) = @_;
805
806     my $dbh = C4::Context->dbh;
807     my $query = "SELECT * FROM import_batches
808                                     WHERE batch_type IN ('batch', 'webservice')
809                                     ORDER BY import_batch_id DESC";
810     my @params;
811     if ($results_per_group){
812         $query .= " LIMIT ?";
813         push(@params, $results_per_group);
814     }
815     if ($offset){
816         $query .= " OFFSET ?";
817         push(@params, $offset);
818     }
819     my $sth = $dbh->prepare_cached($query);
820     $sth->execute(@params);
821     my $results = $sth->fetchall_arrayref({});
822     $sth->finish();
823     return $results;
824 }
825
826 =head2 GetItemNumbersFromImportBatch
827
828   my @itemsnos = GetItemNumbersFromImportBatch($batch_id);
829
830 =cut
831
832 sub GetItemNumbersFromImportBatch {
833         my ($batch_id) = @_;
834         my $dbh = C4::Context->dbh;
835         my $sth = $dbh->prepare("SELECT itemnumber FROM import_batches,import_records,import_items WHERE import_batches.import_batch_id=import_records.import_batch_id AND import_records.import_record_id=import_items.import_record_id AND import_batches.import_batch_id=?");
836         $sth->execute($batch_id);
837         my @items ;
838         while ( my ($itm) = $sth->fetchrow_array ) {
839                 push @items, $itm;
840         }
841         return @items;
842 }
843
844 =head2 GetNumberOfImportBatches 
845
846   my $count = GetNumberOfImportBatches();
847
848 =cut
849
850 sub GetNumberOfNonZ3950ImportBatches {
851     my $dbh = C4::Context->dbh;
852     my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type != 'z3950'");
853     $sth->execute();
854     my ($count) = $sth->fetchrow_array();
855     $sth->finish();
856     return $count;
857 }
858
859 =head2 GetImportBibliosRange
860
861   my $results = GetImportBibliosRange($batch_id, $offset, $results_per_group);
862
863 Returns a reference to an array of hash references corresponding to
864 import_biblios/import_records rows for a given batch
865 starting at the given offset.
866
867 =cut
868
869 sub GetImportBibliosRange {
870     my ($batch_id, $offset, $results_per_group, $status) = @_;
871
872     my $dbh = C4::Context->dbh;
873     my $query = "SELECT title, author, isbn, issn, import_record_id, record_sequence,
874                                            status, overlay_status, matched_biblionumber
875                                     FROM   import_records
876                                     JOIN   import_biblios USING (import_record_id)
877                                     WHERE  import_batch_id = ?";
878     my @params;
879     push(@params, $batch_id);
880     if ($status) {
881         $query .= " AND status=?";
882         push(@params,$status);
883     }
884     $query.=" ORDER BY import_record_id";
885
886     if($results_per_group){
887         $query .= " LIMIT ?";
888         push(@params, $results_per_group);
889     }
890     if($offset){
891         $query .= " OFFSET ?";
892         push(@params, $offset);
893     }
894     my $sth = $dbh->prepare_cached($query);
895     $sth->execute(@params);
896     my $results = $sth->fetchall_arrayref({});
897     $sth->finish();
898     return $results;
899
900 }
901
902 =head2 GetBestRecordMatch
903
904   my $record_id = GetBestRecordMatch($import_record_id);
905
906 =cut
907
908 sub GetBestRecordMatch {
909     my ($import_record_id) = @_;
910
911     my $dbh = C4::Context->dbh;
912     my $sth = $dbh->prepare("SELECT candidate_match_id
913                              FROM   import_record_matches
914                              WHERE  import_record_id = ?
915                              ORDER BY score DESC, candidate_match_id DESC");
916     $sth->execute($import_record_id);
917     my ($record_id) = $sth->fetchrow_array();
918     $sth->finish();
919     return $record_id;
920 }
921
922 =head2 GetImportBatchStatus
923
924   my $status = GetImportBatchStatus($batch_id);
925
926 =cut
927
928 sub GetImportBatchStatus {
929     my ($batch_id) = @_;
930
931     my $dbh = C4::Context->dbh;
932     my $sth = $dbh->prepare("SELECT import_status FROM import_batches WHERE import_batch_id = ?");
933     $sth->execute($batch_id);
934     my ($status) = $sth->fetchrow_array();
935     $sth->finish();
936     return $status;
937
938 }
939
940 =head2 SetImportBatchStatus
941
942   SetImportBatchStatus($batch_id, $new_status);
943
944 =cut
945
946 sub SetImportBatchStatus {
947     my ($batch_id, $new_status) = @_;
948
949     my $dbh = C4::Context->dbh;
950     my $sth = $dbh->prepare("UPDATE import_batches SET import_status = ? WHERE import_batch_id = ?");
951     $sth->execute($new_status, $batch_id);
952     $sth->finish();
953
954 }
955
956 =head2 GetImportBatchOverlayAction
957
958   my $overlay_action = GetImportBatchOverlayAction($batch_id);
959
960 =cut
961
962 sub GetImportBatchOverlayAction {
963     my ($batch_id) = @_;
964
965     my $dbh = C4::Context->dbh;
966     my $sth = $dbh->prepare("SELECT overlay_action FROM import_batches WHERE import_batch_id = ?");
967     $sth->execute($batch_id);
968     my ($overlay_action) = $sth->fetchrow_array();
969     $sth->finish();
970     return $overlay_action;
971
972 }
973
974
975 =head2 SetImportBatchOverlayAction
976
977   SetImportBatchOverlayAction($batch_id, $new_overlay_action);
978
979 =cut
980
981 sub SetImportBatchOverlayAction {
982     my ($batch_id, $new_overlay_action) = @_;
983
984     my $dbh = C4::Context->dbh;
985     my $sth = $dbh->prepare("UPDATE import_batches SET overlay_action = ? WHERE import_batch_id = ?");
986     $sth->execute($new_overlay_action, $batch_id);
987     $sth->finish();
988
989 }
990
991 =head2 GetImportBatchNoMatchAction
992
993   my $nomatch_action = GetImportBatchNoMatchAction($batch_id);
994
995 =cut
996
997 sub GetImportBatchNoMatchAction {
998     my ($batch_id) = @_;
999
1000     my $dbh = C4::Context->dbh;
1001     my $sth = $dbh->prepare("SELECT nomatch_action FROM import_batches WHERE import_batch_id = ?");
1002     $sth->execute($batch_id);
1003     my ($nomatch_action) = $sth->fetchrow_array();
1004     $sth->finish();
1005     return $nomatch_action;
1006
1007 }
1008
1009
1010 =head2 SetImportBatchNoMatchAction
1011
1012   SetImportBatchNoMatchAction($batch_id, $new_nomatch_action);
1013
1014 =cut
1015
1016 sub SetImportBatchNoMatchAction {
1017     my ($batch_id, $new_nomatch_action) = @_;
1018
1019     my $dbh = C4::Context->dbh;
1020     my $sth = $dbh->prepare("UPDATE import_batches SET nomatch_action = ? WHERE import_batch_id = ?");
1021     $sth->execute($new_nomatch_action, $batch_id);
1022     $sth->finish();
1023
1024 }
1025
1026 =head2 GetImportBatchItemAction
1027
1028   my $item_action = GetImportBatchItemAction($batch_id);
1029
1030 =cut
1031
1032 sub GetImportBatchItemAction {
1033     my ($batch_id) = @_;
1034
1035     my $dbh = C4::Context->dbh;
1036     my $sth = $dbh->prepare("SELECT item_action FROM import_batches WHERE import_batch_id = ?");
1037     $sth->execute($batch_id);
1038     my ($item_action) = $sth->fetchrow_array();
1039     $sth->finish();
1040     return $item_action;
1041
1042 }
1043
1044
1045 =head2 SetImportBatchItemAction
1046
1047   SetImportBatchItemAction($batch_id, $new_item_action);
1048
1049 =cut
1050
1051 sub SetImportBatchItemAction {
1052     my ($batch_id, $new_item_action) = @_;
1053
1054     my $dbh = C4::Context->dbh;
1055     my $sth = $dbh->prepare("UPDATE import_batches SET item_action = ? WHERE import_batch_id = ?");
1056     $sth->execute($new_item_action, $batch_id);
1057     $sth->finish();
1058
1059 }
1060
1061 =head2 GetImportBatchMatcher
1062
1063   my $matcher_id = GetImportBatchMatcher($batch_id);
1064
1065 =cut
1066
1067 sub GetImportBatchMatcher {
1068     my ($batch_id) = @_;
1069
1070     my $dbh = C4::Context->dbh;
1071     my $sth = $dbh->prepare("SELECT matcher_id FROM import_batches WHERE import_batch_id = ?");
1072     $sth->execute($batch_id);
1073     my ($matcher_id) = $sth->fetchrow_array();
1074     $sth->finish();
1075     return $matcher_id;
1076
1077 }
1078
1079
1080 =head2 SetImportBatchMatcher
1081
1082   SetImportBatchMatcher($batch_id, $new_matcher_id);
1083
1084 =cut
1085
1086 sub SetImportBatchMatcher {
1087     my ($batch_id, $new_matcher_id) = @_;
1088
1089     my $dbh = C4::Context->dbh;
1090     my $sth = $dbh->prepare("UPDATE import_batches SET matcher_id = ? WHERE import_batch_id = ?");
1091     $sth->execute($new_matcher_id, $batch_id);
1092     $sth->finish();
1093
1094 }
1095
1096 =head2 GetImportRecordOverlayStatus
1097
1098   my $overlay_status = GetImportRecordOverlayStatus($import_record_id);
1099
1100 =cut
1101
1102 sub GetImportRecordOverlayStatus {
1103     my ($import_record_id) = @_;
1104
1105     my $dbh = C4::Context->dbh;
1106     my $sth = $dbh->prepare("SELECT overlay_status FROM import_records WHERE import_record_id = ?");
1107     $sth->execute($import_record_id);
1108     my ($overlay_status) = $sth->fetchrow_array();
1109     $sth->finish();
1110     return $overlay_status;
1111
1112 }
1113
1114
1115 =head2 SetImportRecordOverlayStatus
1116
1117   SetImportRecordOverlayStatus($import_record_id, $new_overlay_status);
1118
1119 =cut
1120
1121 sub SetImportRecordOverlayStatus {
1122     my ($import_record_id, $new_overlay_status) = @_;
1123
1124     my $dbh = C4::Context->dbh;
1125     my $sth = $dbh->prepare("UPDATE import_records SET overlay_status = ? WHERE import_record_id = ?");
1126     $sth->execute($new_overlay_status, $import_record_id);
1127     $sth->finish();
1128
1129 }
1130
1131 =head2 GetImportRecordStatus
1132
1133   my $overlay_status = GetImportRecordStatus($import_record_id);
1134
1135 =cut
1136
1137 sub GetImportRecordStatus {
1138     my ($import_record_id) = @_;
1139
1140     my $dbh = C4::Context->dbh;
1141     my $sth = $dbh->prepare("SELECT status FROM import_records WHERE import_record_id = ?");
1142     $sth->execute($import_record_id);
1143     my ($overlay_status) = $sth->fetchrow_array();
1144     $sth->finish();
1145     return $overlay_status;
1146
1147 }
1148
1149
1150 =head2 SetImportRecordStatus
1151
1152   SetImportRecordStatus($import_record_id, $new_overlay_status);
1153
1154 =cut
1155
1156 sub SetImportRecordStatus {
1157     my ($import_record_id, $new_overlay_status) = @_;
1158
1159     my $dbh = C4::Context->dbh;
1160     my $sth = $dbh->prepare("UPDATE import_records SET status = ? WHERE import_record_id = ?");
1161     $sth->execute($new_overlay_status, $import_record_id);
1162     $sth->finish();
1163
1164 }
1165
1166 =head2 GetImportRecordMatches
1167
1168   my $results = GetImportRecordMatches($import_record_id, $best_only);
1169
1170 =cut
1171
1172 sub GetImportRecordMatches {
1173     my $import_record_id = shift;
1174     my $best_only = @_ ? shift : 0;
1175
1176     my $dbh = C4::Context->dbh;
1177     # FIXME currently biblio only
1178     my $sth = $dbh->prepare_cached("SELECT title, author, biblionumber, score
1179                                     FROM import_records
1180                                     JOIN import_record_matches USING (import_record_id)
1181                                     JOIN biblio ON (biblionumber = candidate_match_id)
1182                                     WHERE import_record_id = ?
1183                                     ORDER BY score DESC, biblionumber DESC");
1184     $sth->bind_param(1, $import_record_id);
1185     my $results = [];
1186     $sth->execute();
1187     while (my $row = $sth->fetchrow_hashref) {
1188         push @$results, $row;
1189         last if $best_only;
1190     }
1191     $sth->finish();
1192
1193     return $results;
1194     
1195 }
1196
1197
1198 =head2 SetImportRecordMatches
1199
1200   SetImportRecordMatches($import_record_id, @matches);
1201
1202 =cut
1203
1204 sub SetImportRecordMatches {
1205     my $import_record_id = shift;
1206     my @matches = @_;
1207
1208     my $dbh = C4::Context->dbh;
1209     my $delsth = $dbh->prepare("DELETE FROM import_record_matches WHERE import_record_id = ?");
1210     $delsth->execute($import_record_id);
1211     $delsth->finish();
1212
1213     my $sth = $dbh->prepare("INSERT INTO import_record_matches (import_record_id, candidate_match_id, score)
1214                                     VALUES (?, ?, ?)");
1215     foreach my $match (@matches) {
1216         $sth->execute($import_record_id, $match->{'record_id'}, $match->{'score'});
1217     }
1218 }
1219
1220
1221 # internal functions
1222
1223 sub _create_import_record {
1224     my ($batch_id, $record_sequence, $marc_record, $record_type, $encoding, $z3950random) = @_;
1225
1226     my $dbh = C4::Context->dbh;
1227     my $sth = $dbh->prepare("INSERT INTO import_records (import_batch_id, record_sequence, marc, marcxml, 
1228                                                          record_type, encoding, z3950random)
1229                                     VALUES (?, ?, ?, ?, ?, ?, ?)");
1230     $sth->execute($batch_id, $record_sequence, $marc_record->as_usmarc(), $marc_record->as_xml(),
1231                   $record_type, $encoding, $z3950random);
1232     my $import_record_id = $dbh->{'mysql_insertid'};
1233     $sth->finish();
1234     return $import_record_id;
1235 }
1236
1237 sub _update_import_record_marc {
1238     my ($import_record_id, $marc_record) = @_;
1239
1240     my $dbh = C4::Context->dbh;
1241     my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ?
1242                              WHERE  import_record_id = ?");
1243     $sth->execute($marc_record->as_usmarc(), $marc_record->as_xml(C4::Context->preference('marcflavour')), $import_record_id);
1244     $sth->finish();
1245 }
1246
1247 sub _add_biblio_fields {
1248     my ($import_record_id, $marc_record) = @_;
1249
1250     my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
1251     my $dbh = C4::Context->dbh;
1252     # FIXME no controlnumber, originalsource
1253     $isbn = C4::Koha::_isbn_cleanup($isbn); # FIXME C4::Koha::_isbn_cleanup should be made public
1254     my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn) VALUES (?, ?, ?, ?, ?)");
1255     $sth->execute($import_record_id, $title, $author, $isbn, $issn);
1256     $sth->finish();
1257                 
1258 }
1259
1260 sub _update_biblio_fields {
1261     my ($import_record_id, $marc_record) = @_;
1262
1263     my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record);
1264     my $dbh = C4::Context->dbh;
1265     # FIXME no controlnumber, originalsource
1266     # FIXME 2 - should regularize normalization of ISBN wherever it is done
1267     $isbn =~ s/\(.*$//;
1268     $isbn =~ tr/ -_//;
1269     $isbn = uc $isbn;
1270     my $sth = $dbh->prepare("UPDATE import_biblios SET title = ?, author = ?, isbn = ?, issn = ?
1271                              WHERE  import_record_id = ?");
1272     $sth->execute($title, $author, $isbn, $issn, $import_record_id);
1273     $sth->finish();
1274 }
1275
1276 sub _parse_biblio_fields {
1277     my ($marc_record) = @_;
1278
1279     my $dbh = C4::Context->dbh;
1280     my $bibliofields = TransformMarcToKoha($dbh, $marc_record, '');
1281     return ($bibliofields->{'title'}, $bibliofields->{'author'}, $bibliofields->{'isbn'}, $bibliofields->{'issn'});
1282
1283 }
1284
1285 sub _update_batch_record_counts {
1286     my ($batch_id) = @_;
1287
1288     my $dbh = C4::Context->dbh;
1289     my $sth = $dbh->prepare_cached("UPDATE import_batches SET
1290                                         num_biblios = (
1291                                             SELECT COUNT(*)
1292                                             FROM import_records
1293                                             WHERE import_batch_id = import_batches.import_batch_id
1294                                             AND record_type = 'biblio'),
1295                                         num_items = (
1296                                             SELECT COUNT(*)
1297                                             FROM import_records
1298                                             JOIN import_items USING (import_record_id)
1299                                             WHERE import_batch_id = import_batches.import_batch_id
1300                                             AND record_type = 'biblio')
1301                                     WHERE import_batch_id = ?");
1302     $sth->bind_param(1, $batch_id);
1303     $sth->execute();
1304     $sth->finish();
1305 }
1306
1307 sub _get_commit_action {
1308     my ($overlay_action, $nomatch_action, $item_action, $overlay_status, $import_record_id) = @_;
1309     
1310     my ($bib_result, $bib_match, $item_result);
1311
1312     if ($overlay_status ne 'no_match') {
1313         $bib_match = GetBestRecordMatch($import_record_id);
1314         if ($overlay_action eq 'replace') {
1315             $bib_result  = defined($bib_match) ? 'replace' : 'create_new';
1316         } elsif ($overlay_action eq 'create_new') {
1317             $bib_result  = 'create_new';
1318         } elsif ($overlay_action eq 'ignore') {
1319             $bib_result  = 'ignore';
1320         } 
1321         $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_matches') ? 'create_new' : 'ignore';
1322     } else {
1323         $bib_result = $nomatch_action;
1324         $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_new')     ? 'create_new' : 'ignore';
1325     }
1326
1327     return ($bib_result, $item_result, $bib_match);
1328 }
1329
1330 sub _get_revert_action {
1331     my ($overlay_action, $overlay_status, $status) = @_;
1332
1333     my $bib_result;
1334
1335     if ($status eq 'ignored') {
1336         $bib_result = 'ignore';
1337     } else {
1338         if ($overlay_action eq 'create_new') {
1339             $bib_result = 'delete';
1340         } else {
1341             $bib_result = ($overlay_status eq 'match_applied') ? 'restore' : 'delete';
1342         }
1343     }
1344     return $bib_result;
1345 }
1346
1347 1;
1348 __END__
1349
1350 =head1 AUTHOR
1351
1352 Koha Development Team <http://koha-community.org/>
1353
1354 Galen Charlton <galen.charlton@liblime.com>
1355
1356 =cut