diff --git a/app/Controllers/AbdmGateway.php b/app/Controllers/AbdmGateway.php index 800e516..000054f 100644 --- a/app/Controllers/AbdmGateway.php +++ b/app/Controllers/AbdmGateway.php @@ -2718,11 +2718,24 @@ class AbdmGateway extends BaseController $abhaDigits = preg_replace('/\D/', '', $rawAbha); $abhaDigits = is_string($abhaDigits) ? $abhaDigits : ''; - $admissionRaw = trim((string) ($ipdRow['register_date'] ?? '')); - $dischargeRaw = trim((string) ($ipdRow['discharge_date'] ?? '')); - $visitDate = $dischargeRaw !== '' - ? date('Y-m-d', strtotime($dischargeRaw)) - : ($admissionRaw !== '' ? date('Y-m-d', strtotime($admissionRaw)) : date('Y-m-d')); + $admissionDate = trim((string) ($ipdRow['register_date'] ?? '')); + $admissionTime = trim((string) ($ipdRow['reg_time'] ?? $ipdRow['reg_time_bak'] ?? '')); + $admissionRaw = $admissionDate; + if ($admissionTime !== '' && ! str_contains($admissionDate, ':')) { + $admissionRaw = trim($admissionDate . ' ' . $admissionTime); + } + + $dischargeDate = trim((string) ($ipdRow['discharge_date'] ?? '')); + $dischargeTime = trim((string) ($ipdRow['discharge_time'] ?? $ipdRow['discharge_time_bak'] ?? '')); + $dischargeAmpm = trim((string) ($ipdRow['discharge_time_ampm'] ?? '')); + $dischargeRaw = $dischargeDate; + if ($dischargeTime !== '' && ! str_contains($dischargeDate, ':')) { + $dischargeRaw = trim($dischargeDate . ' ' . $dischargeTime . ($dischargeAmpm !== '' ? ' ' . $dischargeAmpm : '')); + } + + $visitDate = $dischargeDate !== '' + ? date('Y-m-d', strtotime($dischargeDate)) + : ($admissionDate !== '' ? date('Y-m-d', strtotime($admissionDate)) : date('Y-m-d')); $diagnoses = []; foreach ($this->ipdRows('ipd_discharge_diagnosis', ['comp_report'], $ipdId) as $row) { diff --git a/app/Libraries/Abdm/Fhir/Generators/DischargeFhirGenerator.php b/app/Libraries/Abdm/Fhir/Generators/DischargeFhirGenerator.php index 5c16e48..2a7a756 100644 --- a/app/Libraries/Abdm/Fhir/Generators/DischargeFhirGenerator.php +++ b/app/Libraries/Abdm/Fhir/Generators/DischargeFhirGenerator.php @@ -257,7 +257,7 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac $catText = trim((string) ($obs['category'] ?? $obs['category_text'] ?? $obs['stage'] ?? $obs['timing'] ?? '')); $isAdm = (stripos($catText, 'Admission') !== false || stripos($text, 'Admission') !== false); $isDis = (stripos($catText, 'Discharge') !== false || stripos($text, 'Discharge') !== false); - $obsCategoryDisplay = $isAdm ? 'General Examination on Admission' : ($isDis ? 'Examination on Discharge' : 'Vital Signs'); + $obsCategoryDisplay = $isAdm ? 'Condition on Admission Time' : ($isDis ? 'Condition on Discharge Time' : 'Vital Signs'); $coding = []; $loincCode = trim((string) ($obs['loinc_code'] ?? '')); @@ -484,7 +484,11 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac } } - $builder->addDocumentReference([ + $rawBytes = base64_decode($data); + $fileSize = is_string($rawBytes) ? strlen($rawBytes) : 0; + $sha1Hash = is_string($rawBytes) && $rawBytes !== '' ? base64_encode(sha1($rawBytes, true)) : ''; + + $docRef = [ 'resourceType' => 'DocumentReference', 'id' => 'discharge-document-' . $recordId . '-' . $idx, 'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentReference']], @@ -509,11 +513,18 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac 'contentType' => (string) ($document['content_type'] ?? 'application/pdf'), 'language' => 'en-IN', 'data' => $data, + 'size' => $fileSize, 'title' => $docTitle, 'creation' => (string) ($document['created_at'] ?? $timestamp), ], ]], - ]); + ]; + + if ($sha1Hash !== '') { + $docRef['content'][0]['attachment']['hash'] = $sha1Hash; + } + + $builder->addDocumentReference($docRef); } $rawObservations = (array) ($source['observations'] ?? []); @@ -537,8 +548,24 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac ]; if (! empty($admissionObsIndexed) && ! empty($dischargeObsIndexed)) { - $sectionDefinitions[] = ['title' => 'General Examination on Admission', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $admissionObsIndexed]; - $sectionDefinitions[] = ['title' => 'Examination on Discharge', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $dischargeObsIndexed]; + $sectionDefinitions[] = ['title' => 'Condition on Admission Time', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $admissionObsIndexed]; + $sectionDefinitions[] = ['title' => 'Condition on Discharge Time', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $dischargeObsIndexed]; + } elseif (! empty($admissionObsIndexed)) { + $sectionDefinitions[] = ['title' => 'Condition on Admission Time', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $admissionObsIndexed]; + if (! empty($rawObservations)) { + $otherObs = array_diff_key($rawObservations, $admissionObsIndexed); + if (! empty($otherObs)) { + $sectionDefinitions[] = ['title' => 'Physical examination', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $otherObs]; + } + } + } elseif (! empty($dischargeObsIndexed)) { + $sectionDefinitions[] = ['title' => 'Condition on Discharge Time', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $dischargeObsIndexed]; + if (! empty($rawObservations)) { + $otherObs = array_diff_key($rawObservations, $dischargeObsIndexed); + if (! empty($otherObs)) { + $sectionDefinitions[] = ['title' => 'Physical examination', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items_indexed' => $otherObs]; + } + } } else { $sectionDefinitions[] = ['title' => 'Physical examination', 'code' => '425044008', 'display' => 'Physical exam section', 'prefix' => 'discharge-observation-', 'items' => $rawObservations]; } diff --git a/app/Views/abdm/task_board.php b/app/Views/abdm/task_board.php index 2163c5f..fe05360 100644 --- a/app/Views/abdm/task_board.php +++ b/app/Views/abdm/task_board.php @@ -2371,14 +2371,16 @@ } var admissionObservations = observations.filter(function(o) { - return getObservationCategoryText(o).toLowerCase() === 'condition on admission time'; + var cat = getObservationCategoryText(o).toLowerCase(); + return cat.indexOf('admission') !== -1; }); var dischargeObservations = observations.filter(function(o) { - return getObservationCategoryText(o).toLowerCase() === 'condition on discharge time'; + var cat = getObservationCategoryText(o).toLowerCase(); + return cat.indexOf('discharge') !== -1; }); var remainingObservations = observations.filter(function(o) { var cat = getObservationCategoryText(o).toLowerCase(); - return cat !== 'condition on admission time' && cat !== 'condition on discharge time'; + return cat.indexOf('admission') === -1 && cat.indexOf('discharge') === -1; }); var vitalObservations = remainingObservations.filter(isVitalObservation); var labObservations = remainingObservations.filter(function(o) { return !isVitalObservation(o); }); diff --git a/tests/unit/Abdm/FhirGeneratorsTest.php b/tests/unit/Abdm/FhirGeneratorsTest.php index fee21cc..2960a58 100644 --- a/tests/unit/Abdm/FhirGeneratorsTest.php +++ b/tests/unit/Abdm/FhirGeneratorsTest.php @@ -302,10 +302,10 @@ final class FhirGeneratorsTest extends CIUnitTestCase $bundle = $output['fhir_bundle']; $composition = $bundle['entry'][0]['resource']; - // Verify sections: should contain both General Examination on Admission and Examination on Discharge + // Verify sections: should contain both Condition on Admission Time and Condition on Discharge Time $sectionTitles = array_column($composition['section'], 'title'); - $this->assertContains('General Examination on Admission', $sectionTitles); - $this->assertContains('Examination on Discharge', $sectionTitles); + $this->assertContains('Condition on Admission Time', $sectionTitles); + $this->assertContains('Condition on Discharge Time', $sectionTitles); $this->assertContains('Care plan', $sectionTitles); $this->assertContains('Document reference', $sectionTitles); @@ -333,8 +333,8 @@ final class FhirGeneratorsTest extends CIUnitTestCase // Verify Observation Categories on Admission vs Discharge $observations = array_values(array_filter($bundle['entry'], static fn (array $e): bool => ($e['resource']['resourceType'] ?? '') === 'Observation' && isset($e['resource']['category']))); $this->assertGreaterThanOrEqual(14, count($observations)); - $this->assertSame('General Examination on Admission', $observations[0]['resource']['category'][0]['text']); - $this->assertSame('Examination on Discharge', $observations[7]['resource']['category'][0]['text']); + $this->assertSame('Condition on Admission Time', $observations[0]['resource']['category'][0]['text']); + $this->assertSame('Condition on Discharge Time', $observations[7]['resource']['category'][0]['text']); // Verify Encounter period & location $encounters = array_values(array_filter($bundle['entry'], static fn (array $e): bool => ($e['resource']['resourceType'] ?? '') === 'Encounter'));