cqp пре 2 часа
родитељ
комит
c36abed0e1

+ 2 - 2
app/Exports/ItemSalaryFTSheetExport.php

@@ -63,7 +63,7 @@ class ItemSalaryFTSheetExport implements FromCollection, WithEvents, WithCustomS
                 $sheet->setCellValue('A3', '序号');
                 $sheet->setCellValue('B3', '技术人员');
                 $sheet->setCellValue('C3', '工资');
-                $sheet->setCellValue('D3', '月总工时');
+                $sheet->setCellValue('D3', '出勤总工时');
 
                 // A. 月工时区域 (E列开始)
                 $workHourStartCol = 5;
@@ -71,7 +71,7 @@ class ItemSalaryFTSheetExport implements FromCollection, WithEvents, WithCustomS
                 $workHourStartLetter = Coordinate::stringFromColumnIndex($workHourStartCol);
                 $workHourEndLetter = Coordinate::stringFromColumnIndex($workHourEndCol);
                 $sheet->mergeCells("{$workHourStartLetter}3:{$workHourEndLetter}3");
-                $sheet->setCellValue("{$workHourStartLetter}3", '月 工 时');
+                $sheet->setCellValue("{$workHourStartLetter}3", '当月研发总工时');
                 foreach ($this->projects as $idx => $code) {
                     $sheet->setCellValue(Coordinate::stringFromColumnIndex($workHourStartCol + $idx) . '4', $code);
                 }

+ 3 - 2
app/Service/ExportFileService.php

@@ -724,9 +724,10 @@ class ExportFileService extends Service
                 $first = $records->first();
                 $empMonthSalary = (float)$first['total_salary'];
                 $empTotalHours = $first['total_hours'];
+                $empTotalCQHours = $first['total_cq_hours'];
 
-                // 1-4列:序号、姓名、工资、月总工时
-                $row = [$index++, $first['employee_title'], $empMonthSalary, $empTotalHours];
+                // 1-4列:序号、姓名、工资、出勤总工时
+                $row = [$index++, $first['employee_title'], $empMonthSalary, $empTotalCQHours];
 
                 // 5. 动态项目工时列
                 $empMap = $records->keyBy('item_code');

+ 129 - 1
app/Service/StatisticService.php

@@ -203,7 +203,7 @@ class StatisticService extends StatisticCommonService
         return [true, $item_month_list];
     }
 
-    public function itemDaySalaryStatistic($data, $user)
+    public function itemDaySalaryStatistic1($data, $user)
     {
         //项目编码、项目名称、人员名称、研发工时、研发工资、当月总工时、总计工资、年月
         list($status, $month_start, $month_end) = $this->commonRule($data);
@@ -276,6 +276,134 @@ class StatisticService extends StatisticCommonService
         return [true, $item_month_list];
     }
 
