queueModel = new Queue(); $this->therapistModel = new Therapist(); $this->roomModel = new Room(); } /** * Process walk-in or appointment queue with Smart AI Allocation */ public function allocateQueue(array $queueData): array { // 1. สร้างคิวและเรียกใช้ Stored Procedure sp_assign_smart_queue $result = $this->queueModel->createWithSmartAssign($queueData); // 2. หากจัดสรรสำเร็จ ให้ส่งการแจ้งเตือน (LINE Notify / OA) และสร้างบันทึก Audit if ($result['assigned_therapist_id']) { AuditLogger::logQueueCreate($result['queue_id'], $result['queue_no'], 'Assigned via AI'); (new NotificationService())->notifyQueueAssigned($result); } else { AuditLogger::logQueueCreate($result['queue_id'], $result['queue_no'], 'Waiting (All busy)'); } return $result; } /** * Recalculate estimated start and end times for all waiting queues in a branch */ public function recalculateEstimations(int $branchId): void { $waitingQueues = $this->queueModel->where([ 'branch_id' => $branchId, 'queue_date' => date('Y-m-d'), 'status' => 'Waiting', ], "CASE priority WHEN 'Emergency' THEN 1 WHEN 'VIP' THEN 2 ELSE 3 END ASC, checkin_time ASC"); if (empty($waitingQueues)) return; // หาเวลาสิ้นสุดล่าสุดของคิวที่กำลังทำอยู่ $activeQueues = $this->queueModel->where([ 'branch_id' => $branchId, 'queue_date' => date('Y-m-d'), 'status' => 'In_Progress', ], "est_end_time DESC", 1); $baseTime = !empty($activeQueues) && !empty($activeQueues[0]['est_end_time']) ? strtotime($activeQueues[0]['est_end_time']) : time(); $bufferMins = 15; // 15 นาทีเตรียมเตียงและทำความสะอาดตามมาตรฐานสปา/คลินิก foreach ($waitingQueues as $q) { $estStart = date('Y-m-d H:i:s', $baseTime + ($bufferMins * 60)); // สมมติระยะเวลา 60 นาทีถ้าไม่มี service_time $duration = 60; $estEnd = date('Y-m-d H:i:s', strtotime($estStart) + ($duration * 60)); $this->queueModel->update((int)$q['id'], [ 'est_start_time' => $estStart, 'est_end_time' => $estEnd, 'updated_at' => date('Y-m-d H:i:s'), ]); $baseTime = strtotime($estEnd); } } }