- 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.
134 lines
5.3 KiB
PHP
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']);
|
|
}
|
|
}
|