Bug 33036: REST API: Merge biblio records implements merging of records
[koha.git] / Koha / BackgroundJob / StageMARCForImport.pm
1 package Koha::BackgroundJob::StageMARCForImport;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19 use Try::Tiny;
20
21 use base 'Koha::BackgroundJob';
22
23 use Koha::Database;
24 use Koha::ImportBatches;
25 use C4::Matcher;
26 use C4::ImportBatch qw(
27     RecordsFromMARCXMLFile
28     RecordsFromISO2709File
29     RecordsFromMarcPlugin
30     BatchStageMarcRecords
31     BatchFindDuplicates
32     SetImportBatchMatcher
33     SetImportBatchOverlayAction
34     SetImportBatchNoMatchAction
35     SetImportBatchItemAction
36 );
37
38 =head1 NAME
39
40 Koha::BackgroundJob::StageMARCForImport - Stage MARC records for import
41
42 This is a subclass of Koha::BackgroundJob.
43
44 =head1 API
45
46 =head2 Class methods
47
48 =head3 job_type
49
50 Define the job type of this job: stage_marc_for_import
51
52 =cut
53
54 sub job_type {
55     return 'stage_marc_for_import';
56 }
57
58 =head3 process
59
60 Stage the MARC records for import.
61
62 =cut
63
64 sub process {
65     my ( $self, $args ) = @_;
66
67     $self->start;
68
69     my $record_type                = $args->{record_type};
70     my $encoding                   = $args->{encoding};
71     my $format                     = $args->{format};
72     my $filepath                   = $args->{filepath};
73     my $filename                   = $args->{filename};
74     my $marc_modification_template = $args->{marc_modification_template};
75     my $comments                   = $args->{comments};
76     my $parse_items                = $args->{parse_items};
77     my $matcher_id                 = $args->{matcher_id};
78     my $overlay_action             = $args->{overlay_action};
79     my $nomatch_action             = $args->{nomatch_action};
80     my $item_action                = $args->{item_action};
81     my $vendor_id                  = $args->{vendor_id};
82     my $basket_id                  = $args->{basket_id};
83     my $profile_id                 = $args->{profile_id};
84
85     my @messages;
86     my ( $batch_id, $num_valid, $num_items, @import_errors );
87     my $num_with_matches = 0;
88     my $checked_matches  = 0;
89     my $matcher_failed   = 0;
90     my $matcher_code     = "";
91
92     my $schema = Koha::Database->new->schema;
93     try {
94         $schema->storage->txn_begin;
95
96         my ( $errors, $marcrecords );
97         if ( $format eq 'MARCXML' ) {
98             ( $errors, $marcrecords ) =
99               C4::ImportBatch::RecordsFromMARCXMLFile( $filepath, $encoding );
100         }
101         elsif ( $format eq 'ISO2709' ) {
102             ( $errors, $marcrecords ) =
103               C4::ImportBatch::RecordsFromISO2709File( $filepath, $record_type,
104                 $encoding );
105         }
106         else {    # plugin based
107             $errors = [];
108             $marcrecords =
109               C4::ImportBatch::RecordsFromMarcPlugin( $filepath, $format,
110                 $encoding );
111         }
112
113         $self->size(scalar @$marcrecords)->store;
114
115         ( $batch_id, $num_valid, $num_items, @import_errors ) = BatchStageMarcRecords(
116             $record_type,                $encoding,
117             $marcrecords,                $filename,
118             $marc_modification_template, $comments,
119             '',                          $parse_items,
120             0,                           50,
121             sub {
122                 my $job_progress = shift;
123                 if ($matcher_id) {
124                     $job_progress /= 2;
125                 }
126                 $self->progress( int($job_progress) )->store;
127             }
128         );
129         if( $num_valid ) {
130             $self->set({ progress => $num_valid, size => $num_valid });
131         } else { # We must assume that something went wrong here
132             $self->set({ progress => 0, status => 'failed' });
133         }
134
135         if ($profile_id) {
136             my $ibatch = Koha::ImportBatches->find($batch_id);
137             $ibatch->set( { profile_id => $profile_id } )->store;
138         }
139
140         if ($matcher_id) {
141             my $matcher = C4::Matcher->fetch($matcher_id);
142             if ( defined $matcher ) {
143                 $checked_matches = 1;
144                 $matcher_code    = $matcher->code();
145                 $num_with_matches =
146                   BatchFindDuplicates( $batch_id, $matcher, 10, 50,
147                     sub { my $job_progress = shift; $self->progress( $self->progress + $job_progress )->store } );
148                 SetImportBatchMatcher( $batch_id, $matcher_id );
149                 SetImportBatchOverlayAction( $batch_id, $overlay_action );
150                 SetImportBatchNoMatchAction( $batch_id, $nomatch_action );
151                 SetImportBatchItemAction( $batch_id, $item_action );
152                 $schema->storage->txn_commit;
153             }
154             else {
155                 $matcher_failed = 1;
156                 $schema->storage->txn_rollback;
157             }
158         } else {
159             $schema->storage->txn_commit;
160         }
161     }
162     catch {
163         warn $_;
164         $schema->storage->txn_rollback;
165         die "Something terrible has happened!"
166           if ( $_ =~ /Rollback failed/ );    # TODO Check test: Rollback failed
167         $self->set({ progress => 0, status => 'failed' });
168     };
169
170     my $report = {
171         staged          => $num_valid,
172         matched         => $num_with_matches,
173         num_items       => $num_items,
174         import_errors   => scalar(@import_errors),
175         total           => $num_valid + scalar(@import_errors),
176         checked_matches => $checked_matches,
177         matcher_failed  => $matcher_failed,
178         matcher_code    => $matcher_code,
179         import_batch_id => $batch_id,
180         vendor_id       => $vendor_id,
181         basket_id       => $basket_id,
182     };
183
184     my $data = $self->decoded_data;
185     $data->{messages} = \@messages;
186     $data->{report}   = $report;
187
188     $self->finish($data);
189 }
190
191 =head3 enqueue
192
193 Enqueue the new job
194
195 =cut
196
197 sub enqueue {
198     my ( $self, $args) = @_;
199
200     # FIXME: no $args validation
201     $self->SUPER::enqueue({
202         job_size  => 0, # TODO Unknown for now?
203         job_args  => $args,
204         job_queue => 'long_tasks',
205     });
206 }
207
208 1;