createUser(['ROLE_DOCTOR']); $doctor = new Doctor($owner, 'دکتر'); $this->em->persist($doctor); $this->em->flush(); return [$owner, $doctor]; } public function testCreateWithWorkflowFields(): void { [$owner, $doctor] = $this->doctor(); $section = new ServiceSection('doctor', $doctor->getId(), 'زیبایی'); $item = new ServiceItem($section, 'لیزر فول بادی'); $staff = new ClinicStaff('doctor', $doctor->getId(), 'سحر ایمانی'); $this->em->persist($section); $this->em->persist($item); $this->em->persist($staff); $this->em->flush(); $start = time() + 86_400; $res = $this->authJson('POST', '/api/v1/my/appointment', $owner, [ 'doctor_uuid' => $doctor->getUuid(), 'slot_start' => $start, 'slot_end' => $start + 2_400, 'patient_mobile' => '09' . random_int(100000000, 999999999), 'patient_name' => 'مریم اسکندری', 'patient_national_code' => '00' . str_pad((string) random_int(0, 99_999_999), 8, '0', STR_PAD_LEFT), 'service_section_uuid' => $section->getUuid(), 'service_item_uuid' => $item->getUuid(), 'staff_uuid' => $staff->getUuid(), 'deposit_required' => true, 'deposit_amount_rials' => 5_000_000, ]); self::assertSame(201, $this->responseCode()); self::assertFalse($res['data']['is_reserve']); $list = $this->authJson('GET', '/api/v1/my/appointments?limit=50', $owner); $row = $list['data'][0]; self::assertSame('لیزر فول بادی', $row['service_item']['name']); self::assertSame('سحر ایمانی', $row['staff']['full_name']); self::assertTrue($row['deposit_required']); } public function testReserveEntriesSkipSlotRulesAndAreListedSeparately(): void { [$owner, $doctor] = $this->doctor(); $day = strtotime('today midnight'); // past for a slot booking — fine for a reserve // two reserves on the same day must both succeed (no slot occupation) foreach (['ساغر صابری', 'پریسا همتی'] as $name) { $this->authJson('POST', '/api/v1/my/appointment', $owner, [ 'doctor_uuid' => $doctor->getUuid(), 'slot_start' => $day, 'slot_end' => $day, 'patient_mobile' => '09' . random_int(100000000, 999999999), 'patient_name' => $name, 'patient_national_code' => '00' . str_pad((string) random_int(0, 99_999_999), 8, '0', STR_PAD_LEFT), 'is_reserve' => true, ]); self::assertSame(201, $this->responseCode()); } $reserves = $this->authJson('GET', '/api/v1/my/appointments?reserve=1&limit=50', $owner); self::assertCount(2, $reserves['data']); self::assertTrue($reserves['data'][0]['is_reserve']); // the regular list must not contain reserve entries $regular = $this->authJson('GET', '/api/v1/my/appointments?limit=50', $owner); self::assertCount(0, $regular['data']); } public function testExistingProfileNameWinsOverModalInput(): void { [$owner, $doctor] = $this->doctor(); $nationalCode = '00' . str_pad((string) random_int(0, 99_999_999), 8, '0', STR_PAD_LEFT); $mobile = '09' . random_int(100000000, 999999999); $start = time() + 86_400; // First booking registers the patient's profile under their real name. $this->authJson('POST', '/api/v1/my/appointment', $owner, [ 'doctor_uuid' => $doctor->getUuid(), 'slot_start' => $start, 'slot_end' => $start + 1_800, 'patient_mobile' => $mobile, 'patient_name' => 'علی احمدی', 'patient_national_code' => $nationalCode, ]); self::assertSame(201, $this->responseCode()); // Second booking uses the same national code but a mistyped modal name. $start2 = $start + 3_600; $this->authJson('POST', '/api/v1/my/appointment', $owner, [ 'doctor_uuid' => $doctor->getUuid(), 'slot_start' => $start2, 'slot_end' => $start2 + 1_800, 'patient_mobile' => $mobile, 'patient_name' => 'نام غلط', 'patient_national_code' => $nationalCode, ]); self::assertSame(201, $this->responseCode()); // Every listed appointment must show the profile name, never the mistype. $list = $this->authJson('GET', '/api/v1/my/appointments?limit=50', $owner); $names = array_column($list['data'], 'patient_name'); self::assertContains('علی احمدی', $names); self::assertNotContains('نام غلط', $names); } public function testUnknownServiceUuidIs422(): void { [$owner, $doctor] = $this->doctor(); $start = time() + 86_400; $this->authJson('POST', '/api/v1/my/appointment', $owner, [ 'doctor_uuid' => $doctor->getUuid(), 'slot_start' => $start, 'slot_end' => $start + 1_800, 'patient_mobile' => '09' . random_int(100000000, 999999999), 'patient_name' => 'x', 'patient_national_code' => '00' . str_pad((string) random_int(0, 99_999_999), 8, '0', STR_PAD_LEFT), 'service_item_uuid' => 'missing-uuid', ]); self::assertSame(422, $this->responseCode()); } }