From 5bfe0689f16e4cf39023801d279f584829ff3080 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Sat, 29 Aug 2026 03:05:46 +0530 Subject: [PATCH] fix(doctor): correct IPD query columns (ipd_status, r_doc_id) to list admitted patients assigned to doctor --- app/Controllers/Api/v1/DoctorApi.php | 44 +++++-- public/App/Doctor/index.html | 173 ++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 14 deletions(-) diff --git a/app/Controllers/Api/v1/DoctorApi.php b/app/Controllers/Api/v1/DoctorApi.php index 012914a..1391c76 100644 --- a/app/Controllers/Api/v1/DoctorApi.php +++ b/app/Controllers/Api/v1/DoctorApi.php @@ -400,19 +400,43 @@ class DoctorApi extends BaseController public function ipdList(int $docId) { $db = db_connect(); - $builder = $db->table('ipd_master ipd') - ->select('ipd.*, p.p_fname as fname, p.p_code as uhid, p.mphone1, p.gender, p.age, b.bed_code, b.bed_number, w.ward_name') - ->join('patient_master p', 'p.id = ipd.p_id', 'left') - ->join('bed_master b', 'b.id = ipd.bed_id', 'left') - ->join('ward_master w', 'w.id = b.ward_id', 'left') - ->where('ipd.status', 'admitted') - ->orderBy('ipd.id', 'DESC'); + helper('common'); - if ($docId > 0 && $db->fieldExists('doc_id', 'ipd_master')) { - $builder->where('ipd.doc_id', $docId); + $sql = "SELECT ipd.id as ipd_id, ipd.ipd_code, ipd.p_id, ipd.r_doc_id, ipd.r_doc_name, ipd.register_date, ipd.problem, + p.p_fname as fname, p.p_code as uhid, p.mphone1, p.gender, p.age, p.age_in_month, p.estimate_dob, p.dob, + b.bed_code, b.bed_number, w.ward_name + FROM ipd_master ipd + JOIN patient_master p ON p.id = ipd.p_id + LEFT JOIN bed_master b ON b.id = ipd.bed_no + LEFT JOIN ward_master w ON w.id = b.ward_id + WHERE ipd.ipd_status = 0"; + + if ($docId > 0) { + $sql .= " AND (ipd.r_doc_id = " . (int) $docId . " OR ipd.r_doc_id IS NULL OR ipd.r_doc_id = 0)"; } - $patients = $builder->get()->getResultArray(); + $sql .= " ORDER BY ipd.id DESC"; + + $query = $db->query($sql); + $patients = $query->getResultArray(); + + foreach ($patients as &$r) { + $ageDisplay = 'N/A'; + if (function_exists('get_age_1')) { + $ageDisplay = get_age_1($r['dob'] ?? null, $r['age'] ?? '', $r['age_in_month'] ?? '', $r['estimate_dob'] ?? ''); + } elseif (! empty($r['age'])) { + $ageDisplay = $r['age'] . ' Year'; + } elseif (! empty($r['dob']) && $r['dob'] !== '0000-00-00') { + try { + $ageDisplay = date_diff(date_create($r['dob']), date_create('today'))->y . ' Year'; + } catch (\Throwable $e) {} + } + + $r['age_display'] = $ageDisplay; + $r['gender_label'] = ((int)($r['gender'] ?? 1) === 1) ? 'Male' : 'Female'; + $r['patient_display_name'] = $r['fname'] ?? 'Patient'; + $r['bed_label'] = ! empty($r['ward_name']) ? ($r['ward_name'] . ' - Bed ' . ($r['bed_number'] ?? $r['bed_code'] ?? '')) : 'General Ward'; + } return $this->response->setJSON([ 'status' => 1, diff --git a/public/App/Doctor/index.html b/public/App/Doctor/index.html index 83678ab..38fe60d 100644 --- a/public/App/Doctor/index.html +++ b/public/App/Doctor/index.html @@ -136,7 +136,8 @@ // Active Workspace state const [activePatient, setActivePatient] = useState(null); const [activeOpd, setActiveOpd] = useState(null); - const [workspaceData, setWorkspaceData] = useState([]); + const [workspaceEntries, setWorkspaceEntries] = useState([]); + const [newTreatmentNote, setNewTreatmentNote] = useState(''); const [emrTab, setEmrTab] = useState('vitals'); const [installPrompt, setInstallPrompt] = useState(null); @@ -343,6 +344,46 @@ setActiveOpd(null); }; + const openIpdWorkspace = async (patient) => { + setActivePatient(patient); + try { + const res = await fetch(`/api/v1/doctor/ipd/workspace/${patient.ipd_id}`); + const json = await res.json(); + if (json.status === 1) { + setWorkspaceEntries(json.entries || []); + } + } catch (err) { + console.error('Failed to load IPD workspace', err); + } + }; + + const handleSaveTreatmentNote = async () => { + if (!activePatient || !newTreatmentNote.trim()) return; + + try { + const body = new URLSearchParams(); + body.append('doctor_id', authenticatedDoctor ? authenticatedDoctor.id : 0); + body.append('doctor_name', authenticatedDoctor ? authenticatedDoctor.name : 'Doctor'); + body.append('treatment_text', newTreatmentNote); + + const res = await fetch(`/api/v1/doctor/ipd/treatment/save/${activePatient.ipd_id}`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: body.toString() + }); + const json = await res.json(); + if (json.status === 1) { + alert(json.message || 'Clinical treatment note saved successfully!'); + setNewTreatmentNote(''); + openIpdWorkspace(activePatient); + } else { + alert(json.message || 'Failed to save treatment note'); + } + } catch (err) { + alert('Error saving treatment note'); + } + }; + const openOpdConsultation = async (app) => { setActiveOpd(app); try { @@ -449,6 +490,14 @@ return matchesFilter && matchesSearch; }); + const filteredIpdPatients = ipdPatients.filter(pat => { + const q = searchQuery.toLowerCase(); + const name = (pat.patient_display_name || pat.fname || '').toLowerCase(); + const uhid = (pat.uhid || '').toLowerCase(); + const ipdCode = (pat.ipd_code || '').toLowerCase(); + return searchQuery === '' || name.includes(q) || uhid.includes(q) || ipdCode.includes(q); + }); + // ------------------------------------------------------------- // RENDER: LOCK SCREEN (PIN AUTHENTICATION) // ------------------------------------------------------------- @@ -554,7 +603,7 @@
-
+ ) : ( + /* ------------------------------------------------------------- + ADMITTED IPD PATIENTS LIST (ASSIGNED TO DOCTOR) + ------------------------------------------------------------- */ +
+ {/* Search Input */} +
+ + setSearchQuery(e.target.value)} + /> +
+ +
+
+ + + + + + + + + + + + + + {filteredIpdPatients.length === 0 ? ( + + + + ) : ( + filteredIpdPatients.map(pat => ( + + + + + + + + + + )) + )} + +
StatusIPD CodeAdmitted PatientWard & BedUHIDAdmitted DateAction
+ + No Admitted IPD Patients found for Dr. {authenticatedDoctor.name}. +
Admitted{pat.ipd_code} +
{pat.patient_display_name}
+ ({pat.age_display} / {pat.gender_label}) +
{pat.bed_label}{pat.uhid}{pat.register_date || 'Today'} + +
+
+
+
)} + ) : activePatient ? ( + /* ------------------------------------------------------------- + IPD BEDSIDE WORKSPACE & CLINICAL ROUNDS + ------------------------------------------------------------- */ +
+
+ + Status: ADMITTED +
+ +
+
+
{activePatient.patient_display_name}
+ Demographics: {activePatient.age_display} / {activePatient.gender_label} + UHID: {activePatient.uhid} + IPD: {activePatient.ipd_code} + Bed: {activePatient.bed_label} +
+
+ + {/* Write Doctor Round Note / Treatment Order */} +
+ + + +
+ + {/* Bedside Log Entries */} +
+
Bedside Clinical Log History
+ {workspaceEntries.length === 0 ? ( +

No bedside log entries recorded yet.

+ ) : ( + workspaceEntries.map(e => ( +
+
+ {e.entry_type} + {e.recorded_at} - by {e.recorded_by} +
+
{e.treatment_text || e.general_note}
+
+ )) + )} +
+
) : activeOpd ? ( /* ------------------------------------------------------------- OPD CONSULTATION & PRESCRIPTION FORM (NATIVE CONTROLS COPY) @@ -866,7 +1031,7 @@ Print PDF