fix(abdm): isolate care context hi_types during linking and prevent multiple DocumentReference in DiagnosticReport

This commit is contained in:
DevSoftTech Server 2026-10-08 09:34:34 +05:30
parent a72ab50777
commit e86e73d792
3 changed files with 60 additions and 44 deletions

View File

@ -7070,8 +7070,18 @@ class AbdmGateway extends BaseController
if ($hiType === '' || ($hiType === 'HealthDocumentRecord' && str_starts_with($ccRef, 'WELLNESS-'))) {
$hiType = str_starts_with($ccRef, 'WELLNESS-') ? 'WellnessRecord' : 'HealthDocumentRecord';
}
$dateStr = date('d M Y', strtotime((string) ($row['created_at'] ?? $row['updated_at'] ?? 'now')));
$display = ($hiType === 'WellnessRecord' ? 'Wellness Record - ' : ($hiType . ' - ')) . $dateStr;
$friendlyType = match ($hiType) {
'DiagnosticReportRecord' => 'Diagnostic Report - ',
'PrescriptionRecord' => 'Prescription - ',
'OPConsultRecord' => 'OP Consultation - ',
'DischargeSummaryRecord' => 'Discharge Summary - ',
'ImmunizationRecord' => 'Immunization Record - ',
'WellnessRecord' => 'Wellness Record - ',
'HealthDocumentRecord' => 'Health Document - ',
'InvoiceRecord' => 'Invoice - ',
default => $hiType . ' - ',
};
$display = $friendlyType . $dateStr;
$addContext([
'careContextId' => $ccRef,

View File

@ -981,52 +981,31 @@ class FhirR4Builder
$observationEntries[] = ['fullUrl' => $obsRef, 'resource' => $obsResource];
}
// ── Binary + DocumentReference for HTML report ─────────────────────────
// ── Single DocumentReference (prefer PDF attachment if available, otherwise HTML) ─────
$docRefEntry = null;
$docRefRef = null;
$pdfDocRefRef = null;
$mediaRef = null;
$reportHtml = trim((string) ($diagnosticReport['report_html'] ?? ''));
if ($reportHtml !== '') {
$binaryUuid = $this->generateUuid();
$docRefUuid = $this->generateUuid();
$docRefRef = 'urn:uuid:' . $docRefUuid;
$contentType = trim((string) ($diagnosticReport['report_content_type'] ?? 'text/html; charset=utf-8'));
$pdfBinaryRef = null;
$pdfData = '';
$mediaRef = null;
$resourceEntries[] = ['fullUrl' => 'urn:uuid:' . $binaryUuid, 'resource' => [
'resourceType' => 'Binary',
'id' => $binaryUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/Binary']],
'contentType' => $contentType,
'data' => base64_encode($reportHtml),
]];
$hasAttachment = ($attachment !== null && ! empty($attachment['data_base64']));
$docRefSnomedCode = $isImaging ? '371531008' : '4241000179101';
$docRefSnomedDisplay = $isImaging ? 'Report of radiological study' : 'Laboratory report';
$docRefEntry = [
'resourceType' => 'DocumentReference',
'id' => $docRefUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentReference']],
'status' => 'current',
'type' => ['coding' => [['system' => 'http://snomed.info/sct', 'code' => '721981007', 'display' => 'Diagnostic studies report']]],
'subject' => ['reference' => $patientRef],
'content' => [['attachment' => ['contentType' => $contentType, 'url' => 'urn:uuid:' . $binaryUuid, 'data' => base64_encode($reportHtml), 'title' => $reportTitle]]],
];
$resourceEntries[] = ['fullUrl' => $docRefRef, 'resource' => $docRefEntry];
}
// ── Optional PDF attachment as Binary + DocumentReference ───────────
if ($attachment !== null && ! empty($attachment['data_base64'])) {
if ($hasAttachment) {
$pdfData = trim((string) ($attachment['data_base64'] ?? ''));
if ($pdfData !== '') {
$pdfBinaryUuid = $this->generateUuid();
$pdfBinaryRef = 'urn:uuid:' . $pdfBinaryUuid;
$pdfDocRefUuid = $this->generateUuid();
$pdfDocRefRef = 'urn:uuid:' . $pdfDocRefUuid;
$docRefRef = 'urn:uuid:' . $pdfDocRefUuid;
$pdfContentType = trim((string) ($attachment['content_type'] ?? 'application/pdf')) ?: 'application/pdf';
$pdfTitle = trim((string) ($attachment['title'] ?? 'Lab Report PDF')) ?: 'Lab Report PDF';
$pdfTitle = trim((string) ($attachment['title'] ?? ($isImaging ? 'Radiology Report PDF' : 'Lab Report PDF'))) ?: ($isImaging ? 'Radiology Report PDF' : 'Lab Report PDF');
$pdfBytes = base64_decode($pdfData, true);
$pdfSize = (int) ($attachment['size'] ?? (is_string($pdfBytes) ? strlen($pdfBytes) : 0));
$pdfHash = trim((string) ($attachment['hash'] ?? (is_string($pdfBytes) ? base64_encode(sha1($pdfBytes, true)) : '')));
$resourceEntries[] = ['fullUrl' => 'urn:uuid:' . $pdfBinaryUuid, 'resource' => [
$resourceEntries[] = ['fullUrl' => $pdfBinaryRef, 'resource' => [
'resourceType' => 'Binary',
'id' => $pdfBinaryUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/Binary']],
@ -1034,17 +1013,17 @@ class FhirR4Builder
'data' => $pdfData,
]];
$resourceEntries[] = ['fullUrl' => $pdfDocRefRef, 'resource' => [
$resourceEntries[] = ['fullUrl' => $docRefRef, 'resource' => [
'resourceType' => 'DocumentReference',
'id' => $pdfDocRefUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentReference']],
'status' => 'current',
'type' => ['coding' => [['system' => 'http://snomed.info/sct', 'code' => '721981007', 'display' => 'Diagnostic studies report']]],
'type' => ['coding' => [['system' => 'http://snomed.info/sct', 'code' => $docRefSnomedCode, 'display' => $docRefSnomedDisplay]]],
'subject' => ['reference' => $patientRef],
'content' => [[
'attachment' => array_filter([
'contentType' => $pdfContentType,
'url' => 'urn:uuid:' . $pdfBinaryUuid,
'url' => $pdfBinaryRef,
'data' => $pdfData,
'title' => $pdfTitle,
'size' => $pdfSize > 0 ? $pdfSize : null,
@ -1066,17 +1045,42 @@ class FhirR4Builder
'createdDateTime' => $reportedAt,
'content' => [
'contentType' => $pdfContentType,
'url' => 'urn:uuid:' . $pdfBinaryUuid,
'url' => $pdfBinaryRef,
'data' => $pdfData,
'title' => $pdfTitle,
],
]];
}
}
} elseif ($reportHtml !== '') {
$binaryUuid = $this->generateUuid();
$binaryRef = 'urn:uuid:' . $binaryUuid;
$docRefUuid = $this->generateUuid();
$docRefRef = 'urn:uuid:' . $docRefUuid;
$contentType = trim((string) ($diagnosticReport['report_content_type'] ?? 'text/html; charset=utf-8'));
$resourceEntries[] = ['fullUrl' => $binaryRef, 'resource' => [
'resourceType' => 'Binary',
'id' => $binaryUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/Binary']],
'contentType' => $contentType,
'data' => base64_encode($reportHtml),
]];
$docRefEntry = [
'resourceType' => 'DocumentReference',
'id' => $docRefUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentReference']],
'status' => 'current',
'type' => ['coding' => [['system' => 'http://snomed.info/sct', 'code' => $docRefSnomedCode, 'display' => $docRefSnomedDisplay]]],
'subject' => ['reference' => $patientRef],
'content' => [['attachment' => ['contentType' => $contentType, 'url' => $binaryRef, 'data' => base64_encode($reportHtml), 'title' => $reportTitle]]],
];
$resourceEntries[] = ['fullUrl' => $docRefRef, 'resource' => $docRefEntry];
}
// Pick a single DocumentReference for Composition.section slicing (0..1).
$effectiveDocRefRef = $pdfDocRefRef !== null ? $pdfDocRefRef : $docRefRef;
$effectiveDocRefRef = $docRefRef;
// ── DiagnosticReport ──────────────────────────────────────────────────
$reportRes = [

View File

@ -635,9 +635,9 @@
ctxTaskType = 'health_document_publish';
var dm = firstRef.match(/^DOC-(?:file-)?(\d+)/i);
if (dm && !ctxEntityId) ctxEntityId = dm[1];
} else if (/^(?:OPD|PRESCRIPTION)-/i.test(firstRef)) {
} else if (/^(?:OPD|PRESCRIPTION|PRESC)-/i.test(firstRef)) {
ctxTaskType = 'opd_prescription_publish';
var om = firstRef.match(/^(?:OPD|PRESCRIPTION)-(\d+)/i);
var om = firstRef.match(/^(?:OPD|PRESC)-(?:\d+)-S(\d+)/i) || firstRef.match(/^(?:OPD|PRESCRIPTION|PRESC)-(\d+)/i);
if (om && !ctxEntityId) ctxEntityId = om[1];
} else if (/^WELLNESS-/i.test(firstRef)) {
ctxTaskType = 'wellness_record_publish';
@ -686,7 +686,7 @@
if (!targetOpdId || targetOpdId === '0') {
var refToParse = firstRef || (window.currentHipTaskContext ? window.currentHipTaskContext.careContext : '');
if (refToParse) {
var mOpd = refToParse.match(/OPD-(?:\d+)-S(\d+)/i) || refToParse.match(/OPD-(\d+)/i);
var mOpd = refToParse.match(/(?:OPD|PRESC)-(?:\d+)-S(\d+)/i) || refToParse.match(/(?:OPD|PRESC|PRESCRIPTION)-(\d+)/i);
if (mOpd && mOpd[1]) {
targetOpdId = mOpd[1];
}
@ -874,7 +874,9 @@
itemHiType = 'ImmunizationRecord';
} else if (/^(?:DISCHARGE|IPD)-/i.test(ref)) {
itemHiType = 'DischargeSummaryRecord';
} else if (/^(?:OPD|PRESC)-/i.test(ref)) {
} else if (/^(?:PRESC|PRESCRIPTION)-/i.test(ref)) {
itemHiType = 'PrescriptionRecord';
} else if (/^OPD-/i.test(ref)) {
itemHiType = 'OPConsultRecord';
}
if (!dominantHiType && itemHiType) {