|
@@ -1029,48 +1029,61 @@ class DeviceWorkService extends Service
|
|
|
|
|
|
|
|
private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
|
|
private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
|
|
|
{
|
|
{
|
|
|
- $monthEnd = strtotime('+1 month', $monthStart) - 1;
|
|
|
|
|
-
|
|
|
|
|
- // --- 1. 基础数据预加载 ---
|
|
|
|
|
- // 月度明细 & 设备名称
|
|
|
|
|
|
|
+ // 加载月度设备明细
|
|
|
$monthlyOrder = DB::table('monthly_dw_order_details as d')
|
|
$monthlyOrder = DB::table('monthly_dw_order_details as d')
|
|
|
->join('monthly_dw_order as m', 'm.id', '=', 'd.main_id')
|
|
->join('monthly_dw_order as m', 'm.id', '=', 'd.main_id')
|
|
|
- ->leftJoin('device as dv', 'dv.id', '=', 'd.device_id') // 假设设备表是 device
|
|
|
|
|
- ->where('m.month', $monthStart)->where('m.top_depart_id', $topDepartId)
|
|
|
|
|
- ->where('m.del_time', 0)->where('d.del_time', 0)
|
|
|
|
|
- ->select('d.*', 'dv.name as device_title')->get();
|
|
|
|
|
|
|
+ ->where('m.month', $monthStart)
|
|
|
|
|
+ ->where('m.top_depart_id', $topDepartId)
|
|
|
|
|
+ ->where('m.del_time', 0)
|
|
|
|
|
+ ->where('d.del_time', 0)
|
|
|
|
|
+ ->select('d.*')
|
|
|
|
|
+ ->get();
|
|
|
|
|
|
|
|
if ($monthlyOrder->isEmpty()) return ['status' => false, 'msg' => '未找到设备月度工时明细'];
|
|
if ($monthlyOrder->isEmpty()) return ['status' => false, 'msg' => '未找到设备月度工时明细'];
|
|
|
|
|
|
|
|
- // 项目名称映射
|
|
|
|
|
- $itemMap = DB::table('items')->pluck('name', 'id')->toArray();
|
|
|
|
|
|
|
+ $usedDeviceIds = $monthlyOrder->pluck('device_id')->unique()->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ // 【优化点】按需查询设备名称
|
|
|
|
|
+ $deviceMap = DB::table('device')
|
|
|
|
|
+ ->whereIn('id', $usedDeviceIds)
|
|
|
|
|
+ ->pluck('title', 'id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
|
|
|
- // 设备分配比例规则
|
|
|
|
|
|
|
+ // 加载分配规则
|
|
|
$ruleSet = DB::table('rule_set_details as rd')
|
|
$ruleSet = DB::table('rule_set_details as rd')
|
|
|
->join('rule_set as r', 'r.id', '=', 'rd.main_id')
|
|
->join('rule_set as r', 'r.id', '=', 'rd.main_id')
|
|
|
->where('r.month', $monthStart)
|
|
->where('r.month', $monthStart)
|
|
|
- ->where('rd.type', 2) // 假设 2 是设备规则
|
|
|
|
|
- ->where('r.del_time', 0)->where('rd.del_time', 0)
|
|
|
|
|
- ->select('rd.*')->get()->groupBy('data_id');
|
|
|
|
|
|
|
+ ->where('rd.type', 2) // 设备类型
|
|
|
|
|
+ ->where('r.del_time', 0)
|
|
|
|
|
+ ->where('rd.del_time', 0)
|
|
|
|
|
+ ->select('rd.*')
|
|
|
|
|
+ ->get();
|
|
|
|
|
+
|
|
|
|
|
+ // 【优化点】按需查询项目名称
|
|
|
|
|
+ $usedItemIds = $ruleSet->pluck('item_id')->unique()->toArray();
|
|
|
|
|
+ $itemMap = DB::table('item')
|
|
|
|
|
+ ->whereIn('id', $usedItemIds)
|
|
|
|
|
+ ->pluck('title', 'id') // 这里的 title 对应你之前的需求
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $ruleSetGrouped = $ruleSet->groupBy('data_id'); // 按 device_id 分组
|
|
|
|
|
|
|
|
- // 标准班次
|
|
|
|
|
|
|
+ // 标准班次 & 日历 (逻辑同前)
|
|
|
$standardWorkRanges = DB::table('work_range_details')
|
|
$standardWorkRanges = DB::table('work_range_details')
|
|
|
->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
|
|
->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
|
|
|
-
|
|
|
|
|
$dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
|
|
$dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
|
|
|
|
|
|
|
|
- // 工作日历
|
|
|
|
|
$workDays = DB::table('calendar_details')
|
|
$workDays = DB::table('calendar_details')
|
|
|
->where('month', $monthStart)->where('is_work', 1)->where('del_time', 0)
|
|
->where('month', $monthStart)->where('is_work', 1)->where('del_time', 0)
|
|
|
->orderBy('time', 'asc')->get();
|
|
->orderBy('time', 'asc')->get();
|
|
|
|
|
|
|
|
if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
|
|
if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
|
|
|
|
|
|
|
|
- // --- 2. 阶段一:计算每天每台设备在每个项目下的整数分钟数 ---
|
|
|
|
|
|
|
+ // --- 2. 阶段一:计算每天每台设备分配的项目分钟数 ---
|
|
|
$finalAlloc = [];
|
|
$finalAlloc = [];
|
|
|
foreach ($monthlyOrder as $mDetail) {
|
|
foreach ($monthlyOrder as $mDetail) {
|
|
|
$deviceId = $mDetail->device_id;
|
|
$deviceId = $mDetail->device_id;
|
|
|
- $deviceRules = $ruleSet->get($deviceId);
|
|
|
|
|
|
|
+ $deviceRules = $ruleSetGrouped->get($deviceId);
|
|
|
if (!$deviceRules) continue;
|
|
if (!$deviceRules) continue;
|
|
|
|
|
|
|
|
$remainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
|
|
$remainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
|
|
@@ -1085,7 +1098,6 @@ class DeviceWorkService extends Service
|
|
|
|
|
|
|
|
foreach ($deviceRules as $index => $rule) {
|
|
foreach ($deviceRules as $index => $rule) {
|
|
|
$rate = (float)$rule->rate / 100;
|
|
$rate = (float)$rule->rate / 100;
|
|
|
- // 最后一个项目拿差额,防止精度流失
|
|
|
|
|
if ($index === $ruleCount - 1) {
|
|
if ($index === $ruleCount - 1) {
|
|
|
$projectMin = $canAllocToday - $allocatedInDay;
|
|
$projectMin = $canAllocToday - $allocatedInDay;
|
|
|
} else {
|
|
} else {
|
|
@@ -1101,7 +1113,7 @@ class DeviceWorkService extends Service
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // --- 3. 阶段二:打散到具体时段并生成预览行 ---
|
|
|
|
|
|
|
+ // --- 3. 阶段二:生成预览行 ---
|
|
|
$previewList = [];
|
|
$previewList = [];
|
|
|
$dailyDevicePools = [];
|
|
$dailyDevicePools = [];
|
|
|
$tempMainIdCounter = 1;
|
|
$tempMainIdCounter = 1;
|
|
@@ -1113,7 +1125,6 @@ class DeviceWorkService extends Service
|
|
|
$itemTitle = $itemMap[$itemId] ?? '未知项目';
|
|
$itemTitle = $itemMap[$itemId] ?? '未知项目';
|
|
|
|
|
|
|
|
foreach ($devices as $deviceId => $toAllocMin) {
|
|
foreach ($devices as $deviceId => $toAllocMin) {
|
|
|
- // 初始化该设备当天的标准班次池
|
|
|
|
|
if (!isset($dailyDevicePools[$dayTs][$deviceId])) {
|
|
if (!isset($dailyDevicePools[$dayTs][$deviceId])) {
|
|
|
$pool = [];
|
|
$pool = [];
|
|
|
foreach ($standardWorkRanges as $swr) {
|
|
foreach ($standardWorkRanges as $swr) {
|
|
@@ -1128,7 +1139,6 @@ class DeviceWorkService extends Service
|
|
|
$tempRem = (int)$toAllocMin;
|
|
$tempRem = (int)$toAllocMin;
|
|
|
foreach ($dailyDevicePools[$dayTs][$deviceId] as &$p) {
|
|
foreach ($dailyDevicePools[$dayTs][$deviceId] as &$p) {
|
|
|
if ($tempRem <= 0) break;
|
|
if ($tempRem <= 0) break;
|
|
|
-
|
|
|
|
|
$pMax = $p['e'] - $p['s'];
|
|
$pMax = $p['e'] - $p['s'];
|
|
|
if ($pMax <= 0) continue;
|
|
if ($pMax <= 0) continue;
|
|
|
|
|
|
|
@@ -1143,7 +1153,7 @@ class DeviceWorkService extends Service
|
|
|
'item_id' => $itemId,
|
|
'item_id' => $itemId,
|
|
|
'item_title' => $itemTitle,
|
|
'item_title' => $itemTitle,
|
|
|
'device_id' => $deviceId,
|
|
'device_id' => $deviceId,
|
|
|
- 'device_title' => $monthlyOrder->where('device_id', $deviceId)->first()->device_title ?? '未知设备',
|
|
|
|
|
|
|
+ 'device_title' => $deviceMap[$deviceId] ?? '未知设备',
|
|
|
'start_time' => sprintf('%02d:%02d', floor($start / 60), $start % 60),
|
|
'start_time' => sprintf('%02d:%02d', floor($start / 60), $start % 60),
|
|
|
'end_time' => sprintf('%02d:%02d', floor($end / 60), $end % 60),
|
|
'end_time' => sprintf('%02d:%02d', floor($end / 60), $end % 60),
|
|
|
'start_hour' => (int)floor($start / 60),
|
|
'start_hour' => (int)floor($start / 60),
|
|
@@ -1154,7 +1164,7 @@ class DeviceWorkService extends Service
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
$tempRem -= $take;
|
|
$tempRem -= $take;
|
|
|
- $p['s'] = $end; // 时间指针向后推,确保不重叠
|
|
|
|
|
|
|
+ $p['s'] = $end;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|