| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | 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.employee.vo.HrmEmployeeEducationSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeEmergencyContactSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportExcelVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeePageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeSaveReqVO; |
| | |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | |
| | | 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.*; |
| | | |
| | | /** |
| | | * 员工信息 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private RoleApi roleApi; |
| | | @Resource |
| | | @Lazy // 自注入需延迟加载,否则 bean 被代理包装后注入原始版本导致启动失败 |
| | | private HrmEmployeeService self; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | employeeMapper.insert(employee); |
| | | Long employeeId = employee.getId(); |
| | | // 7. 同步添加教育经历 |
| | | if (CollUtil.isNotEmpty(createReqVO.getEducationList())) { |
| | | createReqVO.getEducationList().forEach(educationVO -> { |
| | | if (CollUtil.isNotEmpty(createReqVO.getEducations())) { |
| | | createReqVO.getEducations().forEach(educationVO -> { |
| | | HrmEmployeeEducationDO education = BeanUtils.toBean(educationVO, HrmEmployeeEducationDO.class); |
| | | education.setEmployeeId(employeeId); |
| | | educationMapper.insert(education); |
| | | }); |
| | | } |
| | | // 8. 同步添加工作经历 |
| | | if (CollUtil.isNotEmpty(createReqVO.getWorkHistoryList())) { |
| | | createReqVO.getWorkHistoryList().forEach(workHistoryVO -> { |
| | | if (CollUtil.isNotEmpty(createReqVO.getWorkHistories())) { |
| | | createReqVO.getWorkHistories().forEach(workHistoryVO -> { |
| | | HrmEmployeeWorkHistoryDO workHistory = BeanUtils.toBean(workHistoryVO, HrmEmployeeWorkHistoryDO.class); |
| | | workHistory.setEmployeeId(employeeId); |
| | | workHistoryMapper.insert(workHistory); |
| | | }); |
| | | } |
| | | // 9. 同步添加紧急联系人 |
| | | if (CollUtil.isNotEmpty(createReqVO.getEmergencyContactList())) { |
| | | createReqVO.getEmergencyContactList().forEach(emergencyContactVO -> { |
| | | if (CollUtil.isNotEmpty(createReqVO.getEmergencyContacts())) { |
| | | createReqVO.getEmergencyContacts().forEach(emergencyContactVO -> { |
| | | HrmEmployeeEmergencyContactDO emergencyContact = BeanUtils.toBean(emergencyContactVO, HrmEmployeeEmergencyContactDO.class); |
| | | emergencyContact.setEmployeeId(employeeId); |
| | | emergencyContactMapper.insert(emergencyContact); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateEmployee(HrmEmployeeSaveReqVO updateReqVO) { |
| | | // 校验存在 |
| | | HrmEmployeeDO employee = validateEmployeeExists(updateReqVO.getId()); |
| | |
| | | && employeeMapper.selectByPhone(updateReqVO.getPhone()) != null) { |
| | | throw exception(EMPLOYEE_PHONE_EXISTS); |
| | | } |
| | | // 更新 |
| | | // 更新员工主表 |
| | | HrmEmployeeDO updateObj = BeanUtils.toBean(updateReqVO, HrmEmployeeDO.class); |
| | | // roleIds 存储为 JSON |
| | | if (CollUtil.isNotEmpty(updateReqVO.getRoleIds())) { |
| | | updateObj.setRoleIds(JSONUtil.toJsonStr(updateReqVO.getRoleIds())); |
| | | } |
| | | employeeMapper.updateById(updateObj); |
| | | Long employeeId = updateReqVO.getId(); |
| | | |
| | | // 同步教育经历 |
| | | syncEducationList(employeeId, updateReqVO.getEducations()); |
| | | // 同步工作经历 |
| | | syncWorkHistoryList(employeeId, updateReqVO.getWorkHistories()); |
| | | // 同步紧急联系人 |
| | | syncEmergencyContactList(employeeId, updateReqVO.getEmergencyContacts()); |
| | | } |
| | | |
| | | private void syncEducationList(Long employeeId, List<HrmEmployeeEducationSaveReqVO> newList) { |
| | | educationMapper.deleteByEmployeeId(employeeId); |
| | | if (CollUtil.isNotEmpty(newList)) { |
| | | newList.forEach(vo -> { |
| | | HrmEmployeeEducationDO education = BeanUtils.toBean(vo, HrmEmployeeEducationDO.class); |
| | | education.setId(null); |
| | | education.setEmployeeId(employeeId); |
| | | educationMapper.insert(education); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | private void syncWorkHistoryList(Long employeeId, List<HrmEmployeeWorkHistorySaveReqVO> newList) { |
| | | workHistoryMapper.deleteByEmployeeId(employeeId); |
| | | if (CollUtil.isNotEmpty(newList)) { |
| | | newList.forEach(vo -> { |
| | | HrmEmployeeWorkHistoryDO workHistory = BeanUtils.toBean(vo, HrmEmployeeWorkHistoryDO.class); |
| | | workHistory.setId(null); |
| | | workHistory.setEmployeeId(employeeId); |
| | | workHistoryMapper.insert(workHistory); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | private void syncEmergencyContactList(Long employeeId, List<HrmEmployeeEmergencyContactSaveReqVO> newList) { |
| | | emergencyContactMapper.deleteByEmployeeId(employeeId); |
| | | if (CollUtil.isNotEmpty(newList)) { |
| | | newList.forEach(vo -> { |
| | | HrmEmployeeEmergencyContactDO emergencyContact = BeanUtils.toBean(vo, HrmEmployeeEmergencyContactDO.class); |
| | | emergencyContact.setId(null); |
| | | emergencyContact.setEmployeeId(employeeId); |
| | | emergencyContactMapper.insert(emergencyContact); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteEmployee(Long id) { |
| | | // 校验存在 |
| | | validateEmployeeExists(id); |
| | | // 删除 |
| | | // 级联删除子表 |
| | | educationMapper.deleteByEmployeeId(id); |
| | | workHistoryMapper.deleteByEmployeeId(id); |
| | | emergencyContactMapper.deleteByEmployeeId(id); |
| | | // 删除员工 |
| | | employeeMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | return employeeMapper.selectByUserId(userId); |
| | | } |
| | | |
| | | @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(); |
| | | 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; |
| | | } |
| | | saveReqVO.setId(existEmployee.getId()); |
| | | self.updateEmployee(saveReqVO); |
| | | respVO.getUpdateNames().add(name); |
| | | } |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureNames().put(name, ex.getMessage()); |
| | | } catch (Exception ex) { |
| | | respVO.getFailureNames().put(name, ex.getMessage()); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | private HrmEmployeeSaveReqVO buildImportSaveReqVO(HrmEmployeeImportExcelVO importEmployee, |
| | | Long deptId, Long postId, Set<Long> roleIds) { |
| | | if (StrUtil.isBlank(importEmployee.getName())) { |
| | | throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "员工姓名"); |
| | | } |
| | | if (StrUtil.isBlank(importEmployee.getPhone())) { |
| | | throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "手机号"); |
| | | } |
| | | if (importEmployee.getHireDate() == null) { |
| | | throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "入职日期"); |
| | | } |
| | | HrmEmployeeSaveReqVO reqVO = new HrmEmployeeSaveReqVO(); |
| | | reqVO.setName(importEmployee.getName()); |
| | | reqVO.setGender(importEmployee.getGender() != null ? importEmployee.getGender() : 1); // 默认男 |
| | | reqVO.setPhone(importEmployee.getPhone()); |
| | | reqVO.setDeptId(deptId); |
| | | reqVO.setPostId(postId); |
| | | reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds)); |
| | | reqVO.setHireDate(importEmployee.getHireDate()); |
| | | reqVO.setEmployeeStatus(importEmployee.getEmployeeStatus() != null |
| | | ? importEmployee.getEmployeeStatus() : 1); // 默认在职 |
| | | reqVO.setEmail(importEmployee.getEmail()); |
| | | reqVO.setBirthday(importEmployee.getBirthday()); |
| | | reqVO.setIdCard(importEmployee.getIdCard()); |
| | | reqVO.setNation(importEmployee.getNation()); |
| | | reqVO.setMarriageStatus(importEmployee.getMarriageStatus()); |
| | | reqVO.setAge(importEmployee.getAge()); |
| | | reqVO.setEducation(importEmployee.getEducation()); |
| | | reqVO.setPoliticalStatus(importEmployee.getPoliticalStatus()); |
| | | reqVO.setRemark(importEmployee.getRemark()); |
| | | 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; |
| | | } |
| | | |
| | | } |