diff --git a/src/Appointment/Command/CancelExpiredAppointmentsCommand.php b/src/Appointment/Command/CancelExpiredAppointmentsCommand.php index f1fd98b8..61d20a75 100644 --- a/src/Appointment/Command/CancelExpiredAppointmentsCommand.php +++ b/src/Appointment/Command/CancelExpiredAppointmentsCommand.php @@ -11,7 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface; #[AsCommand( name: 'app:cancel-expired-appointments', - description: 'Marks pending appointments whose slot_start is in the past as expired', + description: 'Expires pending bookings whose 15-min payment window lapsed or whose slot time has passed', )] class CancelExpiredAppointmentsCommand extends Command { @@ -22,9 +22,14 @@ class CancelExpiredAppointmentsCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - $expired = $this->appointmentRepo->findExpiredPending(time()); - $count = 0; + $now = time(); + $expired = []; + foreach ([...$this->appointmentRepo->findPaymentExpired($now), ...$this->appointmentRepo->findExpiredPending($now)] as $appointment) { + $expired[$appointment->getUuid()] = $appointment; + } + + $count = 0; foreach ($expired as $appointment) { $appointment->transitionTo(Appointment::STATUS_EXPIRED); $this->appointmentRepo->save($appointment, false); @@ -32,7 +37,7 @@ class CancelExpiredAppointmentsCommand extends Command } if ($count > 0) { - $this->appointmentRepo->save($expired[0]); // flush once + $this->appointmentRepo->save(reset($expired)); // flush once } $output->writeln(sprintf('Expired %d appointments.', $count)); diff --git a/src/Appointment/Repository/AppointmentRepository.php b/src/Appointment/Repository/AppointmentRepository.php index 00e6c155..f86aab47 100644 --- a/src/Appointment/Repository/AppointmentRepository.php +++ b/src/Appointment/Repository/AppointmentRepository.php @@ -80,6 +80,19 @@ class AppointmentRepository extends ServiceEntityRepository return $this->findBy($criteria, ['slotStart' => 'DESC']); } + /** @return Appointment[] pending bookings whose 15-minute payment window has lapsed */ + public function findPaymentExpired(int $now): array + { + return $this->createQueryBuilder('a') + ->where('a.status = :status') + ->andWhere('a.expiresAt IS NOT NULL') + ->andWhere('a.expiresAt < :now') + ->setParameter('status', Appointment::STATUS_PENDING) + ->setParameter('now', $now) + ->getQuery() + ->getResult(); + } + /** @return Appointment[] pending appointments older than given timestamp */ public function findExpiredPending(int $before): array {