cqp před 2 měsíci
rodič
revize
f6bdd45eb5
2 změnil soubory, kde provedl 35 přidání a 38 odebrání
  1. 15 27
      app/Service/DeviceWorkService.php
  2. 20 11
      app/Service/PersonWorkService.php

+ 15 - 27
app/Service/DeviceWorkService.php

@@ -1179,31 +1179,26 @@ class DeviceWorkService extends Service
         if (empty($list)) return [false, '提交数据不能为空'];
         if (empty($list)) return [false, '提交数据不能为空'];
 
 
         $topDepartId = $user['top_depart_id'];
         $topDepartId = $user['top_depart_id'];
-        $month = $data['month'];
+        $month = $data['month']; // 格式如: "2026-03"
         $now = time();
         $now = time();
 
 
-        // 1. 预加载设备名称映射 (使用 title 或 name 字段)
+        // 1. 预加载映射
         $deviceIds = collect($list)->pluck('device_id')->unique()->toArray();
         $deviceIds = collect($list)->pluck('device_id')->unique()->toArray();
-        $deviceMap = DB::table('device')
-            ->whereIn('id', $deviceIds)
-            ->pluck('title', 'id')
-            ->toArray();
+        $deviceMap = DB::table('device')->whereIn('id', $deviceIds)->pluck('title', 'id')->toArray();
 
 
-        // --- 2. 重新分组:在分组的同时,利用原始索引记录行号 ---
+        // 2. 重新分组并记录行号
         $groupedByOrder = [];
         $groupedByOrder = [];
         foreach ($list as $index => $item) {
         foreach ($list as $index => $item) {
-            $item['_line'] = $index + 1; // 记录原始行号(从1开始)
-            // 以日期字符串作为分组 Key 之一
+            $item['_line'] = $index + 1;
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupedByOrder[$groupKey][] = $item;
             $groupedByOrder[$groupKey][] = $item;
         }
         }
 
 
