- Updated CoverageRule and related entities to include franchise_percent instead of franchise_rials. - Modified Appointment entity to carry supplementary insurance ID alongside base insurance. - Implemented SessionBillingService to ensure finalized invoices for insured patient sessions. - Created InvoiceFinalized event to trigger claims creation upon invoice finalization. - Added BackfillMissingClaimsCommand to generate claims for finalized invoices without existing claims. - Developed tests to validate the new functionality for supplementary insurance handling in appointments and claims.
126 lines
4.3 KiB
PHP
126 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Billing;
|
|
|
|
use App\Auth\Entity\User;
|
|
use App\Billing\Entity\Invoice;
|
|
use App\Billing\Entity\InvoiceItem;
|
|
use App\Billing\Repository\ClaimRepository;
|
|
use App\Billing\Service\InvoiceService;
|
|
use App\Billing\ValueObject\ShareBreakdown;
|
|
use App\Doctor\Entity\Doctor;
|
|
use App\Patient\Entity\PatientRecord;
|
|
use App\Tests\ApiTestCase;
|
|
|
|
/**
|
|
* مطالبهٔ بیمه اثر جانبیِ نهاییشدن صورتحساب است، نه کارِ یک endpoint خاص.
|
|
* پیش از این فقط `POST /api/v1/patient/{uuid}/session` مطالبه میساخت، و هر
|
|
* صورتحسابی که از مسیر دیگری نهایی میشد بیصدا بدون مطالبه میماند.
|
|
*/
|
|
class ClaimAutoCreationTest extends ApiTestCase
|
|
{
|
|
private Doctor $doctor;
|
|
private PatientRecord $record;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$owner = $this->createUser(['ROLE_DOCTOR']);
|
|
$this->doctor = new Doctor($owner, 'دکتر مطالبه');
|
|
$this->em->persist($this->doctor);
|
|
$this->em->flush();
|
|
|
|
$patient = $this->createUser(['ROLE_USER']);
|
|
$this->record = new PatientRecord('doctor', $this->doctor->getId(), $patient, 'doctor', $this->doctor->getId());
|
|
$this->em->persist($this->record);
|
|
$this->em->flush();
|
|
}
|
|
|
|
/** صورتحساب draft با سهم بیمهٔ پایه/تکمیلی روی تنها آیتمش. */
|
|
private function draftInvoice(?int $baseId, ?int $suppId, int $baseShare, int $suppShare): Invoice
|
|
{
|
|
$total = 10_000_000;
|
|
$invoice = new Invoice('doctor', $this->doctor->getId());
|
|
$invoice->setPatientRecordId((int) $this->record->getId())
|
|
->setBaseInsuranceId($baseId)
|
|
->setSupplementaryInsuranceId($suppId);
|
|
|
|
$item = new InvoiceItem(
|
|
$invoice,
|
|
'ویزیت',
|
|
$total,
|
|
1,
|
|
new ShareBreakdown($total, $baseShare, $suppShare, $total - $baseShare - $suppShare),
|
|
);
|
|
$invoice->addItem($item);
|
|
$invoice->recalculateTotals();
|
|
|
|
$this->em->persist($invoice);
|
|
$this->em->persist($item);
|
|
$this->em->flush();
|
|
|
|
return $invoice;
|
|
}
|
|
|
|
private function claimRepo(): ClaimRepository
|
|
{
|
|
return static::getContainer()->get(ClaimRepository::class);
|
|
}
|
|
|
|
private function invoiceService(): InvoiceService
|
|
{
|
|
return static::getContainer()->get(InvoiceService::class);
|
|
}
|
|
|
|
public function testFinalizingAnInsuredInvoiceCreatesItsClaims(): void
|
|
{
|
|
$invoice = $this->draftInvoice(1, 2, 6_000_000, 2_000_000);
|
|
|
|
$this->invoiceService()->finalize($invoice);
|
|
|
|
$kinds = $this->claimRepo()->kindsForInvoice((int) $invoice->getId());
|
|
sort($kinds);
|
|
self::assertSame(['base', 'supplementary'], $kinds);
|
|
}
|
|
|
|
public function testASupplementaryOnlyInvoiceStillGetsItsClaim(): void
|
|
{
|
|
// همان حالتی که در پنل دیده شد: بیمار بیمهٔ پایه ندارد، فقط تکمیلی.
|
|
$invoice = $this->draftInvoice(null, 2, 0, 4_760_000);
|
|
|
|
$this->invoiceService()->finalize($invoice);
|
|
|
|
self::assertSame(['supplementary'], $this->claimRepo()->kindsForInvoice((int) $invoice->getId()));
|
|
}
|
|
|
|
public function testFinalizingTwiceDoesNotDuplicateClaims(): void
|
|
{
|
|
$invoice = $this->draftInvoice(1, null, 3_000_000, 0);
|
|
|
|
$this->invoiceService()->finalize($invoice);
|
|
$this->invoiceService()->finalize($invoice);
|
|
|
|
self::assertCount(1, $this->claimRepo()->kindsForInvoice((int) $invoice->getId()));
|
|
}
|
|
|
|
public function testAnInvoiceWithoutAnyInsuranceShareGetsNoClaim(): void
|
|
{
|
|
$invoice = $this->draftInvoice(null, null, 0, 0);
|
|
|
|
$this->invoiceService()->finalize($invoice);
|
|
|
|
self::assertSame([], $this->claimRepo()->kindsForInvoice((int) $invoice->getId()));
|
|
}
|
|
|
|
/** بیمهای که فقط روی صورتحساب ثبت شده ولی سهمی نبرده، مطالبه نمیسازد. */
|
|
public function testAZeroShareInsuranceIsNotClaimed(): void
|
|
{
|
|
$invoice = $this->draftInvoice(1, 2, 6_000_000, 0);
|
|
|
|
$this->invoiceService()->finalize($invoice);
|
|
|
|
self::assertSame(['base'], $this->claimRepo()->kindsForInvoice((int) $invoice->getId()));
|
|
}
|
|
}
|