From 52e4ba6897d5d808c4ed08720bbebad9cb006103 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期四, 05 十一月 2026 13:48:56 +0800
Subject: [PATCH] fix(hrm): 修复生成考勤统计报错、实出天数翻倍;调岗/离职审批通过同步人员信息

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java |   93 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 80 insertions(+), 13 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
index c3272ee..69391d3 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
@@ -1,19 +1,24 @@
 package cn.iocoder.yudao.module.hrm.service.approval;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO;
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationPageReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationSaveReqVO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmTransferApplicationDO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
 import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmTransferApplicationMapper;
+import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService;
 import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
 import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum;
 import cn.iocoder.yudao.module.hrm.enums.HrmTransferTypeEnum;
@@ -33,6 +38,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -66,6 +72,8 @@
     @Resource
     private AdminUserApi adminUserApi;
     @Resource
+    private HrmEmployeeService employeeService;
+    @Resource
     private BpmProcessInstanceApi bpmProcessInstanceApi;
     @Resource
     private BpmCategoryService bpmCategoryService;
@@ -73,6 +81,8 @@
     private StorageAttachmentApi storageAttachmentApi;
     @Resource
     private BpmProcessDefinitionService bpmProcessDefinitionService;
+    @Resource
+    private BpmProcessInstanceService bpmProcessInstanceService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -87,14 +97,14 @@
         }
         // 3. 鐢熸垚鐢宠鍗曞彿
         String no = generateUniqueNo();
-        // 4. 璁剧疆鐢宠浜轰俊鎭�
+        // 4. 璁剧疆璋冨矖浜猴紙鍛樺伐ID锛夛細涓虹┖鏃跺彇褰撳墠鐧诲綍鐢ㄦ埛瀵瑰簲鐨勫憳宸�
         Long userId = createReqVO.getUserId();
         if (userId == null) {
-            userId = getCurrentUserId();
+            HrmEmployeeDO currentEmployee = employeeService.getEmployeeByUserId(getCurrentUserId());
+            userId = currentEmployee != null ? currentEmployee.getId() : null;
         }
