client->getResponse()->getContent(), true) ?? []; return $json['data']['data'] ?? []; } private function week(array $session): array { $days = array_fill_keys(range(0, 6), ['sessions' => []]); $days[0] = ['sessions' => [$session]]; return $days; } private function session(bool $active, int $locationId): array { return [ 'active' => $active, 'location_id' => $locationId, 'start_time' => '09:00', 'end_time' => '13:00', 'duration_per_patient' => 20, ]; } /** @return array{doctor: Doctor, personal: WeeklySchedule, clinic: WeeklySchedule} */ private function makeDoctorWithInactivePersonalAndClinic(): array { $doctor = new Doctor($this->createUser(['ROLE_USER', 'ROLE_DOCTOR']), 'دکتر تجمیع'); $this->em->persist($doctor); $clinic = new Clinic($this->createUser(['ROLE_USER', 'ROLE_CLINIC'])); $clinic->setName('کلینیک تجمیع'); $clinic->getDoctors()->add($doctor); $this->em->persist($clinic); $this->em->flush(); $personalAddress = DoctorAddress::forDoctor($doctor); $this->em->persist($personalAddress); $clinicAddress = DoctorAddress::forClinic($clinic->getId()); $this->em->persist($clinicAddress); $this->em->flush(); $personal = $this->newWeeklySchedule($doctor, $this->week($this->session(false, $personalAddress->getId()))); $clinicSchedule = $this->newWeeklySchedule( $doctor, $this->week($this->session(true, $clinicAddress->getId())), $clinic ); $this->em->persist($personal); $this->em->persist($clinicSchedule); $this->em->flush(); return ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule]; } public function testClinicScheduleKeepsDoctorBookableDespiteEmptyPersonalSchedule(): void { ['doctor' => $doctor] = $this->makeDoctorWithInactivePersonalAndClinic(); $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid()); $data = $this->doctorPayload(); $this->assertTrue($data['active']); $this->assertStringContainsString('شنبه', $data['free_turn']); } public function testAllSchedulesDisabledReportsBookingDisabled(): void { ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule] = $this->makeDoctorWithInactivePersonalAndClinic(); $personal->setMeta(['online_booking_enabled' => false]); $clinicSchedule->setMeta(['online_booking_enabled' => false]); $this->em->flush(); $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid()); $data = $this->doctorPayload(); $this->assertFalse($data['active']); $this->assertSame('نوبت‌دهی آنلاین غیرفعال است', $data['free_turn']); } public function testDetailExposesRawIsActiveFlagForDeactivatedDoctor(): void { ['doctor' => $doctor] = $this->makeDoctorWithInactivePersonalAndClinic(); // فلگ روشن (پیش‌فرض): is_active باید true باشد. $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid()); $this->assertTrue($this->doctorPayload()['is_active']); // ادمین پزشک را غیرفعال می‌کند → is_active=false (مبنای 404 در سایت عمومی). $doctor->setActiveDoctorAppointment(false); $this->em->flush(); $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid()); $data = $this->doctorPayload(); $this->assertFalse($data['is_active']); $this->assertFalse($data['active']); } public function testDisabledClinicScheduleDoesNotMaskActivePersonalSchedule(): void { ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule] = $this->makeDoctorWithInactivePersonalAndClinic(); // برعکسِ سناریوی اول: شخصی فعال، کلینیکی خاموش — ترتیب ردیف‌ها نباید مهم باشد. $personal->setSetting($this->week($this->session(true, 0))); $clinicSchedule->setMeta(['online_booking_enabled' => false]); $this->em->flush(); $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid()); $data = $this->doctorPayload(); $this->assertTrue($data['active']); $this->assertStringContainsString('شنبه', $data['free_turn']); } }