From 9c9db05b865273818bc593ff84d03cb65c949463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Fri, 9 Jan 2026 09:39:35 +0100 Subject: [PATCH] feat: cli command to backfill travel dates on draft records, single use --- .../DraftBackfillTravelDateCommand.php | 118 ++++++++++++++++++ src/Entity/BookingEditDraft.php | 7 ++ 2 files changed, 125 insertions(+) create mode 100644 src/Command/DraftBackfillTravelDateCommand.php diff --git a/src/Command/DraftBackfillTravelDateCommand.php b/src/Command/DraftBackfillTravelDateCommand.php new file mode 100644 index 0000000..1cc3abe --- /dev/null +++ b/src/Command/DraftBackfillTravelDateCommand.php @@ -0,0 +1,118 @@ +addOption('dry-run', null, InputOption::VALUE_NONE, 'Show what would be updated without actually updating'); + } + + /** + * @see \Symfony\Component\Console\Command\Command::execute() + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $dryRun = $input->getOption('dry-run'); + + $drafts = $this->draftRepository->findAll(); + + if (0 === \count($drafts)) { + $io->success('No drafts found.'); + + return Command::SUCCESS; + } + + $io->title(sprintf('Processing %d draft(s)', \count($drafts))); + + $updated = 0; + $failed = 0; + $skipped = 0; + + foreach ($drafts as $draft) { + $bookingId = $draft->getBookingId(); + $user = $draft->getUser(); + + $bookingData = $this->dataLoader->fetchBookingData($bookingId, $user); + + if (!$bookingData instanceof Booking) { + $io->warning(sprintf('Could not fetch booking %d for user %s', $bookingId, $user->getEmail())); + ++$failed; + + continue; + } + + $travelDate = $bookingData->travel->dateFrom ?? null; + + if (null === $travelDate) { + $io->warning(sprintf('No travel date found for booking %d', $bookingId)); + ++$skipped; + + continue; + } + + if ($dryRun) { + $io->text(sprintf( + '[DRY RUN] Would set travel date %s for draft %d (booking %d)', + $travelDate->format('Y-m-d'), + $draft->getId(), + $bookingId + )); + } else { + $draft->setTravelDate($travelDate); + } + + ++$updated; + } + + if (false === $dryRun) { + $this->entityManager->flush(); + } + + $io->newLine(); + $io->table( + ['Status', 'Count'], + [ + ['Updated', $updated], + ['Failed (API error)', $failed], + ['Skipped (no date)', $skipped], + ] + ); + + if ($dryRun) { + $io->note('Dry run - no changes were made.'); + } else { + $io->success(sprintf('Updated %d draft(s).', $updated)); + } + + return Command::SUCCESS; + } +} diff --git a/src/Entity/BookingEditDraft.php b/src/Entity/BookingEditDraft.php index c10c93a..651521c 100644 --- a/src/Entity/BookingEditDraft.php +++ b/src/Entity/BookingEditDraft.php @@ -67,6 +67,13 @@ class BookingEditDraft return $this->travelDate; } + public function setTravelDate(\DateTimeImmutable $travelDate): static + { + $this->travelDate = $travelDate; + + return $this; + } + public function getFormData(): array { return $this->formData;