-        // 冲突校验器容器:记录 [设备ID][日期字符串] 下已占用的时间段
         $deviceTimeline = [];
         $deviceTimeline = [];
 
 
         DB::beginTransaction();
         DB::beginTransaction();
         try {
         try {
-            // A. 清理该月份旧数据
+            // A. 清理旧数据
             $monthStart = $this->changeDateToDate($month);
             $monthStart = $this->changeDateToDate($month);
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
 
 
@@ -1218,14 +1213,12 @@ class DeviceWorkService extends Service
                 DB::table('daily_dw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
                 DB::table('daily_dw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
             }
             }
 
 
-            // B. 遍历重组后的分组,生成单据
+            // B. 遍历重组后的分组
             foreach ($groupedByOrder as $details) {
             foreach ($groupedByOrder as $details) {
                 $first = $details[0];
                 $first = $details[0];
-                // 【修正】统一将前端日期字符串转为时间戳入库
                 $orderTimestamp = strtotime($first['order_time']);
                 $orderTimestamp = strtotime($first['order_time']);
                 $itemId = $first['item_id'];
                 $itemId = $first['item_id'];
 
 
-                // 写入设备日工时主表
                 $mainId = DB::table('daily_dw_order')->insertGetId([
                 $mainId = DB::table('daily_dw_order')->insertGetId([
                     'code'          => '',
                     'code'          => '',
                     'item_id'       => $itemId,
                     'item_id'       => $itemId,
@@ -1242,30 +1235,28 @@ class DeviceWorkService extends Service
                     $devId = $d['device_id'];
                     $devId = $d['device_id'];
                     $devName = $deviceMap[$devId] ?? "设备(ID:{$devId})";
                     $devName = $deviceMap[$devId] ?? "设备(ID:{$devId})";
 
 
-                    // 【修正】强制后端计算分钟数,防止前端传错或篡改
+                    // --- 新增:校验 order_time 是否属于当前选择的 month ---
+                    if (date("Y-m", strtotime($d['order_time'])) !== $month) {
+                        return [false, "第 {$rowNum} 行:日期[{$d['order_time']}]不属于保存月份[{$month}],请修正!"];
+                    }
+
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
                     $calcTotalMin = $e - $s;
                     $calcTotalMin = $e - $s;
 
 
-                    // --- 校验逻辑 ---
-
-                    // 校验1:逻辑合法性
                     if ($calcTotalMin <= 0) {
                     if ($calcTotalMin <= 0) {
                         return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的结束时间必须晚于开始时间"];
                         return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的结束时间必须晚于开始时间"];
                     }
                     }
 
 
-                    // 校验2:跨单据冲突校验
+                    // 冲突校验
                     $dateStr = $d['order_time'];
                     $dateStr = $d['order_time'];
                     if (isset($deviceTimeline[$devId][$dateStr])) {
                     if (isset($deviceTimeline[$devId][$dateStr])) {
                         foreach ($deviceTimeline[$devId][$dateStr] as $exist) {
                         foreach ($deviceTimeline[$devId][$dateStr] as $exist) {
-                            // 碰撞算法: (开始A < 结束B) 且 (结束A > 开始B)
                             if ($s < $exist['e'] && $e > $exist['s']) {
                             if ($s < $exist['e'] && $e > $exist['s']) {
-                                return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$dateStr}]存在时间冲突({$d['start_time']}-{$d['end_time']}),请检查!"];
+                                return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$dateStr}]存在时间冲突({$d['start_time']}-{$d['end_time']})"];
                             }
                             }
                         }
                         }
                     }
                     }
-
-                    // 记录当前时间段
                     $deviceTimeline[$devId][$dateStr][] = ['s' => $s, 'e' => $e];
                     $deviceTimeline[$devId][$dateStr][] = ['s' => $s, 'e' => $e];
 
 
                     $insertDetails[] = [
                     $insertDetails[] = [
@@ -1276,15 +1267,12 @@ class DeviceWorkService extends Service
                         'start_time_min'  => $d['start_min'],
                         'start_time_min'  => $d['start_min'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_min'    => $d['end_min'],
                         'end_time_min'    => $d['end_min'],
-                        'total_work_min'  => $calcTotalMin, // 使用后端计算结果
+                        'total_work_min'  => $calcTotalMin,
                         'crt_time'        => $now,
                         'crt_time'        => $now,
                     ];
                     ];
                 }
                 }
-
-                // 执行明细批量插入
                 DB::table('daily_dw_order_details')->insert($insertDetails);
                 DB::table('daily_dw_order_details')->insert($insertDetails);
 
 
-                // C. 回填单号
                 $code = $this->generateBillNo([
                 $code = $this->generateBillNo([
                     'top_depart_id' => $topDepartId,
                     'top_depart_id' => $topDepartId,
                     'type' => DailyDwOrder::Order_type,
                     'type' => DailyDwOrder::Order_type,

+ 20 - 11
app/Service/PersonWorkService.php

@@ -1235,22 +1235,23 @@ class PersonWorkService extends Service
         if (empty($list)) return [false, '没有可保存的数据'];
         if (empty($list)) return [false, '没有可保存的数据'];
 
 
         $topDepartId = $user['top_depart_id'];
         $topDepartId = $user['top_depart_id'];
-        $month = $data['month'];
+        $month = $data['month']; // 格式如: "2026-03"
         $now = time();
         $now = time();
 
 
-        // 1. 预加载员工姓名 (注意字段名,如果是 employee 表通常用 title 或 name)
+        // 1. 预加载员工名称映射 (使用 title 字段)
         $empIds = collect($list)->pluck('employee_id')->unique()->toArray();
         $empIds = collect($list)->pluck('employee_id')->unique()->toArray();
         $empMap = DB::table('employee')->whereIn('id', $empIds)->pluck('title', 'id')->toArray();
         $empMap = DB::table('employee')->whereIn('id', $empIds)->pluck('title', 'id')->toArray();
 
 
         // --- 2. 重新分组并记录行号 ---
         // --- 2. 重新分组并记录行号 ---
         $groupedByOrder = [];
         $groupedByOrder = [];
         foreach ($list as $index => $item) {
         foreach ($list as $index => $item) {
-            $item['_line'] = $index + 1;
-            // 确保使用日期字符串作为分组 Key
+            $item['_line'] = $index + 1; // 记录原始行号(从1开始)
+            // 以日期字符串和项目ID作为分组 Key
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupKey = $item['order_time'] . '_' . $item['item_id'];
             $groupedByOrder[$groupKey][] = $item;
             $groupedByOrder[$groupKey][] = $item;
         }
         }
 
 
+        // 冲突校验器容器:记录 [员工ID][日期字符串] 下已占用的时间段
         $empTimeline = [];
         $empTimeline = [];
 
 
         DB::beginTransaction();
         DB::beginTransaction();
@@ -1270,13 +1271,14 @@ class PersonWorkService extends Service
                 DB::table('daily_pw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
                 DB::table('daily_pw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
             }
             }
 
 
-            // B. 遍历分组写入
+            // B. 遍历重组后的分组写入
             foreach ($groupedByOrder as $details) {
             foreach ($groupedByOrder as $details) {
                 $first = $details[0];
                 $first = $details[0];
-                // 【修正】统一将前端 order_time 日期字符串转为时间戳
+                // 【修正】统一将前端日期字符串转为时间戳入库
                 $orderTimestamp = strtotime($first['order_time']);
                 $orderTimestamp = strtotime($first['order_time']);
                 $itemId = $first['item_id'];
                 $itemId = $first['item_id'];
 
 
+                // 写入主表
                 $mainId = DB::table('daily_pw_order')->insertGetId([
                 $mainId = DB::table('daily_pw_order')->insertGetId([
                     'code'          => '',
                     'code'          => '',
                     'item_id'       => $itemId,
                     'item_id'       => $itemId,
@@ -1293,22 +1295,28 @@ class PersonWorkService extends Service
                     $empId = $d['employee_id'];
                     $empId = $d['employee_id'];
                     $empName = $empMap[$empId] ?? "人员(ID:{$empId})";
                     $empName = $empMap[$empId] ?? "人员(ID:{$empId})";
 
 
-                    // 【修正】强制由后端计算分钟数,防止前端篡改
+                    // --- 新增:月份一致性校验 ---
+                    // 校验这行数据的日期是否属于当前保存的月份
+                    if (date("Y-m", strtotime($d['order_time'])) !== $month) {
+                        return [false, "第 {$rowNum} 行:人员[{$empName}]的日期[{$d['order_time']}]不属于保存月份[{$month}]"];
+                    }
+
+                    // 【修正】强制由后端计算分钟数
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
                     $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
                     $calcTotalMin = $e - $s;
                     $calcTotalMin = $e - $s;
 
 
                     // 校验1:逻辑合法性
                     // 校验1:逻辑合法性
                     if ($calcTotalMin <= 0) {
                     if ($calcTotalMin <= 0) {
-                        return [false, "第 {$rowNum} 行:人员[{$empName}]的结束时间必须晚于开始时间"];
+                        return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$d['order_time']}]时间段无效:结束时间必须晚于开始时间"];
                     }
                     }
 
 
-                    // 校验2:跨单据时间重叠校验 (使用 order_time 字符串作为 Timeline Key 即可)
+                    // 校验2:跨单据时间重叠校验
                     $dateStr = $d['order_time'];
                     $dateStr = $d['order_time'];
                     if (isset($empTimeline[$empId][$dateStr])) {
                     if (isset($empTimeline[$empId][$dateStr])) {
                         foreach ($empTimeline[$empId][$dateStr] as $exist) {
                         foreach ($empTimeline[$empId][$dateStr] as $exist) {
                             if ($s < $exist['e'] && $e > $exist['s']) {
                             if ($s < $exist['e'] && $e > $exist['s']) {
-                                return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$dateStr}]存在时间重叠({$d['start_time']}-{$d['end_time']}),请检查!"];
+                                return [false, "第 {$rowNum} 行:人员[{$empName}]在[{$dateStr}]存在时间冲突({$d['start_time']}-{$d['end_time']}),请检查!"];
                             }
                             }
                         }
                         }
                     }
                     }
@@ -1322,11 +1330,12 @@ class PersonWorkService extends Service
                         'start_time_min'  => $d['start_min'],
                         'start_time_min'  => $d['start_min'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_hour'   => $d['end_hour'],
                         'end_time_min'    => $d['end_min'],
                         'end_time_min'    => $d['end_min'],
-                        'total_work_min'  => $calcTotalMin, // 使用计算出的分钟数
+                        'total_work_min'  => $calcTotalMin,
                         'crt_time'        => $now,
                         'crt_time'        => $now,
                     ];
                     ];
                 }
                 }
 
 
+                // 批量写入明细
                 DB::table('daily_pw_order_details')->insert($insertDetails);
                 DB::table('daily_pw_order_details')->insert($insertDetails);
 
 
                 // C. 回填单号
                 // C. 回填单号