diff --git a/app/Views/Setting/Template/document_print_settings.php b/app/Views/Setting/Template/document_print_settings.php index 78c7ed1..ea799df 100644 --- a/app/Views/Setting/Template/document_print_settings.php +++ b/app/Views/Setting/Template/document_print_settings.php @@ -106,17 +106,110 @@ $columnsReady = (bool) ($columns_ready ?? false);
If Header HTML is blank, default hospital header logic is used based on print mode.
+ +
+
+ Available Placeholders — click any to insert into focused textarea + Focus a textarea below first +
+
+
Hospital + 'Hospital Name', + '{{H_address_1}}' => 'Address Line 1', + '{{H_address_2}}' => 'Address Line 2', + '{{H_phone_No}}' => 'Phone No.', + '{{H_Email}}' => 'Email', + '{{H_logo}}' => 'Logo filename', + '{{H_logo_abs}}' => 'Logo absolute path', + '{{hospital_logo_html}}' => 'Logo tag', + ] as $ph => $desc): ?> + + +
+
Patient / IPD + 'Full patient name', + '{{UHID}}' => 'Patient UHID', + '{{IPD_CODE}}' => 'IPD admission number', + '{{ADMIT_DATE}}' => 'Date of admission', + '{{AGE_GENDER}}' => 'Age & gender combined', + '{{age_sex}}' => 'Age/sex short form', + '{{phoneno}}' => 'Patient phone', + '{{DOCTORS}}' => 'Treating doctors', + '{{doctor_name}}' => 'Primary doctor name', + '{{doctor_sign_html}}' => 'Doctor signature img', + ] as $ph => $desc): ?> + + +
+
Date / Page + 'Today\'s date', + '{{CURRENT_DATETIME}}' => 'Today date + time', + '{{print_time}}' => 'Print timestamp', + '{PAGENO}' => 'mPDF: current page', + '{nbpg}' => 'mPDF: total pages', + ] as $ph => $desc): ?> + + +
+
QR / Barcode + 'QR raw content string', + '{{qr_code_html}}' => 'QR code tag', + ] as $ph => $desc): ?> + + +
+
+
+
- +
- +
+ +
diff --git a/app/Views/billing/opd_prescription_basic.php b/app/Views/billing/opd_prescription_basic.php index b7d3663..e1e3e5f 100644 --- a/app/Views/billing/opd_prescription_basic.php +++ b/app/Views/billing/opd_prescription_basic.php @@ -777,7 +777,7 @@
- +
@@ -1019,7 +1019,7 @@
Add Medicines
- +
@@ -1114,6 +1114,9 @@ var medicineSuggestRows = []; var medicineSearchCache = {}; var medicineSearchCacheTtlMs = 120000; + var medicineSearchLocalDbKey = 'opd_medicine_search_cache_v1'; + var medicineSearchCacheMaxEntries = 250; + var medicineSearchLocalDbReady = false; var medInputTimer = null; var crgcMedInputTimer = null; var medicineDoseMasterCache = { dose: [], when: [], freq: [], where: [] }; @@ -1181,6 +1184,69 @@ return (scope || 'all') + '|' + (query || '').trim().toUpperCase(); } + function pruneMedicineSearchCacheStore(nowMs) { + var now = nowMs || Date.now(); + var keys = Object.keys(medicineSearchCache || {}); + if (!keys.length) { + medicineSearchCache = {}; + return; + } + + var rows = []; + keys.forEach(function(k) { + var item = medicineSearchCache[k] || {}; + var ts = Number(item.ts || 0); + if (!ts || (now - ts) > medicineSearchCacheTtlMs) { + return; + } + rows.push({ key: k, ts: ts, rows: Array.isArray(item.rows) ? item.rows : [] }); + }); + + rows.sort(function(a, b) { return b.ts - a.ts; }); + if (rows.length > medicineSearchCacheMaxEntries) { + rows = rows.slice(0, medicineSearchCacheMaxEntries); + } + + var next = {}; + rows.forEach(function(item) { + next[item.key] = { ts: item.ts, rows: item.rows }; + }); + medicineSearchCache = next; + } + + function persistMedicineSearchCacheToLocalDb() { + try { + pruneMedicineSearchCacheStore(Date.now()); + localStorage.setItem(medicineSearchLocalDbKey, JSON.stringify({ + saved_at: Date.now(), + entries: medicineSearchCache + })); + } catch (e) { + // Ignore storage quota/private-mode failures; memory cache still works. + } + } + + function ensureMedicineSearchLocalDbLoaded() { + if (medicineSearchLocalDbReady) { + return; + } + medicineSearchLocalDbReady = true; + try { + var raw = localStorage.getItem(medicineSearchLocalDbKey); + if (!raw) { + return; + } + var parsed = JSON.parse(raw); + var entries = parsed && parsed.entries ? parsed.entries : {}; + if (entries && typeof entries === 'object') { + medicineSearchCache = entries; + pruneMedicineSearchCacheStore(Date.now()); + } + } catch (e) { + medicineSearchCache = {}; + } + } + function fetchMedicineSuggestions(query, scope, done) { var q = (query || '').trim(); if (q.length < 2) { @@ -1188,6 +1254,8 @@ return; } + ensureMedicineSearchLocalDbLoaded(); + var useScope = (scope || 'all').toString(); var cacheKey = getMedicineSearchCacheKey(q, useScope); var now = Date.now(); @@ -1199,7 +1267,8 @@ apiGet('?q=' + encodeURIComponent(q) + '&scope=' + encodeURIComponent(useScope) + '&limit=10', function(data) { var rows = (data && data.rows) ? data.rows : []; - medicineSearchCache[cacheKey] = { ts: now, rows: rows }; + medicineSearchCache[cacheKey] = { ts: Date.now(), rows: rows }; + persistMedicineSearchCacheToLocalDb(); done(rows); }); }