Optimize OPD dashboard query path for appointment data

This commit is contained in:
DevSoftTech Server 2026-03-01 01:51:25 +05:30
parent 0417c68773
commit 7cbf2b28ba

View File

@ -370,24 +370,19 @@ class Opd extends BaseController
$opdDateSql = $this->db->escape($opdDate); $opdDateSql = $this->db->escape($opdDate);
$sql = "select d.id as doc_id, $sql = "select
d.id as doc_id,
d.p_fname, d.p_fname,
ds.Spec, coalesce(ds.Spec, '') as Spec,
coalesce(oa.No_opd, 0) as No_opd, oa.No_opd,
coalesce(oa.count_booking, 0) as count_booking, oa.count_booking,
coalesce(oa.count_wait, 0) as count_wait, oa.count_wait,
coalesce(oa.count_visit, 0) as count_visit, oa.count_visit,
coalesce(oa.count_cancel, 0) as count_cancel, oa.count_cancel,
MOD(d.id,5) as color_code MOD(d.id,5) as color_code
from doctor_master d from (
join ( select
select s.doc_id, group_concat(DISTINCT m.SpecName) as Spec o.doc_id,
from doc_spec s
join med_spec m on m.id = s.med_spec_id
group by s.doc_id
) ds on ds.doc_id = d.id
left join (
select o.doc_id,
count(*) as No_opd, count(*) as No_opd,
sum(case when o.opd_status = 1 and pr.id is null then 1 else 0 end) as count_booking, sum(case when o.opd_status = 1 and pr.id is null then 1 else 0 end) as count_booking,
sum(case when o.opd_status = 1 and pr.id is not null then 1 else 0 end) as count_wait, sum(case when o.opd_status = 1 and pr.id is not null then 1 else 0 end) as count_wait,
@ -395,11 +390,16 @@ class Opd extends BaseController
sum(case when o.opd_status = 3 then 1 else 0 end) as count_cancel sum(case when o.opd_status = 3 then 1 else 0 end) as count_cancel
from opd_master o from opd_master o
left join opd_prescription pr on pr.opd_id = o.opd_id left join opd_prescription pr on pr.opd_id = o.opd_id
where o.apointment_date = " . $opdDateSql . " where o.apointment_date = " . $opdDateSql . "
group by o.doc_id group by o.doc_id
) oa on oa.doc_id = d.id ) oa
where d.active = 1 join doctor_master d on d.id = oa.doc_id and d.active = 1
and coalesce(oa.No_opd, 0) > 0 left join (
select s.doc_id, group_concat(DISTINCT m.SpecName) as Spec
from doc_spec s
join med_spec m on m.id = s.med_spec_id
group by s.doc_id
) ds on ds.doc_id = d.id
order by d.p_fname"; order by d.p_fname";
$query = $this->db->query($sql); $query = $this->db->query($sql);
@ -438,18 +438,11 @@ class Opd extends BaseController
$opdDateSql = $this->db->escape($opdDate); $opdDateSql = $this->db->escape($opdDate);
$sql = "select d.id as doc_id, d.p_fname, $sql = "select d.id as doc_id, d.p_fname,
group_concat(DISTINCT m.SpecName) as Spec, group_concat(DISTINCT m.SpecName) as Spec
count(DISTINCT o.opd_id) as No_opd, from doctor_master d
count(DISTINCT case when o.opd_status=1 and p.id is null then o.opd_id end) as count_booking, left join doc_spec s on d.id=s.doc_id
count(DISTINCT case when o.opd_status=1 and p.id is not null then o.opd_id end) as count_wait, left join med_spec m on m.id=s.med_spec_id
count(DISTINCT case when o.opd_status=2 then o.opd_id end) as count_visit, where d.id=" . $docId . " and d.active=1
count(DISTINCT case when o.opd_status=3 then o.opd_id end) as count_cancel
from (doctor_master d
join doc_spec s on d.id=s.doc_id
join med_spec m on m.id=s.med_spec_id)
left join opd_master o on d.id=o.doc_id and o.apointment_date=" . $opdDateSql . "
left join opd_prescription p on o.opd_id=p.opd_id
where d.id=" . $docId . "
group by d.id"; group by d.id";
$query = $this->db->query($sql); $query = $this->db->query($sql);
$docMaster = $query->getResult(); $docMaster = $query->getResult();
@ -458,48 +451,11 @@ class Opd extends BaseController
return $this->response->setStatusCode(404)->setBody('Doctor not found for selected date.'); return $this->response->setStatusCode(404)->setBody('Doctor not found for selected date.');
} }
// Booked: OPD records without an initialized prescription row. $sql = "select o.opd_id,o.opd_code,o.opd_no,o.opd_status,
$sql = "select o.opd_id,o.opd_code,o.opd_no,p.id,p.p_code,p.p_fname as P_name,p.p_rname, p.id,p.p_code,p.p_fname as P_name,p.p_rname,
o.opd_fee_desc,o.opd_fee_amount,o.payment_status,
if(o.payment_mode=4,'Credit to ECHS',if(o.payment_mode=1,'Cash','Pending')) as opd_type,
0 as has_vitals
from opd_master o
join patient_master p on o.p_id=p.id
left join opd_prescription pr on o.opd_id=pr.opd_id
where o.apointment_date=" . $opdDateSql . " and o.doc_id=" . $docId . " and o.opd_status=1 and pr.id is null
order by o.opd_code desc";
$query = $this->db->query($sql);
$opdList0 = $query->getResult();
// Waiting: OPD records with prescription row and active (status=1).
$sql = "select o.opd_id,o.opd_code,o.opd_no,p.id,p.p_code,p.p_fname as P_name,p.p_rname,
o.opd_fee_desc,o.opd_fee_amount,o.payment_status,
if(o.payment_mode=4,'Credit to ECHS',if(o.payment_mode=1,'Cash','Pending')) as opd_type,
if(
coalesce(trim(pr.pulse),'')<>''
or coalesce(trim(pr.spo2),'')<>''
or coalesce(trim(pr.bp),'')<>''
or coalesce(trim(pr.diastolic),'')<>''
or coalesce(trim(pr.temp),'')<>''
or coalesce(trim(pr.rr_min),'')<>''
or coalesce(trim(pr.height),'')<>''
or coalesce(trim(pr.weight),'')<>''
or coalesce(trim(pr.waist),'')<>'',
1,0
) as has_vitals,
coalesce(pr.queue_no,0) as queue_no
from opd_master o
join patient_master p on o.p_id=p.id
join opd_prescription pr on o.opd_id=pr.opd_id
where o.apointment_date=" . $opdDateSql . " and o.doc_id=" . $docId . " and o.opd_status=1
order by has_vitals asc, coalesce(nullif(pr.queue_no,0),999999) asc, o.opd_id asc";
$query = $this->db->query($sql);
$opdList1 = $query->getResult();
// Visited: consultation completed (status=2).
$sql = "select o.opd_id,o.opd_code,o.opd_no,p.id,p.p_code,p.p_fname as P_name,p.p_rname,
o.opd_fee_desc,o.opd_fee_amount,o.payment_status, o.opd_fee_desc,o.opd_fee_amount,o.payment_status,
if(o.payment_mode=4,'Credit to ECHS',if(o.payment_mode=1,'Cash','Pending')) as opd_type, if(o.payment_mode=4,'Credit to ECHS',if(o.payment_mode=1,'Cash','Pending')) as opd_type,
if(pr.id is null, 0, 1) as has_prescription,
if( if(
coalesce(trim(pr.pulse),'')<>'' coalesce(trim(pr.pulse),'')<>''
or coalesce(trim(pr.spo2),'')<>'' or coalesce(trim(pr.spo2),'')<>''
@ -516,35 +472,74 @@ class Opd extends BaseController
from opd_master o from opd_master o
join patient_master p on o.p_id=p.id join patient_master p on o.p_id=p.id
left join opd_prescription pr on o.opd_id=pr.opd_id left join opd_prescription pr on o.opd_id=pr.opd_id
where o.apointment_date=" . $opdDateSql . " and o.doc_id=" . $docId . " and o.opd_status=2 where o.apointment_date=" . $opdDateSql . " and o.doc_id=" . $docId;
order by o.opd_id";
$query = $this->db->query($sql); $query = $this->db->query($sql);
$opdList2 = $query->getResult(); $allRows = $query->getResult();
// Cancelled: OPD records cancelled by staff/doctor (status=3). $opdList0 = [];
$sql = "select o.opd_id,o.opd_code,o.opd_no,p.id,p.p_code,p.p_fname as P_name,p.p_rname, $opdList1 = [];
o.opd_fee_desc,o.opd_fee_amount,o.payment_status, $opdList2 = [];
if(o.payment_mode=4,'Credit to ECHS',if(o.payment_mode=1,'Cash','Pending')) as opd_type, $opdList3 = [];
if(
coalesce(trim(pr.pulse),'')<>'' foreach ($allRows as $row) {
or coalesce(trim(pr.spo2),'')<>'' $status = (int) ($row->opd_status ?? 0);
or coalesce(trim(pr.bp),'')<>'' $hasPrescription = (int) ($row->has_prescription ?? 0) === 1;
or coalesce(trim(pr.diastolic),'')<>''
or coalesce(trim(pr.temp),'')<>'' if ($status === 1 && ! $hasPrescription) {
or coalesce(trim(pr.rr_min),'')<>'' $opdList0[] = $row;
or coalesce(trim(pr.height),'')<>'' continue;
or coalesce(trim(pr.weight),'')<>'' }
or coalesce(trim(pr.waist),'')<>'',
1,0 if ($status === 1 && $hasPrescription) {
) as has_vitals, $opdList1[] = $row;
coalesce(pr.queue_no,0) as queue_no continue;
from opd_master o }
join patient_master p on o.p_id=p.id
left join opd_prescription pr on o.opd_id=pr.opd_id if ($status === 2) {
where o.apointment_date=" . $opdDateSql . " and o.doc_id=" . $docId . " and o.opd_status=3 $opdList2[] = $row;
order by o.opd_id"; continue;
$query = $this->db->query($sql); }
$opdList3 = $query->getResult();
if ($status === 3) {
$opdList3[] = $row;
}
}
usort($opdList0, static function ($left, $right): int {
return strcmp((string) ($right->opd_code ?? ''), (string) ($left->opd_code ?? ''));
});
usort($opdList1, static function ($left, $right): int {
$leftVitals = (int) ($left->has_vitals ?? 0);
$rightVitals = (int) ($right->has_vitals ?? 0);
if ($leftVitals !== $rightVitals) {
return $leftVitals <=> $rightVitals;
}
$leftQueue = (int) ($left->queue_no ?? 0);
$rightQueue = (int) ($right->queue_no ?? 0);
$leftQueueSort = $leftQueue > 0 ? $leftQueue : 999999;
$rightQueueSort = $rightQueue > 0 ? $rightQueue : 999999;
if ($leftQueueSort !== $rightQueueSort) {
return $leftQueueSort <=> $rightQueueSort;
}
return ((int) ($left->opd_id ?? 0)) <=> ((int) ($right->opd_id ?? 0));
});
usort($opdList2, static function ($left, $right): int {
return ((int) ($left->opd_id ?? 0)) <=> ((int) ($right->opd_id ?? 0));
});
usort($opdList3, static function ($left, $right): int {
return ((int) ($left->opd_id ?? 0)) <=> ((int) ($right->opd_id ?? 0));
});
$docMaster[0]->No_opd = count($allRows);
$docMaster[0]->count_booking = count($opdList0);
$docMaster[0]->count_wait = count($opdList1);
$docMaster[0]->count_visit = count($opdList2);
$docMaster[0]->count_cancel = count($opdList3);
return view('billing/opd_appointment_list', [ return view('billing/opd_appointment_list', [
'opd_date' => $opdDate, 'opd_date' => $opdDate,