Ver Fonte

公司初始化

cqp há 1 mês atrás
pai
commit
f0a2262763
2 ficheiros alterados com 35 adições e 170 exclusões
  1. 17 161
      app/Service/DeviceWorkService.php
  2. 18 9
      app/Service/PersonWorkService.php

+ 17 - 161
app/Service/DeviceWorkService.php

@@ -620,6 +620,8 @@ class DeviceWorkService extends Service
         $internalOverlap = [];
         $internalOverlap = [];
 
 
         foreach ($data['details'] as $key => $value){
         foreach ($data['details'] as $key => $value){
+            $line = $key + 1;
+            $t = "第" . $line . "行";
             $empId = $value['device_id'] ?? 0;
             $empId = $value['device_id'] ?? 0;
             if(empty($empId)) return [false, '设备不能为空'];
             if(empty($empId)) return [false, '设备不能为空'];
 
 
@@ -627,23 +629,29 @@ class DeviceWorkService extends Service
 
 
             // 校验数字有效性
             // 校验数字有效性
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}开始点:" . $res['error']];
-            if($value['start_time_hour'] > 23) return [false, false, "设备{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "设备{$empName}开始点:" . $res['error']];
+            if($value['start_time_hour'] > 23) return [false, false, $t . "设备{$empName}开始点不合法"];
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}开始分:" . $res['error']];
-            if($value['start_time_min'] > 60) return [false, false, "设备{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}开始分:" . $res['error']];
+            if($value['start_time_min'] > 60) return [false, false, $t . "设备{$empName}开始点不合法"];
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}结束点:" . $res['error']];
-            if($value['end_time_hour'] > 24) return [false, false, "设备{$empName}结束点不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}结束点:" . $res['error']];
+            if($value['end_time_hour'] > 24) return [false, false, $t . "设备{$empName}结束点不合法"];
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}结束分:" . $res['error']];
-            if($value['end_time_min'] > 60) return [false, false, "设备{$empName}结束分不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}结束分:" . $res['error']];
+            if($value['end_time_min'] > 60) return [false, false, $t . "设备{$empName}结束分不合法"];
 
 
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
 
 
             if ($currentStart >= $currentEnd) {
             if ($currentStart >= $currentEnd) {
-                return [false, "设备{$empName}:开始时间必须早于结束时间"];
+                return [false, $t . "设备{$empName}:开始时间必须早于结束时间"];
+            }
+
+            // --- 新增:总分钟数校验 ---
+            $calculatedTotal = $currentEnd - $currentStart;
+            if (!isset($value['total_work_min']) || intval($value['total_work_min']) !== $calculatedTotal) {
+                return [false, $t . "设备{$empName}:工时计算有误,应为 {$calculatedTotal} 分钟"];
             }
             }
 
 
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---
@@ -1046,158 +1054,6 @@ class DeviceWorkService extends Service
         ]];
         ]];
     }
     }
 
 
