feat: Enhance insurance billing system to support supplementary insurance
- 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.
This commit is contained in:
@@ -390,6 +390,26 @@ class ClaimRepository extends ServiceEntityRepository
|
||||
return $count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* نوع مطالبههایی که برای این صورتحساب از قبل ثبت شدهاند (`base` / `supplementary`).
|
||||
* مبنای idempotent بودنِ ساخت خودکار مطالبه است.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function kindsForInvoice(int $invoiceId): array
|
||||
{
|
||||
$rows = $this->createQueryBuilder('c')
|
||||
->select('DISTINCT c.insuranceKind AS kind')
|
||||
->join('c.items', 'ci')
|
||||
->join('App\Billing\Entity\InvoiceItem', 'ii', 'WITH', 'ii.id = ci.invoiceItemId')
|
||||
->where('IDENTITY(ii.invoice) = :invoiceId')
|
||||
->setParameter('invoiceId', $invoiceId)
|
||||
->getQuery()
|
||||
->getArrayResult();
|
||||
|
||||
return array_column($rows, 'kind');
|
||||
}
|
||||
|
||||
public function save(Claim $entity, bool $flush = true): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
@@ -29,6 +29,28 @@ class InvoiceRepository extends ServiceEntityRepository
|
||||
return $this->findOneBy(['patientSessionId' => $patientSessionId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* صورتحسابهای نهاییشدهای که بیمهای روی خودشان دارند ولی هیچ مطالبهای برایشان
|
||||
* ثبت نشده — بازماندههای دورانی که مطالبه فقط در یک مسیر ساخته میشد.
|
||||
*
|
||||
* @return Invoice[]
|
||||
*/
|
||||
public function findFinalizedInsuredWithoutClaims(): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->where('i.status = :finalized')
|
||||
->andWhere('i.baseInsuranceId IS NOT NULL OR i.supplementaryInsuranceId IS NOT NULL')
|
||||
->andWhere('NOT EXISTS (
|
||||
SELECT 1 FROM App\Billing\Entity\ClaimItem ci
|
||||
JOIN App\Billing\Entity\InvoiceItem ii WITH ii.id = ci.invoiceItemId
|
||||
WHERE IDENTITY(ii.invoice) = i.id
|
||||
)')
|
||||
->setParameter('finalized', Invoice::STATUS_FINALIZED)
|
||||
->orderBy('i.id', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* A flat, newest-first page of a tenant's recorded (finalized/paid) invoices,
|
||||
* one row per invoice with the patient's name and national code joined in.
|
||||
|
||||
Reference in New Issue
Block a user