cqp hai 2 meses
pai
achega
aeca5dc566
Modificáronse 1 ficheiros con 34 adicións e 53 borrados
  1. 34 53
      app/Service/PersonWorkService.php

+ 34 - 53
app/Service/PersonWorkService.php

@@ -1086,32 +1086,38 @@ class PersonWorkService extends Service
         $now = time();
 
         // --- 1. 基础数据加载 ---
+
+        // 加载月度工时明细,并关联人员姓名
         $monthlyOrder = DB::table('monthly_pw_order_details as d')
             ->join('monthly_pw_order as m', 'm.id', '=', 'd.main_id')
+            ->leftJoin('employee as e', 'e.id', '=', 'd.employee_id') // 关联人员表
             ->where('m.month', $monthStart)
             ->where('m.top_depart_id', $topDepartId)
             ->where('m.del_time', 0)
             ->where('d.del_time', 0)
-            ->select('d.*')
+            ->select('d.*', 'e.title as employee_title') // 获取人员姓名
             ->get();
 
         if ($monthlyOrder->isEmpty()) return ['status' => false, 'msg' => '未找到该月份的月度工时明细'];
 
-        $empIds = $monthlyOrder->pluck('employee_id')->unique()->toArray();
+        // 建立人员 ID -> 姓名的映射,方便后续取用
+        $empNameMap = $monthlyOrder->pluck('employee_title', 'employee_id')->toArray();
+        $empIds = array_keys($empNameMap);
 
-        // 加载员工/标准班次
-        $empWorkRanges = DB::table('employee_work_range')
-            ->whereIn('employee_id', $empIds)
-            ->where('top_depart_id', $topDepartId)
-            ->get()
-            ->groupBy('employee_id');
+        // 加载项目信息,用于获取项目名称
+        // 假设项目表名为 items,请根据你实际的表名修改
+        $itemIds = DB::table('rule_set_details as rd')
+            ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
+            ->where('r.month', $monthStart)
+            ->where('r.top_depart_id', $topDepartId)
+            ->pluck('rd.item_id')->unique()->toArray();
 
-        $standardWorkRanges = DB::table('work_range_details')
-            ->where('top_depart_id', $topDepartId)
-            ->where('del_time', 0)
-            ->get();
+        $itemMap = DB::table('item')
+        ->whereIn('id', $itemIds)
+            ->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)
@@ -1122,21 +1128,13 @@ class PersonWorkService extends Service
             ->get()
             ->groupBy('data_id');
 
-        // 加载日历
-        $allDays = DB::table('calendar_details')
-            ->where('month', $monthStart)
-            ->where('del_time', 0)
-            ->orderBy('time', 'asc')
-            ->get();
-
-        // 加载请假/加班数据
-        $leaveOverData = DB::table('p_leave_over_order_details as d')
-            ->join('p_leave_over_order as m', 'd.main_id', '=', 'm.id')
-            ->whereBetween('m.order_time', [$monthStart, $monthEnd])
-            ->where('m.del_time', 0)
-            ->select('d.*', 'm.order_time', 'm.type as main_type')
-            ->get()
-            ->groupBy(['employee_id', 'order_time']);
+        // 加载员工/标准班次、日历、请假加班数据 (逻辑同前)
+        $empWorkRanges = DB::table('employee_work_range')->whereIn('employee_id', $empIds)->where('top_depart_id', $topDepartId)->get()->groupBy('employee_id');
+        $standardWorkRanges = DB::table('work_range_details')->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
+        $allDays = DB::table('calendar_details')->where('month', $monthStart)->where('del_time', 0)->orderBy('time', 'asc')->get();
+        $leaveOverData = DB::table('p_leave_over_order_details as d')->join('p_leave_over_order as m', 'd.main_id', '=', 'm.id')
+            ->whereBetween('m.order_time', [$monthStart, $monthEnd])->where('m.del_time', 0)
+            ->select('d.*', 'm.order_time', 'm.type as main_type')->get()->groupBy(['employee_id', 'order_time']);
 
         // --- 2. 阶段一:计算每个人每天在每个项目上应分配的整数分钟数 ---
         $finalAlloc = [];
