From 41c70c0151c1cfb3e163a3ca23bca08fa8445e49 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Wed, 21 Oct 2026 04:36:54 +0530 Subject: [PATCH] fix(abdm): provide separate Document Reference section in InvoiceRecord so PHR renders DocumentReference accordion card with embedded PDF --- app/Controllers/AbdmGateway.php | 85 +++++++++++--------------- tests/unit/Abdm/FhirGeneratorsTest.php | 8 +-- 2 files changed, 41 insertions(+), 52 deletions(-) diff --git a/app/Controllers/AbdmGateway.php b/app/Controllers/AbdmGateway.php index 130bcf9..74544ba 100644 --- a/app/Controllers/AbdmGateway.php +++ b/app/Controllers/AbdmGateway.php @@ -11508,35 +11508,9 @@ class AbdmGateway extends BaseController public function buildInvoiceRecordPayload(int $invoiceId, int $patientId, string $abhaId): ?array { - if ($this->db->tableExists('invoice_master')) { - $invoice = $this->db->table('invoice_master')->where('id', $invoiceId)->get(1)->getRowArray() ?? []; - if (! empty($invoice)) { - if ($patientId <= 0) { - $patientId = (int) ($invoice['attach_id'] ?? 0); - } - $patientRow = $this->loadPatientRow($patientId); - if ($patientId > 0 && ! empty($patientRow)) { - $items = $this->db->tableExists('invoice_item') - ? $this->db->table('invoice_item')->where('inv_master_id', $invoiceId)->orderBy('id', 'ASC')->get()->getResultArray() - : []; - - $visitDate = (string) ($invoice['inv_date'] ?? date('Y-m-d')); - $patient = $this->buildAbdmPatientResource($patientRow, $patientId, $abhaId); - $bundle = $this->buildSimpleInvoiceBundle($patient, $invoice, $items); - - return [ - 'hi_type' => 'InvoiceRecord', - 'entity_type' => 'invoice', - 'entity_id' => (string) $invoiceId, - 'patient_id' => $patientId, - 'patient_name' => $this->patientDisplayName($patientRow), - 'visit_date' => date('Y-m-d', strtotime($visitDate)), - 'care_context_reference' => 'INV-' . $invoiceId . '-' . date('Y-m-d', strtotime($visitDate)), - 'care_context_display' => 'Invoice ' . (string) ($invoice['invoice_code'] ?? $invoiceId), - 'bundle' => $bundle, - ]; - } - } + $payload = $this->buildInvoiceSourceRecordPayload('charges_invoice', $invoiceId, $patientId, $abhaId); + if ($payload !== null) { + return $payload; } // Support pharmacy invoice_med_master as well @@ -12650,13 +12624,41 @@ class AbdmGateway extends BaseController ]; } - $sectionEntries = [ - ['reference' => $invoiceRef, 'type' => 'Invoice'], + $sections = [ + [ + 'title' => 'Invoice details', + 'code' => ['coding' => [[ + 'system' => 'http://loinc.org', + 'code' => '34775-2', + 'display' => 'Hospital Invoice', + ]]], + 'text' => [ + 'status' => 'generated', + 'div' => '

Billing details for invoice ' + . $escape($invoiceNumber) . '

', + ], + 'entry' => [ + ['reference' => $invoiceRef, 'type' => 'Invoice'], + ], + ], ]; + if ($documentReference !== null) { - $sectionEntries[] = [ - 'reference' => $documentReferenceRef, - 'type' => 'DocumentReference', + $sections[] = [ + 'title' => 'Document Reference', + 'code' => ['coding' => [[ + 'system' => 'http://snomed.info/sct', + 'code' => '419891008', + 'display' => 'Record artifact', + ]]], + 'text' => [ + 'status' => 'generated', + 'div' => '

Document reference for invoice ' + . $escape($invoiceNumber) . '

', + ], + 'entry' => [ + ['reference' => $documentReferenceRef, 'type' => 'DocumentReference'], + ], ]; } @@ -12691,20 +12693,7 @@ class AbdmGateway extends BaseController ]], 'title' => 'Invoice ' . $invoiceNumber, 'custodian' => ['reference' => 'Organization/' . $organizationId], - 'section' => [[ - 'title' => 'Invoice details', - 'code' => ['coding' => [[ - 'system' => 'http://loinc.org', - 'code' => '34775-2', - 'display' => 'Hospital Invoice', - ]]], - 'text' => [ - 'status' => 'generated', - 'div' => '

Billing details for invoice ' - . $escape($invoiceNumber) . '

', - ], - 'entry' => $sectionEntries, - ]], + 'section' => $sections, ]; $resources = [$composition, $patient, $organization, $encounter, $invoiceResource]; diff --git a/tests/unit/Abdm/FhirGeneratorsTest.php b/tests/unit/Abdm/FhirGeneratorsTest.php index 29592a7..3f3e9ea 100644 --- a/tests/unit/Abdm/FhirGeneratorsTest.php +++ b/tests/unit/Abdm/FhirGeneratorsTest.php @@ -422,7 +422,7 @@ final class FhirGeneratorsTest extends CIUnitTestCase $composition['section'][0]['entry'][0]['type'] ?? null, 'NRCeS InvoiceRecord 6.5.0 requires Reference.type to be Invoice' ); - $this->assertCount(2, $composition['section'][0]['entry'] ?? []); + $this->assertCount(1, $composition['section'][0]['entry'] ?? []); $this->assertNotEmpty($composition['author'][0]['reference'] ?? ''); $this->assertNotEmpty($composition['custodian']['reference'] ?? ''); $this->assertContains('https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient', $patient['meta']['profile'] ?? []); @@ -469,9 +469,9 @@ final class FhirGeneratorsTest extends CIUnitTestCase $composition['section'][0]['entry'][0]['reference'] ?? null, $documentReference['context']['related'][0]['reference'] ?? null ); - $this->assertCount(1, $composition['section'], 'NRCeS InvoiceRecord profile requires max 1 section'); - $this->assertSame('DocumentReference', $composition['section'][0]['entry'][1]['type'] ?? null); - $this->assertSame($fullUrlByResourceType['DocumentReference'][0] ?? null, $composition['section'][0]['entry'][1]['reference'] ?? null, 'Document Reference entry must point to the DocumentReference'); + $this->assertCount(2, $composition['section'], 'Composition sections for invoice and document reference'); + $this->assertSame('DocumentReference', $composition['section'][1]['entry'][0]['type'] ?? null); + $this->assertSame($fullUrlByResourceType['DocumentReference'][0] ?? null, $composition['section'][1]['entry'][0]['reference'] ?? null, 'Document Reference entry must point to the DocumentReference'); $this->assertSame('725458005', $documentReference['type']['coding'][0]['code'] ?? null); $this->assertSame('Receipt', $documentReference['type']['coding'][0]['display'] ?? null); $binaries = array_values(array_filter(