= 10) ? $current_year + 1 : $current_year; $filter_type = $_GET['filter_type'] ?? 'fiscal'; $selected_fy = isset($_GET['fiscal_year']) ? (int)$_GET['fiscal_year'] : $current_fy; // แก้ไขปัญหาปี พ.ศ. ให้เป็น ค.ศ. if ($selected_fy > 2500) { $selected_fy -= 543; } if ($filter_type === 'fiscal') { $start_date = ($selected_fy - 1) . '-10-01'; $end_date = $selected_fy . '-09-30'; } else { $start_date = $_GET['start_date'] ?? date('Y-m-01'); $end_date = $_GET['end_date'] ?? date('Y-m-d'); $s_parts = explode('-', $start_date); if (count($s_parts) === 3 && (int)$s_parts[0] > 2500) { $s_parts[0] = (int)$s_parts[0] - 543; $start_date = implode('-', $s_parts); } $e_parts = explode('-', $end_date); if (count($e_parts) === 3 && (int)$e_parts[0] > 2500) { $e_parts[0] = (int)$e_parts[0] - 543; $end_date = implode('-', $e_parts); } } $response = [ 'kpi_summary' => [ 'opd_count' => 0, 'ipd_count' => 0, 'opd_wait' => 0, 'ipd_occ' => 0, 'cmi_avg' => 0, 'refer_out' => 0, 'refer_in' => 0, 'refer_back' => 0, 'doc_before_9' => 0, 'satisfaction' => 0 ], 'trend_opd' => ['labels' => [], 'data' => [], 'pt' => []], 'trend_ipd' => ['labels' => [], 'data' => []], 'display_start' => date('d/m/Y', strtotime($start_date)), 'display_end' => date('d/m/Y', strtotime($end_date)), 'sql_logs' => [], 'debug_enabled' => ($show_sql_log_btn === 'Y') ]; $addLog = function ($name, $sql, $error = null) use (&$response) { $response['sql_logs'][] = [ 'name' => $name, 'sql' => trim(preg_replace('/\s+/', ' ', $sql)), 'status' => $error ? 'Error' : 'Success', 'error' => $error ]; }; $addLog('ตรวจสอบช่วงวันที่ (Overview)', "ค้นหาตั้งแต่: $start_date ถึง $end_date"); $thai_months = ['01' => 'ม.ค.', '02' => 'ก.พ.', '03' => 'มี.ค.', '04' => 'เม.ย.', '05' => 'พ.ค.', '06' => 'มิ.ย.', '07' => 'ก.ค.', '08' => 'ส.ค.', '09' => 'ก.ย.', '10' => 'ต.ค.', '11' => 'พ.ย.', '12' => 'ธ.ค.']; if ($pdo) { // 1. นับจำนวน OPD try { $sql_opd_count = $sql_config['overview']['opd_count'] ?? "SELECT count(distinct vn) FROM ovst WHERE vstdate BETWEEN :start AND :end AND an IS NULL"; $stmt = $pdo->prepare($sql_opd_count); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['opd_count'] = (int)$stmt->fetchColumn(); } catch (\Exception $e) { $addLog('จำนวนผู้ป่วยนอก', 'SELECT count...', $e->getMessage()); } // 2. นับจำนวน IPD try { $sql_ipd_count = $sql_config['overview']['ipd_count'] ?? "SELECT count(distinct an) FROM ipt WHERE dchdate BETWEEN :start AND :end"; $stmt = $pdo->prepare($sql_ipd_count); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['ipd_count'] = (int)$stmt->fetchColumn(); } catch (\Exception $e) { $addLog('จำนวนผู้ป่วยใน', 'SELECT count...', $e->getMessage()); } // 3. ค่า CMI เฉลี่ย try { $sql_cmi_avg = $sql_config['overview']['cmi_avg'] ?? "SELECT (SUM(adjrw)/ count(an)) FROM ipt WHERE dchdate BETWEEN :start AND :end"; $stmt = $pdo->prepare($sql_cmi_avg); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['cmi_avg'] = (float)$stmt->fetchColumn(); } catch (\Exception $e) { $addLog('ค่า CMI เฉลี่ย', 'SELECT AVG(adjrw)...', $e->getMessage()); } // 4. แนวโน้มระยะเวลารอคอย OPD รายเดือน $sql_opd = $sql_config['overview']['trend_opd'] ?? "SELECT DATE_FORMAT(s.vstdate, '%Y-%m') as ym, IFNULL(ROUND(AVG((time_to_sec(s.service6)-time_to_sec(s.service4))/60), 2), 0) as avg_wait, COUNT(DISTINCT s.vn) as pt_count FROM service_time s WHERE s.vstdate BETWEEN :start AND :end AND EXISTS (SELECT 1 FROM rx_operator rx WHERE rx.vn = s.vn AND rx.pay='Y' AND rx.rx_time BETWEEN '08:00:00' AND '16:00:00') AND s.service3 IS NOT NULL AND s.service4 IS NOT NULL AND s.service5 IS NOT NULL AND s.service11 IS NOT NULL AND s.service12 IS NOT NULL AND s.service6 IS NOT NULL AND s.service11>=s.service4 AND s.service5>=s.service11 AND s.service12>=s.service5 AND s.service6>s.service12 AND s.service16>s.service7 AND dayofweek(s.vstdate) NOT IN (1,7) AND EXISTS (SELECT 1 FROM ovst o WHERE o.vn = s.vn AND o.main_dep='000') GROUP BY ym ORDER BY ym ASC"; try { $stmt = $pdo->prepare($sql_opd); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $total_wait = 0; $count_month = 0; while ($row = $stmt->fetch()) { $parts = explode('-', $row['ym']); if (count($parts) == 2) { $y_th = (int)$parts[0] + 543; $response['trend_opd']['labels'][] = $thai_months[$parts[1]] . ' ' . substr($y_th, 2, 2); $response['trend_opd']['data'][] = (float)$row['avg_wait']; $response['trend_opd']['pt'][] = (int)$row['pt_count']; $total_wait += (float)$row['avg_wait']; $count_month++; } } if ($count_month > 0) { $response['kpi_summary']['opd_wait'] = round($total_wait / $count_month, 2); } $addLog('แนวโน้มระยะเวลารอคอย OPD', $sql_opd); } catch (\Exception $e) { $addLog('แนวโน้มระยะเวลารอคอย OPD', $sql_opd, $e->getMessage()); } // 5. แนวโน้มอัตราครองเตียง IPD รายเดือน $sql_ipd = $sql_config['overview']['trend_ipd'] ?? "SELECT DATE_FORMAT(dchdate, '%Y-%m') as ym, IFNULL(ROUND((SUM(admdate) / (160 * DAY(LAST_DAY(dchdate)))) * 100, 2), 0) as occ_rate FROM an_stat WHERE dchdate BETWEEN :start AND :end GROUP BY ym ORDER BY ym ASC"; try { $stmt = $pdo->prepare($sql_ipd); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $total_occ = 0; $count_month = 0; while ($row = $stmt->fetch()) { $parts = explode('-', $row['ym']); if (count($parts) == 2) { $y_th = (int)$parts[0] + 543; $response['trend_ipd']['labels'][] = $thai_months[$parts[1]] . ' ' . substr($y_th, 2, 2); $response['trend_ipd']['data'][] = (float)$row['occ_rate']; $total_occ += (float)$row['occ_rate']; $count_month++; } } if ($count_month > 0) { $response['kpi_summary']['ipd_occ'] = round($total_occ / $count_month, 2); } $addLog('อัตราครองเตียง IPD รายเดือน', $sql_ipd); } catch (\Exception $e) { $addLog('อัตราครองเตียง IPD รายเดือน', $sql_ipd, $e->getMessage()); } // 6. Refer In / Out $sql_refer_in = $sql_config['overview']['refer_in'] ?? "SELECT count(vn) FROM referin WHERE refer_hospcode IN ('09192','11359') AND refer_date BETWEEN :start AND :end"; $sql_refer_out = $sql_config['overview']['refer_out'] ?? "SELECT count(vn) FROM referout WHERE refer_date BETWEEN :start AND :end"; try { $stmt = $pdo->prepare($sql_refer_in); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['refer_in'] = (int)$stmt->fetchColumn(); $addLog('รับ Refer In', $sql_refer_in); $stmt = $pdo->prepare($sql_refer_out); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['refer_out'] = (int)$stmt->fetchColumn(); $addLog('ส่ง Refer Out', $sql_refer_out); } catch (\Exception $e) { $addLog('ข้อมูล Refer In/Out', $sql_refer_in . " | " . $sql_refer_out, $e->getMessage()); } // 7. แพทย์ออกตรวจก่อน 9 โมง try { $sql_doc = $sql_config['overview']['doc_before_9'] ?? "SELECT IFNULL(ROUND(SUM(CASE WHEN first_service < '09:00:00' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2), 0) AS percent_before_9am FROM (SELECT v.vstdate, d.name, MIN(s.service5) AS first_service FROM vn_stat v LEFT JOIN ovst o ON v.vn=o.vn LEFT JOIN service_time s ON v.vn=s.vn LEFT JOIN doctor d ON v.dx_doctor=d.code WHERE v.vstdate BETWEEN :start AND :end AND v.dx_doctor <> '' AND o.main_dep='000' AND s.service5 IS NOT NULL AND d.position_id='1' AND d.doctor_department_id='58' AND v.vstdate NOT IN (SELECT holiday_date FROM holiday) AND o.vn NOT IN (SELECT vn FROM er_regist) GROUP BY v.vstdate,d.name) as x"; $stmt = $pdo->prepare($sql_doc); $stmt->execute(['start' => $start_date, 'end' => $end_date]); $response['kpi_summary']['doc_before_9'] = (float)$stmt->fetchColumn(); $addLog('แพทย์ลงตรวจก่อน 9.00 น.', $sql_doc); } catch (\Exception $e) { $addLog('แพทย์ลงตรวจก่อน 9.00 น.', $sql_doc, $e->getMessage()); } // 8. ความพึงพอใจ (จำลองคำสั่ง SQL) try { $sql_sat = $sql_config['overview']['satisfaction'] ?? "SELECT ROUND(85 + (RAND() * 10), 2) as sat_score"; $stmt = $pdo->prepare($sql_sat); $stmt->execute(); $response['kpi_summary']['satisfaction'] = (float)$stmt->fetchColumn(); $addLog('ความพึงพอใจผู้รับบริการ', $sql_sat); } catch (\Exception $e) { $addLog('ความพึงพอใจผู้รับบริการ', $sql_sat, $e->getMessage()); } // 9. ส่งกลับ Refer Back (จำลองคำสั่ง SQL) try { $sql_ref_back = $sql_config['overview']['refer_back'] ?? "SELECT FLOOR(0 + (RAND() * 0)) as ref_back"; $stmt = $pdo->prepare($sql_ref_back); $stmt->execute(); $response['kpi_summary']['refer_back'] = (int)$stmt->fetchColumn(); $addLog('ยอดส่งกลับ (Refer Back)', $sql_ref_back); } catch (\Exception $e) { $addLog('ยอดส่งกลับ (Refer Back)', $sql_ref_back, $e->getMessage()); } } echo "---AJAX_OVERVIEW_START---"; $json_output = @json_encode($response, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE); if (!$json_output) { echo json_encode(['error' => 'JSON Encode Error']); } else { echo $json_output; } echo "---AJAX_OVERVIEW_END---"; exit; } // ------------------------------------------------------------------------- // HTML & UI ส่วนหน้าเว็บ // ------------------------------------------------------------------------- $c_m = (int)date('m'); $c_y = (int)date('Y'); $c_fy = ($c_m >= 10) ? $c_y + 1 : $c_y; $options_html = ''; for ($i = 0; $i <= 5; $i++) { $y = $c_fy - $i; $yth = $y + 543; $options_html .= ""; } $start_d = date('Y-m-01'); $end_d = date('Y-m-d'); $overview_filter_html = '
'; ?>ผู้ป่วยนอกรวม (OPD)
ผู้ป่วยในรวม (IPD)
เวลารอคอย OPD
อัตราครองเตียง IPD
ค่า CMI เฉลี่ย
เป้าหมาย 100.00%
คะแนนเต็ม 5.00
1.การเข้าถึง
-
2.ความรวดเร็ว
-
3.พฤติกรรม
-
4.ข้อมูลสุขภาพ
-
5.ความเชื่อมั่น
-
6.ภาพรวม
-
รับ Refer In
รพ.เกาะพะงัน, เกาะเต่า
ส่ง Refer Out
ทุกปลายทาง
ส่งกลับ (Refer Back)
รพ.สต. ในเครือข่าย