Bug 14957: (QA follow-up) Clarify 'context' param
[koha.git] / Koha / BackgroundJob / BatchUpdateItem.pm
1 package Koha::BackgroundJob::BatchUpdateItem;
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 JSON qw( encode_json decode_json );
20 use Encode qw( encode_utf8 );
21 use List::MoreUtils qw( uniq );
22 use Try::Tiny;
23
24 use MARC::Record;
25 use MARC::Field;
26
27 use C4::Biblio;
28 use C4::Items;
29
30 use Koha::BackgroundJobs;
31 use Koha::DateUtils qw( dt_from_string );
32 use Koha::SearchEngine::Indexer;
33 use Koha::Items;
34 use Koha::UI::Table::Builder::Items;
35
36 use base 'Koha::BackgroundJob';
37
38 =head1 NAME
39
40 Koha::BackgroundJob::BatchUpdateItem - Background job derived class to process item modification in batch
41
42 =head1 API
43
44 =head2 Class methods
45
46 =head3 job_type
47
48 Define the job type of this job: batch_item_record_modification
49
50 =cut
51
52 sub job_type {
53     return 'batch_item_record_modification';
54 }
55
56 =head3 process
57
58     Koha::BackgroundJobs->find($id)->process(
59         {
60             record_ids => \@itemnumbers,
61             new_values => {
62                 itemnotes => $new_item_notes,
63                 k         => $k,
64             },
65             regex_mod => {
66                 itemnotes_nonpublic => {
67                     search => 'foo',
68                     replace => 'bar',
69                     modifiers => 'gi',
70                 },
71             },
72             exclude_from_local_holds_priority => 1|0
73         }
74     );
75
76 Process the modification.
77
78 new_values allows to set a new value for given fields.
79 The key can be one of the item's column name, or one subfieldcode of a MARC subfields not linked with a Koha field.
80
81 regex_mod allows to modify existing subfield's values using a regular expression.
82
83 =cut
84
85 sub process {
86     my ( $self, $args ) = @_;
87
88     my $job = Koha::BackgroundJobs->find( $args->{job_id} );
89
90     if ( !exists $args->{job_id} || !$job || $job->status eq 'cancelled' ) {
91         return;
92     }
93
94     # FIXME If the job has already been started, but started again (worker has been restart for instance)
95     # Then we will start from scratch and so double process the same records
96
97     my $job_progress = 0;
98     $job->started_on(dt_from_string)->progress($job_progress)
99       ->status('started')->store;
100
101     my @record_ids = @{ $args->{record_ids} };
102     my $regex_mod  = $args->{regex_mod};
103     my $new_values = $args->{new_values};
104     my $exclude_from_local_holds_priority =
105       $args->{exclude_from_local_holds_priority};
106
107     my $report = {
108         total_records            => scalar @record_ids,
109         modified_itemitemnumbers => [],
110         modified_fields          => 0,
111     };
112
113     try {
114         my ($results) =
115           Koha::Items->search( { itemnumber => \@record_ids } )
116           ->batch_update(
117             {
118                 regex_mod  => $regex_mod,
119                 new_values => $new_values,
120                 exclude_from_local_holds_priority =>
121                   $exclude_from_local_holds_priority,
122                 callback => sub {
123                     my ($progress) = @_;
124                     $job->progress($progress)->store;
125                 },
126             }
127           );
128         $report->{modified_itemnumbers} = $results->{modified_itemnumbers};
129         $report->{modified_fields}      = $results->{modified_fields};
130     }
131     catch {
132         warn $_;
133         die "Something terrible has happened!"
134           if ( $_ =~ /Rollback failed/ );    # Rollback failed
135     };
136
137     $job->discard_changes;
138     my $job_data = decode_json encode_utf8 $job->data;
139     $job_data->{report} = $report;
140
141     $job->ended_on(dt_from_string)->data( encode_json $job_data);
142     $job->status('finished') if $job->status ne 'cancelled';
143     $job->store;
144 }
145
146 =head3 enqueue
147
148 Enqueue the new job
149
150 =cut
151
152 sub enqueue {
153     my ( $self, $args ) = @_;
154
155     # TODO Raise exception instead
156     return unless exists $args->{record_ids};
157
158     my @record_ids = @{ $args->{record_ids} };
159
160     $self->SUPER::enqueue(
161         {
162             job_size => scalar @record_ids,
163             job_args => {%$args},
164         }
165     );
166 }
167
168 =head3 additional_report
169
170 Sent the infos to generate the table containing the details of the modified items.
171
172 =cut
173
174 sub additional_report {
175     my ( $self, $args ) = @_;
176
177     my $job = Koha::BackgroundJobs->find( $args->{job_id} );
178
179     my $itemnumbers = $job->report->{modified_itemnumbers};
180     if ( scalar(@$itemnumbers) > C4::Context->preference('MaxItemsToDisplayForBatchMod') ) {
181         return { too_many_items_display => 1 };
182     } else {
183         my $items_table =
184           Koha::UI::Table::Builder::Items->new( { itemnumbers => $itemnumbers } )
185           ->build_table;
186
187         return {
188             items            => $items_table->{items},
189             item_header_loop => $items_table->{headers},
190         };
191     }
192 }
193
194 1;