From 0b05d7284cfb5f508867a3ca77e271d68ef9b376 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Fri, 5 Jun 2026 10:24:31 +0530 Subject: [PATCH] feat(discharge): support section placeholders --- app/Controllers/Ipd_discharge.php | 159 +++++++++++++++++- .../Setting/Template/discharge_templates.php | 8 +- 2 files changed, 162 insertions(+), 5 deletions(-) diff --git a/app/Controllers/Ipd_discharge.php b/app/Controllers/Ipd_discharge.php index d1d07e8..138bba2 100644 --- a/app/Controllers/Ipd_discharge.php +++ b/app/Controllers/Ipd_discharge.php @@ -333,6 +333,11 @@ class Ipd_discharge extends BaseController 'hospital_email' => esc($hEmail), ]; + $sectionVars = $this->buildDischargeSectionTokenVars($content); + foreach ($sectionVars as $key => $value) { + $tokens[$key] = $value; + } + foreach ($tokens as $key => $value) { $key = (string) $key; $value = (string) $value; @@ -356,6 +361,135 @@ class Ipd_discharge extends BaseController return $tokens; } + private function buildDischargeSectionTokenVars(string $content): array + { + $full = trim($content); + if ($full === '') { + return []; + } + + $allMarkers = [ + 'Discharge Summary', + 'Presenting Complaints and Reason for Admission', + 'General Examination on Admission', + 'Clinical Investigation Reports', + 'Final Diagnosis', + 'Course in the hospital', + 'Examination on Discharge', + 'Surgery', + 'Procedure', + 'Personal History', + 'Discharge Medications', + 'Discharge Advice/Instructions/Summary', + 'Dietary Advice', + 'Signature of Consultant', + 'Drug Allergy / ADR', + 'Co-Morbidities', + 'Summary of key investigations during Hospitalization', + 'Nursing Trend', + ]; + + $section = function (array $starts, array $extraEnds = []) use ($full, $allMarkers): string { + return $this->extractDischargeSectionByMarkers($full, $starts, array_merge($allMarkers, $extraEnds)); + }; + + $summary = $section(['Discharge Summary']); + $finalDiagnosis = $section(['Final Diagnosis']); + $surgery = $section(['Surgery']); + $procedure = $section(['Procedure']); + $personalHistory = $section(['Personal History']); + $presentingComplaints = $section(['Presenting Complaints and Reason for Admission']); + $generalExam = $section(['General Examination on Admission']); + $clinicalInvestigations = $section(['Clinical Investigation Reports']); + $courseInHospital = $section(['Course in the hospital']); + $examOnDischarge = $section(['Examination on Discharge']); + $dischargeMedications = $section(['Discharge Medications']); + $dietaryAdvice = $section(['Dietary Advice']); + $dischargeInstructions = $section(['Discharge Advice/Instructions/Summary']); + $signatureBlock = $section(['Signature of Consultant'], ['Signature of Medical Officer', 'Signature of Receiver / Date']); + + $vars = [ + 'DISCHARGE_SUMMARY' => $summary, + 'FINAL_DIAGNOSIS' => $finalDiagnosis, + 'SURGERY' => $surgery, + 'PROCEDURE' => $procedure, + 'PERSONAL_HISTORY' => $personalHistory, + 'PRESENTING_COMPLAINTS' => $presentingComplaints, + 'GENERAL_EXAM_ADMISSION' => $generalExam, + 'CLINICAL_INVESTIGATION_REPORTS' => $clinicalInvestigations, + 'COURSE_IN_HOSPITAL' => $courseInHospital, + 'EXAMINATION_ON_DISCHARGE' => $examOnDischarge, + 'DISCHARGE_MEDICATIONS' => $dischargeMedications, + 'DIETARY_ADVICE' => $dietaryAdvice, + 'DISCHARGE_INSTRUCTIONS' => $dischargeInstructions, + 'SIGNATURE_BLOCK' => $signatureBlock, + // Legacy style aliases to ease migration from CI3-style template variables. + 'FinalDiagnosis' => $finalDiagnosis, + 'Surgery' => $surgery, + 'Procedure' => $procedure, + 'personal_history' => $personalHistory, + 'discharge_complaint' => $presentingComplaints, + 'discharge_general_exam' => $generalExam, + 'lab_test_content' => $clinicalInvestigations, + 'Course_in_the_hospital' => $courseInHospital, + 'discharge_exam_on_discharge' => $examOnDischarge, + 'Discharge_Medications' => $dischargeMedications, + 'diet_advice' => $dietaryAdvice, + 'Discharge_Instructions' => $dischargeInstructions, + ]; + + return $vars; + } + + private function extractDischargeSectionByMarkers(string $html, array $startNeedles, array $endNeedles): string + { + $startPos = null; + foreach ($startNeedles as $needle) { + $pos = stripos($html, (string) $needle); + if ($pos !== false && ($startPos === null || $pos < $startPos)) { + $startPos = $pos; + } + } + + if ($startPos === null) { + return ''; + } + + $tagStart = strrpos(substr($html, 0, $startPos), '<'); + $sliceStart = $tagStart !== false ? $tagStart : $startPos; + + $sliceEnd = strlen($html); + foreach ($endNeedles as $needle) { + $needle = (string) $needle; + if ($needle === '') { + continue; + } + + $isStartNeedle = false; + foreach ($startNeedles as $startNeedle) { + if (strcasecmp($needle, (string) $startNeedle) === 0) { + $isStartNeedle = true; + break; + } + } + if ($isStartNeedle) { + continue; + } + + $candidate = stripos($html, $needle, $startPos + 1); + if ($candidate !== false && $candidate < $sliceEnd) { + $tag = strrpos(substr($html, 0, $candidate), '<'); + $sliceEnd = $tag !== false ? $tag : $candidate; + } + } + + if ($sliceEnd <= $sliceStart) { + return ''; + } + + return trim(substr($html, $sliceStart, $sliceEnd - $sliceStart)); + } + private function normalizeLegacyDischargeTemplate(string $html): string { $out = str_replace(["\r\n", "\r"], "\n", $html); @@ -429,11 +563,10 @@ class Ipd_discharge extends BaseController $templateHtml = '{{CONTENT}}'; } - if (strpos($templateHtml, '{{CONTENT}}') === false) { + $tokenVars = $this->buildDischargeTemplateTokenVars($panelData, $content); + if (! $this->templateHasKnownDischargeTokens($templateHtml, $tokenVars)) { $templateHtml .= "\n{{CONTENT}}"; } - - $tokenVars = $this->buildDischargeTemplateTokenVars($panelData, $content); $patientName = html_entity_decode((string) ($tokenVars['PATIENT_NAME'] ?? ''), ENT_QUOTES, 'UTF-8'); $patientCode = html_entity_decode((string) ($tokenVars['UHID'] ?? ''), ENT_QUOTES, 'UTF-8'); $ipdCode = html_entity_decode((string) ($tokenVars['IPD_CODE'] ?? ''), ENT_QUOTES, 'UTF-8'); @@ -475,6 +608,26 @@ class Ipd_discharge extends BaseController ]; } + private function templateHasKnownDischargeTokens(string $templateHtml, array $tokenVars): bool + { + if (trim($templateHtml) === '') { + return false; + } + + foreach (array_keys($tokenVars) as $tokenName) { + $tokenName = (string) $tokenName; + if ($tokenName === '') { + continue; + } + + if (strpos($templateHtml, '{{' . $tokenName . '}}') !== false || strpos($templateHtml, '{' . $tokenName . '}') !== false) { + return true; + } + } + + return false; + } + private function shouldUseContentOnlyTemplate(string $content, string $templateHtml): bool { $content = trim($content); diff --git a/app/Views/Setting/Template/discharge_templates.php b/app/Views/Setting/Template/discharge_templates.php index a882ebc..c9a5e3a 100644 --- a/app/Views/Setting/Template/discharge_templates.php +++ b/app/Views/Setting/Template/discharge_templates.php @@ -39,7 +39,11 @@ $status = (int) ($edit['status'] ?? 1); {{AGE_GENDER}}, {{ADMIT_DATE}}, {{DISCHARGE_DATE}}, {{CURRENT_DATE}}, {{H_Name}}, {{H_address_1}}, {{H_address_2}}, {{H_phone_No}}, {{H_Email}}, {{hospital_name}}, {{hospital_address}}, {{hospital_phone}}, {{hospital_email}}, - {{PRINT_TIME}}. + {{PRINT_TIME}}.
+ Section placeholders for custom layout/order: {{DISCHARGE_SUMMARY}}, {{FINAL_DIAGNOSIS}}, {{SURGERY}}, + {{PROCEDURE}}, {{PERSONAL_HISTORY}}, {{PRESENTING_COMPLAINTS}}, {{GENERAL_EXAM_ADMISSION}}, + {{CLINICAL_INVESTIGATION_REPORTS}}, {{COURSE_IN_HOSPITAL}}, {{EXAMINATION_ON_DISCHARGE}}, + {{DISCHARGE_MEDICATIONS}}, {{DIETARY_ADVICE}}, {{DISCHARGE_INSTRUCTIONS}}, {{SIGNATURE_BLOCK}}.
@@ -155,7 +159,7 @@ $status = (int) ($edit['status'] ?? 1);
- Use the editor to format layout. Use the Source button for raw HTML. Keep {{CONTENT}} in the template. + Use the editor to format layout. Use the Source button for raw HTML. You can use one {{CONTENT}} block or arrange section placeholders in any custom order.