|
|
@@ -1176,52 +1176,97 @@ class DeviceWorkService extends Service
|
|
|
public function dailyDwOrderSave($data, $user)
|
|
|
{
|
|
|
$list = $data['list'] ?? [];
|
|
|
- if (empty($list)) return [false, '没有可保存的数据'];
|
|
|
+ if (empty($list)) return [false, '提交数据不能为空'];
|
|
|
|
|
|
$topDepartId = $user['top_depart_id'];
|
|
|
+ $month = $data['month'];
|
|
|
$now = time();
|
|
|
|
|
|
+ // 1. 预加载设备名称映射,用于友好报错
|
|
|
+ $deviceIds = collect($list)->pluck('device_id')->unique()->toArray();
|
|
|
+ $deviceMap = DB::table('device')
|
|
|
+ ->whereIn('id', $deviceIds)
|
|
|
+ ->pluck('title', 'id')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ // --- 2. 重新分组:在分组的同时,利用原始索引 index 记录行号 ---
|
|
|
+ $groupedByOrder = [];
|
|
|
+ foreach ($list as $index => $item) {
|
|
|
+ $item['_line'] = $index + 1; // 记录原始行号(从1开始)
|
|
|
+ $groupKey = $item['order_time'] . '_' . $item['item_id'];
|
|
|
+ $groupedByOrder[$groupKey][] = $item;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 冲突校验器容器:记录 [设备ID][日期] 下已占用的时间段
|
|
|
+ $deviceTimeline = [];
|
|
|
+
|
|
|
DB::beginTransaction();
|
|
|
try {
|
|
|
- // 清理旧数据
|
|
|
- $monthStart = $this->changeDateToDate($data['month']);
|
|
|
+ // A. 清理该月份旧数据
|
|
|
+ $monthStart = $this->changeDateToDate($month);
|
|
|
$monthEnd = strtotime('+1 month', $monthStart) - 1;
|
|
|
|
|
|
$oldOrderIds = DB::table('daily_dw_order')
|
|
|
->where('top_depart_id', $topDepartId)
|
|
|
- ->where('order_time', '>=', $monthStart)
|
|
|
- ->where('order_time', '<=', $monthEnd)
|
|
|
- ->where('is_create', 0)
|
|
|
- ->where('del_time', 0)->pluck('id');
|
|
|
+ ->whereBetween('order_time', [$monthStart, $monthEnd])
|
|
|
+ ->where('del_time', 0)
|
|
|
+ ->pluck('id');
|
|
|
|
|
|
if ($oldOrderIds->isNotEmpty()) {
|
|
|
DB::table('daily_dw_order')->whereIn('id', $oldOrderIds)->update(['del_time' => $now]);
|
|
|
DB::table('daily_dw_order_details')->whereIn('main_id', $oldOrderIds)->update(['del_time' => $now]);
|
|
|
}
|
|
|
|
|
|
- // 按 temp_main_id 分组批量插入
|
|
|
- $grouped = collect($list)->groupBy('temp_main_id');
|
|
|
-
|
|
|
- foreach ($grouped as $tempMainId => $details) {
|
|
|
- $first = $details->first();
|
|
|
+ // B. 遍历重组后的分组,生成单据
|
|
|
+ foreach ($groupedByOrder as $details) {
|
|
|
+ $first = $details[0];
|
|
|
+ $orderTime = $first['order_timestamp'];
|
|
|
+ $itemId = $first['item_id'];
|
|
|
|
|
|
+ // 写入设备日工时主表
|
|
|
$mainId = DB::table('daily_dw_order')->insertGetId([
|
|
|
- 'code' => '',
|
|
|
- 'item_id' => $first['item_id'],
|
|
|
- 'order_time' => $first['order_timestamp'],
|
|
|
+ 'code' => '',
|
|
|
+ 'item_id' => $itemId,
|
|
|
+ 'order_time' => $orderTime,
|
|
|
'top_depart_id' => $topDepartId,
|
|
|
- 'is_create' => 1,
|
|
|
- 'crt_id' => $user['id'],
|
|
|
- 'crt_time' => $now,
|
|
|
- 'upd_time' => $now,
|
|
|
- 'del_time' => 0
|
|
|
+ 'is_create' => 1,
|
|
|
+ 'crt_id' => $user['id'],
|
|
|
+ 'crt_time' => $now,
|
|
|
]);
|
|
|
|
|
|
- $insertData = [];
|
|
|
+ $insertDetails = [];
|
|
|
foreach ($details as $d) {
|
|
|
- $insertData[] = [
|
|
|
+ $rowNum = $d['_line'];
|
|
|
+ $devId = $d['device_id'];
|
|
|
+ $devName = $deviceMap[$devId] ?? "设备(ID:{$devId})";
|
|
|
+
|
|
|
+ // 时间转分钟数进行冲突校验
|
|
|
+ $s = (int)$d['start_hour'] * 60 + (int)$d['start_min'];
|
|
|
+ $e = (int)$d['end_hour'] * 60 + (int)$d['end_min'];
|
|
|
+
|
|
|
+ // --- 核心校验:精准提示行号 ---
|
|
|
+
|
|
|
+ // 校验1:逻辑合法性
|
|
|
+ if ($e <= $s) {
|
|
|
+ return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的结束时间必须晚于开始时间"];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验2:跨单据冲突校验
|
|
|
+ if (isset($deviceTimeline[$devId][$orderTime])) {
|
|
|
+ foreach ($deviceTimeline[$devId][$orderTime] as $exist) {
|
|
|
+ // 碰撞算法: (开始A < 结束B) 且 (结束A > 开始B)
|
|
|
+ if ($s < $exist['e'] && $e > $exist['s']) {
|
|
|
+ return [false, "第 {$rowNum} 行:设备[{$devName}]在[{$d['order_time']}]的时间段({$d['start_time']}-{$d['end_time']})与其他项目存在冲突,请检查!"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录当前时间段用于后续校验
|
|
|
+ $deviceTimeline[$devId][$orderTime][] = ['s' => $s, 'e' => $e];
|
|
|
+
|
|
|
+ $insertDetails[] = [
|
|
|
'main_id' => $mainId,
|
|
|
- 'device_id' => $d['device_id'],
|
|
|
+ 'device_id' => $devId,
|
|
|
'top_depart_id' => $topDepartId,
|
|
|
'start_time_hour' => $d['start_hour'],
|
|
|
'start_time_min' => $d['start_min'],
|
|
|
@@ -1229,17 +1274,17 @@ class DeviceWorkService extends Service
|
|
|
'end_time_min' => $d['end_min'],
|
|
|
'total_work_min' => $d['total_work_min'],
|
|
|
'crt_time' => $now,
|
|
|
- 'upd_time' => $now,
|
|
|
- 'del_time' => 0
|
|
|
];
|
|
|
}
|
|
|
- DB::table('daily_dw_order_details')->insert($insertData);
|
|
|
|
|
|
- // 回填单号
|
|
|
+ // 执行明细批量插入
|
|
|
+ DB::table('daily_dw_order_details')->insert($insertDetails);
|
|
|
+
|
|
|
+ // C. 回填单号
|
|
|
$code = $this->generateBillNo([
|
|
|
'top_depart_id' => $topDepartId,
|
|
|
'type' => DailyDwOrder::Order_type,
|
|
|
- 'period' => date("Ym", $first['order_timestamp'])
|
|
|
+ 'period' => date("Ym", $orderTime)
|
|
|
]);
|
|
|
DB::table('daily_dw_order')->where('id', $mainId)->update(['code' => $code]);
|
|
|
}
|
|
|
@@ -1248,7 +1293,7 @@ class DeviceWorkService extends Service
|
|
|
return [true, ''];
|
|
|
} catch (\Exception $e) {
|
|
|
DB::rollBack();
|
|
|
- return [false, '保存失败: ' . $e->getMessage()];
|
|
|
+ return [false, "保存失败:" . $e->getMessage()];
|
|
|
}
|
|
|
}
|
|
|
}
|