88 lines
3.1 KiB
PHP
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);
|
|
}
|
|
}
|
|
}
|