1 package Koha::BackgroundJob::BatchDeleteBiblio;
7 use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
8 use Koha::DateUtils qw( dt_from_string );
9 use Koha::SearchEngine;
10 use Koha::SearchEngine::Indexer;
12 use base 'Koha::BackgroundJob';
16 Koha::BackgroundJob::BatchDeleteBiblio - Batch delete bibliographic records
18 This is a subclass of Koha::BackgroundJob.
26 Define the job type of this job: batch_biblio_record_deletion
31 return 'batch_biblio_record_deletion';
41 my ( $self, $args ) = @_;
43 if ( $self->status eq 'cancelled' ) {
47 # FIXME If the job has already been started, but started again (worker has been restart for instance)
48 # Then we will start from scratch and so double delete the same records
51 $self->started_on(dt_from_string)
52 ->progress($job_progress)
56 my $mmtid = $args->{mmtid};
57 my @record_ids = @{ $args->{record_ids} };
60 total_records => scalar @record_ids,
64 my $schema = Koha::Database->new->schema;
65 RECORD_IDS: for my $record_id ( sort { $a <=> $b } @record_ids ) {
67 last if $self->get_from_storage->status eq 'cancelled';
69 next unless $record_id;
71 $schema->storage->txn_begin;
73 my $biblionumber = $record_id;
74 # First, checking if issues exist.
75 # If yes, nothing to do
76 my $biblio = Koha::Biblios->find( $biblionumber );
78 # TODO Replace with $biblio->get_issues->count
79 if ( C4::Biblio::CountItemsIssued( $biblionumber ) ) {
82 code => 'item_issued',
83 biblionumber => $biblionumber,
85 $schema->storage->txn_rollback;
86 $self->progress( ++$job_progress )->store;
91 my $holds = $biblio->holds;
92 while ( my $hold = $holds->next ) {
94 $hold->cancel({ skip_holds_queue => 1 });
99 code => 'reserve_not_cancelled',
100 biblionumber => $biblionumber,
101 reserve_id => $hold->reserve_id,
104 $schema->storage->txn_rollback;
105 $self->progress( ++$job_progress )->store;
111 my $items = Koha::Items->search({ biblionumber => $biblionumber });
112 while ( my $item = $items->next ) {
113 my $deleted = $item->safe_delete({ skip_record_index => 1, skip_holds_queue => 1 });
114 unless ( $deleted ) {
117 code => 'item_not_deleted',
118 biblionumber => $biblionumber,
119 itemnumber => $item->itemnumber,
120 error => @{$deleted->messages}[0]->message,
122 $schema->storage->txn_rollback;
123 $self->progress( ++$job_progress )->store;
128 # Finally, delete the biblio
130 C4::Biblio::DelBiblio( $biblionumber, { skip_record_index => 1, skip_holds_queue => 1 } );
132 if ( $error or $@ ) {
135 code => 'biblio_not_deleted',
136 biblionumber => $biblionumber,
137 error => ($@ ? $@ : $error),
139 $schema->storage->txn_rollback;
140 $self->progress( ++$job_progress )->store;
146 code => 'biblio_deleted',
147 biblionumber => $biblionumber,
149 $report->{total_success}++;
150 $schema->storage->txn_commit;
151 $self->progress( ++$job_progress )->store;
154 my @deleted_biblionumbers =
155 map { $_->{code} eq 'biblio_deleted' ? $_->{biblionumber} : () }
158 if ( @deleted_biblionumbers ) {
159 my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
160 $indexer->index_records( \@deleted_biblionumbers, "recordDelete", "biblioserver" );
162 Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
164 biblio_ids => \@deleted_biblionumbers
166 ) if C4::Context->preference('RealTimeHoldsQueue');
169 my $json = $self->json;
170 my $job_data = $json->decode($self->data);
171 $job_data->{messages} = \@messages;
172 $job_data->{report} = $report;
174 $self->ended_on(dt_from_string)
175 ->data($json->encode($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',