fix(abdm): deduplicate chief complaints and medical history, fix medication coding to NRCES spec, and resilient instruction parsing
This commit is contained in:
parent
0af2d557b2
commit
0344561808
|
|
@ -72,6 +72,14 @@ class ResyncDischarge extends BaseCommand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLI::write("\nConditions:", 'cyan');
|
||||||
|
foreach ($entries as $e) {
|
||||||
|
if (($e['resource']['resourceType'] ?? '') === 'Condition') {
|
||||||
|
$c = $e['resource'];
|
||||||
|
CLI::write(" - ID: " . ($c['id'] ?? '') . " | Text: " . ($c['code']['text'] ?? ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CLI::write("\nMedicationRequests:", 'cyan');
|
CLI::write("\nMedicationRequests:", 'cyan');
|
||||||
foreach ($entries as $e) {
|
foreach ($entries as $e) {
|
||||||
if (($e['resource']['resourceType'] ?? '') === 'MedicationRequest') {
|
if (($e['resource']['resourceType'] ?? '') === 'MedicationRequest') {
|
||||||
|
|
|
||||||
|
|
@ -3429,13 +3429,6 @@ class AbdmGateway extends BaseController
|
||||||
? date('Y-m-d', strtotime($dischargeDate))
|
? date('Y-m-d', strtotime($dischargeDate))
|
||||||
: ($admissionDate !== '' ? date('Y-m-d', strtotime($admissionDate)) : date('Y-m-d'));
|
: ($admissionDate !== '' ? date('Y-m-d', strtotime($admissionDate)) : date('Y-m-d'));
|
||||||
|
|
||||||
$diagnoses = [];
|
|
||||||
foreach ($this->ipdRows('ipd_discharge_diagnosis', ['comp_report'], $ipdId) as $row) {
|
|
||||||
$text = trim((string) ($row['comp_report'] ?? ''));
|
|
||||||
if ($text !== '') {
|
|
||||||
$diagnoses[] = ['text' => $text, 'code' => ''];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$chiefComplaints = [];
|
$chiefComplaints = [];
|
||||||
foreach ($this->ipdRows('ipd_discharge_complaint', ['comp_report'], $ipdId) as $row) {
|
foreach ($this->ipdRows('ipd_discharge_complaint', ['comp_report'], $ipdId) as $row) {
|
||||||
$text = trim((string) ($row['comp_report'] ?? ''));
|
$text = trim((string) ($row['comp_report'] ?? ''));
|
||||||
|
|
@ -3443,19 +3436,95 @@ class AbdmGateway extends BaseController
|
||||||
$chiefComplaints[] = ['text' => $text, 'code' => ''];
|
$chiefComplaints[] = ['text' => $text, 'code' => ''];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$chiefComplaintNarrative = trim((string) (($this->ipdRows('ipd_discharge_complaint_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
||||||
|
|
||||||
|
// Build normalized lookup of chief complaints
|
||||||
|
$complaintLookup = [];
|
||||||
|
foreach ($chiefComplaints as $cc) {
|
||||||
|
$t = strtolower(trim((string) ($cc['text'] ?? '')));
|
||||||
|
if ($t !== '') {
|
||||||
|
$complaintLookup[$t] = true;
|
||||||
|
if (str_contains($t, ' - ')) {
|
||||||
|
$parts = explode(' - ', $t);
|
||||||
|
$complaintLookup[trim($parts[0])] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch instructions early for comorbidities
|
||||||
|
$instructionRows = $this->ipdRows('ipd_discharge_instructions', ['comp_report', 'comp_remark', 'review_after'], $ipdId);
|
||||||
|
$instructionRow = ! empty($instructionRows) ? $instructionRows[0] : [];
|
||||||
|
$instructionMeta = ! empty($instructionRow) ? $this->parseJsonArray((string) ($instructionRow['comp_report'] ?? '')) : [];
|
||||||
|
$nabhMeta = is_array($instructionMeta['nabh'] ?? null) ? $instructionMeta['nabh'] : [];
|
||||||
|
|
||||||
|
// Build diagnoses / medical history
|
||||||
|
$diagnoses = [];
|
||||||
|
foreach ($this->ipdRows('ipd_discharge_diagnosis', ['comp_report'], $ipdId) as $row) {
|
||||||
|
$text = trim((string) ($row['comp_report'] ?? ''));
|
||||||
|
if ($text !== '' && ! isset($complaintLookup[strtolower($text)])) {
|
||||||
|
$diagnoses[] = ['text' => $text, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add comorbidities from NABH
|
||||||
|
$coMorbRaw = trim((string) ($nabhMeta['co_morbidities'] ?? ''));
|
||||||
|
if ($coMorbRaw !== '') {
|
||||||
|
$coMorbParts = preg_split('/[,;\n]+/', $coMorbRaw);
|
||||||
|
foreach ($coMorbParts as $cPart) {
|
||||||
|
$cText = trim((string) $cPart);
|
||||||
|
if ($cText !== '' && $this->isMeaningfulClinicalValue($cText) && ! isset($complaintLookup[strtolower($cText)])) {
|
||||||
|
$diagnoses[] = ['text' => $cText, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add chronic conditions from patient_master
|
||||||
|
if ($patientId > 0 && $this->db && $this->db->tableExists('patient_master')) {
|
||||||
|
$historyFields = [
|
||||||
|
'is_smoking' => 'Smoking',
|
||||||
|
'is_alcohol' => 'Alcohol',
|
||||||
|
'is_drug_abuse' => 'Drug Abuse',
|
||||||
|
'is_tobacoo' => 'Tobacco',
|
||||||
|
'is_hypertesion' => 'Hypertension',
|
||||||
|
'is_niddm' => 'Diabetes',
|
||||||
|
'is_diabetes' => 'Diabetes',
|
||||||
|
'is_ischaemic_heart_ds' => 'Ischemic Heart Disease',
|
||||||
|
'is_asthma_copd' => 'Asthma/COPD',
|
||||||
|
'is_bleeding_disorder' => 'Bleeding Disorder',
|
||||||
|
'is_heapatitis_type' => 'Hepatitis',
|
||||||
|
'is_blood_transfusion' => 'Blood Transfusion',
|
||||||
|
'is_hiv_std' => 'HIV/STD',
|
||||||
|
'is_hiv_I_II' => 'HIV/STD',
|
||||||
|
'is_epilepsy' => 'Epilepsy',
|
||||||
|
'is_tb' => 'TB',
|
||||||
|
'is_psychiatric_illness' => 'Psychiatric Illness',
|
||||||
|
'is_thyroid' => 'Thyroid',
|
||||||
|
];
|
||||||
|
foreach ($historyFields as $f => $label) {
|
||||||
|
if ((int) ($patientRow[$f] ?? 0) === 1 && ! isset($complaintLookup[strtolower($label)])) {
|
||||||
|
$diagnoses[] = ['text' => $label, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($diagnoses)) {
|
if (empty($diagnoses)) {
|
||||||
$problem = trim((string) ($ipdRow['problem'] ?? ''));
|
$problem = trim((string) ($ipdRow['problem'] ?? ''));
|
||||||
if ($problem !== '') {
|
if ($problem !== '' && $this->isMeaningfulClinicalValue($problem) && ! isset($complaintLookup[strtolower($problem)])) {
|
||||||
$diagnoses[] = ['text' => $problem, 'code' => ''];
|
$diagnoses[] = ['text' => $problem, 'code' => ''];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (empty($diagnoses) && ! empty($chiefComplaints)) {
|
|
||||||
$diagnoses = $chiefComplaints;
|
// Deduplicate diagnoses
|
||||||
|
$uniqueDiag = [];
|
||||||
|
$seenDiag = [];
|
||||||
|
foreach ($diagnoses as $dRow) {
|
||||||
|
$dt = strtolower(trim((string) ($dRow['text'] ?? '')));
|
||||||
|
if ($dt !== '' && empty($seenDiag[$dt])) {
|
||||||
|
$seenDiag[$dt] = true;
|
||||||
|
$uniqueDiag[] = $dRow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (empty($diagnoses) && empty($procedures)) {
|
$diagnoses = $uniqueDiag;
|
||||||
$diagnoses[] = ['text' => 'Medical care and evaluation', 'code' => ''];
|
|
||||||
}
|
|
||||||
$chiefComplaintNarrative = trim((string) (($this->ipdRows('ipd_discharge_complaint_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
|
||||||
$diagnosisNarrative = trim((string) (($this->ipdRows('ipd_discharge_diagnosis_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
$diagnosisNarrative = trim((string) (($this->ipdRows('ipd_discharge_diagnosis_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
||||||
|
|
||||||
$procedures = [];
|
$procedures = [];
|
||||||
|
|
@ -4300,7 +4369,34 @@ class AbdmGateway extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = json_decode($json, true);
|
$decoded = json_decode($json, true);
|
||||||
return is_array($decoded) ? $decoded : [];
|
if (is_array($decoded)) {
|
||||||
|
return $decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resilient fallback for truncated JSON strings
|
||||||
|
$cleanIds = [];
|
||||||
|
if (preg_match('/"food_ids"\s*:\s*\[([^\]]*)\]/', $json, $m)) {
|
||||||
|
$cleanIds = array_values(array_filter(array_map('intval', explode(',', $m[1]))));
|
||||||
|
}
|
||||||
|
$extractKey = function (string $key) use ($json): string {
|
||||||
|
if (preg_match('/"' . preg_quote($key, '/') . '"\s*:\s*"([^"]*)/', $json, $m)) {
|
||||||
|
return trim($m[1]);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
'food_ids' => $cleanIds,
|
||||||
|
'other_text' => $extractKey('other_text'),
|
||||||
|
'nabh' => [
|
||||||
|
'drug_allergy_status' => $extractKey('drug_allergy_status'),
|
||||||
|
'drug_allergy_details' => $extractKey('drug_allergy_details'),
|
||||||
|
'adr_history' => $extractKey('adr_history'),
|
||||||
|
'current_medications' => $extractKey('current_medications'),
|
||||||
|
'co_morbidities' => $extractKey('co_morbidities'),
|
||||||
|
'hpi_note' => $extractKey('hpi_note'),
|
||||||
|
],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isMeaningfulClinicalValue(string $value): bool
|
private function isMeaningfulClinicalValue(string $value): bool
|
||||||
|
|
|
||||||
|
|
@ -5472,7 +5472,32 @@ class Ipd_discharge extends BaseController
|
||||||
|
|
||||||
$decoded = json_decode($raw, true);
|
$decoded = json_decode($raw, true);
|
||||||
if (! is_array($decoded)) {
|
if (! is_array($decoded)) {
|
||||||
return ['food_ids' => [], 'other_text' => '', 'nabh' => []];
|
$cleanIds = [];
|
||||||
|
if (preg_match('/"food_ids"\s*:\s*\[([^\]]*)\]/', $raw, $m)) {
|
||||||
|
$cleanIds = array_values(array_filter(array_map('intval', explode(',', $m[1]))));
|
||||||
|
}
|
||||||
|
$extractKey = function (string $key) use ($raw): string {
|
||||||
|
if (preg_match('/"' . preg_quote($key, '/') . '"\s*:\s*"([^"]*)/', $raw, $m)) {
|
||||||
|
return trim($m[1]);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
return [
|
||||||
|
'food_ids' => $cleanIds,
|
||||||
|
'other_text' => $extractKey('other_text'),
|
||||||
|
'nabh' => [
|
||||||
|
'drug_allergy_status' => $extractKey('drug_allergy_status'),
|
||||||
|
'drug_allergy_details' => $extractKey('drug_allergy_details'),
|
||||||
|
'adr_history' => $extractKey('adr_history'),
|
||||||
|
'current_medications' => $extractKey('current_medications'),
|
||||||
|
'co_morbidities' => $extractKey('co_morbidities'),
|
||||||
|
'hpi_note' => $extractKey('hpi_note'),
|
||||||
|
'women_lmp' => $extractKey('women_lmp'),
|
||||||
|
'women_last_baby' => $extractKey('women_last_baby'),
|
||||||
|
'women_pregnancy_related' => $extractKey('women_pregnancy_related'),
|
||||||
|
'women_related_problems' => $extractKey('women_related_problems'),
|
||||||
|
],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$ids = $decoded['food_ids'] ?? [];
|
$ids = $decoded['food_ids'] ?? [];
|
||||||
|
|
@ -9401,21 +9426,6 @@ class Ipd_discharge extends BaseController
|
||||||
? date('Y-m-d', strtotime($dischargeDateRaw))
|
? date('Y-m-d', strtotime($dischargeDateRaw))
|
||||||
: ($admissionDateRaw !== '' ? date('Y-m-d', strtotime($admissionDateRaw)) : date('Y-m-d'));
|
: ($admissionDateRaw !== '' ? date('Y-m-d', strtotime($admissionDateRaw)) : date('Y-m-d'));
|
||||||
|
|
||||||
$diagnosisRows = $this->byIpdRows('ipd_discharge_diagnosis', ['comp_report'], 'id ASC', $ipdId);
|
|
||||||
$conditionRows = [];
|
|
||||||
foreach ($diagnosisRows as $row) {
|
|
||||||
$text = trim((string) ($row['comp_report'] ?? ''));
|
|
||||||
if ($text !== '') {
|
|
||||||
$conditionRows[] = ['text' => $text, 'code' => ''];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (empty($conditionRows) && ! empty($ipdRow['problem'])) {
|
|
||||||
$prob = trim((string) $ipdRow['problem']);
|
|
||||||
if ($this->isMeaningfulDischargeValue($prob)) {
|
|
||||||
$conditionRows[] = ['text' => $prob, 'code' => ''];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$chiefComplaintsList = [];
|
$chiefComplaintsList = [];
|
||||||
if ($this->tableHasColumns('ipd_discharge_complaint', ['ipd_id', 'comp_report'])) {
|
if ($this->tableHasColumns('ipd_discharge_complaint', ['ipd_id', 'comp_report'])) {
|
||||||
$complaintRows = $this->byIpdRows('ipd_discharge_complaint', ['comp_report', 'comp_remark'], 'id ASC', $ipdId);
|
$complaintRows = $this->byIpdRows('ipd_discharge_complaint', ['comp_report', 'comp_remark'], 'id ASC', $ipdId);
|
||||||
|
|
@ -9439,13 +9449,96 @@ class Ipd_discharge extends BaseController
|
||||||
$chiefComplaintsList[] = ['text' => $complaintRemarkText, 'code' => ''];
|
$chiefComplaintsList[] = ['text' => $complaintRemarkText, 'code' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($conditionRows) && ! empty($chiefComplaintsList)) {
|
// Build normalized lookup of chief complaints to avoid duplicating them into medical history
|
||||||
$conditionRows = $chiefComplaintsList;
|
$complaintLookup = [];
|
||||||
|
foreach ($chiefComplaintsList as $cc) {
|
||||||
|
$t = strtolower(trim((string) ($cc['text'] ?? '')));
|
||||||
|
if ($t !== '') {
|
||||||
|
$complaintLookup[$t] = true;
|
||||||
|
if (str_contains($t, ' - ')) {
|
||||||
|
$parts = explode(' - ', $t);
|
||||||
|
$complaintLookup[trim($parts[0])] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (empty($conditionRows)) {
|
|
||||||
$conditionRows[] = ['text' => 'Medical care and evaluation', 'code' => ''];
|
// Fetch discharge instructions early for comorbidities
|
||||||
|
$instructionRows = $this->byIpdRows('ipd_discharge_instructions', ['comp_report', 'comp_remark', 'review_after'], 'id DESC', $ipdId);
|
||||||
|
$instructionRow = ! empty($instructionRows) ? $instructionRows[0] : [];
|
||||||
|
$instructionMeta = ! empty($instructionRow) ? $this->parseInstructionMetaPayload((string) ($instructionRow['comp_report'] ?? '')) : ['food_ids' => [], 'other_text' => '', 'nabh' => []];
|
||||||
|
$nabhMeta = is_array($instructionMeta['nabh'] ?? null) ? $instructionMeta['nabh'] : [];
|
||||||
|
|
||||||
|
// Build Medical History / Diagnoses (discharge diagnoses + comorbidities + chronic illness, NEVER chief complaints)
|
||||||
|
$medicalHistoryRows = [];
|
||||||
|
$diagnosisRows = $this->byIpdRows('ipd_discharge_diagnosis', ['comp_report'], 'id ASC', $ipdId);
|
||||||
|
foreach ($diagnosisRows as $row) {
|
||||||
|
$text = trim((string) ($row['comp_report'] ?? ''));
|
||||||
|
if ($text !== '' && ! isset($complaintLookup[strtolower($text)])) {
|
||||||
|
$medicalHistoryRows[] = ['text' => $text, 'code' => ''];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comorbidities from NABH metadata
|
||||||
|
$coMorbRaw = trim((string) ($nabhMeta['co_morbidities'] ?? ''));
|
||||||
|
if ($coMorbRaw !== '') {
|
||||||
|
$coMorbParts = preg_split('/[,;\n]+/', $coMorbRaw);
|
||||||
|
foreach ($coMorbParts as $cPart) {
|
||||||
|
$cText = trim((string) $cPart);
|
||||||
|
if ($cText !== '' && $this->isMeaningfulDischargeValue($cText) && ! isset($complaintLookup[strtolower($cText)])) {
|
||||||
|
$medicalHistoryRows[] = ['text' => $cText, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chronic illness from patient_master
|
||||||
|
if ($patientId > 0 && $this->db->tableExists('patient_master')) {
|
||||||
|
$historyFields = [
|
||||||
|
'is_smoking' => 'Smoking',
|
||||||
|
'is_alcohol' => 'Alcohol',
|
||||||
|
'is_drug_abuse' => 'Drug Abuse',
|
||||||
|
'is_tobacoo' => 'Tobacco',
|
||||||
|
'is_hypertesion' => 'Hypertension',
|
||||||
|
'is_niddm' => 'Diabetes',
|
||||||
|
'is_diabetes' => 'Diabetes',
|
||||||
|
'is_ischaemic_heart_ds' => 'Ischemic Heart Disease',
|
||||||
|
'is_asthma_copd' => 'Asthma/COPD',
|
||||||
|
'is_bleeding_disorder' => 'Bleeding Disorder',
|
||||||
|
'is_heapatitis_type' => 'Hepatitis',
|
||||||
|
'is_blood_transfusion' => 'Blood Transfusion',
|
||||||
|
'is_hiv_std' => 'HIV/STD',
|
||||||
|
'is_hiv_I_II' => 'HIV/STD',
|
||||||
|
'is_epilepsy' => 'Epilepsy',
|
||||||
|
'is_tb' => 'TB',
|
||||||
|
'is_psychiatric_illness' => 'Psychiatric Illness',
|
||||||
|
'is_thyroid' => 'Thyroid',
|
||||||
|
];
|
||||||
|
foreach ($historyFields as $f => $label) {
|
||||||
|
if ((int) ($patientRow[$f] ?? 0) === 1 && ! isset($complaintLookup[strtolower($label)])) {
|
||||||
|
$medicalHistoryRows[] = ['text' => $label, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Problem from IPD record if non-blank and not duplicate of complaints
|
||||||
|
if (empty($medicalHistoryRows) && ! empty($ipdRow['problem'])) {
|
||||||
|
$prob = trim((string) $ipdRow['problem']);
|
||||||
|
if ($this->isMeaningfulDischargeValue($prob) && ! isset($complaintLookup[strtolower($prob)])) {
|
||||||
|
$medicalHistoryRows[] = ['text' => $prob, 'code' => ''];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deduplicate medical history rows by text
|
||||||
|
$uniqueMedHistory = [];
|
||||||
|
$seenMedHistory = [];
|
||||||
|
foreach ($medicalHistoryRows as $mRow) {
|
||||||
|
$mt = strtolower(trim((string) ($mRow['text'] ?? '')));
|
||||||
|
if ($mt !== '' && empty($seenMedHistory[$mt])) {
|
||||||
|
$seenMedHistory[$mt] = true;
|
||||||
|
$uniqueMedHistory[] = $mRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$conditionRows = $uniqueMedHistory;
|
||||||
|
|
||||||
$procedureRows = [];
|
$procedureRows = [];
|
||||||
foreach ($this->byIpdRows('ipd_discharge_surgery', ['surgery_name', 'surgery_date'], 'id ASC', $ipdId) as $row) {
|
foreach ($this->byIpdRows('ipd_discharge_surgery', ['surgery_name', 'surgery_date'], 'id ASC', $ipdId) as $row) {
|
||||||
$text = trim((string) ($row['surgery_name'] ?? ''));
|
$text = trim((string) ($row['surgery_name'] ?? ''));
|
||||||
|
|
|
||||||
|
|
@ -94,12 +94,35 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac
|
||||||
$patientRef = 'urn:uuid:patient-' . $patientId;
|
$patientRef = 'urn:uuid:patient-' . $patientId;
|
||||||
$encounterRef = is_array($encounter) ? 'urn:uuid:' . (string) ($encounter['id'] ?? '') : null;
|
$encounterRef = is_array($encounter) ? 'urn:uuid:' . (string) ($encounter['id'] ?? '') : null;
|
||||||
|
|
||||||
$diagnosesList = (array) ($source['diagnoses'] ?? $source['conditions'] ?? $source['ui_final_diagnosis'] ?? []);
|
|
||||||
$chiefComplaintsList = (array) ($source['chief_complaints'] ?? $source['ui_complaints'] ?? []);
|
$chiefComplaintsList = (array) ($source['chief_complaints'] ?? $source['ui_complaints'] ?? []);
|
||||||
|
$rawDiagnosesList = (array) ($source['diagnoses'] ?? $source['conditions'] ?? $source['ui_final_diagnosis'] ?? []);
|
||||||
|
|
||||||
|
// Build normalized lookup of chief complaints to ensure Medical History never duplicates Chief Complaints
|
||||||
|
$complaintLookup = [];
|
||||||
|
foreach ($chiefComplaintsList as $cc) {
|
||||||
|
$t = strtolower(trim((string) ($cc['text'] ?? $cc['name'] ?? '')));
|
||||||
|
if ($t !== '') {
|
||||||
|
$complaintLookup[$t] = true;
|
||||||
|
if (str_contains($t, ' - ')) {
|
||||||
|
$parts = explode(' - ', $t);
|
||||||
|
$complaintLookup[trim($parts[0])] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$diagnosesList = [];
|
||||||
|
$seenDiag = [];
|
||||||
|
foreach ($rawDiagnosesList as $diag) {
|
||||||
|
$dt = strtolower(trim((string) ($diag['text'] ?? $diag['name'] ?? '')));
|
||||||
|
if ($dt !== '' && ! isset($complaintLookup[$dt]) && empty($seenDiag[$dt])) {
|
||||||
|
$seenDiag[$dt] = true;
|
||||||
|
$diagnosesList[] = $diag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($diagnosesList) && empty($chiefComplaintsList)) {
|
if (empty($diagnosesList) && empty($chiefComplaintsList)) {
|
||||||
$problem = trim((string) ($source['problem'] ?? ''));
|
$problem = trim((string) ($source['problem'] ?? ''));
|
||||||
if ($problem !== '') {
|
if ($problem !== '' && ! isset($complaintLookup[strtolower($problem)])) {
|
||||||
$diagnosesList = [['text' => $problem, 'code' => '']];
|
$diagnosesList = [['text' => $problem, 'code' => '']];
|
||||||
} else {
|
} else {
|
||||||
$diagnosesList = [['text' => 'Medical care and evaluation', 'code' => '']];
|
$diagnosesList = [['text' => 'Medical care and evaluation', 'code' => '']];
|
||||||
|
|
@ -594,41 +617,81 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac
|
||||||
$chiefComplaintsList = (array) ($source['ui_complaints'] ?? $source['chief_complaints'] ?? []);
|
$chiefComplaintsList = (array) ($source['ui_complaints'] ?? $source['chief_complaints'] ?? []);
|
||||||
$complaintsNarrative = trim((string) ($source['ui_complaint_narrative'] ?? $source['chief_complaint_narrative'] ?? ''));
|
$complaintsNarrative = trim((string) ($source['ui_complaint_narrative'] ?? $source['chief_complaint_narrative'] ?? ''));
|
||||||
|
|
||||||
$diagnosesList = (array) ($source['ui_final_diagnosis'] ?? $source['diagnoses'] ?? $source['conditions'] ?? []);
|
$rawDiagnosesList = (array) ($source['ui_final_diagnosis'] ?? $source['diagnoses'] ?? $source['conditions'] ?? []);
|
||||||
$clinicalHistoryNarrative = trim((string) ($source['ui_clinical_history'] ?? ''));
|
$clinicalHistoryNarrative = trim((string) ($source['ui_clinical_history'] ?? ''));
|
||||||
|
|
||||||
|
// Build normalized lookup of chief complaints
|
||||||
|
$complaintLookup = [];
|
||||||
|
foreach ($chiefComplaintsList as $cc) {
|
||||||
|
$t = strtolower(trim((string) ($cc['text'] ?? $cc['name'] ?? '')));
|
||||||
|
if ($t !== '') {
|
||||||
|
$complaintLookup[$t] = true;
|
||||||
|
if (str_contains($t, ' - ')) {
|
||||||
|
$parts = explode(' - ', $t);
|
||||||
|
$complaintLookup[trim($parts[0])] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$diagnosesList = [];
|
||||||
|
$seenDiag = [];
|
||||||
|
foreach ($rawDiagnosesList as $diag) {
|
||||||
|
$dt = strtolower(trim((string) ($diag['text'] ?? $diag['name'] ?? '')));
|
||||||
|
if ($dt !== '' && ! isset($complaintLookup[$dt]) && empty($seenDiag[$dt])) {
|
||||||
|
$seenDiag[$dt] = true;
|
||||||
|
$diagnosesList[] = $diag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$sectionDefinitions = [];
|
$sectionDefinitions = [];
|
||||||
// Chief complaints
|
// Chief complaints
|
||||||
if (! empty($chiefComplaintsList) || $complaintsNarrative !== '') {
|
if (! empty($chiefComplaintsList) || $complaintsNarrative !== '') {
|
||||||
$sectionDefinitions[] = ['title' => 'Chief complaints', 'code' => '422843007', 'display' => 'Chief complaint section', 'prefix' => 'discharge-chief-complaint-', 'items' => $chiefComplaintsList, 'narrative' => $complaintsNarrative];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Chief complaints',
|
||||||
|
'code' => '422843007',
|
||||||
|
'display' => 'Chief complaint section',
|
||||||
|
'prefix' => 'discharge-chief-complaint-',
|
||||||
|
'items' => $chiefComplaintsList,
|
||||||
|
'narrative' => $complaintsNarrative,
|
||||||
|
'entry_display' => 'Condition',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discharge Diagnosis (Medical History)
|
// Discharge Diagnosis (Medical History)
|
||||||
if (! empty($diagnosesList) || $clinicalHistoryNarrative !== '') {
|
if (! empty($diagnosesList) || $clinicalHistoryNarrative !== '') {
|
||||||
$sectionDefinitions[] = ['title' => 'Medical History', 'code' => '1003642006', 'display' => 'Past medical history section', 'prefix' => 'discharge-diagnosis-', 'items' => $diagnosesList, 'narrative' => $clinicalHistoryNarrative];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Medical History',
|
||||||
|
'code' => '1003642006',
|
||||||
|
'display' => 'Past medical history section',
|
||||||
|
'prefix' => 'discharge-diagnosis-',
|
||||||
|
'items' => $diagnosesList,
|
||||||
|
'narrative' => $clinicalHistoryNarrative,
|
||||||
|
'entry_display' => 'Condition',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Surgery / Procedure
|
// Surgery / Procedure
|
||||||
$surgeries = (array) ($source['ui_surgeries'] ?? $source['procedures'] ?? []);
|
$surgeries = (array) ($source['ui_surgeries'] ?? $source['procedures'] ?? []);
|
||||||
if (! empty($surgeries)) {
|
if (! empty($surgeries)) {
|
||||||
$sectionDefinitions[] = ['title' => 'Procedures', 'code' => '1003640003', 'display' => 'History of past procedure section', 'prefix' => 'discharge-procedure-', 'items' => $surgeries];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Procedures',
|
||||||
|
'code' => '1003640003',
|
||||||
|
'display' => 'History of past procedure section',
|
||||||
|
'prefix' => 'discharge-procedure-',
|
||||||
|
'items' => $surgeries,
|
||||||
|
'entry_display' => 'Procedure',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Medications
|
// Medications - NRCES DischargeSummaryRecord profile specifies SNOMED 1003606003 (Medication history section)
|
||||||
if (! empty($validMeds)) {
|
if (! empty($validMeds)) {
|
||||||
$sectionDefinitions[] = [
|
$sectionDefinitions[] = [
|
||||||
'title' => 'Medications',
|
'title' => 'Medications',
|
||||||
'code' => '721912009',
|
'code' => '1003606003',
|
||||||
'display' => 'Medication summary document',
|
'display' => 'Medication history section',
|
||||||
'prefix' => 'discharge-medication-',
|
'prefix' => 'discharge-medication-',
|
||||||
'items' => $validMeds,
|
'items' => $validMeds,
|
||||||
'additional_coding' => [
|
'entry_display' => 'MedicationRequest',
|
||||||
[
|
|
||||||
'system' => 'http://snomed.info/sct',
|
|
||||||
'code' => '1003606003',
|
|
||||||
'display' => 'Medication history section',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -636,23 +699,52 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac
|
||||||
$investigations = (array) ($source['ui_investigations'] ?? $source['investigations'] ?? []);
|
$investigations = (array) ($source['ui_investigations'] ?? $source['investigations'] ?? []);
|
||||||
$invNarrative = trim((string) ($source['ui_summary_investigation'] ?? ''));
|
$invNarrative = trim((string) ($source['ui_summary_investigation'] ?? ''));
|
||||||
if (! empty($investigations) || $invNarrative !== '') {
|
if (! empty($investigations) || $invNarrative !== '') {
|
||||||
$sectionDefinitions[] = ['title' => 'Investigations', 'code' => '721981007', 'display' => 'Diagnostic studies report', 'prefix' => 'discharge-investigation-', 'items' => $investigations, 'narrative' => $invNarrative];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Investigations',
|
||||||
|
'code' => '721981007',
|
||||||
|
'display' => 'Diagnostic studies report',
|
||||||
|
'prefix' => 'discharge-investigation-',
|
||||||
|
'items' => $investigations,
|
||||||
|
'narrative' => $invNarrative,
|
||||||
|
'entry_display' => 'Diagnostic Report',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Care plans / Discharge advice & hospital course
|
// Care plans / Discharge advice & hospital course
|
||||||
if (! empty($validCarePlans)) {
|
if (! empty($validCarePlans)) {
|
||||||
$sectionDefinitions[] = ['title' => 'Care Plan', 'code' => '734163000', 'display' => 'Care plan', 'prefix' => 'discharge-careplan-', 'items' => $validCarePlans];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Care Plan',
|
||||||
|
'code' => '734163000',
|
||||||
|
'display' => 'Care plan',
|
||||||
|
'prefix' => 'discharge-careplan-',
|
||||||
|
'items' => $validCarePlans,
|
||||||
|
'entry_display' => 'Care plan',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Document Reference
|
// Document Reference
|
||||||
if (! empty($documentsList)) {
|
if (! empty($documentsList)) {
|
||||||
$sectionDefinitions[] = ['title' => 'Document Reference', 'code' => '373942005', 'display' => 'Discharge summary', 'prefix' => 'discharge-document-', 'items' => $documentsList];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Document Reference',
|
||||||
|
'code' => '373942005',
|
||||||
|
'display' => 'Discharge summary',
|
||||||
|
'prefix' => 'discharge-document-',
|
||||||
|
'items' => $documentsList,
|
||||||
|
'entry_display' => 'Discharge Summary',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allergies
|
// Allergies
|
||||||
$allergies = (array) ($source['allergies'] ?? []);
|
$allergies = (array) ($source['allergies'] ?? []);
|
||||||
if (! empty($allergies)) {
|
if (! empty($allergies)) {
|
||||||
$sectionDefinitions[] = ['title' => 'Allergies', 'code' => '722446000', 'display' => 'Allergy record', 'prefix' => 'discharge-allergy-', 'items' => $allergies];
|
$sectionDefinitions[] = [
|
||||||
|
'title' => 'Allergies',
|
||||||
|
'code' => '722446000',
|
||||||
|
'display' => 'Allergy record',
|
||||||
|
'prefix' => 'discharge-allergy-',
|
||||||
|
'items' => $allergies,
|
||||||
|
'entry_display' => 'AllergyIntolerance',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$sections = [];
|
$sections = [];
|
||||||
|
|
@ -660,7 +752,7 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac
|
||||||
$references = [];
|
$references = [];
|
||||||
$items = isset($definition['items_indexed']) ? $definition['items_indexed'] : (array) ($definition['items'] ?? []);
|
$items = isset($definition['items_indexed']) ? $definition['items_indexed'] : (array) ($definition['items'] ?? []);
|
||||||
foreach ($items as $idx => $item) {
|
foreach ($items as $idx => $item) {
|
||||||
$itemDisplay = $this->cleanPlainText((string) ($item['name'] ?? $item['text'] ?? $item['title'] ?? $definition['title']));
|
$itemDisplay = $definition['entry_display'] ?? $this->cleanPlainText((string) ($item['name'] ?? $item['text'] ?? $item['title'] ?? $definition['title']));
|
||||||
if ($itemDisplay === '') {
|
if ($itemDisplay === '') {
|
||||||
$itemDisplay = $definition['title'];
|
$itemDisplay = $definition['title'];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user