Files
2026-09-16 23:20:08 +07:00

88 lines
3.1 KiB
PHP

<?php
namespace App\Services;
use App\Models\Queue;
use App\Models\Room;
use App\Models\Therapist;
/**
* Class SmartQueueEngine
* AI Queue Allocation & Dynamic Time Estimator Engine
*
* @package App\Services
*/
class SmartQueueEngine
{
private Queue $queueModel;
private Therapist $therapistModel;
private Room $roomModel;
public function __construct()
{
$this->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);
}
}
}