createUser(['ROLE_DOCTOR']); $doctor = new Doctor($owner, 'دکتر تست'); $this->em->persist($doctor); $this->em->flush(); $patient = $this->createUser(['ROLE_USER']); $record = new PatientRecord('doctor', $doctor->getId(), $patient, 'doctor', $doctor->getId()); $this->em->persist($record); $this->em->flush(); return [$owner, $doctor, $record]; } private function serviceItem(Doctor $doctor, int $priceRials, bool $insuranceCovered): ServiceItem { $section = new ServiceSection('doctor', $doctor->getId(), 'جراحی'); $this->em->persist($section); $item = new ServiceItem($section, 'جراحی بینی', $priceRials); $item->setInsuranceCovered($insuranceCovered); $this->em->persist($item); $this->em->flush(); return $item; } /** Active contract covering $coveragePercent of every covered service. */ private function contract(Doctor $doctor, float $coveragePercent, ?ServiceItem $item = null): Insurance { $insurance = new Insurance('تامین اجتماعی', InsuranceType::Basic); $this->em->persist($insurance); $this->em->flush(); $contract = new TenantInsurance('doctor', $doctor->getId(), $insurance->getId()); $contract->setCoveragePercent($coveragePercent)->setActive(true); $this->em->persist($contract); $this->em->flush(); if ($item !== null) { $coverage = new TenantServiceCoverage($contract->getId(), $item->getId()); $coverage->setCovered(true)->setCoveragePercent($coveragePercent); $this->em->persist($coverage); $this->em->flush(); } return $insurance; } public function testSessionStoresInsuranceAndPatientSharesForACoveredService(): void { [$owner, $doctor, $record] = $this->tenant(); $item = $this->serviceItem($doctor, 40_000_000, true); $insurance = $this->contract($doctor, 70.0, $item); $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'visit_price_rials' => 3_000_000, 'insurance_base_id' => $insurance->getId(), 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 1]], ]); self::assertSame(201, $this->responseCode()); $session = $res['data']; // 70% of both the visit and the service is carried by the insurer. self::assertSame(43_000_000, $session['gross_total_rials']); self::assertSame(30_100_000, $session['base_insurance_rials']); self::assertSame(0, $session['supplementary_insurance_rials']); self::assertSame(12_900_000, $session['patient_share_rials']); // The payable amount is the patient share, not the gross total. self::assertSame(12_900_000, $session['final_price_rials']); self::assertSame(12_900_000, $session['remaining_rials']); } public function testTheBreakdownAlwaysSumsBackToTheGrossTotal(): void { [$owner, $doctor, $record] = $this->tenant(); $item = $this->serviceItem($doctor, 1_234_567, true); $insurance = $this->contract($doctor, 33.33, $item); $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'visit_price_rials' => 987_654, 'insurance_base_id' => $insurance->getId(), 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 3]], ]); self::assertSame(201, $this->responseCode()); $s = $res['data']; self::assertSame( $s['gross_total_rials'], $s['base_insurance_rials'] + $s['supplementary_insurance_rials'] + $s['patient_share_rials'], ); } public function testAServiceWithoutCoverageLeavesTheWholeAmountToThePatient(): void { [$owner, $doctor, $record] = $this->tenant(); $item = $this->serviceItem($doctor, 40_000_000, false); $insurance = $this->contract($doctor, 70.0); $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'visit_price_rials' => 0, 'insurance_base_id' => $insurance->getId(), 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 1]], ]); self::assertSame(201, $this->responseCode()); $s = $res['data']; self::assertSame(0, $s['base_insurance_rials']); self::assertSame(40_000_000, $s['patient_share_rials']); self::assertSame(40_000_000, $s['final_price_rials']); } public function testSessionWithoutInsuranceKeepsTheFullAmountAsThePatientShare(): void { [$owner, $doctor, $record] = $this->tenant(); $item = $this->serviceItem($doctor, 2_400_000, true); $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'visit_price_rials' => 500_000, 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 1]], ]); self::assertSame(201, $this->responseCode()); $s = $res['data']; self::assertSame(2_900_000, $s['gross_total_rials']); self::assertSame(0, $s['base_insurance_rials']); self::assertSame(2_900_000, $s['patient_share_rials']); } }