-        AdminUserRespDTO user = adminUserApi.getUser(userId);
-        if (user == null) {
-            userId = getCurrentUserId();
+        if (userId != null && employeeService.getEmployee(userId) == null) {
+            throw exception(EMPLOYEE_NOT_EXISTS);
         }
         // 5. 鎻掑叆
         HrmTransferApplicationDO application = BeanUtils.toBean(createReqVO, HrmTransferApplicationDO.class);
@@ -168,9 +178,9 @@
         }
         HrmTransferApplicationRespVO respVO = BeanUtils.toBean(application, HrmTransferApplicationRespVO.class);
         if (application.getUserId() != null) {
-            AdminUserRespDTO user = adminUserApi.getUser(application.getUserId());
-            if (user != null) {
-                respVO.setUserName(user.getNickname());
+            HrmEmployeeDO employee = employeeService.getEmployee(application.getUserId());
+            if (employee != null) {
+                respVO.setUserName(employee.getName());
             }
         }
         fillDeptNames(respVO, application);
@@ -215,7 +225,14 @@
                 .map(HrmTransferApplicationDO::getUserId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
-        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
+        // userId 瀛樼殑鏄憳宸D锛屾寜鍛樺伐琛ㄦ煡璇㈠鍚�
+        Map<Long, String> employeeNameMap = new HashMap<>();
+        for (Long userId : userIds) {
+            HrmEmployeeDO employee = employeeService.getEmployee(userId);
+            if (employee != null) {
+                employeeNameMap.put(userId, employee.getName());
+            }
+        }
         Set<Long> deptIds = pageResult.getList().stream()
                 .flatMap(app -> Stream.of(app.getCurrentDeptId(), app.getTargetDeptId()))
                 .filter(Objects::nonNull)
@@ -228,8 +245,8 @@
         Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
         List<HrmTransferApplicationRespVO> list = pageResult.getList().stream().map(app -> {
             HrmTransferApplicationRespVO vo = BeanUtils.toBean(app, HrmTransferApplicationRespVO.class);
-            if (app.getUserId() != null && userMap.containsKey(app.getUserId())) {
-                vo.setUserName(userMap.get(app.getUserId()).getNickname());
+            if (app.getUserId() != null && employeeNameMap.containsKey(app.getUserId())) {
+                vo.setUserName(employeeNameMap.get(app.getUserId()));
             }
             if (app.getCurrentDeptId() != null && deptMap.containsKey(app.getCurrentDeptId())) {
                 vo.setCurrentDeptName(deptMap.get(app.getCurrentDeptId()).getName());
@@ -258,17 +275,41 @@
             throw exception(TRANSFER_APPLICATION_SUBMIT_FAIL_NOT_DRAFT);
         }
         validateApproveCategoryAndProcessDefinition();
-        ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey);
+        // 鏈寚瀹氭祦绋嬪畾涔� Key 鏃讹紝鑷姩鍙栥�岃皟鍔ㄥ鎵广�嶅垎绫讳笅褰撳墠娲昏穬鐨勬祦绋嬶紝
+        // 閬垮厤鍓嶇鏈紶 key 瀵艰嚧鎺ュ彛鍙傛暟缂哄け鐩存帴鎶ョ郴缁熷紓甯�
+        String key = resolveProcessDefinitionKey(processDefinitionKey);
+        ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(key);
         if (processDefinition == null) {
             throw exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
         }
         String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
-                .setProcessDefinitionKey(processDefinitionKey).setBusinessKey(String.valueOf(id)));
+                .setProcessDefinitionKey(key).setBusinessKey(String.valueOf(id)));
         transferApplicationMapper.updateById(HrmTransferApplicationDO.builder()
                 .id(id)
                 .processInstanceId(processInstanceId)
                 .status(HrmAuditStatusEnum.PROCESS.getStatus())
                 .build());
+    }
+
+    /**
+     * 瑙f瀽娴佺▼瀹氫箟 Key锛氫紭鍏堜娇鐢ㄨ皟鐢ㄦ柟浼犲叆鍊硷紝涓虹┖鏃跺彇銆岃皟鍔ㄥ鎵广�嶅垎绫讳笅鏈�鏂扮殑娲昏穬娴佺▼
+     */
+    private String resolveProcessDefinitionKey(String processDefinitionKey) {
+        if (StrUtil.isNotBlank(processDefinitionKey)) {
+            return processDefinitionKey.trim();
+        }
+        List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
+                .getProcessDefinitionInfoListByCategory(APPROVE_CATEGORY_CODE);
+        if (CollUtil.isEmpty(definitionInfoList)) {
+            throw exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
+        }
+        Set<String> processDefinitionIds = convertSet(definitionInfoList, BpmProcessDefinitionInfoDO::getProcessDefinitionId);
+        List<ProcessDefinition> processDefinitions = bpmProcessDefinitionService.getProcessDefinitionList(processDefinitionIds);
+        return processDefinitions.stream()
+                .filter(pd -> !pd.isSuspended())
+                .max(Comparator.comparingInt(ProcessDefinition::getVersion))
+                .map(ProcessDefinition::getKey)
+                .orElseThrow(() -> exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS));
     }
 
     private void validateApproveCategoryAndProcessDefinition() {
@@ -288,6 +329,26 @@
         if (!hasActiveDefinition) {
             throw exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
         }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void cancelTransferApplication(Long id, Long userId) {
+        HrmTransferApplicationDO application = validateTransferApplicationExists(id);
+        if (ObjUtil.notEqual(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) {
+            throw exception(TRANSFER_APPLICATION_CANCEL_FAIL_NOT_PROCESS);
+        }
+        // 鍙栨秷瀵瑰簲鐨� BPM 娴佺▼瀹炰緥锛堜互鍙戣捣浜鸿韩浠芥挙閿�锛�
+        if (StrUtil.isNotBlank(application.getProcessInstanceId())) {
+            BpmProcessInstanceCancelReqVO cancelReqVO = new BpmProcessInstanceCancelReqVO();
+            cancelReqVO.setId(application.getProcessInstanceId());
+            cancelReqVO.setReason("鍛樺伐鎾ら攢璋冨矖鐢宠");
+            bpmProcessInstanceService.cancelProcessInstanceByStartUser(userId, cancelReqVO);
+        }
+        transferApplicationMapper.updateById(HrmTransferApplicationDO.builder()
+                .id(id)
+                .status(HrmAuditStatusEnum.CANCEL.getStatus())
+                .build());
     }
 
     @Override
@@ -329,6 +390,12 @@
                 .status(status)
                 .approveTime(java.time.LocalDateTime.now())
                 .build());
+        // 瀹℃壒閫氳繃锛氱珛鍗冲悓姝ュ埌浜哄憳淇℃伅锛堝鎴疯姹傘�屽鎵归�氳繃绔嬪嵆鐢熸晥銆嶏級
+        // 璋冨矖鐢宠鍗曠殑 userId 瀛樼殑鏄� hrm_employee.id
+        if (HrmAuditStatusEnum.APPROVE.getStatus().equals(status)) {
+            employeeService.syncEmployeeTransfer(application.getUserId(),
+                    application.getTargetDeptId(), application.getTargetPostId());
+        }
     }
 
     @Override

--
Gitblit v1.9.3