1 package Koha::BackgroundJob::BatchDeleteBiblio;
4 use JSON qw( encode_json decode_json );
8 use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
9 use Koha::DateUtils qw( dt_from_string );
10 use Koha::SearchEngine;
11 use Koha::SearchEngine::Indexer;
13 use base 'Koha::BackgroundJob';
17 Koha::BackgroundJob::BatchDeleteBiblio - Batch delete bibliographic records
19 This is a subclass of Koha::BackgroundJob.
27 Define the job type of this job: batch_biblio_record_deletion
32 return 'batch_biblio_record_deletion';
42 my ( $self, $args ) = @_;
44 if ( $self->status eq 'cancelled' ) {
48 # FIXME If the job has already been started, but started again (worker has been restart for instance)
49 # Then we will start from scratch and so double delete the same records
52 $self->started_on(dt_from_string)
53 ->progress($job_progress)
57 my $mmtid = $args->{mmtid};
58 my @record_ids = @{ $args->{record_ids} };
61 total_records => scalar @record_ids,
65 my $schema = Koha::Database->new->schema;
66 RECORD_IDS: for my $record_id ( sort { $a <=> $b } @record_ids ) {
68 last if $self->get_from_storage->status eq 'cancelled';
70 next unless $record_id;
72 $schema->storage->txn_begin;
74 my $biblionumber = $record_id;
75 # First, checking if issues exist.
76 # If yes, nothing to do
77 my $biblio = Koha::Biblios->find( $biblionumber );
79 # TODO Replace with $biblio->get_issues->count
80 if ( C4::Biblio::CountItemsIssued( $biblionumber ) ) {
83 code => 'item_issued',
84 biblionumber => $biblionumber,
86 $schema->storage->txn_rollback;
87 $self->progress( ++$job_progress )->store;
92 my $holds = $biblio->holds;
93 while ( my $hold = $holds->next ) {
95 $hold->cancel({ skip_holds_queue => 1 });
100 code => 'reserve_not_cancelled',
101 biblionumber => $biblionumber,
102 reserve_id => $hold->reserve_id,
105 $schema->storage->txn_rollback;
106 $self->progress( ++$job_progress )->store;
112 my $items = Koha::Items->search({ biblionumber => $biblionumber });
113 while ( my $item = $items->next ) {
114 my $deleted = $item->safe_delete({ skip_record_index => 1, skip_holds_queue => 1 });
115 unless ( $deleted ) {
118 code => 'item_not_deleted',
119 biblionumber => $biblionumber,
120 itemnumber => $item->itemnumber,
121 error => @{$deleted->messages}[0]->message,
123 $schema->storage->txn_rollback;
124 $self->progress( ++$job_progress )->store;
129 # Finally, delete the biblio
131 C4::Biblio::DelBiblio( $biblionumber, { skip_record_index => 1, skip_holds_queue => 1 } );
133 if ( $error or $@ ) {
136 code => 'biblio_not_deleted',
137 biblionumber => $biblionumber,
138 error => ($@ ? $@ : $error),
140 $schema->storage->txn_rollback;
141 $self->progress( ++$job_progress )->store;
147 code => 'biblio_deleted',
148 biblionumber => $biblionumber,
150 $report->{total_success}++;
151 $schema->storage->txn_commit;
152 $self->progress( ++$job_progress )->store;
155 my @deleted_biblionumbers =
156 map { $_->{code} eq 'biblio_deleted' ? $_->{biblionumber} : () }
159 if ( @deleted_biblionumbers ) {
160 my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
161 $indexer->index_records( \@deleted_biblionumbers, "recordDelete", "biblioserver" );
163 Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
165 biblio_ids => \@deleted_biblionumbers
167 ) if C4::Context->preference('RealTimeHoldsQueue');
170 my $job_data = decode_json $self->data;
171 $job_data->{messages} = \@messages;
172 $job_data->{report} = $report;
174 $self->ended_on(dt_from_string)
175 ->data(encode_json $job_data);
176 $self->status('finished') if $self->status ne 'cancelled';
187 my ( $self, $args) = @_;
189 # TODO Raise exception instead
190 return unless exists $args->{record_ids};
192 my @record_ids = @{ $args->{record_ids} };
194 $self->SUPER::enqueue({
195 job_size => scalar @record_ids,
196 job_args => {record_ids => \@record_ids,},
197 queue => 'long_tasks',