doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر بیمه تکمیلی'); $this->em->persist($this->doctor); $this->basic = new Insurance('پایهٔ تست ' . random_int(1000, 9999), InsuranceType::Basic); $this->supplementary = new Insurance('تکمیلی تست ' . random_int(1000, 9999), InsuranceType::Supplementary); $this->em->persist($this->basic); $this->em->persist($this->supplementary); $this->em->flush(); } private function contract(Insurance $insurance, float $percent, float $franchise = 0.0): TenantInsurance { $service = static::getContainer()->get(TenantInsuranceService::class); $contract = $service->activate( TenantInsurance::TYPE_DOCTOR, (int) $this->doctor->getId(), (int) $insurance->getId(), $percent, $franchise, ); $service->setCategoryCoverages($contract, [ ['key' => 'outpatient', 'coverage_percent' => $percent], ['key' => 'inpatient', 'coverage_percent' => $percent], ]); return $contract; } private function appointmentWithVisitPrice(int $rials): Appointment { $appointment = $this->newAppointment($this->doctor, $this->createUser(['ROLE_USER']), 1_790_000_000, 1_790_001_800); $appointment->setVisitPriceRials($rials); $appointment->setInsuranceServiceCategory(ServiceCategory::Outpatient); $appointment->transitionTo(Appointment::STATUS_CONFIRMED); $this->em->persist($appointment); $this->em->flush(); return $appointment; } public function testTheSessionBillsBaseThenSupplementaryOnTheRemainder(): void { $this->contract($this->basic, 30.0); $this->contract($this->supplementary, 90.0, 10.0); $appointment = $this->appointmentWithVisitPrice(10_000_000); static::getContainer()->get(AppointmentInsuranceService::class)->apply($appointment, [ 'insurance_base_id' => $this->basic->getId(), 'insurance_supplementary_id' => $this->supplementary->getId(), ]); $this->em->flush(); $session = static::getContainer()->get(PatientService::class)->autoCreateOnAppointmentConfirm($appointment); // پایه ۳۰٪ از ۱۰,۰۰۰,۰۰۰ → ۳,۰۰۰,۰۰۰؛ باقیمانده ۷,۰۰۰,۰۰۰؛ // تکمیلی ۹۰٪ منهای فرانشیز ۱۰٪ → ۵,۶۰۰,۰۰۰؛ سهم بیمار ۱,۴۰۰,۰۰۰. self::assertSame((int) $this->supplementary->getId(), $session->getInsuranceSupplementaryId()); self::assertSame(3_000_000, $session->getBaseInsuranceRials()); self::assertSame(5_600_000, $session->getSupplementaryInsuranceRials()); self::assertSame(1_400_000, $session->getPatientShareRials()); self::assertSame( $session->getGrossTotalRials(), $session->getBaseInsuranceRials() + $session->getSupplementaryInsuranceRials() + $session->getPatientShareRials(), ); } public function testASupplementaryInsuranceCannotBePickedAsTheBasicOne(): void { $this->contract($this->supplementary, 90.0); $appointment = $this->appointmentWithVisitPrice(1_000_000); $this->expectExceptionMessage('اینجا فقط بیمهٔ پایه قابل انتخاب است'); static::getContainer()->get(AppointmentInsuranceService::class)->apply($appointment, [ 'insurance_base_id' => $this->supplementary->getId(), ]); } public function testABasicInsuranceCannotBePickedAsTheSupplementaryOne(): void { $this->contract($this->basic, 30.0); $appointment = $this->appointmentWithVisitPrice(1_000_000); $this->expectExceptionMessage('اینجا فقط بیمهٔ تکمیلی قابل انتخاب است'); static::getContainer()->get(AppointmentInsuranceService::class)->apply($appointment, [ 'insurance_supplementary_id' => $this->basic->getId(), ]); } public function testAnInsuranceWithoutAnActiveContractIsRefused(): void { $appointment = $this->appointmentWithVisitPrice(1_000_000); $this->expectExceptionMessage('این بیمه برای این پزشک/کلینیک قرارداد فعال ندارد'); static::getContainer()->get(AppointmentInsuranceService::class)->apply($appointment, [ 'insurance_supplementary_id' => $this->supplementary->getId(), ]); } /** مراجعهٔ تکمیلی‌دار باید مطالبهٔ تکمیلی هم بگیرد، نه فقط پایه. */ public function testTheConfirmedVisitProducesBothClaims(): void { $this->contract($this->basic, 30.0); $this->contract($this->supplementary, 90.0, 10.0); $appointment = $this->appointmentWithVisitPrice(10_000_000); static::getContainer()->get(AppointmentInsuranceService::class)->apply($appointment, [ 'insurance_base_id' => $this->basic->getId(), 'insurance_supplementary_id' => $this->supplementary->getId(), ]); $this->em->flush(); // قطعی‌کردن به‌تنهایی باید صورتحساب و مطالبه بسازد — بدون هیچ گام دستی. $session = static::getContainer()->get(PatientService::class)->autoCreateOnAppointmentConfirm($appointment); $invoice = static::getContainer()->get(\App\Billing\Repository\InvoiceRepository::class) ->findBySession((int) $session->getId()); self::assertNotNull($invoice, 'مراجعهٔ بیمه‌دارِ آمده از نوبت باید صورتحساب داشته باشد'); $kinds = static::getContainer()->get(ClaimRepository::class)->kindsForInvoice((int) $invoice->getId()); sort($kinds); self::assertSame(['base', 'supplementary'], $kinds); } }