From bf5f52656e128f578ed42c7979c31cf4b476ce46 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 31 十月 2026 19:04:40 +0800
Subject: [PATCH] feat: 优化业务导入及工艺流程管理

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java |  158 ++++++++++++++++++++++------------------------------
 1 files changed, 68 insertions(+), 90 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
index 6a0e028..424a3ea 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -57,7 +57,6 @@
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*;
 
 /**
@@ -210,11 +209,11 @@
         }
 
         // 鍚屾鏁欒偛缁忓巻
-        syncEducationList(employeeId, updateReqVO.getEducations());
+        if (updateReqVO.getEducations() != null) syncEducationList(employeeId, updateReqVO.getEducations());
         // 鍚屾宸ヤ綔缁忓巻
-        syncWorkHistoryList(employeeId, updateReqVO.getWorkHistories());
+        if (updateReqVO.getWorkHistories() != null) syncWorkHistoryList(employeeId, updateReqVO.getWorkHistories());
         // 鍚屾绱ф�ヨ仈绯讳汉
-        syncEmergencyContactList(employeeId, updateReqVO.getEmergencyContacts());
+        if (updateReqVO.getEmergencyContacts() != null) syncEmergencyContactList(employeeId, updateReqVO.getEmergencyContacts());
     }
 
     /**
@@ -222,7 +221,7 @@
      *
      * 鍙悓姝ワ細濮撳悕鈫旀樀绉般�佹墜鏈哄彿鈫攎obile銆侀儴闂ㄣ�佹�у埆銆侀偖绠便��
      * 鐧诲綍鍚� username銆佸矖浣嶃�佽鑹层�佺姸鎬佷笉鍚屾銆�
-     * 鍚屾澶辫触鍙褰曟棩蹇楋紝涓嶉樆鏂憳宸ヤ慨鏀逛富娴佺▼銆�
+     * 鍚屾澶辫触鏃跺洖婊氬憳宸ユ洿鏂帮紝閬垮厤鍛樺伐鍜岀郴缁熻处鍙蜂笉涓�鑷淬��
      */
     private void syncSystemUserForEmployee(HrmEmployeeDO employee, HrmEmployeeSaveReqVO reqVO) {
         try {
@@ -235,7 +234,8 @@
             dto.setEmail(reqVO.getEmail() != null ? reqVO.getEmail() : employee.getEmail());
             adminUserApi.updateUserForEmployee(dto);
         } catch (Exception ex) {
-            log.warn("[updateEmployee][鍛樺伐({}) 鍚屾璐﹀彿({}) 澶辫触锛屽凡蹇界暐]", employee.getId(), employee.getUserId(), ex);
+            log.warn("[updateEmployee] 鍛樺伐璐﹀彿鍚屾澶辫触锛屽憳宸ョ紪鍙�={}", employee.getId());
+            throw exception(EMPLOYEE_USER_SYNC_FAILED);
         }
     }
 
@@ -432,57 +432,75 @@
     }
 
     @Override
