false, 'message' => 'Unauthorized']); exit; } $conn = Database::getInstance(); $period = $_GET['period'] ?? 'today'; try { $start_date = ''; $end_date = date('Y-m-d') . ' 23:59:59'; if ($period === 'week') { $start_date = date('Y-m-d', strtotime('-7 days')) . ' 00:00:00'; } elseif ($period === 'month') { $start_date = date('Y-m-01') . ' 00:00:00'; } else { // today $start_date = date('Y-m-d') . ' 00:00:00'; } // 1. SLA & Times $sla_target = 15; $query_times = "SELECT TIMESTAMPDIFF(MINUTE, created_at, accepted_at) as wait_time, TIMESTAMPDIFF(MINUTE, accepted_at, completed_at) as service_time FROM jobs WHERE status = 'completed' AND created_at BETWEEN :start AND :end"; $stmt_times = $conn->prepare($query_times); $stmt_times->bindParam(':start', $start_date); $stmt_times->bindParam(':end', $end_date); $stmt_times->execute(); $completed_jobs = $stmt_times->fetchAll(PDO::FETCH_ASSOC); $total_wait = 0; $total_service = 0; $sla_met = 0; foreach ($completed_jobs as $job) { $w = max(0, (int)$job['wait_time']); $s = max(0, (int)$job['service_time']); $total_wait += $w; $total_service += $s; if ($w <= $sla_target) { $sla_met++; } } $completed_count = count($completed_jobs); $avg_wait = $completed_count > 0 ? round($total_wait / $completed_count) : 0; $avg_service = $completed_count > 0 ? round($total_service / $completed_count) : 0; $sla_percent = $completed_count > 0 ? round(($sla_met / $completed_count) * 100) : 100; // 2. Trend Data (7 days) $trend_data = []; $trend_labels = []; for ($i = 6; $i >= 0; $i--) { $d = date('Y-m-d', strtotime("-$i days")); $thai_days = ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.']; $day_index = date('w', strtotime($d)); $trend_labels[] = $thai_days[$day_index]; $q = "SELECT COUNT(*) as cnt FROM jobs WHERE DATE(created_at) = :d"; $s = $conn->prepare($q); $s->bindParam(':d', $d); $s->execute(); $trend_data[] = $s->fetch(PDO::FETCH_ASSOC)['cnt']; } // 3. Department Workload $query_dept = "SELECT d.name, COUNT(j.id) as count FROM jobs j JOIN departments d ON j.from_department_id = d.id WHERE j.created_at BETWEEN :start AND :end GROUP BY d.id ORDER BY count DESC LIMIT 5"; $stmt_dept = $conn->prepare($query_dept); $stmt_dept->bindParam(':start', $start_date); $stmt_dept->bindParam(':end', $end_date); $stmt_dept->execute(); $dept_labels = []; $dept_data = []; while ($row = $stmt_dept->fetch(PDO::FETCH_ASSOC)) { $name = mb_strlen($row['name'], 'UTF-8') > 15 ? mb_substr($row['name'], 0, 15, 'UTF-8') . '...' : $row['name']; $dept_labels[] = $name; $dept_data[] = (int)$row['count']; } $jobModel = new Job(); $staffPerformance = $jobModel->getStaffPerformance($period); echo json_encode([ 'success' => true, 'kpi' => [ 'sla_percent' => $sla_percent, 'avg_wait_time' => $avg_wait, 'avg_service_time' => $avg_service ], 'charts' => [ 'trend' => [ 'labels' => $trend_labels, 'data' => $trend_data ], 'departments' => [ 'labels' => $dept_labels, 'data' => $dept_data ] ], 'staff_performance' => $staffPerformance ]); exit; } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); }