Bug 27421: Use Background job for staging MARC records for import
[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 C4::Matcher;
24 use C4::ImportBatch qw(
25     RecordsFromMARCXMLFile
26     RecordsFromISO2709File
27     RecordsFromMarcPlugin
28     BatchStageMarcRecords
29     BatchFindDuplicates
30     SetImportBatchMatcher
31     SetImportBatchOverlayAction
32     SetImportBatchNoMatchAction
33     SetImportBatchItemAction
34 );
35
36 =head1 NAME
37
38 Koha::BackgroundJob::StageMARCForImport - Stage MARC records for import
39
40 This is a subclass of Koha::BackgroundJob.
41
42 =head1 API
43
44 =head2 Class methods
45
46 =head3 job_type
47
48 Define the job type of this job: stage_marc_for_import
49
50 =cut
51
52 sub job_type {
53     return 'stage_marc_for_import';
54 }
55
56 =head3 process
57
58 Stage the MARC records for import.
59
60 =cut
61
62 sub process {
63     my ( $self, $args ) = @_;
64
65     $self->start;
66
67     my $record_type                = $args->{record_type};
68     my $encoding                   = $args->{encoding};
69     my $format                     = $args->{format};
70     my $filepath                   = $args->{filepath};
71     my $filename                   = $args->{filename};
72     my $marc_modification_template = $args->{marc_modification_template};
73     my $comments                   = $args->{comments};
74     my $parse_items                = $args->{parse_items};
75     my $matcher_id                 = $args->{matcher_id};
76     my $overlay_action             = $args->{overlay_action};
77     my $nomatch_action             = $args->{nomatch_action};
78     my $item_action                = $args->{item_action};
79     my $vendor_id                  = $args->{vendor_id};
80     my $basket_id                  = $args->{basket_id};
81     my $profile_id                 = $args->{profile_id};
82
83     my @messages;
84     my ( $batch_id, $num_valid, $num_items, @import_errors );
85     my $num_with_matches = 0;
86     my $checked_matches  = 0;
87     my $matcher_failed   = 0;
88     my $matcher_code     = "";
89
90     try {
91         my $schema = Koha::Database->new->schema;
92         $schema->storage->txn_begin;
93
94         my ( $errors, $marcrecords );
95         if ( $format eq 'MARCXML' ) {
96             ( $errors, $marcrecords ) =
97               C4::ImportBatch::RecordsFromMARCXMLFile( $filepath, $encoding );
98         }
99         elsif ( $format eq 'ISO2709' ) {
100             ( $errors, $marcrecords ) =
101               C4::ImportBatch::RecordsFromISO2709File( $filepath, $record_type,
102                 $encoding );
103         }
104         else {    # plugin based
105             $errors = [];
106             $marcrecords =
107               C4::ImportBatch::RecordsFromMarcPlugin( $filepath, $format,
108                 $encoding );
109         }
110
111         $self->size(scalar @$marcrecords)->store;
112
113         ( $batch_id, $num_valid, $num_items, @import_errors ) =
114           BatchStageMarcRecords(
115             $record_type,                $encoding,
116             $marcrecords,                $filename,
117             $marc_modification_template, $comments,
118             '',                          $parse_items,
119             0,                           50,
120             sub {
121                 my $job_progress = shift;
122                 if ($matcher_id) {
123                     $job_progress /= 2;
124                 }
125                 $self->progress( int($job_progress) )->store;
126               }
127           );
128
129         if ($profile_id) {
130             my $ibatch = Koha::ImportBatches->find($batch_id);
131             $ibatch->set( { profile_id => $profile_id } )->store;
132         }
133
134         if ($matcher_id) {
135             my $matcher = C4::Matcher->fetch($matcher_id);
136             if ( defined $matcher ) {
137                 $checked_matches = 1;
138                 $matcher_code    = $matcher->code();
139                 $num_with_matches =
140                   BatchFindDuplicates( $batch_id, $matcher, 10, 50,
141                     sub { my $job_progress = shift; $self->progress( $self->progress + $job_progress )->store } );
142                 SetImportBatchMatcher( $batch_id, $matcher_id );
143                 SetImportBatchOverlayAction( $batch_id, $overlay_action );
144                 SetImportBatchNoMatchAction( $batch_id, $nomatch_action );
145                 SetImportBatchItemAction( $batch_id, $item_action );
146                 $schema->storage->txn_commit;
147             }
148             else {
149                 $matcher_failed = 1;
150                 $schema->storage->txn_rollback;
151             }
152         } else {
153             $schema->storage->txn_commit;
154         }
155     }
156     catch {
157         warn $_;
158         die "Something terrible has happened!"
159           if ( $_ =~ /Rollback failed/ );    # Rollback failed
160     };
161
162     my $report = {
163         staged          => $num_valid,
164         matched         => $num_with_matches,
165         num_items       => $num_items,
166         import_errors   => scalar(@import_errors),
167         total           => $num_valid + scalar(@import_errors),
168         checked_matches => $checked_matches,
169         matcher_failed  => $matcher_failed,
170         matcher_code    => $matcher_code,
171         import_batch_id => $batch_id,
172         vendor_id       => $vendor_id,
173         basket_id       => $basket_id,
174     };
175
176     my $data = $self->decoded_data;
177     $data->{messages} = \@messages;
178     $data->{report}   = $report;
179
180     $self->finish($data);
181 }
182
183 =head3 enqueue
184
185 Enqueue the new job
186
187 =cut
188
189 sub enqueue {
190     my ( $self, $args) = @_;
191
192     $self->SUPER::enqueue({
193         job_size => 0, # unknown for now
194         job_args => $args
195     });
196 }
197
198 1;