From 8c65f898ed6e5b0c7a94c792c4562f6ec831dccd Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期六, 07 十一月 2026 08:50:53 +0800
Subject: [PATCH] feat: 完善质检、生产、销售、财务与人事模块并接入审批流程

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java |  101 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
index 6cf8b19..7fefce0 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.hrm.service.salary;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSalaryCalculationPageReqVO;
@@ -31,6 +32,8 @@
 import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSocialSecuritySchemeMapper;
 import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryStructureMapper;
 import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
+import cn.iocoder.yudao.module.mes.api.feedback.MesProFeedbackWageApi;
+import cn.iocoder.yudao.module.mes.api.feedback.dto.MesProFeedbackWageDetailRespDTO;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.hrm.enums.HrmOvertimeTypeEnum;
 import jakarta.annotation.Resource;
@@ -44,6 +47,7 @@
 import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -107,6 +111,8 @@
     private HrmEmployeeScheduleMapper employeeScheduleMapper;
     @Resource
     private HrmShiftMapper shiftMapper;
+    @Resource
+    private MesProFeedbackWageApi feedbackWageApi;
 
     @Override
     public PageResult<HrmSalaryCalculationDO> getSalaryCalculationPage(HrmSalaryCalculationPageReqVO pageReqVO) {
@@ -139,6 +145,11 @@
                 .filter(e -> deptId == null || deptId.equals(e.getDeptId()))
                 .toList();
 
+        // 1.1 涓�娆℃眹鎬绘墍鏈夊憳宸ュ綋鏈堢殑鐢熶骇鎶ュ伐宸ヨ祫锛岄伩鍏嶉�愪汉鏌ヨ
+        Map<Long, BigDecimal> workWageMap = loadWorkWageMap(employees, period);
+        // 1.2 涓�娆″姞杞芥秹鍙婇儴闂ㄧ殑鏈�鏂扮ぞ淇濆叕绉噾妗f锛岄伩鍏嶉�愪汉鏌ヨ
+        Map<Long, HrmEmployeeSocialSecurityDO> deptSocialSecurityMap = loadDeptSocialSecurityMap(employees);
+
         // 2. 閬嶅巻鍛樺伐杩涜钖叕鏍哥畻
         for (HrmEmployeeDO employee : employees) {
             // employeeId 鏄憳宸D锛岀敤浜庡叧鑱旇柂閰。妗堛�佺ぞ淇濇。妗堛�佹牳绠楄褰�
@@ -163,8 +174,9 @@
                 employeeSalary = buildDefaultEmployeeSalary(employeeId, employee);
             }
 
-            // 2.3 鑾峰彇鍛樺伐绀句繚鍏Н閲戞。妗堬紙鎸夊憳宸D鏌ヨ锛屽彇鏈�鏂扮敓鏁堢殑锛�
-            HrmEmployeeSocialSecurityDO socialSecurity = employeeSocialSecurityMapper.selectLatestByUserId(employeeId);
+            // 2.3 鑾峰彇鍛樺伐鎵�鍦ㄩ儴闂ㄧ殑绀句繚鍏Н閲戞。妗堬紙鎸夐儴闂ㄥ彇鏈�鏂扮敓鏁堢殑锛�
+            HrmEmployeeSocialSecurityDO socialSecurity = employee.getDeptId() == null
+                    ? null : deptSocialSecurityMap.get(employee.getDeptId());
             // 2.4 濡傛灉鏈夌ぞ淇濇。妗堬紝鑾峰彇缁戝畾鐨勬柟妗�
             HrmSocialSecuritySchemeDO scheme = null;
             if (socialSecurity != null && socialSecurity.getSocialSecuritySchemeId() != null) {
@@ -172,7 +184,8 @@
             }
 
             // 2.5 鏋勫缓鏍哥畻璁板綍锛堝寘鍚墸闄よ绠楋紝閫氳繃鏂规鑾峰彇姣斾緥锛�
-            HrmSalaryCalculationDO calculation = buildSalaryCalculation(period, employeeId, employee, employeeSalary, socialSecurity, scheme, effectiveDate);
+            HrmSalaryCalculationDO calculation = buildSalaryCalculation(period, employeeId, employee, employeeSalary,
+                    socialSecurity, scheme, effectiveDate, workWageMap);
 
             // 2.6 淇濆瓨锛氶娆$敓鎴愬崟鍙凤紱宸叉湁寰呯‘璁よ褰曞垯淇濈暀鍗曞彿骞惰鐩栭噸绠楃粨鏋�
             if (CollUtil.isNotEmpty(existCalculations)) {
@@ -202,6 +215,46 @@
     }
 
     /**
+     * 姹囨�绘牳绠楀懆鏈熷唴鎵�鏈夊憳宸ョ殑鐢熶骇鎶ュ伐宸ヨ祫銆�
+     *
+     * <p>鎶ュ伐鍗曡褰曠殑鏄姤宸ヤ汉锛堢郴缁熺敤鎴稩D锛夛紝钖叕鏍哥畻璁板綍鐨勬槸鍛樺伐ID锛屼袱鑰呴渶閫氳繃
+     * {@link HrmEmployeeDO#getUserId()} 鏄犲皠锛涙病鏈夌粦瀹氱郴缁熻处鍙风殑鍛樺伐涓嶄骇鐢熸姤宸ュ伐璧勩��
+     */
+    private Map<Long, BigDecimal> loadWorkWageMap(List<HrmEmployeeDO> employees, String period) {
+        Set<Long> userIds = employees.stream()
+                .map(HrmEmployeeDO::getUserId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (CollUtil.isEmpty(userIds)) {
+            return Collections.emptyMap();
+        }
+        YearMonth month = YearMonth.parse(period);
+        return feedbackWageApi.getWageAmountMap(userIds, month.atDay(1).atStartOfDay(),
+                month.atEndOfMonth().atTime(23, 59, 59));
+    }
+
+    /**
+     * 鍔犺浇娑夊強閮ㄩ棬鍚勮嚜鏈�鏂扮敓鏁堢殑绀句繚鍏Н閲戞。妗堛��
+     *
+     * <p>妗f鎸夐儴闂ㄧ淮鎶わ紝閮ㄩ棬涓嬫墍鏈夊憳宸ュ叡鐢ㄥ悓涓�浠芥。妗堬紱鏌ヨ缁撴灉宸叉寜鐢熸晥鏃ユ湡鍊掑簭锛�
+     * 姣忎釜閮ㄩ棬鍙栫涓�鏉″嵆鍙��
+     */
+    private Map<Long, HrmEmployeeSocialSecurityDO> loadDeptSocialSecurityMap(List<HrmEmployeeDO> employees) {
+        Set<Long> deptIds = employees.stream()
+                .map(HrmEmployeeDO::getDeptId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (CollUtil.isEmpty(deptIds)) {
+            return Collections.emptyMap();
+        }
+        Map<Long, HrmEmployeeSocialSecurityDO> result = new HashMap<>();
+        for (HrmEmployeeSocialSecurityDO socialSecurity : employeeSocialSecurityMapper.selectListByDeptIds(deptIds)) {
+            result.putIfAbsent(socialSecurity.getDeptId(), socialSecurity);
+        }
+        return result;
+    }
+
+    /**
      * 鏋勫缓榛樿鐨勫憳宸ヨ柂閰。妗堛�傚熀鏈伐璧勭粺涓�鍙栧憳宸ユ。妗堬紝缁╂晥宸ヨ祫榛樿涓嶈嚜鍔ㄧ敓鎴愩��
      */
     private HrmEmployeeSalaryDO buildDefaultEmployeeSalary(Long employeeId, HrmEmployeeDO employee) {
@@ -226,7 +279,8 @@
                                                           HrmEmployeeSalaryDO employeeSalary,
                                                           HrmEmployeeSocialSecurityDO socialSecurity,
                                                           HrmSocialSecuritySchemeDO scheme,
-                                                          LocalDate effectiveDate) {
+                                                          LocalDate effectiveDate,
+                                                          Map<Long, BigDecimal> workWageMap) {
         // 璁$畻搴斿彂钖祫
         BigDecimal baseSalary = employeeSalary.getBaseSalary() != null ? employeeSalary.getBaseSalary() : BigDecimal.ZERO;
         BigDecimal performanceSalary = employeeSalary.getPerformanceSalary() != null ? employeeSalary.getPerformanceSalary() : BigDecimal.ZERO;
@@ -236,14 +290,19 @@
         OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary);
         BigDecimal overtimePay = overtimeSalary.pay();
 
+        // 鎶ュ伐宸ヨ祫锛氭姤宸ヤ汉锛堢郴缁熺敤鎴稩D锛夊湪鏍哥畻鍛ㄦ湡鍐呭凡瀹℃壒閫氳繃鐨勬姤宸ュ伐璧勫悎璁�
+        BigDecimal workWage = employee.getUserId() != null
+                ? workWageMap.getOrDefault(employee.getUserId(), BigDecimal.ZERO)
+                : BigDecimal.ZERO;
+
         // 鎸夋帓鐝疮璁″嚭鍕ゅぉ鏁颁笌鎺掔彮鎬诲伐鏃讹紙鏃犳帓鐝椂鍑哄嫟澶╂暟鍥為��榛樿 22锛�
         ScheduleStat scheduleStat = calculateScheduleStat(employeeId, period);
         Integer workDays = scheduleStat.scheduledDays() > 0 ? scheduleStat.scheduledDays() : 22;
         BigDecimal totalWorkHours = scheduleStat.totalWorkHours();
 
-        // 搴斿彂宸ヨ祫鎬婚
+        // 搴斿彂宸ヨ祫鎬婚锛堝惈鎶ュ伐宸ヨ祫锛�
         BigDecimal totalIncome = baseSalary.add(performanceSalary).add(mealAllowance)
-                .add(transportAllowance).add(otherAllowance).add(overtimePay);
+                .add(transportAllowance).add(otherAllowance).add(overtimePay).add(workWage);
 
         // 鑾峰彇绀句繚鍩烘暟锛氬憳宸ョぞ淇濇。妗� > 鍛樺伐鍩烘湰宸ヨ祫
         BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null)
@@ -305,6 +364,7 @@
                 .mealAllowance(mealAllowance)
                 .transportAllowance(transportAllowance)
                 .otherAllowance(otherAllowance)
+                .workWage(workWage)
                 .socialSecurityDeduction(socialSecurityDeduction)
                 .housingFundDeduction(housingFundDeduction)
                 .taxDeduction(taxDeduction)
@@ -529,7 +589,12 @@
                 .filter(e -> deptId == null || deptId.equals(e.getDeptId()))
                 .toList();
 
-        // 2. 閬嶅巻鍛樺伐瀹炴椂璁$畻钖叕
+        // 2. 涓�娆℃眹鎬绘墍鏈夊憳宸ュ綋鏈堢殑鐢熶骇鎶ュ伐宸ヨ祫
+        Map<Long, BigDecimal> workWageMap = loadWorkWageMap(employees, period);
+        // 2.1 涓�娆″姞杞芥秹鍙婇儴闂ㄧ殑鏈�鏂扮ぞ淇濆叕绉噾妗f
+        Map<Long, HrmEmployeeSocialSecurityDO> deptSocialSecurityMap = loadDeptSocialSecurityMap(employees);
+
+        // 3. 閬嶅巻鍛樺伐瀹炴椂璁$畻钖叕
         List<HrmSalaryCalculationDO> resultList = new java.util.ArrayList<>();
         for (HrmEmployeeDO employee : employees) {
             Long employeeId = employee.getId();
@@ -541,8 +606,9 @@
                 employeeSalary = buildDefaultEmployeeSalary(employeeId, employee);
             }
 
-            // 2.2 鑾峰彇鍛樺伐绀句繚鍏Н閲戞。妗堬紙鎸夊憳宸D鏌ヨ锛屽彇鏈�鏂扮敓鏁堢殑锛�
-            HrmEmployeeSocialSecurityDO socialSecurity = employeeSocialSecurityMapper.selectLatestByUserId(employeeId);
+            // 2.2 鑾峰彇鍛樺伐鎵�鍦ㄩ儴闂ㄧ殑绀句繚鍏Н閲戞。妗堬紙鎸夐儴闂ㄥ彇鏈�鏂扮敓鏁堢殑锛�
+            HrmEmployeeSocialSecurityDO socialSecurity = employee.getDeptId() == null
+                    ? null : deptSocialSecurityMap.get(employee.getDeptId());
             // 2.3 濡傛灉鏈夌ぞ淇濇。妗堬紝鑾峰彇缁戝畾鐨勬柟妗�
             HrmSocialSecuritySchemeDO scheme = null;
             if (socialSecurity != null && socialSecurity.getSocialSecuritySchemeId() != null) {
@@ -550,7 +616,8 @@
             }
 
             // 2.4 鏋勫缓鏍哥畻璁板綍锛堝疄鏃惰绠楋紝涓嶅瓨鍌級
-            HrmSalaryCalculationDO calculation = buildSalaryCalculation(period, employeeId, employee, employeeSalary, socialSecurity, scheme, effectiveDate);
+            HrmSalaryCalculationDO calculation = buildSalaryCalculation(period, employeeId, employee, employeeSalary,
+                    socialSecurity, scheme, effectiveDate, workWageMap);
             resultList.add(calculation);
         }
         return resultList;
@@ -576,6 +643,20 @@
         }
     }
 
+    @Override
+    public List<MesProFeedbackWageDetailRespDTO> getWorkWageDetailList(String period, Long employeeId) {
+        if (employeeId == null || StrUtil.isBlank(period)) {
+            return Collections.emptyList();
+        }
+        HrmEmployeeDO employee = employeeMapper.selectById(employeeId);
+        if (employee == null || employee.getUserId() == null) {
+            return Collections.emptyList();
+        }
+        YearMonth month = YearMonth.parse(period);
+        return feedbackWageApi.getWageDetailList(employee.getUserId(),
+                month.atDay(1).atStartOfDay(), month.atEndOfMonth().atTime(23, 59, 59));
+    }
+
     /**
      * 鍐呴儴鐢熸垚鍙戞斁鍙拌处鏂规硶锛堜緵鑷姩鐢熸垚璋冪敤锛�
      */

--
Gitblit v1.9.3