+    public function itemDaySalaryStatistic($data, $user)
+    {
+        // 项目编码、项目名称、人员名称、研发工时、研发工资、当月总工时、总计工资、年月
+        list($status, $month_start, $month_end) = $this->commonRule($data);
+        if (!$status) return [false, $month_start];
+
+        // 1. 确认所有项目、人员、人员工时(日工时单汇总)
+        $month_employee_list = $this->getItemEmployeeMonthWorkList($user, $data, $month_start, $month_end);
+
+        // 2. 查询所有人员工资
+        $salary_map = $this->getEmployeeSalary($user, $data, $month_start, $month_end);
+
+        // --- 3. 查询所有人员月度工时单 (作为出勤工时来源 / 分摊分母) ---
+        $monthly_pw_order_key_list = MonthlyPwOrder::Clear($user, $data)
+            ->where('del_time', 0)
+            ->where("month", ">=", $month_start)
+            ->where("month", "<", $month_end)
+            ->select('id', DB::raw("FROM_UNIXTIME(month, '%Y-%m') as month_str"))
+            ->pluck('month_str', 'id')
+            ->toArray();
+
+        $monthly_pw_order_ids = array_keys($monthly_pw_order_key_list);
+
+        $month_employee_pw = MonthlyPwOrderDetails::whereIn('main_id', $monthly_pw_order_ids)
+            ->where('del_time', 0)
+            ->select('employee_id', 'main_id', 'total_hours')
+            ->get()->toArray();
+
+        $pw_hours_map = [];
+        foreach ($month_employee_pw as $pw_val) {
+            $pw_month = $monthly_pw_order_key_list[$pw_val['main_id']] ?? '';
+            if ($pw_month) {
+                $pw_key = $pw_val['employee_id'] . '_' . $pw_month;
+                $pw_hours_map[$pw_key] = (float)$pw_val['total_hours'];
+            }
+        }
+
+        // 4. 计算每个员工在每个月的研发总工时(来源于日工时单,单位:分钟)
+        $keys = ["employee_id", "order_month"];
+        $employee_monthly_total_min = $this->calculateSum($month_employee_list, $keys, "total_work");
+
+        // 5. 计算分摊比例
+        list($item_month_list, ) = $this->calculateRatioForMonth(
+            $month_employee_list,
+            $employee_monthly_total_min,
+            $salary_map,
+            ["employee_id", "order_month"],
+            ["order_month", "item_id", "employee_id"]
+        );
+
+        $collect = collect($item_month_list);
+        $employee_count = $collect->groupBy(function ($item) {
+            return $item['employee_id'] . '_' . $item['month'];
+        })->map(function ($group) {
+            return $group->count();
+        })->toArray();
+
+        $item_month_list = $collect->sortBy('month')->values()->all();
+
+        // 6. 提取关联的 Item 和 Employee 字典数据
+        $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
+        $employee_ids = collect($item_month_list)->pluck('employee_id')->unique()->values()->all();
+
+        $item_query = Item::TopClear($user, $data)->wherein('id', $items);
+        $item_title_key_list = (clone $item_query)->pluck("title", "id")->toArray();
+        $item_code_key_list = (clone $item_query)->pluck("code", "id")->toArray();
+
+        $employee_key_list = Employee::TopClear($user, $data)
+            ->wherein('id', $employee_ids)
+            ->pluck("title", "id")
+            ->toArray();
+
+        // 7. 修正计算精度:日工时单研发总工时分钟转小时放大值(保留两位小数 * 100)
+        $month_total_hour = collect($employee_monthly_total_min)->map(function ($value) {
+            return round($value / 60, 2) * 100;
+        })->toArray();
+
+        $sums = [
+            "work_hours" => $month_total_hour,
+            "allocated_salary" => $salary_map
+        ];
+
+        $word_keys = [
+            "allocated_salary" => [
+                "key" => "allocated_salary",
+                "value" => "allocated_salary",
+                "type" => "100b",
+            ],
+            "work_hours" => [
+                "key" => "work_minutes",
+                "value" => "work_hours",
+                "type" => "hour",
+            ],
+        ];
+
+        $counts = [];
+        foreach ($word_keys as $k => $v) {
+            $counts[$k] = $employee_count;
+        }
+
+        // 8. 数据转换与结果组装
+        $item_month_list = collect($item_month_list)->transform(function ($item) use (
+            $item_title_key_list,
+            $item_code_key_list,
+            $employee_key_list,
+            $pw_hours_map,
+            &$sums,
+            &$counts,
+            $word_keys
+        ) {
+            $key = $item['employee_id'] . '_' . $item['month'];
+
+            $item['item_title'] = $item_title_key_list[$item['item_id']] ?? "未知项目({$item['item_id']})";
+            $item['item_code'] = $item_code_key_list[$item['item_id']] ?? "未知项目({$item['item_id']})";
+            $item['employee_title'] = $employee_key_list[$item['employee_id']] ?? "未知人员({$item['employee_id']})";
+            $item['total_salary'] = round(($item['total_salary'] ?? 0) / 100, 2);
+
+            $item['total_cq_hours'] = $pw_hours_map[$key] ?? 0;
+
+            // 执行反扣平差逻辑
+            $this->calculateClosure($key, $item, $counts, $sums, $word_keys);
+
+            return $item;
+        })->all();
+
+        return [true, $item_month_list];
+    }
+
     public function itemDeviceMonthStatistic($data, $user)
     {
         //项目编码、项目名称、设备名称、项目工时、研发工时占比、设备原值、设备折旧额、本项目帐面归集的折旧额、确定的本项目折旧额、加计调整金额、当月工时、日期