diff --git a/app/Controllers/Opd.php b/app/Controllers/Opd.php
index 9961ad5..a7669f4 100644
--- a/app/Controllers/Opd.php
+++ b/app/Controllers/Opd.php
@@ -3939,6 +3939,9 @@ class Opd extends BaseController
foreach ($detailMap as $detailKey => $detailLabel) {
$value = trim((string) ($item[$detailKey] ?? ''));
if ($value !== '') {
+ if ($detailKey === 'date' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) === 1 && ($ts = strtotime($value)) !== false) {
+ $value = date('d-m-Y', $ts);
+ }
$details[] = $detailLabel . ': ' . $value;
}
}
@@ -3966,6 +3969,19 @@ class Opd extends BaseController
$tokens['next_visit_raw'] = (string) ($tokens['next_visit'] ?? '');
$complaintItems = $parseClinicalJsonItems((string) ($tokens['complaint_snomed_json'] ?? ''));
+ if (empty($complaintItems)) {
+ $complaintItems = $splitClinicalText((string) ($tokens['Complaint_raw'] ?? ''));
+ if (! empty($complaintItems)) {
+ $legacySev = trim((string) ($tokens['complaint_severity'] ?? ''));
+ $legacyDur = trim((string) ($tokens['complaint_duration_days'] ?? ''));
+ if ($legacySev !== '' && empty($complaintItems[0]['severity'])) {
+ $complaintItems[0]['severity'] = $legacySev;
+ }
+ if ($legacyDur !== '' && empty($complaintItems[0]['duration'])) {
+ $complaintItems[0]['duration'] = is_numeric($legacyDur) ? ($legacyDur . ' days') : $legacyDur;
+ }
+ }
+ }
if (empty($complaintItems)) {
$complaintItems = $splitClinicalText((string) ($tokens['Complaint_raw'] ?? ''));
}
@@ -3999,7 +4015,19 @@ class Opd extends BaseController
foreach ($diagnosisItems as $item) {
$term = trim((string) ($item['term'] ?? ''));
if ($term !== '') {
- $diagnosisTerms[] = $term;
+ $dxDetails = [];
+ $dxDur = trim((string) ($item['duration'] ?? ''));
+ $dxDate = trim((string) ($item['date'] ?? ''));
+ if ($dxDur !== '') {
+ $dxDetails[] = 'Duration: ' . $dxDur;
+ }
+ if ($dxDate !== '') {
+ if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $dxDate) === 1 && ($ts = strtotime($dxDate)) !== false) {
+ $dxDate = date('d-m-Y', $ts);
+ }
+ $dxDetails[] = 'Date: ' . $dxDate;
+ }
+ $diagnosisTerms[] = $term . (! empty($dxDetails) ? ' (' . implode(' | ', $dxDetails) . ')' : '');
}
}
$tokens['diagnosis_list_compact'] = implode(', ', array_values(array_unique($diagnosisTerms)));
@@ -4008,11 +4036,21 @@ class Opd extends BaseController
$vitalCoreRaw = (string) ($tokens['vital_content_raw'] ?? '');
$tokens['vital_content'] = $vitalCoreRaw;
$tokens['vital_content_block'] = $formatBlock('Vitals', $vitalCoreRaw, false);
- $complaintBlockValue = trim((string) ($tokens['complaint_list_compact'] ?? ''));
+ $complaintBlockValue = trim((string) ($tokens['complaint_list'] ?? ''));
if ($complaintBlockValue === '') {
- $complaintBlockValue = trim((string) ($tokens['Complaint_raw'] ?? ''));
+ $rawComplaintFallback = trim(str_replace(["\r\n", "\r"], "\n", (string) ($tokens['Complaint_raw'] ?? '')));
+ $complaintBlockValue = $rawComplaintFallback !== '' ? nl2br($escape($rawComplaintFallback)) : '';
}
- $tokens['Complaint'] = $formatBlock('Complaint', $escape($complaintBlockValue), false);
+ $tokens['Complaint'] = $formatBlock('Complaint', $complaintBlockValue, true);
+ $tokens['complaint'] = $tokens['Complaint'];
+ $tokens['complaints'] = $tokens['Complaint'];
+ if ($complaintBlockValue === '') {
+ if ($complaintBlockValue === '') {
+ $rawComplaintFallback = trim(str_replace(["\r\n", "\r"], "\n", (string) ($tokens['Complaint_raw'] ?? '')));
+ $complaintBlockValue = $rawComplaintFallback !== '' ? nl2br($escape($rawComplaintFallback)) : '';
+ }
+ }
+ // Keep multi-line complaint list with Frequency, Severity, Duration, Date intact.
$tokens['complaint'] = $tokens['Complaint'];
$diagnosisBlockValue = trim((string) ($tokens['diagnosis_list_compact'] ?? ''));
if ($diagnosisBlockValue === '') {
diff --git a/app/Views/billing/opd_letter_head_pdf.php b/app/Views/billing/opd_letter_head_pdf.php
index 20940d6..b08047e 100644
--- a/app/Views/billing/opd_letter_head_pdf.php
+++ b/app/Views/billing/opd_letter_head_pdf.php
@@ -285,7 +285,36 @@ $toLocalText = static function (string $input): string {
+
+
+
Complaint :
+
+
+ - = esc($cTerm) ?>= ! empty($cMeta) ? ' (' . esc(implode(' | ', $cMeta)) . ')' : '' ?>
+
+
+
+
Complaint : = nl2br(esc((string) ($rx['complaints'] ?? ''))) ?>
+
diff --git a/app/Views/billing/opd_prescription_basic.php b/app/Views/billing/opd_prescription_basic.php
index 9c05909..b4c2a67 100644
--- a/app/Views/billing/opd_prescription_basic.php
+++ b/app/Views/billing/opd_prescription_basic.php
@@ -4023,6 +4023,9 @@
}
function getPayload() {
+ if (typeof syncComplaintSnomedJson === 'function') {
+ syncComplaintSnomedJson();
+ }
var normalizedVitals = normalizeVitalsInputs(true);
var morbidities = [];
var morbiditiesText = [];
@@ -4398,6 +4401,9 @@
});
function openLegacyPrescriptionPrint(printType) {
+ if (typeof syncComplaintSnomedJson === 'function') {
+ syncComplaintSnomedJson();
+ }
var openPrint = function() {
var opdId = $('#opd_id').val() || '0';
var sessionId = $('#opd_session_id').val() || '0';
@@ -5266,6 +5272,22 @@
}
function syncComplaintSnomedJson() {
+ $('#complaint_tbody tr[data-idx]').each(function() {
+ var $tr = $(this);
+ var idx = parseInt($tr.attr('data-idx'), 10);
+ if (!isNaN(idx) && idx >= 0 && idx < selectedComplaintItems.length) {
+ var $nameInp = $tr.find('.complaint-name-input');
+ var $freqInp = $tr.find('.complaint-freq-input');
+ var $sevInp = $tr.find('.complaint-sev-input');
+ var $durInp = $tr.find('.complaint-dur-input');
+ var $dateInp = $tr.find('.complaint-date-input');
+ if ($nameInp.length) selectedComplaintItems[idx].term = ($nameInp.val() || '').toString().trim();
+ if ($freqInp.length) selectedComplaintItems[idx].frequency = ($freqInp.val() || '').toString().trim();
+ if ($sevInp.length) selectedComplaintItems[idx].severity = ($sevInp.val() || '').toString().trim();
+ if ($durInp.length) selectedComplaintItems[idx].duration = ($durInp.val() || '').toString().trim();
+ if ($dateInp.length) selectedComplaintItems[idx].date = ($dateInp.val() || '').toString().trim();
+ }
+ });
var json = JSON.stringify(selectedComplaintItems.map(function(item) {
return {
term: item.term,
@@ -5579,7 +5601,16 @@
var _freqDdIdx = -1;
- $(document).on('input focus', '.complaint-freq-input', function() {
+ $(document).on('input focus', '.complaint-freq-input', function(e) {
+ if (e && e.type === 'input') {
+ var idxInp = parseInt($(this).attr('data-idx'), 10);
+ if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
+ selectedComplaintItems[idxInp].frequency = ($(this).val() || '').trim();
+ syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ }
+ }
_freqDdIdx = -1;
var $inp = $(this);
var q = ($inp.val() || '').trim().toLowerCase();
@@ -5594,6 +5625,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].frequency = val;
syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ syncComplaintSnomedJson();
}
$('#_freq_dd').remove();
_freqDdIdx = -1;
@@ -5630,6 +5664,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].frequency = ($(this).val() || '').trim();
syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ syncComplaintSnomedJson();
}
setTimeout(function() { $('#_freq_dd').remove(); }, 150);
});
@@ -5653,7 +5690,16 @@
});
// ─── Duration: event delegation on table rows ────────────────────────────
- $(document).on('input focus', '.complaint-dur-input', function() {
+ $(document).on('input focus', '.complaint-dur-input', function(e) {
+ if (e && e.type === 'input') {
+ var idxInp = parseInt($(this).attr('data-idx'), 10);
+ if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
+ selectedComplaintItems[idxInp].duration = ($(this).val() || '').trim();
+ syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ }
+ }
_durDdIdx = -1;
var $inp = $(this);
var sugs = getDurationSuggestions($inp.val());
@@ -5666,6 +5712,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].duration = val;
syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ syncComplaintSnomedJson();
}
$dd.hide().empty();
// Done with this row — move to lookup for next complaint
@@ -5716,7 +5765,16 @@
return _SEVERITY_OPTIONS.filter(function(s) { return s.startsWith(q); });
}
- $(document).on('input focus', '.complaint-sev-input', function() {
+ $(document).on('input focus', '.complaint-sev-input', function(e) {
+ if (e && e.type === 'input') {
+ var idxInp = parseInt($(this).attr('data-idx'), 10);
+ if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
+ selectedComplaintItems[idxInp].severity = ($(this).val() || '').trim();
+ syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ }
+ }
_sevDdIdx = -1;
var $inp = $(this);
var sugs = getSeveritySuggestions($inp.val());
@@ -5729,6 +5787,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].severity = val;
syncComplaintSnomedJson();
+ markDirty('Complaint detail updated');
+ scheduleAutoSave();
+ syncComplaintSnomedJson();
}
$dd.hide().empty();
// Move focus to Duration input in same row