gaoluyang
3 天以前 ef3cbc1c6882786e8218b08be3e52ea44587f03b
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmOvertimeApplicationServiceImpl.java
@@ -2,6 +2,8 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
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;
@@ -58,7 +60,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) {
        HrmEmployeeDO employee = requireEmployee(loginUserId);
        HrmEmployeeDO employee = resolveEmployee(reqVO.getEmployeeId(), loginUserId);
        HrmOvertimeApplicationDO application = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class);
        applyApplicantAndCalculatedTime(application, employee);
        application.setNo(noRedisDAO.generateOvertimeApplicationNo());
@@ -68,20 +70,20 @@
    }
    @Override
    public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) {
        HrmOvertimeApplicationDO existing = requireOwnedDraft(reqVO.getId(), loginUserId);
    public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId, boolean canManage) {
        HrmOvertimeApplicationDO existing = requireManageableDraft(reqVO.getId(), loginUserId, canManage);
        HrmOvertimeApplicationDO update = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class);
        applyApplicantAndCalculatedTime(update, requireEmployee(loginUserId));
        applyApplicantAndCalculatedTime(update, resolveEmployee(reqVO.getEmployeeId(), loginUserId));
        update.setId(existing.getId());
        mapper.updateById(update);
    }
    @Override
    public void delete(Long id, Long loginUserId) {
    public void delete(Long id, Long loginUserId, boolean canManage) {
        HrmOvertimeApplicationDO application = require(id);
        boolean deletable = Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())
                || Objects.equals(application.getStatus(), HrmAuditStatusEnum.CANCEL.getStatus());
        if (!Objects.equals(application.getUserId(), loginUserId) || !deletable) {
        if ((!canManage && !Objects.equals(application.getUserId(), loginUserId)) || !deletable) {
            throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT);
        }
        mapper.deleteById(id);
@@ -113,14 +115,15 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(Long id, String processDefinitionKey, Long loginUserId) {
        HrmOvertimeApplicationDO application = requireOwnedDraft(id, loginUserId);
    public void submit(Long id, String processDefinitionKey, Long loginUserId, boolean canManage) {
        HrmOvertimeApplicationDO application = requireManageableDraft(id, loginUserId, canManage);
        validateProcessDefinitions();
        ProcessDefinition definition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey);
        if (definition == null || !BPM_PROCESS_DEFINITION_KEY.equals(definition.getKey())) {
            throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
        }
        String processInstanceId = bpmProcessInstanceApi.createProcessInstance(loginUserId,
        // 代员工提交时,流程发起人仍应为申请表上的申请人
        String processInstanceId = bpmProcessInstanceApi.createProcessInstance(application.getUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(processDefinitionKey)
                        .setBusinessKey(String.valueOf(id)));
        mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).processInstanceId(processInstanceId)
@@ -129,13 +132,13 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id, Long loginUserId) {
    public void cancel(Long id, Long loginUserId, boolean canManage) {
        HrmOvertimeApplicationDO application = require(id);
        if (!Objects.equals(application.getUserId(), loginUserId)
        if ((!canManage && !Objects.equals(application.getUserId(), loginUserId))
                || !Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) {
            throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS);
        }
        bpmProcessInstanceService.cancelProcessInstanceByStartUser(loginUserId,
        bpmProcessInstanceService.cancelProcessInstanceByStartUser(application.getUserId(),
                new BpmProcessInstanceCancelReqVO().setId(application.getProcessInstanceId()).setReason("申请人撤销加班申请"));
    }
@@ -213,9 +216,9 @@
        return value;
    }
    private HrmOvertimeApplicationDO requireOwnedDraft(Long id, Long userId) {
    private HrmOvertimeApplicationDO requireManageableDraft(Long id, Long userId, boolean canManage) {
        HrmOvertimeApplicationDO value = require(id);
        if (!Objects.equals(value.getUserId(), userId)
        if ((!canManage && !Objects.equals(value.getUserId(), userId))
                || !Objects.equals(value.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) {
            throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT);
        }
@@ -225,6 +228,23 @@
    private HrmEmployeeDO requireEmployee(Long userId) {
        HrmEmployeeDO employee = employeeMapper.selectByUserId(userId);
        if (employee == null) throw exception(OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS);
        return employee;
    }
    /**
     * 申请人为空时回退到当前登录账号关联的员工;选择他人时按员工ID加载
     */
    private HrmEmployeeDO resolveEmployee(Long employeeId, Long loginUserId) {
        if (employeeId == null) {
            return requireEmployee(loginUserId);
        }
        HrmEmployeeDO employee = employeeMapper.selectById(employeeId);
        if (employee == null) {
            throw exception(OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NOT_EXISTS);
        }
        if (employee.getUserId() == null) {
            throw exception(OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NO_USER, employee.getName());
        }
        return employee;
    }
@@ -255,9 +275,17 @@
        resp.setEmployeeName(employee.getName()); resp.setEmployeeNo(employee.getEmployeeNo());
        resp.setDeptId(employee.getDeptId());
        DeptRespDTO dept = employee.getDeptId() == null ? null : deptApi.getDept(employee.getDeptId());
        PostRespDTO post = employee.getPostId() == null ? null
                : postApi.getPostMap(Collections.singleton(employee.getPostId())).get(employee.getPostId());
        resp.setDeptName(dept == null ? null : dept.getName());
        resp.setPostName(post == null ? null : post.getName());
        // 岗位多选:解析 postIds JSON,拼接岗位名称
        if (StrUtil.isNotBlank(employee.getPostIds())) {
            List<Long> postIds = JSONUtil.toList(employee.getPostIds(), Long.class);
            if (CollUtil.isNotEmpty(postIds)) {
                Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
                resp.setPostName(postIds.stream()
                        .filter(postMap::containsKey)
                        .map(id -> postMap.get(id).getName())
                        .collect(Collectors.joining(",")));
            }
        }
    }
}