diff --git a/includes/pages/reports.php b/includes/pages/reports.php index 957a1cb..3b63bd2 100644 --- a/includes/pages/reports.php +++ b/includes/pages/reports.php @@ -115,6 +115,95 @@ foreach ($patients_by_nationality_raw as $key => $val) { $chart_nationality_labels = array_keys($patients_by_nationality); $chart_nationality_data = array_values($patients_by_nationality); +// 11. Visits with Lab Tests by Nationality +$stmt = $db->prepare(" + SELECT + CASE + WHEN p.nationality = 'Oman' THEN 'omani' + WHEN p.nationality IS NULL OR p.nationality = '' THEN 'unknown_nationality' + ELSE 'non_omani' + END as nat_group, + COUNT(DISTINCT v.id) as count + FROM visits v + JOIN patients p ON v.patient_id = p.id + JOIN laboratory_inquiries l ON l.visit_id = v.id + WHERE DATE(v.visit_date) BETWEEN ? AND ? + GROUP BY nat_group"); +$stmt->execute([$start_date, $end_date]); +$lab_by_nationality_raw = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); + +$lab_by_nationality = []; +foreach ($lab_by_nationality_raw as $key => $val) { + $lab_by_nationality[__($key)] = $val; +} +$chart_lab_nat_labels = array_keys($lab_by_nationality); +$chart_lab_nat_data = array_values($lab_by_nationality); + +// 12. Visits with X-Ray by Nationality +$stmt = $db->prepare(" + SELECT + CASE + WHEN p.nationality = 'Oman' THEN 'omani' + WHEN p.nationality IS NULL OR p.nationality = '' THEN 'unknown_nationality' + ELSE 'non_omani' + END as nat_group, + COUNT(DISTINCT v.id) as count + FROM visits v + JOIN patients p ON v.patient_id = p.id + JOIN xray_inquiries x ON x.visit_id = v.id + WHERE DATE(v.visit_date) BETWEEN ? AND ? + GROUP BY nat_group"); +$stmt->execute([$start_date, $end_date]); +$xray_by_nationality_raw = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); + +$xray_by_nationality = []; +foreach ($xray_by_nationality_raw as $key => $val) { + $xray_by_nationality[__($key)] = $val; +} +$chart_xray_nat_labels = array_keys($xray_by_nationality); +$chart_xray_nat_data = array_values($xray_by_nationality); + +// 13. Visits by Department and Nationality +$stmt = $db->prepare(" + SELECT + d.name_$lang as dept_name, + SUM(CASE WHEN p.nationality = 'Oman' THEN 1 ELSE 0 END) as omani_count, + SUM(CASE WHEN p.nationality != 'Oman' AND p.nationality IS NOT NULL AND p.nationality != '' THEN 1 ELSE 0 END) as non_omani_count, + SUM(CASE WHEN p.nationality IS NULL OR p.nationality = '' THEN 1 ELSE 0 END) as unknown_count + FROM visits v + JOIN patients p ON v.patient_id = p.id + JOIN employees e ON v.doctor_id = e.id + JOIN departments d ON e.department_id = d.id + WHERE DATE(v.visit_date) BETWEEN ? AND ? + GROUP BY d.id"); +$stmt->execute([$start_date, $end_date]); +$dept_nat_data = $stmt->fetchAll(PDO::FETCH_ASSOC); + +$chart_dept_nat_labels = array_column($dept_nat_data, 'dept_name'); +$chart_dept_nat_omani = array_column($dept_nat_data, 'omani_count'); +$chart_dept_nat_non_omani = array_column($dept_nat_data, 'non_omani_count'); +$chart_dept_nat_unknown = array_column($dept_nat_data, 'unknown_count'); + +// 14. Visits by Doctor and Nationality +$stmt = $db->prepare(" + SELECT + e.name_$lang as doctor_name, + SUM(CASE WHEN p.nationality = 'Oman' THEN 1 ELSE 0 END) as omani_count, + SUM(CASE WHEN p.nationality != 'Oman' AND p.nationality IS NOT NULL AND p.nationality != '' THEN 1 ELSE 0 END) as non_omani_count, + SUM(CASE WHEN p.nationality IS NULL OR p.nationality = '' THEN 1 ELSE 0 END) as unknown_count + FROM visits v + JOIN patients p ON v.patient_id = p.id + JOIN employees e ON v.doctor_id = e.id + WHERE DATE(v.visit_date) BETWEEN ? AND ? + GROUP BY e.id"); +$stmt->execute([$start_date, $end_date]); +$doc_nat_data = $stmt->fetchAll(PDO::FETCH_ASSOC); + +$chart_doc_nat_labels = array_column($doc_nat_data, 'doctor_name'); +$chart_doc_nat_omani = array_column($doc_nat_data, 'omani_count'); +$chart_doc_nat_non_omani = array_column($doc_nat_data, 'non_omani_count'); +$chart_doc_nat_unknown = array_column($doc_nat_data, 'unknown_count'); + // --- PREPARE DATA FOR JS --- $chart_dept_revenue_labels = array_column($dept_revenue, 'name'); $chart_dept_revenue_data = array_column($dept_revenue, 'revenue'); @@ -164,6 +253,11 @@ $chart_gender_data = array_values($patients_by_gender); } /* Ensure Charts are Visible */ + .g-4, .gy-4 { --bs-gutter-y: 0.5rem !important; --bs-gutter-x: 0.5rem !important; } + .mb-5, .mb-4 { margin-bottom: 0.5rem !important; } + .card-body { min-height: auto !important; padding: 0.5rem !important; } + .card-body > div { height: 250px !important; max-height: 250px !important; } + h5 { font-size: 14pt !important; margin-bottom: 5px !important; } canvas { max-width: 100% !important; height: auto !important; @@ -182,7 +276,7 @@ $chart_gender_data = array_values($patients_by_gender); /* Page Break */ .page-break { - page-break-before: always; + page-break-inside: avoid; margin-bottom: 20px !important; } /* Header for Print */ @@ -233,7 +327,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -246,7 +340,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -259,7 +353,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -272,7 +366,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -289,19 +383,19 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
-
+
-
+
@@ -317,7 +411,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -329,13 +423,13 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
()
-
+
@@ -346,24 +440,76 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
-
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
-
+
@@ -398,7 +544,7 @@ $chart_gender_data = array_values($patients_by_gender);
-
+
@@ -592,5 +738,120 @@ document.addEventListener('DOMContentLoaded', function() { } }); + // 6. Lab by Nationality (Doughnut) + const ctxLabNat = document.getElementById('labNatChart').getContext('2d'); + new Chart(ctxLabNat, { + type: 'doughnut', + data: { + labels: , + datasets: [{ + data: , + backgroundColor: [colors.teal, colors.warning, colors.secondary], + borderWidth: 0 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { position: 'bottom' } + } + } + }); + + // 7. X-Ray by Nationality (Doughnut) + const ctxXrayNat = document.getElementById('xrayNatChart').getContext('2d'); + new Chart(ctxXrayNat, { + type: 'doughnut', + data: { + labels: , + datasets: [{ + data: , + backgroundColor: [colors.teal, colors.warning, colors.secondary], + borderWidth: 0 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { position: 'bottom' } + } + } + }); + + // 8. Dept by Nationality (Stacked Bar) + const ctxDeptNat = document.getElementById('deptNatChart').getContext('2d'); + new Chart(ctxDeptNat, { + type: 'bar', + data: { + labels: , + datasets: [ + { + label: '', + data: , + backgroundColor: colors.teal + }, + { + label: '', + data: , + backgroundColor: colors.warning + }, + { + label: '', + data: , + backgroundColor: colors.secondary + } + ] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + x: { stacked: true }, + y: { stacked: true } + }, + plugins: { + legend: { position: 'bottom' } + } + } + }); + + // 9. Doctor by Nationality (Stacked Bar) + const ctxDoctorNat = document.getElementById('doctorNatChart').getContext('2d'); + new Chart(ctxDoctorNat, { + type: 'bar', + data: { + labels: , + datasets: [ + { + label: '', + data: , + backgroundColor: colors.teal + }, + { + label: '', + data: , + backgroundColor: colors.warning + }, + { + label: '', + data: , + backgroundColor: colors.secondary + } + ] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + x: { stacked: true }, + y: { stacked: true } + }, + plugins: { + legend: { position: 'bottom' } + } + } + }); }); \ No newline at end of file diff --git a/includes/pages/sick_leave_report.php b/includes/pages/sick_leave_report.php index a832501..b628eca 100644 --- a/includes/pages/sick_leave_report.php +++ b/includes/pages/sick_leave_report.php @@ -23,7 +23,7 @@ $query = " e.name_$lang as doctor_name FROM visits v JOIN patients p ON v.patient_id = p.id - JOIN employees e ON v.doctor_id = e.id + LEFT JOIN employees e ON v.doctor_id = e.id WHERE v.sick_leave_days IS NOT NULL AND v.sick_leave_days > 0 "; $params = []; @@ -166,7 +166,7 @@ $doctors = $stmt->fetchAll(PDO::FETCH_ASSOC); - + diff --git a/lang.php b/lang.php index 0100efe..a0feb71 100644 --- a/lang.php +++ b/lang.php @@ -1,14 +1,17 @@ - array + array ( 'nationality' => 'Nationality', 'omani' => 'Omani', 'non_omani' => 'Non-Omani', 'unknown_nationality' => 'Unknown Nationality', 'patients_by_nationality' => 'Patients by Nationality', -( +'visits_with_lab_tests_by_nationality' => 'Visits with Lab Tests by Nationality', + 'visits_with_xray_by_nationality' => 'Visits with X-Ray by Nationality', + 'visits_by_dept_nationality' => 'Visits by Department (Nationality)', + 'visits_by_doctor_nationality' => 'Visits by Doctor (Nationality)', 'sick_leave_report' => 'Patient Sick Leave', 'date_issued' => 'Date Issued', 'number_of_days' => 'Number of Days', @@ -538,14 +541,17 @@ $translations = array ( 'confirm_delete_request' => 'Are you sure you want to delete this request?' ), 'ar' => - array + array ( 'nationality' => 'الجنسية', 'omani' => 'عماني', 'non_omani' => 'غير عماني', 'unknown_nationality' => 'جنسية غير معروفة', 'patients_by_nationality' => 'المرضى حسب الجنسية', -( +'visits_with_lab_tests_by_nationality' => 'الزيارات مع الفحوصات المخبرية حسب الجنسية', + 'visits_with_xray_by_nationality' => 'الزيارات مع الأشعة حسب الجنسية', + 'visits_by_dept_nationality' => 'الزيارات حسب القسم (الجنسية)', + 'visits_by_doctor_nationality' => 'الزيارات حسب الطبيب (الجنسية)', 'sick_leave_report' => 'إجازات المرضى', 'date_issued' => 'تاريخ الإصدار', 'number_of_days' => 'عدد الأيام',