| | |
| | | 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; |
| | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | /** |
| | | * 调岗申请 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private HrmEmployeeService employeeService; |
| | | @Resource |
| | | private BpmProcessInstanceApi bpmProcessInstanceApi; |
| | | @Resource |
| | | private BpmCategoryService bpmCategoryService; |
| | |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | @Resource |
| | | private BpmProcessInstanceService bpmProcessInstanceService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | } |
| | | // 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); |
| | |
| | | } |
| | | 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); |
| | |
| | | .map(HrmTransferApplicationDO::getUserId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| | | // userId 存的是员工ID,按员工表查询姓名 |
| | | 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) |
| | |
| | | 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()); |
| | |
| | | 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()); |
| | | } |
| | | |
| | | /** |
| | | * 解析流程定义 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() { |
| | |
| | | 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 |
| | |
| | | .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 |