From 0fe556f37ec6d0cc05a7979e92fd274f14f0f105 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Wed, 20 May 2026 03:14:17 +0530 Subject: [PATCH] fix: preserve doctor original text in FHIR form; add live complaint/diagnosis terms to preview --- app/Controllers/Opd_prescription.php | 78 +++++++++++++++++++++++----- app/Views/abdm/task_board.php | 53 ++++++++++++++----- 2 files changed, 104 insertions(+), 27 deletions(-) diff --git a/app/Controllers/Opd_prescription.php b/app/Controllers/Opd_prescription.php index 37ce65a..8865e18 100644 --- a/app/Controllers/Opd_prescription.php +++ b/app/Controllers/Opd_prescription.php @@ -4603,14 +4603,52 @@ class Opd_prescription extends BaseController // AJAX callers (modal preview) get JSON directly if ($this->request->isAJAX()) { + // Fetch live complaint and diagnosis terms from current prescription row + $liveComplaints = []; + $liveDiagnoses = []; + $storedSessionId = (int) ($row['opd_session_id'] ?? 0); + if ($this->db->tableExists('opd_prescription') && ($storedSessionId > 0 || $opdId > 0)) { + $prescBuilder = $this->db->table('opd_prescription'); + if ($storedSessionId > 0) { + $prescBuilder->where('id', $storedSessionId); + } else { + $prescBuilder->where('opd_id', (int) $opdId)->orderBy('id', 'DESC'); + } + $pRow = $prescBuilder->get(1)->getRowArray() ?? []; + if (! empty($pRow)) { + $sj = trim((string) ($pRow['complaint_snomed_json'] ?? '')); + if ($sj !== '' && $sj !== '[]') { + $sit = json_decode($sj, true); + if (is_array($sit)) { $liveComplaints = array_values($sit); } + } + $diagText = trim((string) ($pRow['diagnosis'] ?? '')); + $provText = trim((string) ($pRow['Provisional_diagnosis'] ?? '')); + if ($diagText !== '') { + $liveDiagnoses[] = [ + 'term' => $diagText, + 'concept_id' => trim((string) ($pRow['diagnosis_snomed_id'] ?? '')), + 'type' => 'confirmed', + ]; + } + if ($provText !== '') { + $liveDiagnoses[] = [ + 'term' => $provText, + 'concept_id' => trim((string) ($pRow['provisional_diagnosis_snomed_id'] ?? '')), + 'type' => 'provisional', + ]; + } + } + } return $this->response->setJSON([ - 'status' => 'ok', - 'bundle' => $bundle, - 'document_id' => (int) ($row['id'] ?? 0), - 'generated_at' => (string) ($row['generated_at'] ?? ''), - 'bundle_type' => (string) ($row['bundle_type'] ?? ''), - 'opd_id' => (int) $opdId, - 'opd_session_id' => (int) $sessionId, + 'status' => 'ok', + 'bundle' => $bundle, + 'document_id' => (int) ($row['id'] ?? 0), + 'generated_at' => (string) ($row['generated_at'] ?? ''), + 'bundle_type' => (string) ($row['bundle_type'] ?? ''), + 'opd_id' => (int) $opdId, + 'opd_session_id' => (int) $sessionId, + 'live_complaints' => $liveComplaints, + 'live_diagnoses' => $liveDiagnoses, ]); } @@ -4699,9 +4737,14 @@ class Opd_prescription extends BaseController $found = false; foreach ($items as &$item) { if (strtolower(trim((string) ($item['term'] ?? ''))) === strtolower($complaintText)) { - $item['concept_id'] = $snomedId; - $item['term'] = $snomedTerm ?: $complaintText; - $item['source'] = $snomedId !== '' ? 'snomed' : ($item['source'] ?? 'local'); + // Preserve original term (what doctor typed) + if (! isset($item['original_term']) || (string) ($item['original_term'] ?? '') === '') { + $item['original_term'] = $item['term']; + } + $item['concept_id'] = $snomedId; + $item['snomed_display'] = $snomedTerm ?: $item['term']; + // Do NOT overwrite term — keep doctor's original text + $item['source'] = $snomedId !== '' ? 'snomed' : ($item['source'] ?? 'local'); $found = true; break; } @@ -4709,11 +4752,15 @@ class Opd_prescription extends BaseController unset($item); if (! $found) { - $items[] = ['term' => $snomedTerm ?: $complaintText, 'concept_id' => $snomedId, + $items[] = ['term' => $complaintText, 'original_term' => $complaintText, + 'concept_id' => $snomedId, 'snomed_display' => $snomedTerm ?: $complaintText, 'source' => $snomedId !== '' ? 'snomed' : 'local', 'hierarchy' => '', 'severity' => '', 'duration' => '', 'frequency' => '', 'date' => '']; } + // Also update getPrescriptionClinicalContext — use snomed_display for FHIR coding + // (handled in getPrescriptionClinicalContext via snomed_display field) + $newJson = (string) json_encode(array_values($items), JSON_UNESCAPED_UNICODE); $this->db->table('opd_prescription')->where('id', $prescId)->update(['complaint_snomed_json' => $newJson]); @@ -4723,6 +4770,7 @@ class Opd_prescription extends BaseController 'presc_id' => $prescId, 'snomed_concept_id'=> $snomedId, 'snomed_term' => $snomedTerm, + 'original_term' => $complaintText, 'csrfName' => csrf_token(), 'csrfHash' => csrf_hash(), ]); @@ -9747,6 +9795,7 @@ class Opd_prescription extends BaseController // Primary: use structured complaint_snomed_json (has SNOMED codes, severity, duration) $complaints = []; $snomedJson = trim((string) ($row['complaint_snomed_json'] ?? '')); + // Also use snomed_display for FHIR coding display if ($snomedJson !== '' && $snomedJson !== '[]') { $items = json_decode($snomedJson, true); if (is_array($items)) { @@ -9761,10 +9810,13 @@ class Opd_prescription extends BaseController continue; } $seen[$k] = true; + // Use original_term if available (preserves doctor's original text) + $displayText = trim((string) ($item['original_term'] ?? $text)); + $snomedDisplay = trim((string) ($item['snomed_display'] ?? $text)); $complaints[] = [ - 'text' => $text, + 'text' => $displayText, 'snomed_code' => trim((string) ($item['concept_id'] ?? '')), - 'snomed_display' => $text, + 'snomed_display' => $snomedDisplay, 'severity' => trim((string) ($item['severity'] ?? '')), 'duration' => trim((string) ($item['duration'] ?? '')), 'frequency' => trim((string) ($item['frequency'] ?? '')), diff --git a/app/Views/abdm/task_board.php b/app/Views/abdm/task_board.php index bb9f32e..e9948bf 100644 --- a/app/Views/abdm/task_board.php +++ b/app/Views/abdm/task_board.php @@ -990,6 +990,7 @@ // ── Track current bundle context for edits ────────────────────── var _fhirOpdId = 0, _fhirSessionId = 0; + var _fhirLiveComplaints = [], _fhirLiveDiagnoses = []; // ── Inline complaint SNOMED edit (event delegation on fhirFormView) ─ var _editTimer = null; @@ -1232,7 +1233,9 @@ var d = s.toString().substring(0, 10).split('-'); return d.length === 3 ? d[2]+'/'+d[1]+'/'+d[0] : s.toString().substring(0,16); } - function renderFhirBundleForm(bundle) { + function renderFhirBundleForm(bundle, liveComplaints, liveDiagnoses) { + liveComplaints = liveComplaints || []; + liveDiagnoses = liveDiagnoses || []; var resources = (bundle.entry || []).map(function(e) { return e.resource; }).filter(Boolean); function byType(t) { return resources.filter(function(r){ return r.resourceType === t; }); } var patient = byType('Patient')[0]; @@ -1288,27 +1291,37 @@ var sev = ((c.severity || {}).coding || [{}])[0]; var sevText = (sev && sev.display) ? sev.display : ((c.severity || {}).text || ''); var note = ((c.note || [{}])[0] || {}).text || ''; + // Resolve doctor's original text from live complaint_snomed_json + var doctorText = codeText; + var liveItem = null; + if (snomed && liveComplaints.length) { + for (var li = 0; li < liveComplaints.length; li++) { + if ((liveComplaints[li].concept_id || '') === snomed) { liveItem = liveComplaints[li]; break; } + } + } + if (!liveItem && liveComplaints.length > idx) { liveItem = liveComplaints[idx]; } + if (liveItem) { doctorText = liveItem.original_term || liveItem.term || codeText; } html += '
  • '; html += '
    '; html += '
    '; - html += '' + hesc(codeText) + ''; + html += '' + hesc(doctorText) + ''; if (snomed) html += ' SNOMED ' + hesc(snomed) + ''; if (sevText) html += ' ' + hesc(sevText) + ''; if (note) html += ' (' + hesc(note) + ')'; - if (display && display !== codeText) html += ' SNOMED term: ' + hesc(display) + ''; + if (display && display !== doctorText) html += ' SNOMED: ' + hesc(display) + ''; html += '
    '; html += ''; html += '
    '; // inline edit panel - html += '
  • '; html += '
    '; html += '
    '; - html += '' + hesc(text) + ''; + html += '' + hesc(doctorDiagText) + ''; if (snomed) html += ' SNOMED ' + hesc(snomed) + ''; html += ' ' + (isProvisional ? 'Provisional' : 'Confirmed') + ''; - if (display && display !== text) html += ' SNOMED term: ' + hesc(display) + ''; + if (display && display !== doctorDiagText) html += ' SNOMED: ' + hesc(display) + ''; html += '
    '; html += ''; html += '
    '; - html += '