-    public HrmEmployeeImportRespVO importEmployeeList(List<HrmEmployeeImportExcelVO> importEmployees,
-                                                      HrmEmployeeImportReqVO importReqVO) {
-        // 1. 鏍¢獙闈炵┖
-        importEmployees = filterList(importEmployees, item -> Objects.nonNull(item.getName()));
-        if (CollUtil.isEmpty(importEmployees)) {
-            throw exception(EMPLOYEE_IMPORT_LIST_IS_EMPTY);
-        }
-        // 2. 棰勫姞杞介儴闂�/宀椾綅/瑙掕壊 鍚嶇О -> 瀹炰綋 鏄犲皠
-        Map<String, DeptRespDTO> deptMap = deptApi.getDeptList().stream()
-                .collect(Collectors.toMap(DeptRespDTO::getName, dept -> dept, (v1, v2) -> v1));
-        Map<String, PostRespDTO> postMap = postApi.getPostList().stream()
-                .collect(Collectors.toMap(PostRespDTO::getName, post -> post, (v1, v2) -> v1));
-        Map<String, RoleRespDTO> roleMap = roleApi.getRoleList().stream()
-                .collect(Collectors.toMap(RoleRespDTO::getName, role -> role, (v1, v2) -> v1));
-        // 3. 閫愭潯澶勭悊
-        HrmEmployeeImportRespVO respVO = HrmEmployeeImportRespVO.builder()
-                .createNames(new ArrayList<>())
-                .updateNames(new ArrayList<>())
-                .failureNames(new LinkedHashMap<>())
-                .build();
-        for (HrmEmployeeImportExcelVO importEmployee : importEmployees) {
-            String name = importEmployee.getName();
+    public HrmEmployeeImportRespVO importEmployeeList(List<HrmEmployeeImportExcelVO> rows, HrmEmployeeImportReqVO req) {
+        if (CollUtil.isEmpty(rows)) throw exception(EMPLOYEE_IMPORT_LIST_IS_EMPTY);
+        Map<String, List<DeptRespDTO>> depts = deptApi.getDeptList().stream()
+                .filter(v -> StrUtil.isNotBlank(v.getName())).collect(Collectors.groupingBy(v -> v.getName().trim()));
+        Map<String, List<PostRespDTO>> posts = postApi.getPostList().stream()
+                .filter(v -> StrUtil.isNotBlank(v.getName())).collect(Collectors.groupingBy(v -> v.getName().trim()));
+        Map<String, List<RoleRespDTO>> roles = roleApi.getRoleList().stream()
+                .filter(v -> StrUtil.isNotBlank(v.getName())).collect(Collectors.groupingBy(v -> v.getName().trim()));
+        HrmEmployeeImportRespVO result = HrmEmployeeImportRespVO.builder()
+                .createNames(new ArrayList<>()).updateNames(new ArrayList<>()).failureNames(new LinkedHashMap<>()).build();
+        Set<String> phones = new LinkedHashSet<>();
+        boolean hasData = false;
+        for (int i = 0; i < rows.size(); i++) {
+            HrmEmployeeImportExcelVO row = rows.get(i);
+            if (row == null || cn.hutool.core.bean.BeanUtil.beanToMap(row).values().stream()
+                    .noneMatch(v -> v != null && (!(v instanceof String) || StrUtil.isNotBlank((String) v)))) continue;
+            hasData = true;
+            String label = "绗�" + (i + 2) + "琛�" + (StrUtil.isBlank(row.getName()) ? "" : "锛�" + row.getName().trim() + "锛�");
             try {
-                // 3.1 鍚嶇О杞� ID
-                Long deptId = parseDeptId(importEmployee.getDeptName(), deptMap);
-                Long postId = parsePostId(importEmployee.getPostName(), postMap);
-                Set<Long> roleIds = parseRoleIds(importEmployee.getRoleNames(), roleMap);
-                // 3.2 鏋勫缓淇濆瓨璇锋眰
-                HrmEmployeeSaveReqVO saveReqVO = buildImportSaveReqVO(importEmployee, deptId, postId, roleIds);
-                // 3.3 鍒ゆ柇瀛樺湪鎬э細鎸夋墜鏈哄彿
-                HrmEmployeeDO existEmployee = employeeMapper.selectByPhone(importEmployee.getPhone());
-                if (existEmployee == null) {
-                    self.createEmployee(saveReqVO);
-                    respVO.getCreateNames().add(name);
-                } else {
-                    if (!Boolean.TRUE.equals(importReqVO.getUpdateSupport())) {
-                        respVO.getFailureNames().put(name, EMPLOYEE_PHONE_EXISTS.getMsg());
-                        continue;
+                if (StrUtil.isBlank(row.getName()) || StrUtil.isBlank(row.getPhone()) || row.getHireDate() == null) {
+                    throw exception(EMPLOYEE_IMPORT_INVALID, "鍛樺伐濮撳悕銆佹墜鏈哄彿鍜屽叆鑱屾棩鏈熶笉鑳戒负绌�");
+                }
+                row.setName(row.getName().trim()); row.setPhone(row.getPhone().trim());
+                if (!phones.add(row.getPhone())) throw exception(EMPLOYEE_IMPORT_INVALID, "鏂囦欢鍐呮墜鏈哄彿閲嶅");
+                if (StrUtil.isBlank(row.getDeptName()) || StrUtil.isBlank(row.getPostName())) {
+                    throw exception(EMPLOYEE_IMPORT_INVALID, "閮ㄩ棬鍜屽矖浣嶄笉鑳戒负绌�");
+                }
+                List<DeptRespDTO> deptMatches = depts.get(row.getDeptName().trim());
+                List<PostRespDTO> postMatches = posts.get(row.getPostName().trim());
+                if (deptMatches == null || deptMatches.size() != 1) throw exception(EMPLOYEE_IMPORT_INVALID, "閮ㄩ棬鍚嶇О涓嶅瓨鍦ㄦ垨涓嶅敮涓�");
+                if (postMatches == null || postMatches.size() != 1) throw exception(EMPLOYEE_IMPORT_INVALID, "宀椾綅鍚嶇О涓嶅瓨鍦ㄦ垨涓嶅敮涓�");
+                Set<Long> roleIds = new LinkedHashSet<>();
+                if (StrUtil.isNotBlank(row.getRoleNames())) {
+                    for (String value : row.getRoleNames().split("[,锛宂")) {
+                        String name = value.trim();
+                        if (name.isEmpty()) continue;
+                        List<RoleRespDTO> matches = roles.get(name);
+                        if (matches == null || matches.size() != 1) throw exception(EMPLOYEE_IMPORT_INVALID, "瑙掕壊鍚嶇О涓嶅瓨鍦ㄦ垨涓嶅敮涓�锛�" + name);
+                        roleIds.add(matches.get(0).getId());
                     }
-                    saveReqVO.setId(existEmployee.getId());
-                    self.updateEmployee(saveReqVO);
-                    respVO.getUpdateNames().add(name);
+                }
+                HrmEmployeeSaveReqVO save = buildImportSaveReqVO(row, deptMatches.get(0).getId(), postMatches.get(0).getId(), roleIds);
+                HrmEmployeeDO existing = employeeMapper.selectByPhone(row.getPhone());
+                if (existing == null) {
+                    if (row.getGender() == null) throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鎬у埆");
+                    self.createEmployee(save);
+                    result.getCreateNames().add(label);
+                } else {
+                    if (!Boolean.TRUE.equals(req.getUpdateSupport())) throw exception(EMPLOYEE_PHONE_EXISTS);
+                    if (StrUtil.isNotBlank(row.getPassword())) throw exception(EMPLOYEE_IMPORT_INVALID, "瑕嗙洊宸叉湁鍛樺伐鏃跺垵濮嬪瘑鐮侀』鐣欑┖锛屽瘑鐮佽鍦ㄨ处鍙风鐞嗕腑淇敼");
+                    if (!roleIds.isEmpty()) throw exception(EMPLOYEE_IMPORT_INVALID, "瑕嗙洊鍛樺伐鏃朵笉鏀寔淇敼鐢ㄦ埛瑙掕壊锛岃鐣欑┖骞跺湪璐﹀彿绠$悊涓淮鎶�");
+                    if (!Objects.equals(existing.getPostId(), save.getPostId())) throw exception(EMPLOYEE_IMPORT_INVALID, "瑕嗙洊鍛樺伐鏃舵殏涓嶆敮鎸佸彉鏇村矖浣嶏紝璇峰厛澶勭悊璐﹀彿宀椾綅閰嶇疆");
+                    save.setId(existing.getId());
+                    if (row.getGender() == null) save.setGender(existing.getGender());
+                    if (row.getEmployeeStatus() == null) save.setEmployeeStatus(existing.getEmployeeStatus());
+                    self.updateEmployee(save);
+                    result.getUpdateNames().add(label);
                 }
             } catch (ServiceException ex) {
-                respVO.getFailureNames().put(name, ex.getMessage());
-            } catch (Exception ex) {
-                respVO.getFailureNames().put(name, ex.getMessage());
+                result.getFailureNames().put(label, ex.getMessage());
+            } catch (RuntimeException ex) {
+                log.warn("[importEmployeeList] 鍛樺伐瀵煎叆澶辫触锛岃鍙�={}", i + 2);
+                result.getFailureNames().put(label, "淇濆瓨鎴栬处鍙峰悓姝ュけ璐ワ紝璇锋鏌ヨ琛屾暟鎹強璐﹀彿閰嶇疆");
             }
         }
-        return respVO;
+        if (!hasData) throw exception(EMPLOYEE_IMPORT_LIST_IS_EMPTY);
+        return result;
     }
+
 
     /**
      * 瑙f瀽鍛樺伐鍒濆瀵嗙爜锛�
@@ -535,45 +553,5 @@
         return reqVO;
     }
 
-    private Long parseDeptId(String deptName, Map<String, DeptRespDTO> deptMap) {
-        if (StrUtil.isBlank(deptName)) {
-            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "閮ㄩ棬鍚嶇О");
-        }
-        DeptRespDTO dept = deptMap.get(deptName.trim());
-        if (dept == null) {
-            throw exception(EMPLOYEE_DEPT_NAME_NOT_EXISTS, deptName.trim());
-        }
-        return dept.getId();
-    }
-
-    private Long parsePostId(String postName, Map<String, PostRespDTO> postMap) {
-        if (StrUtil.isBlank(postName)) {
-            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "宀椾綅鍚嶇О");
-        }
-        PostRespDTO post = postMap.get(postName.trim());
-        if (post == null) {
-            throw exception(EMPLOYEE_POST_NAME_NOT_EXISTS, postName.trim());
-        }
-        return post.getId();
-    }
-
-    private Set<Long> parseRoleIds(String roleNames, Map<String, RoleRespDTO> roleMap) {
-        if (StrUtil.isBlank(roleNames)) {
-            return Collections.emptySet();
-        }
-        Set<Long> roleIds = new LinkedHashSet<>();
-        for (String roleName : roleNames.split("[,锛宂")) {
-            String trimmed = roleName.trim();
-            if (StrUtil.isBlank(trimmed)) {
-                continue;
-            }
-            RoleRespDTO role = roleMap.get(trimmed);
-            if (role == null) {
-                throw exception(EMPLOYEE_ROLE_NAME_NOT_EXISTS, trimmed);
-            }
-            roleIds.add(role.getId());
-        }
-        return roleIds;
-    }
 
 }
\ No newline at end of file

--
Gitblit v1.9.3