From 9755b9db7ee9a59836e45c821b1b2d10bd022898 Mon Sep 17 00:00:00 2001 From: stevan Date: Mon, 20 Oct 2025 13:04:22 +0200 Subject: [PATCH] Command find duplicate and delete --- app/Console/Commands/CleanDuplicateEvents.php | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 app/Console/Commands/CleanDuplicateEvents.php diff --git a/app/Console/Commands/CleanDuplicateEvents.php b/app/Console/Commands/CleanDuplicateEvents.php new file mode 100644 index 000000000..672910af5 --- /dev/null +++ b/app/Console/Commands/CleanDuplicateEvents.php @@ -0,0 +1,128 @@ +option('delete'); + + $this->info(sprintf( + 'Scanning for possible duplicate events... (mode: %s)', + $shouldDelete ? 'DELETE' : 'DRY-RUN' + )); + + // --- Detect duplicate event pairs --- + $duplicates = DB::select(" + SELECT + e1.id AS id1, + e2.id AS id2, + e1.title, + e1.start_date, + e1.end_date, + TIMESTAMPDIFF(SECOND, e1.created_at, e2.created_at) AS diff_seconds + FROM events e1 + JOIN events e2 ON e2.id = e1.id + 1 + WHERE e1.title = e2.title + AND e1.start_date = e2.start_date + AND e1.end_date = e2.end_date + AND ABS(TIMESTAMPDIFF(SECOND, e1.created_at, e2.created_at)) < 2 + ORDER BY e1.id + "); + + if (empty($duplicates)) { + $this->info('No duplicate events found.'); + return self::SUCCESS; + } + + $this->info(sprintf('Found %d duplicate pair(s):', count($duplicates))); + + $rows = []; + foreach ($duplicates as $row) { + $rows[] = [ + $row->id1, + $row->id2, + $row->title, + $row->start_date, + $row->end_date, + $row->diff_seconds . 's', + ]; + } + + $this->table(['Event ID A', 'Event ID B', 'Title', 'Start', 'End', 'At'], $rows); + + if (!$shouldDelete) { + $this->newLine(); + $this->info('💡 Use --delete to remove duplicates permanently after review.'); + return self::SUCCESS; + } + + $confirm = $this->confirm( + sprintf('Are you sure you want to delete %d duplicate entries (including pivot records)?', count($duplicates)) + ); + if (!$confirm) { + $this->warn('Aborted. No records deleted.'); + return self::SUCCESS; + } + + // --- Proceed deletion safely --- + $toDelete = array_column($duplicates, 'id2'); + $deleted = 0; + + $bar = $this->output->createProgressBar(count($toDelete)); + $bar->start(); + + DB::beginTransaction(); + try { + foreach ($toDelete as $eventId) { + DB::table('event_tag')->where('event_id', $eventId)->delete(); + DB::table('event_theme')->where('event_id', $eventId)->delete(); + DB::table('audience_event')->where('event_id', $eventId)->delete(); + + DB::table('events')->where('id', $eventId)->delete(); + + $deleted++; + $bar->advance(); + } + + DB::commit(); + } catch (\Throwable $e) { + DB::rollBack(); + $bar->finish(); + $this->error("\nError occurred: " . $e->getMessage()); + return self::FAILURE; + } + + $bar->finish(); + $this->newLine(2); + $this->info(sprintf('Successfully deleted %d duplicate event(s) and related pivot records.', $deleted)); + + return self::SUCCESS; + } +}