-    private function calculateDailyDeviceAllocation1($monthStart, $topDepartId, $user)
-    {
-        // 加载月度设备明细
-        $monthlyOrder = DB::table('monthly_dw_order_details as d')
-            ->join('monthly_dw_order as m', 'm.id', '=', 'd.main_id')
-            ->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' => '未找到设备月度工时明细'];
-
-        $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')
-            ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
-            ->where('r.month', $monthStart)
-            ->where('rd.type', RuleSetDetails::type_two) // 设备类型
-            ->where('rd.top_depart_id', $topDepartId)
-            ->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')
-            ->toArray();
-
-        $ruleSetGrouped = $ruleSet->groupBy('data_id'); // 按 device_id 分组
-
-        // 标准班次 & 日历 (逻辑同前)
-        $standardWorkRanges = DB::table('work_range_details')
-            ->where('top_depart_id', $topDepartId)
-            ->where('del_time', 0)
-            ->get();
-        $dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
-
-        $workDays = DB::table('calendar_details')
-            ->where('top_depart_id', $topDepartId)
-            ->where('month', $monthStart)
-            ->where('is_work', 1)
-            ->where('del_time', 0)
-            ->orderBy('time', 'asc')->get();
-
-        if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
-
-        // --- 2. 阶段一:计算每天每台设备分配的项目分钟数 ---
-        $finalAlloc = [];
-        foreach ($monthlyOrder as $mDetail) {
-            $deviceId = $mDetail->device_id;
-            $deviceRules = $ruleSetGrouped->get($deviceId);
-            if (!$deviceRules) continue;
-
-            $remainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
-            if ($remainingMin <= 0) continue;
-
-            foreach ($workDays as $dayInfo) {
-                if ($remainingMin <= 0) break;
-
-                $canAllocToday = min($remainingMin, $dayMaxAvail);
-                $allocatedInDay = 0;
-                $ruleCount = count($deviceRules);
-
-                foreach ($deviceRules as $index => $rule) {
-                    $rate = (float)$rule->rate / 100;
-                    if ($index === $ruleCount - 1) {
-                        $projectMin = $canAllocToday - $allocatedInDay;
-                    } else {
-                        $projectMin = (int)round($canAllocToday * $rate);
-                    }
-
-                    if ($projectMin > 0) {
-                        $finalAlloc[$dayInfo->time][$rule->item_id][$deviceId] = $projectMin;
-                        $allocatedInDay += $projectMin;
-                    }
-                }
-                $remainingMin -= $canAllocToday;
-            }
-        }
-
-        // --- 3. 阶段二:生成预览行 ---
-        $previewList = [];
-        $dailyDevicePools = [];
-        $tempMainIdCounter = 1;
-
-        foreach ($finalAlloc as $dayTs => $projects) {
-            foreach ($projects as $itemId => $devices) {
-
-                $currentTempMainId = $tempMainIdCounter++;
-                $itemTitle = $itemMap[$itemId] ?? '未知项目';
-
-                foreach ($devices as $deviceId => $toAllocMin) {
-                    if (!isset($dailyDevicePools[$dayTs][$deviceId])) {
-                        $pool = [];
-                        foreach ($standardWorkRanges as $swr) {
-                            $pool[] = [
-                                's' => (int)($swr->start_time_hour * 60 + $swr->start_time_min),
-                                'e' => (int)($swr->end_time_hour * 60 + $swr->end_time_min)
-                            ];
-                        }
-                        $dailyDevicePools[$dayTs][$deviceId] = $pool;
-                    }
-
-                    $tempRem = (int)$toAllocMin;
-                    foreach ($dailyDevicePools[$dayTs][$deviceId] as &$p) {
-                        if ($tempRem <= 0) break;
-                        $pMax = $p['e'] - $p['s'];
-                        if ($pMax <= 0) continue;
-
-                        $take = min($tempRem, $pMax);
-                        $start = (int)$p['s'];
-                        $end = $start + $take;
-
-                        $previewList[] = [
-                            'temp_main_id'    => $currentTempMainId,
-                            'order_time'      => date('Y-m-d', $dayTs),
-                            'order_timestamp' => $dayTs,
-                            'item_id'         => $itemId,
-                            'item_title'      => $itemTitle,
-                            'device_id'       => $deviceId,
-                            'device_title'    => $deviceMap[$deviceId] ?? '未知设备',
-                            'start_time'      => sprintf('%02d:%02d', floor($start / 60), $start % 60),
-                            'end_time'        => sprintf('%02d:%02d', floor($end / 60), $end % 60),
-                            'start_hour'      => (int)floor($start / 60),
-                            'start_min'       => (int)($start % 60),
-                            'end_hour'        => (int)floor($end / 60),
-                            'end_min'         => (int)($end % 60),
-                            'total_work_min'  => $take,
-                        ];
-
-                        $tempRem -= $take;
-                        $p['s'] = $end;
-                    }
-                }
-            }
-        }
-
-        return ['status' => true, 'data' => $previewList];
-    }
-
     private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
     private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
     {
     {
         // 加载月度设备明细
         // 加载月度设备明细

+ 18 - 9
app/Service/PersonWorkService.php

@@ -605,29 +605,38 @@ class PersonWorkService extends Service
         $internalOverlap = [];
         $internalOverlap = [];
 
 
         foreach ($data['details'] as $key => $value){
         foreach ($data['details'] as $key => $value){
+            $line = $key + 1;
+            $t = "第" . $line . "行";
+
             $empId = $value['employee_id'] ?? 0;
             $empId = $value['employee_id'] ?? 0;
             if(empty($empId)) return [false, '人员不能为空'];
             if(empty($empId)) return [false, '人员不能为空'];
 
 
             $empName = $empDisplayMap[$empId] ?? "ID:{$empId}";
             $empName = $empDisplayMap[$empId] ?? "ID:{$empId}";
 
 
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}开始点:" . $res['error']];
-            if($value['start_time_hour'] > 23) return [false, false, "人员{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}开始点:" . $res['error']];
+            if($value['start_time_hour'] > 23) return [false, false, $t . "人员{$empName}开始点不合法"];
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}开始分:" . $res['error']];
-            if($value['start_time_min'] > 60) return [false, false, "人员{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}开始分:" . $res['error']];
+            if($value['start_time_min'] > 60) return [false, false, $t . "人员{$empName}开始点不合法"];
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}结束点:" . $res['error']];
-            if($value['end_time_hour'] > 24) return [false, false, "人员{$empName}结束点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}结束点:" . $res['error']];
+            if($value['end_time_hour'] > 24) return [false, false, $t . "人员{$empName}结束点不合法"];
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}结束分:" . $res['error']];
-            if($value['end_time_min'] > 60) return [false, false, "人员{$empName}结束分不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}结束分:" . $res['error']];
+            if($value['end_time_min'] > 60) return [false, false, $t .  "人员{$empName}结束分不合法"];
 
 
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
 
 
             if ($currentStart >= $currentEnd) {
             if ($currentStart >= $currentEnd) {
-                return [false, "人员{$empName}:开始时间必须早于结束时间"];
+                return [false, $t . "人员{$empName}:开始时间必须早于结束时间"];
+            }
+
+            // --- 新增:总分钟数校验 ---
+            $calculatedTotal = $currentEnd - $currentStart;
+            if (!isset($value['total_work_min']) || intval($value['total_work_min']) !== $calculatedTotal) {
+                return [false, $t . "人员{$empName}:总工时计算有误,应为 {$calculatedTotal} 分钟"];
             }
             }
 
 
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---