createUser(['ROLE_CLINIC']); $clinic = new Clinic($owner); $this->em->persist($clinic); $doctors = []; for ($i = 0; $i < $count; $i++) { $doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), "دکتر $i"); $this->em->persist($doctor); $clinic->getDoctors()->add($doctor); $doctors[] = $doctor; } $this->em->flush(); return [$owner, $clinic, $doctors]; } private function mobile(): string { return '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT); } public function testClinicOwnerAssignsSecretaryToMultipleDoctors(): void { [$owner, , $doctors] = $this->makeClinicWithDoctors(3); $body = $this->authJson('POST', '/api/v1/secretary', $owner, [ 'mobile_number' => $this->mobile(), 'name' => 'منشی مشترک', 'doctor_uuids' => [$doctors[0]->getUuid(), $doctors[1]->getUuid()], ]); $this->assertSame(201, $this->responseCode()); $this->assertCount(2, $body['data']['created']); $this->assertSame([], $body['data']['skipped_not_in_clinic']); $this->assertNotEmpty($body['data']['secretary_uuid']); } public function testSkipsDuplicatesOnReassign(): void { [$owner, , $doctors] = $this->makeClinicWithDoctors(2); $mobile = $this->mobile(); $uuids = [$doctors[0]->getUuid(), $doctors[1]->getUuid()]; $this->authJson('POST', '/api/v1/secretary', $owner, ['mobile_number' => $mobile, 'doctor_uuids' => $uuids]); $body = $this->authJson('POST', '/api/v1/secretary', $owner, ['mobile_number' => $mobile, 'doctor_uuids' => $uuids]); $this->assertSame(201, $this->responseCode()); $this->assertCount(0, $body['data']['created']); $this->assertCount(2, $body['data']['skipped_duplicate']); } public function testRejectsDoctorOutsideClinic(): void { [$owner, , $doctors] = $this->makeClinicWithDoctors(1); $foreignDoctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'خارج از کلینیک'); $this->em->persist($foreignDoctor); $this->em->flush(); $body = $this->authJson('POST', '/api/v1/secretary', $owner, [ 'mobile_number' => $this->mobile(), 'doctor_uuids' => [$doctors[0]->getUuid(), $foreignDoctor->getUuid()], ]); $this->assertSame(201, $this->responseCode()); $this->assertCount(1, $body['data']['created']); $this->assertContains($foreignDoctor->getUuid(), $body['data']['skipped_not_in_clinic']); } public function testSyncAddsAndRemovesDoctors(): void { [$owner, $clinic, $doctors] = $this->makeClinicWithDoctors(3); $mobile = $this->mobile(); $assigned = $this->authJson('POST', '/api/v1/secretary', $owner, [ 'mobile_number' => $mobile, 'doctor_uuids' => [$doctors[0]->getUuid(), $doctors[1]->getUuid()], ]); $secretaryUuid = $assigned['data']['secretary_uuid']; // sync to {doctor1, doctor2} → drop doctor0, add doctor2 $body = $this->authJson('PUT', '/api/v1/secretaries/clinic/' . $clinic->getUuid() . '/doctors', $owner, [ 'secretary_uuid' => $secretaryUuid, 'doctor_uuids' => [$doctors[1]->getUuid(), $doctors[2]->getUuid()], ]); $this->assertSame(200, $this->responseCode()); $this->assertSame(1, $body['data']['added']); // doctor2 $this->assertSame(1, $body['data']['removed']); // doctor0 } public function testSyncCopiesProfileAndPermissionsToNewLinks(): void { [$owner, $clinic, $doctors] = $this->makeClinicWithDoctors(2); $mobile = $this->mobile(); $assigned = $this->authJson('POST', '/api/v1/secretary', $owner, [ 'mobile_number' => $mobile, 'doctor_uuids' => [$doctors[0]->getUuid()], 'national_code' => '1212121212', 'address' => 'یزد، خیابان تست', 'permissions' => ['version' => 1, 'resources' => ['patients' => ['view' => true]]], ]); $secretaryUuid = $assigned['data']['secretary_uuid']; // adding a second doctor must clone the person's profile onto the new link $this->authJson('PUT', '/api/v1/secretaries/clinic/' . $clinic->getUuid() . '/doctors', $owner, [ 'secretary_uuid' => $secretaryUuid, 'doctor_uuids' => [$doctors[0]->getUuid(), $doctors[1]->getUuid()], ]); $this->assertSame(200, $this->responseCode()); $rows = $this->authJson('GET', '/api/v1/secretaries/clinic/' . $clinic->getUuid(), $owner); $this->assertCount(2, $rows['data']); foreach ($rows['data'] as $row) { $this->assertSame('1212121212', $row['national_code']); $this->assertSame('یزد، خیابان تست', $row['address']); $this->assertTrue($row['permissions']['patients']['view']); } } public function testForeignOwnerCannotSync(): void { [, $clinic, ] = $this->makeClinicWithDoctors(1); $intruder = $this->createUser(['ROLE_CLINIC']); $this->authJson('PUT', '/api/v1/secretaries/clinic/' . $clinic->getUuid() . '/doctors', $intruder, [ 'secretary_uuid' => 'whatever', 'doctor_uuids' => [], ]); $this->assertSame(403, $this->responseCode()); } }