@@ -1145,43 +1143,28 @@ class PersonWorkService extends Service
             $empRules = $ruleSet->get($empId);
             if (!$empRules) continue;
 
-            // 月度总额(转为整数分钟)
             $empRemainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
             if ($empRemainingMin <= 0) continue;
 
             foreach ($allDays as $dayInfo) {
                 if ($empRemainingMin <= 0) break;
-
                 $dayTs = $dayInfo->time;
-
-                // 获取当天可用时间池段落(此处调用你原来的 buildAvailablePool)
                 $tempPool = $this->buildAvailablePool($empId, $dayTs, $allDays, $empWorkRanges, $standardWorkRanges, $leaveOverData);
-
-                // 计算当天总可用整数分钟
                 $dayAvailableMin = 0;
-                foreach ($tempPool as $p) {
-                    $dayAvailableMin += (int)($p['e'] - $p['s']);
-                }
-
+                foreach ($tempPool as $p) { $dayAvailableMin += (int)($p['e'] - $p['s']); }
                 if ($dayAvailableMin <= 0) continue;
 
-                // 当天实际能分配的量(取小者)
                 $canAllocToday = min($empRemainingMin, $dayAvailableMin);
-
-                // --- 核心:按项目比例切分并强制取整 ---
                 $allocatedInDay = 0;
                 $ruleCount = count($empRules);
 
                 foreach ($empRules 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[$dayTs][$rule->item_id][$empId] = $projectMin;
                         $allocatedInDay += $projectMin;
@@ -1192,29 +1175,25 @@ class PersonWorkService extends Service
         }
 
         // --- 3. 阶段二:打散到具体时间点并生成预览行 ---
-
         $previewList = [];
         $dailyEmpTimePools = [];
         $tempMainIdCounter = 1;
 
         foreach ($finalAlloc as $dayTs => $projects) {
             foreach ($projects as $itemId => $employees) {
-
-                // 同日期同项目,视为一张“模拟单据”
                 $currentTempMainId = $tempMainIdCounter++;
 
+                // 获取项目名称
+                $itemTitle = $itemMap[$itemId] ?? '未知项目';
+
                 foreach ($employees as $empId => $toAllocMin) {
-                    // 初始化当天该员工的时间池引用
                     if (!isset($dailyEmpTimePools[$dayTs][$empId])) {
                         $dailyEmpTimePools[$dayTs][$empId] = $this->buildAvailablePool($empId, $dayTs, $allDays, $empWorkRanges, $standardWorkRanges, $leaveOverData);
                     }
 
                     $tempRem = (int)$toAllocMin;
-
-                    // 从时间池里“取”整数时间
                     foreach ($dailyEmpTimePools[$dayTs][$empId] as &$p) {
                         if ($tempRem <= 0) break;
-
                         $pMax = (int)($p['e'] - $p['s']);
                         if ($pMax <= 0) continue;
 
@@ -1222,13 +1201,15 @@ class PersonWorkService extends Service
                         $realStart = (int)$p['s'];
                         $realEnd = $realStart + $take;
 
-                        // 构造预览行(全部字段已处理为整数)
+                        // 写入带 Title 的结果
                         $previewList[] = [
                             'temp_main_id'    => $currentTempMainId,
                             'order_time'      => date('Y-m-d', $dayTs),
                             'order_timestamp' => $dayTs,
                             'item_id'         => $itemId,
+                            'item_title'      => $itemTitle, // 项目名称
                             'employee_id'     => $empId,
+                            'employee_title'  => $empNameMap[$empId] ?? '未知人员', // 人员姓名
                             'start_time'      => sprintf('%02d:%02d', floor($realStart / 60), $realStart % 60),
                             'end_time'        => sprintf('%02d:%02d', floor($realEnd / 60), $realEnd % 60),
                             'start_hour'      => (int)floor($realStart / 60),
@@ -1239,7 +1220,7 @@ class PersonWorkService extends Service
                         ];
 
                         $tempRem -= $take;
-                        $p['s'] = $realEnd; // 消耗池子
+                        $p['s'] = $realEnd;
                     }
                 }
             }