createUser(['ROLE_DOCTOR']), 'دکتر تست'); $this->em->persist($doctor); $this->em->flush(); return $doctor; } private function newBooking(Doctor $doctor, int $start): Appointment { $a = $this->newAppointment($doctor, $this->createUser(), $start, $start + 1_800); $this->em->persist($a); $this->em->flush(); return $a; } public function testDayOfWorkflowTransitions(): void { $a = $this->newBooking($this->makeDoctor(), time() + 86_400); $a->transitionTo(Appointment::STATUS_CONFIRMED); $a->transitionTo(Appointment::STATUS_FOLLOWING_UP); $a->transitionTo(Appointment::STATUS_SALON); $a->transitionTo(Appointment::STATUS_COMPLETED); $this->em->flush(); self::assertSame(Appointment::STATUS_COMPLETED, $a->getStatus()); } public function testPendingCannotJumpToSalon(): void { $a = $this->newBooking($this->makeDoctor(), time() + 86_400); $this->expectException(\LogicException::class); $a->transitionTo(Appointment::STATUS_SALON); } public function testWorkflowFieldsPersistAndSerialize(): void { $a = $this->newBooking($this->makeDoctor(), time() + 86_400); $a->setDepositRequired(true) ->setDepositAmountRials(5_000_000); $a->rescheduleTo($a->getSlotStart(), $a->getSlotEnd(), true); $this->em->flush(); $this->em->clear(); $reloaded = $this->em->getRepository(Appointment::class)->findOneBy(['uuid' => $a->getUuid()]); $arr = $reloaded->toArray(); self::assertTrue($arr['deposit_required']); self::assertSame(5_000_000, $arr['deposit_amount_rials']); self::assertTrue($arr['is_reserve']); self::assertNull($arr['service_section']); self::assertNull($arr['staff']); } public function testRescheduleFreesTheOldSlot(): void { $doctor = $this->makeDoctor(); $start = time() + 86_400; $first = $this->newBooking($doctor, $start); $first->rescheduleTo($start + 3_600, $start + 5_400); $this->em->flush(); // old slot must be free again — a new live booking on it succeeds $second = $this->newBooking($doctor, $start); self::assertNotNull($second->getId()); } }