68 lines
2.2 KiB
PHP
68 lines
2.2 KiB
PHP
<?php
|
|
namespace App\Services;
|
|
|
|
use App\Models\Therapist;
|
|
|
|
/**
|
|
* Class WorkloadBalancer
|
|
* Enterprise Workload Calculation & Load Balancing Service
|
|
*
|
|
* @package App\Services
|
|
*/
|
|
class WorkloadBalancer
|
|
{
|
|
private Therapist $therapistModel;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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()");
|
|
}
|
|
}
|