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 | 261 +++++++++++++++++++++++++++++++++------------------
1 files changed, 169 insertions(+), 92 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 a857776..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
@@ -28,6 +28,7 @@
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeWorkHistoryMapper;
import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
+import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -36,7 +37,9 @@
import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserSyncReqDTO;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -54,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.*;
/**
@@ -64,6 +66,7 @@
*/
@Service
@Validated
+@Slf4j
public class HrmEmployeeServiceImpl implements HrmEmployeeService {
@Resource
@@ -87,6 +90,13 @@
@Resource
private MesCalTeamApi mesCalTeamApi;
@Resource
+ private ConfigApi configApi;
+
+ /**
+ * 鐢ㄦ埛鍒濆瀵嗙爜鐨勭郴缁熷弬鏁伴厤缃」
+ */
+ private static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
+ @Resource
@Lazy // 鑷敞鍏ラ渶寤惰繜鍔犺浇锛屽惁鍒� bean 琚唬鐞嗗寘瑁呭悗娉ㄥ叆鍘熷鐗堟湰瀵艰嚧鍚姩澶辫触
private HrmEmployeeService self;
@@ -108,7 +118,8 @@
userCreateReqDTO.setDeptId(createReqVO.getDeptId());
userCreateReqDTO.setPostIds(Collections.singleton(createReqVO.getPostId()));
userCreateReqDTO.setMobile(createReqVO.getPhone());
- userCreateReqDTO.setPassword(createReqVO.getPhone());
+ // 鍒濆瀵嗙爜锛氫紭鍏堢敤瀵煎叆/鏂板鏃舵寚瀹氱殑瀵嗙爜锛屽惁鍒欒鍙栫郴缁熷弬鏁帮紱涓よ�呴兘娌℃湁鍒欐姤閿�
+ userCreateReqDTO.setPassword(resolveInitialPassword(createReqVO.getPassword()));
userCreateReqDTO.setSex(createReqVO.getGender());
userCreateReqDTO.setEmail(createReqVO.getEmail());
userCreateReqDTO.setRemark(createReqVO.getRemark());
@@ -187,12 +198,45 @@
employeeMapper.updateById(updateObj);
Long employeeId = updateReqVO.getId();
+ // 鍚屾绯荤粺鐢ㄦ埛瀵嗙爜锛氫粎褰撴樉寮忓~鍐欎簡瀵嗙爜鏃舵墠鏇存柊锛屾湭濉啓淇濇寔鍘熷瘑鐮佷笉鍙�
+ if (StrUtil.isNotBlank(updateReqVO.getPassword()) && employee.getUserId() != null) {
+ adminUserApi.updateUserPassword(employee.getUserId(), updateReqVO.getPassword());
+ }
+
+ // 鍚屾绯荤粺璐﹀彿鍙搴斿瓧娈碉紙濮撳悕 / 鎵嬫満鍙� / 閮ㄩ棬 / 鎬у埆 / 閭锛�
+ if (employee.getUserId() != null) {
+ syncSystemUserForEmployee(employee, updateReqVO);
+ }
+
// 鍚屾鏁欒偛缁忓巻
- 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());
+ }
+
+ /**
+ * 鍛樺伐淇敼鍚庯紝鎶婂彲涓�涓�瀵瑰簲鐨勫瓧娈靛悓姝ュ埌绯荤粺璐﹀彿銆�
+ *
+ * 鍙悓姝ワ細濮撳悕鈫旀樀绉般�佹墜鏈哄彿鈫攎obile銆侀儴闂ㄣ�佹�у埆銆侀偖绠便��
+ * 鐧诲綍鍚� username銆佸矖浣嶃�佽鑹层�佺姸鎬佷笉鍚屾銆�
+ * 鍚屾澶辫触鏃跺洖婊氬憳宸ユ洿鏂帮紝閬垮厤鍛樺伐鍜岀郴缁熻处鍙蜂笉涓�鑷淬��
+ */
+ private void syncSystemUserForEmployee(HrmEmployeeDO employee, HrmEmployeeSaveReqVO reqVO) {
+ try {
+ AdminUserSyncReqDTO dto = new AdminUserSyncReqDTO();
+ dto.setUserId(employee.getUserId());
+ dto.setNickname(reqVO.getName() != null ? reqVO.getName() : employee.getName());
+ dto.setMobile(reqVO.getPhone() != null ? reqVO.getPhone() : employee.getPhone());
+ dto.setDeptId(reqVO.getDeptId() != null ? reqVO.getDeptId() : employee.getDeptId());
+ dto.setSex(reqVO.getGender() != null ? reqVO.getGender() : employee.getGender());
+ dto.setEmail(reqVO.getEmail() != null ? reqVO.getEmail() : employee.getEmail());
+ adminUserApi.updateUserForEmployee(dto);
+ } catch (Exception ex) {
+ log.warn("[updateEmployee] 鍛樺伐璐﹀彿鍚屾澶辫触锛屽憳宸ョ紪鍙�={}", employee.getId());
+ throw exception(EMPLOYEE_USER_SYNC_FAILED);
+ }
}
private void syncEducationList(Long employeeId, List<HrmEmployeeEducationSaveReqVO> newList) {
@@ -235,13 +279,40 @@
@Transactional(rollbackFor = Exception.class)
public void deleteEmployee(Long id) {
// 鏍¢獙瀛樺湪
- validateEmployeeExists(id);
- // 绾ц仈鍒犻櫎瀛愯〃
+ HrmEmployeeDO employee = validateEmployeeExists(id);
+ // 1. 鑱斿姩鍒犻櫎绯荤粺璐﹀彿锛堜笉鍙戝竷浜嬩欢锛岄伩鍏嶅洖鐜級
+ deleteLinkedSystemUser(employee);
+ // 2. 绾ц仈鍒犻櫎瀛愯〃
educationMapper.deleteByEmployeeId(id);
workHistoryMapper.deleteByEmployeeId(id);
emergencyContactMapper.deleteByEmployeeId(id);
- // 鍒犻櫎鍛樺伐
+ // 3. 鍒犻櫎鍛樺伐
employeeMapper.deleteById(id);
+ }
+
+ /**
+ * 鍒犻櫎鍛樺伐鏃惰仈鍔ㄥ垹闄ゅ叾绯荤粺璐﹀彿銆�
+ *
+ * 瀹堝崼锛�
+ * 1. 鏈粦瀹氳处鍙� -> 璺宠繃
+ * 2. 鍐呯疆 admin锛坕d=1锛� -> 璺宠繃
+ * 3. 鍚屼竴璐﹀彿琚鏉″憳宸ユ。妗堝紩鐢� -> 璺宠繃锛堜竴鍛樺伐涓�璐﹀彿绾﹀畾涓嬩笉搴斿嚭鐜帮級
+ */
+ private void deleteLinkedSystemUser(HrmEmployeeDO employee) {
+ Long userId = employee.getUserId();
+ if (userId == null) {
+ return;
+ }
+ if (Long.valueOf(1L).equals(userId)) {
+ log.warn("[deleteEmployee][鍛樺伐({}) 缁戝畾鐨勬槸鍐呯疆绠$悊鍛樿处鍙�({})锛屼笉鑷姩鍒犻櫎璐﹀彿]", employee.getId(), userId);
+ return;
+ }
+ Long count = employeeMapper.selectCount(HrmEmployeeDO::getUserId, userId);
+ if (count != null && count > 1) {
+ log.warn("[deleteEmployee][璐﹀彿({}) 鍏宠仈浜� {} 鏉″憳宸ユ。妗堬紝涓嶈嚜鍔ㄥ垹闄よ处鍙穄", userId, count);
+ return;
+ }
+ adminUserApi.deleteUserSilently(userId);
}
private HrmEmployeeDO validateEmployeeExists(Long id) {
@@ -351,56 +422,101 @@
}
@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 HrmEmployeeDO getEmployeeByName(String name) {
+ return employeeMapper.selectByName(name);
+ }
+
+ @Override
+ public List<HrmEmployeeDO> getEmployeeListByName(String name) {
+ return employeeMapper.selectListByName(name);
+ }
+
+ @Override
+ 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瀽鍛樺伐鍒濆瀵嗙爜锛�
+ * 1. 瀵煎叆/鏂板鏃舵樉寮忔寚瀹氫簡瀵嗙爜锛屼紭鍏堜娇鐢紱
+ * 2. 鏈寚瀹氬垯璇诲彇绯荤粺鍙傛暟 {@code system.user.init-password}锛�
+ * 3. 涓よ�呴兘娌℃湁鏃舵槑纭姤閿欙紝閬垮厤鎮勬倓鐢ㄦ墜鏈哄彿绛夊急鍙d护鍏滃簳銆�
+ */
+ private String resolveInitialPassword(String specifiedPassword) {
+ if (StrUtil.isNotBlank(specifiedPassword)) {
+ return specifiedPassword;
+ }
+ String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY);
+ if (StrUtil.isBlank(initPassword)) {
+ throw exception(EMPLOYEE_INIT_PASSWORD_NOT_CONFIGURED);
+ }
+ return initPassword;
}
private HrmEmployeeSaveReqVO buildImportSaveReqVO(HrmEmployeeImportExcelVO importEmployee,
@@ -418,6 +534,7 @@
reqVO.setName(importEmployee.getName());
reqVO.setGender(importEmployee.getGender() != null ? importEmployee.getGender() : 1); // 榛樿鐢�
reqVO.setPhone(importEmployee.getPhone());
+ reqVO.setPassword(importEmployee.getPassword());
reqVO.setDeptId(deptId);
reqVO.setPostId(postId);
reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds));
@@ -436,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