therapistModel = new Therapist(); } /** * Update workload score for a therapist after queue completion or assignment * * Score Formula: (total_minutes_today / max_daily_minutes) * 10.0 + (in_progress_count * 2.0) */ public function updateScore(int $therapistId): float { $therapist = $this->therapistModel->find($therapistId); if (!$therapist) return 0.00; $maxMins = (int)($therapist['max_daily_minutes'] ?? 480); if ($maxMins <= 0) $maxMins = 480; // Query today's queues for this therapist $db = \App\Models\Model::getDB(); $stmt = $db->prepare("SELECT COALESCE(SUM(CASE WHEN status = 'Completed' THEN COALESCE(service_time_mins, 60) ELSE 0 END), 0) as completed_mins, SUM(CASE WHEN status IN ('Assigned', 'In_Progress') THEN 1 ELSE 0 END) as active_queues FROM `queues` WHERE therapist_id = :tid AND queue_date = CURDATE()"); $stmt->execute(['tid' => $therapistId]); $row = $stmt->fetch(); $completedMins = (float)($row['completed_mins'] ?? 0); $activeCount = (float)($row['active_queues'] ?? 0); // คำนวณคะแนนภาระงาน ยิ่งคะแนนต่ำยิ่งว่างและมีโอกาสได้รับคิวต่อไป $score = round(($completedMins / $maxMins) * 10.0 + ($activeCount * 2.5), 2); // อัปเดตลงตาราง $this->therapistModel->update($therapistId, [ 'current_workload_score' => $score, 'is_available' => ($activeCount == 0 && $completedMins < $maxMins) ? 1 : 0, ]); return $score; } /** * Reset all workload scores (Called by midnight event or manually) */ public function resetAll(): void { $db = \App\Models\Model::getDB(); $db->exec("CALL sp_reset_daily_workloads()"); } }