Files
clinicpro/tests/Insurance/TenantInsurancePerDoctorTest.php
T
hamed 5507b42fd8 feat: implement per-doctor insurance settings in multi-doctor clinics
- Updated InsuranceModal to include doctorUuid in the payload for insurance contracts.
- Enhanced TenantInsuranceContracts to allow selection of doctors and pass doctorUuid in API requests.
- Modified InsuranceController to handle doctorUuid for tenant insurance endpoints, ensuring contracts are stored per doctor.
- Updated API documentation to reflect the new optional doctor_uuid parameter for tenant insurance endpoints.
- Added tests to verify the functionality of per-doctor insurance contracts and ensure isolation of contracts between doctors.
2026-07-21 19:21:55 +03:30

134 lines
5.3 KiB
PHP

<?php
namespace App\Tests\Insurance;
use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
use App\Insurance\Entity\Insurance;
use App\Insurance\Enum\InsuranceType;
use App\Tests\ApiTestCase;
use Symfony\Component\Uid\Uuid;
/**
* درصد و شرایط هر بیمه می‌تواند برای هر پزشک متفاوت باشد؛ در کلینیک چندپزشکه قرارداد
* بیمه به‌ازای پزشک (`doctor_uuid`) ذخیره می‌شود، نه یک‌بار در سطح کلینیک. این تست
* هدف‌گیری per-doctor روی اندپوینت‌های tenant-insurances را پوشش می‌دهد.
*/
class TenantInsurancePerDoctorTest extends ApiTestCase
{
private function makeDoctor(string $name): Doctor
{
$user = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
$doctor = new Doctor($user, $name);
$doctor->setMobileNumber($user->getMobileNumber());
$this->em->persist($doctor);
$this->em->flush();
return $doctor;
}
/** @return array{0: \App\Auth\Entity\User, 1: Clinic} */
private function makeClinicWith(Doctor ...$doctors): array
{
$owner = $this->createUser(['ROLE_USER', 'ROLE_CLINIC']);
$clinic = new Clinic($owner);
$clinic->setName('کلینیک تست بیمه');
foreach ($doctors as $d) {
$clinic->getDoctors()->add($d);
}
$this->em->persist($clinic);
$this->em->flush();
return [$owner, $clinic];
}
private function makeInsurance(InsuranceType $type = InsuranceType::Basic): Insurance
{
$insurance = new Insurance('بیمه ' . random_int(1000, 9999), $type);
$this->em->persist($insurance);
$this->em->flush();
return $insurance;
}
public function testClinicOwnerCreatesContractForMemberDoctor(): void
{
$doctor = $this->makeDoctor('دکتر عضو');
[$owner, $clinic] = $this->makeClinicWith($doctor);
$insurance = $this->makeInsurance();
$body = $this->authJson('POST', '/api/v1/billing/tenant-insurances', $owner, [
'doctor_uuid' => $doctor->getUuid(),
'insurance_id' => $insurance->getId(),
'coverage_percent' => 80,
]);
self::assertSame(201, $this->responseCode());
self::assertSame('doctor', $body['data']['data']['entity_type']);
self::assertSame($doctor->getId(), $body['data']['data']['entity_id']);
}
public function testContractsAreIsolatedPerDoctor(): void
{
$first = $this->makeDoctor('دکتر اول');
$second = $this->makeDoctor('دکتر دوم');
[$owner, $clinic] = $this->makeClinicWith($first, $second);
$insA = $this->makeInsurance();
$insB = $this->makeInsurance();
$this->authJson('POST', '/api/v1/billing/tenant-insurances', $owner, [
'doctor_uuid' => $first->getUuid(), 'insurance_id' => $insA->getId(), 'coverage_percent' => 70,
]);
$this->authJson('POST', '/api/v1/billing/tenant-insurances', $owner, [
'doctor_uuid' => $second->getUuid(), 'insurance_id' => $insB->getId(), 'coverage_percent' => 40,
]);
$body = $this->authJson('GET', "/api/v1/billing/tenant-insurances?doctor_uuid={$first->getUuid()}", $owner);
self::assertSame(200, $this->responseCode());
$insuranceIds = array_map(fn ($r) => $r['insurance_id'], $body['data']['data']);
self::assertContains($insA->getId(), $insuranceIds, 'قرارداد پزشک اول باید دیده شود');
self::assertNotContains($insB->getId(), $insuranceIds, 'قرارداد پزشک دوم نباید در فهرست پزشک اول باشد');
}
public function testStrangerDoctorUuidIsForbidden(): void
{
$member = $this->makeDoctor('دکتر عضو');
$outsider = $this->makeDoctor('دکتر بیرونی');
[$owner, $clinic] = $this->makeClinicWith($member);
$insurance = $this->makeInsurance();
$this->authJson('POST', '/api/v1/billing/tenant-insurances', $owner, [
'doctor_uuid' => $outsider->getUuid(),
'insurance_id' => $insurance->getId(),
'coverage_percent' => 50,
]);
self::assertSame(403, $this->responseCode(), 'پزشکِ خارج از کلینیک قابل تنظیم نیست');
}
public function testUnknownDoctorUuidReturns404(): void
{
[$owner] = $this->makeClinicWith($this->makeDoctor('دکتر عضو'));
$this->authJson('GET', '/api/v1/billing/tenant-insurances?doctor_uuid=' . Uuid::v4()->toRfc4122(), $owner);
self::assertSame(404, $this->responseCode());
}
public function testWithoutDoctorUuidKeepsLegacyBehavior(): void
{
$doctor = $this->makeDoctor('دکتر مستقل');
$insurance = $this->makeInsurance();
$body = $this->authJson('POST', '/api/v1/billing/tenant-insurances', $doctor->getUser(), [
'insurance_id' => $insurance->getId(),
'coverage_percent' => 60,
]);
self::assertSame(201, $this->responseCode());
self::assertSame('doctor', $body['data']['data']['entity_type']);
self::assertSame($doctor->getId(), $body['data']['data']['entity_id']);
}
}