package cn.iocoder.yudao.module.hrm.service.employee;
|
|
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.hrm.controller.admin.employee.vo.HrmEmployeeSimpleRespVO;
|
import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeWorkHistorySaveReqVO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeEducationDO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeEmergencyContactDO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeWorkHistoryDO;
|
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEducationMapper;
|
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEmergencyContactMapper;
|
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.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
|
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
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 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.Set;
|
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 超级管理员
|
*/
|
@Service
|
@Validated
|
public class HrmEmployeeServiceImpl implements HrmEmployeeService {
|
|
@Resource
|
private HrmEmployeeMapper employeeMapper;
|
@Resource
|
private HrmEmployeeEducationMapper educationMapper;
|
@Resource
|
private HrmEmployeeWorkHistoryMapper workHistoryMapper;
|
@Resource
|
private HrmEmployeeEmergencyContactMapper emergencyContactMapper;
|
@Resource
|
private HrmNoRedisDAO noRedisDAO;
|
@Resource
|
private DeptApi deptApi;
|
@Resource
|
private PostApi postApi;
|
@Resource
|
private AdminUserApi adminUserApi;
|
@Resource
|
private RoleApi roleApi;
|
@Resource
|
@Lazy // 自注入需延迟加载,否则 bean 被代理包装后注入原始版本导致启动失败
|
private HrmEmployeeService self;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createEmployee(HrmEmployeeSaveReqVO createReqVO) {
|
// 1. 校验部门
|
deptApi.validateDeptList(Collections.singleton(createReqVO.getDeptId()));
|
// 2. 校验岗位
|
postApi.validPostList(Collections.singleton(createReqVO.getPostId()));
|
// 3. 校验手机号是否已存在
|
if (employeeMapper.selectByPhone(createReqVO.getPhone()) != null) {
|
throw exception(EMPLOYEE_PHONE_EXISTS);
|
}
|
// 4. 同步创建系统用户
|
AdminUserCreateReqDTO userCreateReqDTO = new AdminUserCreateReqDTO();
|
userCreateReqDTO.setUsername(createReqVO.getPhone());
|
userCreateReqDTO.setNickname(createReqVO.getName());
|
userCreateReqDTO.setDeptId(createReqVO.getDeptId());
|
userCreateReqDTO.setPostIds(Collections.singleton(createReqVO.getPostId()));
|
userCreateReqDTO.setMobile(createReqVO.getPhone());
|
userCreateReqDTO.setPassword(createReqVO.getPhone());
|
userCreateReqDTO.setSex(createReqVO.getGender());
|
userCreateReqDTO.setEmail(createReqVO.getEmail());
|
userCreateReqDTO.setRemark(createReqVO.getRemark());
|
// 设置角色
|
if (CollUtil.isNotEmpty(createReqVO.getRoleIds())) {
|
userCreateReqDTO.setRoleIds(createReqVO.getRoleIds().stream().collect(Collectors.toSet()));
|
}
|
Long userId = adminUserApi.createUser(userCreateReqDTO);
|
// 5. 生成员工编号
|
String employeeNo = generateUniqueEmployeeNo();
|
// 6. 插入员工记录
|
HrmEmployeeDO employee = BeanUtils.toBean(createReqVO, HrmEmployeeDO.class);
|
employee.setEmployeeNo(employeeNo);
|
employee.setUserId(userId); // 关联系统用户ID
|
// roleIds 存储为 JSON
|
if (CollUtil.isNotEmpty(createReqVO.getRoleIds())) {
|
employee.setRoleIds(JSONUtil.toJsonStr(createReqVO.getRoleIds()));
|
}
|
employeeMapper.insert(employee);
|
Long employeeId = employee.getId();
|
// 7. 同步添加教育经历
|
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.getWorkHistories())) {
|
createReqVO.getWorkHistories().forEach(workHistoryVO -> {
|
HrmEmployeeWorkHistoryDO workHistory = BeanUtils.toBean(workHistoryVO, HrmEmployeeWorkHistoryDO.class);
|
workHistory.setEmployeeId(employeeId);
|
workHistoryMapper.insert(workHistory);
|
});
|
}
|
// 9. 同步添加紧急联系人
|
if (CollUtil.isNotEmpty(createReqVO.getEmergencyContacts())) {
|
createReqVO.getEmergencyContacts().forEach(emergencyContactVO -> {
|
HrmEmployeeEmergencyContactDO emergencyContact = BeanUtils.toBean(emergencyContactVO, HrmEmployeeEmergencyContactDO.class);
|
emergencyContact.setEmployeeId(employeeId);
|
emergencyContactMapper.insert(emergencyContact);
|
});
|
}
|
return employeeId;
|
}
|
|
private String generateUniqueEmployeeNo() {
|
String employeeNo = noRedisDAO.generateEmployeeNo();
|
if (employeeMapper.selectByEmployeeNo(employeeNo) != null) {
|
return generateUniqueEmployeeNo();
|
}
|
return employeeNo;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateEmployee(HrmEmployeeSaveReqVO updateReqVO) {
|
// 校验存在
|
HrmEmployeeDO employee = validateEmployeeExists(updateReqVO.getId());
|
// 校验部门
|
deptApi.validateDeptList(Collections.singleton(updateReqVO.getDeptId()));
|
// 校验岗位
|
postApi.validPostList(Collections.singleton(updateReqVO.getPostId()));
|
// 校验手机号是否已存在(如果手机号有变更)
|
if (!Objects.equals(employee.getPhone(), updateReqVO.getPhone())
|
&& 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);
|
}
|
|
private HrmEmployeeDO validateEmployeeExists(Long id) {
|
HrmEmployeeDO employee = employeeMapper.selectById(id);
|
if (employee == null) {
|
throw exception(EMPLOYEE_NOT_EXISTS);
|
}
|
return employee;
|
}
|
|
@Override
|
public HrmEmployeeDO getEmployee(Long id) {
|
return employeeMapper.selectById(id);
|
}
|
|
@Override
|
public HrmEmployeeRespVO getEmployeeDetail(Long id) {
|
HrmEmployeeDO employee = getEmployee(id);
|
if (employee == null) {
|
return null;
|
}
|
HrmEmployeeRespVO respVO = BeanUtils.toBean(employee, HrmEmployeeRespVO.class);
|
// 解析 roleIds JSON
|
if (StrUtil.isNotBlank(employee.getRoleIds())) {
|
respVO.setRoleIds(JSONUtil.toList(employee.getRoleIds(), Long.class));
|
}
|
// 填充部门名称
|
if (employee.getDeptId() != null) {
|
DeptRespDTO dept = deptApi.getDept(employee.getDeptId());
|
if (dept != null) {
|
respVO.setDeptName(dept.getName());
|
}
|
}
|
// 填充岗位名称
|
if (employee.getPostId() != null) {
|
Map<Long, PostRespDTO> postMap = postApi.getPostMap(Collections.singleton(employee.getPostId()));
|
PostRespDTO post = postMap.get(employee.getPostId());
|
if (post != null) {
|
respVO.setPostName(post.getName());
|
}
|
}
|
// 填充角色名称
|
if (CollUtil.isNotEmpty(respVO.getRoleIds())) {
|
List<RoleRespDTO> roles = roleApi.getRoleList(respVO.getRoleIds());
|
if (CollUtil.isNotEmpty(roles)) {
|
respVO.setRoleNames(roles.stream().map(RoleRespDTO::getName).collect(Collectors.joining(",")));
|
}
|
}
|
return respVO;
|
}
|
|
@Override
|
public HrmEmployeeDO validateEmployee(Long id) {
|
HrmEmployeeDO employee = employeeMapper.selectById(id);
|
if (employee == null) {
|
throw exception(EMPLOYEE_NOT_EXISTS);
|
}
|
return employee;
|
}
|
|
@Override
|
public PageResult<HrmEmployeeDO> getEmployeePage(HrmEmployeePageReqVO pageReqVO) {
|
return employeeMapper.selectPage(pageReqVO);
|
}
|
|
@Override
|
public List<HrmEmployeeDO> getEmployeeList(Collection<Long> ids) {
|
return employeeMapper.selectByIds(ids);
|
}
|
|
@Override
|
public List<HrmEmployeeSimpleRespVO> getEmployeeSimpleList(Integer employeeStatus) {
|
List<HrmEmployeeDO> list = employeeMapper.selectListByStatus(employeeStatus);
|
// 填充部门名称
|
Set<Long> deptIds = list.stream()
|
.map(HrmEmployeeDO::getDeptId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds);
|
return list.stream().map(emp -> {
|
HrmEmployeeSimpleRespVO vo = new HrmEmployeeSimpleRespVO();
|
vo.setId(emp.getId());
|
vo.setEmployeeNo(emp.getEmployeeNo());
|
vo.setName(emp.getName());
|
vo.setEmployeeStatus(emp.getEmployeeStatus());
|
if (emp.getDeptId() != null && deptMap.containsKey(emp.getDeptId())) {
|
vo.setDeptName(deptMap.get(emp.getDeptId()).getName());
|
}
|
return vo;
|
}).collect(Collectors.toList());
|
}
|
|
@Override
|
public HrmEmployeeDO getEmployeeByUserId(Long userId) {
|
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;
|
}
|
|
}
|