JAVA简易审批流-09

public interface ProApprovalFlowAppService {
    /**
     * 提交
     *
     * @param submitDto submitDto
     * @return ResultDto
     */
    ResultDto<ProApprovalFlowInstanceDto> submit(SubmitDto submitDto);

    /**
     * 异步提交
     *
     * @param submitDto submitDto
     * @return ResultDto
     */
    ResultDto<String> submitAsync(SubmitDto submitDto);

    /**
     * 撤回
     *
     * @param approvalDto approvalDto
     * @return ResultDto
     */
    ResultDto<String> revoke(ApprovalDto approvalDto);

    /**
     * 同意
     *
     * @param approvalDto approvalDto
     * @return ResultDto
     */
    ResultDto<String> agree(ApprovalDto approvalDto);

    /**
     * 驳回
     *
     * @param approvalDto approvalDto
     * @return ResultDto
     */
    ResultDto<String> reject(ApprovalDto approvalDto);

    /**
     * 转审
     *
     * @param approvalDto approvalDto
     * @return ResultDto
     */
    ResultDto<String> referral(ApprovalDto approvalDto);

    /**
     * 作废
     *
     * @param approvalDto approvalDto
     * @return ResultDto
     */
    ResultDto<String> abort(ApprovalDto approvalDto);

    /**
     * 删除
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<String> delete(String bizType, String bizDataId);

    /**
     * 清空日志
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<String> clearLog(String bizType, String bizDataId);

    /**
     * 修改Owner
     *
     * @param modifyOwnerDto modifyOwnerDto
     * @return ResultDto
     */
    ResultDto<String> modifyOwner(ModifyOwnerDto modifyOwnerDto);

    /**
     * 获取流程实例的基本信息
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<ProApprovalFlowInstanceDto> getInstanceInfo(String bizType, String bizDataId);

    /**
     * 保存日志
     *
     * @param logDto logDto
     * @return ResultDto
     */
    ResultDto<String> saveLog(ApprovalLogDto logDto);

    /**
     * 异步保存日志
     *
     * @param logDto logDto
     * @return ResultDto
     */
    ResultDto<String> saveLogAsync(ApprovalLogDto logDto);

    /**
     * 获取审批日志
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<List<ProApprovalFlowLogDto>> getLog(String bizType, String bizDataId);

    /**
     * 审批系统节点
     *
     * @param approveSysNodeDto approveSysNodeDto
     * @return ResultDto
     */
    ResultDto<String> approveSysNode(ApproveSysNodeDto approveSysNodeDto);

    /**
     * 获取审批人
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<List<NodeApproverDto>> getApprover(String bizType, String bizDataId);

    /**
     * 获取流程节点
     *
     * @param bizType bizType
     * @param bizDataId bizDataId
     * @return ResultDto
     */
    ResultDto<List<FlowNodeDto>> getFlow(String bizType, String bizDataId);

    /**
     * 重新启动
     *
     * @param restartDto restartDto
     * @return ResultDto
     */
    ResultDto<String> restart(RestartDto restartDto);
}
@Service
@Slf4j
public class ProApprovalFlowAppServiceImpl implements ProApprovalFlowAppService {
    private static final String COMMON_LOG_MSG = "bizType : {},bizDataId : {}";

    @Autowired
    private ProApprovalFlowInstanceDomainService instanceService;

    @Autowired
    private ProApprovalFlowNodeDomainService nodeService;

    @Autowired
    private ProApprovalFlowNodeHandlerDomainService nodeHandlerService;

    @Autowired
    private ProApprovalFlowDomainService flowService;

    @Autowired
    private ProApprovalFlowTodoDomainService toDoService;

    @Autowired
    private ProApprovalFlowLogDomainService logService;

    @Autowired
    private ApplicationContext context;

    @Autowired
    private ApprovalEventPublisher eventPublisher;

    @Autowired
    private TodoWeLinkService todoWelinkService;

    @Autowired
    private ApprovalSubmitUtil approvalSubmitUtil;

    @Autowired
    private ApprovalAgreeUtil approvalAgreeUtil;

    @Autowired
    private ApprovalRejectUtil approvalRejectUtil;

    @Override
    public ResultDto<ProApprovalFlowInstanceDto> submit(SubmitDto submitDto) {
        CommonUtil.setContext(submitDto.getW3account(), submitDto.getUserCn());
        log.info("ApprovalFlow submit : {}", JSON.toJSONString(submitDto));
        Long flowId = submitDto.getFlowId();
        String logRemark = "用户提交";
        String opType = ApprovalEnum.SUBMIT.name();

        // 参数校验
        CommonUtil.validate(submitDto);

        // 查询流程实例
        ProApprovalFlowInstanceDto instance =
                instanceService.loadByBizTypeBizDataId(submitDto.getBizType(), submitDto.getBizDataId());

        if (instance.getFlowInstanceId() != null) {
            // 处理待办
            ResultDto resultDto = completeRejectTodo(instance);
            if (resultDto.getCode() != SUCCESS_CODE) {
                return resultDto;
            }

            // 删除该实例下的所有节点处理人
            logRemark = "用户重新提交";
            opType = ApprovalEnum.RESUBMIT.name();
            nodeHandlerService.deleteByInstanceId(instance.getFlowInstanceId());
        }

        // 保存流程实例
        ProApprovalFlowInstanceDto instanceDto = approvalSubmitUtil.saveInstance(submitDto, instance);

        // 保存节点处理人
        approvalSubmitUtil.saveNodeHandler(instanceDto, submitDto);

        // 激活节点
        String flowNodeVersion = instanceDto.getFlowNodeVersion();
        ProApprovalFlowNodeDto nextNode = new ProApprovalFlowNodeDto();
        if (instance.getFlowInstanceId() != null && instance.getResubmitNode() != null) {
            nextNode = nodeService.load(instance.getResubmitNode());
            instanceService.modifyResubmitNode(instance.getFlowInstanceId(), null);
        }
        if (nextNode.getFlowNodeId() == null) {
            nextNode = nodeService.loadByFlowIdAndVersion(flowId, flowNodeVersion, SORT_NUM_2);
        }
        ProApprovalFlowNodeDto curNode;
        if (instance.getFlowInstanceId() == null) {
            curNode = nodeService.loadByFlowIdAndVersion(flowId, flowNodeVersion, SORT_NUM_1);
        } else {
            curNode = nodeService.load(instance.getCurrentNode());
        }
        instanceDto.setCurrentNode(curNode.getFlowNodeId());
        logRemark = StringUtils.hasText(submitDto.getRemark()) ? submitDto.getRemark() : logRemark;
        approvalSubmitUtil.activateNode(instanceDto, nextNode, opType, logRemark);

        return new ResultDto<>(getInstanceInfo(submitDto.getBizType(), submitDto.getBizDataId()).getData());
    }

    private ResultDto completeRejectTodo(ProApprovalFlowInstanceDto instance) {
        // 重新提交的前提是实例状态为驳回、撤回、重新启动
        if (!ApprovalEnum.REJECT.name().equals(instance.getStatus())
                && !ApprovalEnum.REVOKE.name().equals(instance.getStatus())
                && !ApprovalEnum.RESTART.name().equals(instance.getStatus())) {
            return ResultDto.fail(ApprovalErrorEnum.ILLEGAL_INSTANCE_STATUS);
        }

        // 驳回、重新启动完成待办
        UserVO user = CommonUtil.getCurrentUser();
        if (ApprovalEnum.REJECT.name().equals(instance.getStatus())
                || ApprovalEnum.RESTART.name().equals(instance.getStatus())) {
            Optional<ProApprovalFlowTodoDto> todoOpt = toDoService.loadByHandler(instance.getFlowInstanceId(),
                    instance.getCurrentNode(), user.getUserAccount());
            if (ApprovalEnum.REJECT.name().equals(instance.getStatus()) && !todoOpt.isPresent()) {
                return ResultDto.fail(ApprovalErrorEnum.NO_AUTH);
            }
            if (todoOpt.isPresent()) {
                ProApprovalFlowTodoDto todoDto = todoOpt.get();
                todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
                todoDto.setResult(ApprovalEnum.AGREE.name());
                todoDto.setActiveFlag(NO);
                toDoService.modify(todoDto);
            }
        }
        return new ResultDto();
    }

    @Override
    public ResultDto<String> submitAsync(SubmitDto submitDto) {
        ApprovalTask.submit(submitDto);
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> revoke(ApprovalDto approvalDto) {
        CommonUtil.setContext(approvalDto.getW3account(), approvalDto.getUserCn());
        log.info("ApprovalFlow revoke start: {}", JSON.toJSONString(approvalDto));
        TimerUtil timerAll = new TimerUtil();

        // 参数校验
        CommonUtil.validate(approvalDto);
        String bizType = approvalDto.getBizType();
        String bizDataId = approvalDto.getBizDataId();
        UserVO user = CommonUtil.getCurrentUser();

        // 权限校验
        ProApprovalFlowInstanceDto instance = instanceService.loadByBizTypeBizDataId(bizType, bizDataId);
        if (instance.getFlowInstanceId() == null || !instance.getOwner().equals(user.getUserAccount())
                || !instance.getStatus().equals(ApprovalEnum.RUNNING.name())) {
            return ResultDto.fail(ApprovalErrorEnum.NO_AUTH_REVOKE);
        }

        // 完成当前实例的所有待办
        Long flowInstanceId = instance.getFlowInstanceId();
        Long currentNode = instance.getCurrentNode();
        List<ProApprovalFlowTodoDto> todoList = toDoService.loadByInstance(flowInstanceId);
        for (ProApprovalFlowTodoDto todoDto : todoList) {
            if (todoDto.getResult().equals(ApprovalEnum.UNHANDLED.name())) {
                todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
                todoDto.setResult(ApprovalEnum.REVOKE.name());
            }
        }

        // 把当前实例所有待办的激活状态改为未激活,待办结果置为撤回
        toDoService.invalid(todoList);

        // 实例状态置为撤回
        instanceService.modifyStatus(flowInstanceId, ApprovalEnum.REVOKE.name());

        // 激活第一个流程节点
        ProApprovalFlowNodeDto nextNode =
                nodeService.loadByFlowIdAndVersion(instance.getFlowId(), instance.getFlowNodeVersion(), SORT_NUM_1);
        instanceService.updateCurNode(flowInstanceId, nextNode.getFlowNodeId());
        instance.setCurrentNode(nextNode.getFlowNodeId());
        instance.setCurrentNodeCode(nextNode.getFlowNodeCode());
        instance.setCurrentNodeName(nextNode.getFlowNodeName());

        // 触发流程撤回事件
        RevokeEvent revokeEvent = new RevokeEvent(instance);
        eventPublisher.publishEvent(revokeEvent);

        // 保存撤回日志
        logService.save(flowInstanceId, currentNode, ApprovalEnum.REVOKE.name(), "用户主动撤回");
        timerAll.print("==========revoke end");
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> agree(ApprovalDto approvalDto) {
        CommonUtil.setContext(approvalDto.getW3account(), approvalDto.getUserCn());
        log.info("ApprovalFlow agree start: {}", JSON.toJSONString(approvalDto));

        // 参数校验
        CommonUtil.validate(approvalDto);

        // 权限校验
        ResultDto checkAuthResult = approvalAgreeUtil.checkAuth(approvalDto.getBizType(), approvalDto.getBizDataId());
        if (checkAuthResult.getCode() != SUCCESS_CODE) {
            return checkAuthResult;
        }
        ProApprovalFlowInstanceDto instance = (ProApprovalFlowInstanceDto) checkAuthResult.getResult();

        // 完成自己的待办
        ProApprovalFlowTodoDto todoDto = (ProApprovalFlowTodoDto) checkAuthResult.getData();
        todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));

        // 将自己的待办结果置为同意,保存审批意见
        todoDto.setResult(ApprovalEnum.AGREE.name());
        todoDto.setComment(approvalDto.getComment());
        toDoService.modify(todoDto);

        // 激活下一个流程节点,如果已经是最后一个节点,则触发流程已完成事件
        ProApprovalFlowNodeDto curNode = nodeService.load(instance.getCurrentNode());
        boolean isNodeFinishedFlag = approvalAgreeUtil.isFinished(instance, curNode);
        log.info("isNodeFinishedFlag: {}", isNodeFinishedFlag);
        Long flowInstanceId = instance.getFlowInstanceId();
        ResultDto<String> resultDto = new ResultDto<>();
        if (isNodeFinishedFlag) {
            // 节点完成,需完成其他未处理人的待办
            approvalRejectUtil.cancelOtherTodo(flowInstanceId);
            if (YES.equals(curNode.getLastFlag())) {
                approvalSubmitUtil.processLastNode(instance, curNode, todoDto);
                return resultDto;
            }

            // 激活下一个流程节点
            ProApprovalFlowNodeDto nextNode = nodeService.loadByFlowIdAndVersion(instance.getFlowId(), instance.getFlowNodeVersion(),
                    curNode.getSortNum() + 1);
            approvalSubmitUtil.activateNode(instance, nextNode, ApprovalEnum.AGREE.name(), approvalDto.getComment());
            return resultDto;
        }

        // 保存同意日志
        logService.save(flowInstanceId, curNode.getFlowNodeId(), ApprovalEnum.AGREE.name(),
                approvalDto.getComment());
        return resultDto;
    }

    private void finishLastNode(ProApprovalFlowInstanceDto instance, ProApprovalFlowTodoDto todoDto) {
        // 如果是最后节点则更新实例状态为已完成
        instanceService.modifyStatus(instance.getFlowInstanceId(), ApprovalEnum.FINISHED.name());
        ProApprovalFlowDto flowDto = flowService.load(instance.getFlowId());
        instance.setBizStatus(flowDto.getBizFinishedStatus());

        // 给责任人发已完成WeLink通知
        TodoDto todo = ApprovalSubmitUtil.getTodo(instance.getBizData(), flowDto.getTodoDoneRule());
        approvalSubmitUtil.sendWeLinkNotice(todo.getTitle(), todo.getDesc(), instance.getOwner(), todo.getUrl());

        // 最后一个节点将待办失效
        todoDto.setActiveFlag(NO);
        toDoService.modify(todoDto);
    }

    @Override
    public ResultDto<String> reject(ApprovalDto approvalDto) {
        CommonUtil.setContext(approvalDto.getW3account(), approvalDto.getUserCn());
        log.info("ApprovalFlow reject start: {}", JSON.toJSONString(approvalDto));
        TimerUtil timerAll = new TimerUtil();

        // 参数校验
        CommonUtil.validate(approvalDto);
        Assert.hasText(approvalDto.getComment(), "reject comment is required");
        String bizType = approvalDto.getBizType();
        String bizDataId = approvalDto.getBizDataId();

        // 权限校验
        ResultDto checkAuthResult = approvalAgreeUtil.checkAuth(bizType, bizDataId);
        if (checkAuthResult.getCode() != SUCCESS_CODE) {
            return checkAuthResult;
        }
        ProApprovalFlowInstanceDto instance = (ProApprovalFlowInstanceDto) checkAuthResult.getResult();
        ProApprovalFlowNodeDto curNode = nodeService.load(instance.getCurrentNode());

        // 完成自己的待办
        ProApprovalFlowTodoDto todoDto = (ProApprovalFlowTodoDto) checkAuthResult.getData();
        todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));

        // 将自己的待办结果置为驳回,保存审批意见
        todoDto.setResult(ApprovalEnum.REJECT.name());
        todoDto.setComment(approvalDto.getComment());
        toDoService.modify(todoDto);

        // 判断是否驳回
        boolean isRejectFlag = approvalRejectUtil.isReject(instance, curNode);
        log.info("isRejectFlag : {}", isRejectFlag);
        if (isRejectFlag) {
            // 完成当前实例的所有待办,待办结果置为取消
            Long flowInstanceId = instance.getFlowInstanceId();
            approvalRejectUtil.cancelOtherTodo(flowInstanceId);

            // 实例状态置为驳回
            instanceService.modifyStatus(flowInstanceId, ApprovalEnum.REJECT.name());

            // 激活驳回节点
            Long rejectNodeId = approvalRejectUtil.getRejectNode(instance.getBizData(), curNode.getRejectNodeRule());
            ProApprovalFlowNodeDto rejectNode = nodeService.load(rejectNodeId);
            approvalSubmitUtil.activateNode(instance, rejectNode, ApprovalEnum.REJECT.name(), approvalDto.getComment());

            // 保存重新提交节点
            if (approvalRejectUtil.getResubmitToSelf(instance.getBizData(), curNode.getResubmitToSelf())) {
                instanceService.modifyResubmitNode(instance.getFlowInstanceId(), curNode.getFlowNodeId());
            }
        }

        timerAll.print("==========reject end");
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> referral(ApprovalDto approvalDto) {
        CommonUtil.setContext(approvalDto.getW3account(), approvalDto.getUserCn());
        log.info("ApprovalFlow referral start: {}", JSON.toJSONString(approvalDto));
        TimerUtil timerAll = new TimerUtil();

        // 参数校验
        CommonUtil.validate(approvalDto);

        // 权限校验
        ResultDto checkAuthResult = approvalAgreeUtil.checkAuthReferral(approvalDto);
        if (checkAuthResult.getCode() != SUCCESS_CODE) {
            return checkAuthResult;
        }
        ProApprovalFlowInstanceDto instance = (ProApprovalFlowInstanceDto) checkAuthResult.getResult();

        // 完成自己的待办
        ProApprovalFlowTodoDto todoDto = (ProApprovalFlowTodoDto) checkAuthResult.getData();
        todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));

        // 将自己的待办结果置为转审,保存转审意见
        UserVO user = CommonUtil.getCurrentUser();
        todoDto.setResult(ApprovalEnum.REFERRAL.name());
        todoDto.setForwardUser(user.getUserAccount());
        todoDto.setForwardUserName(user.getUserCN());
        todoDto.setComment(todoDto.getHandler() + " forward to " + approvalDto.getForwardUser());
        toDoService.modify(todoDto);

        // 给转后审批人发待办
        ProApprovalFlowNodeHandlerDto handlerDto = new ProApprovalFlowNodeHandlerDto();
        handlerDto.setHandler(approvalDto.getForwardUser());
        handlerDto.setHandlerName(approvalDto.getForwardUserName());
        ProApprovalFlowNodeDto curNode = nodeService.load(instance.getCurrentNode());
        TodoDto todo = ApprovalSubmitUtil.getTodo(instance.getBizData(), curNode.getActiveTodoRule());
        ApprovalDto approval = new ApprovalDto();
        approval.setForwardUser(user.getUserAccount());
        approval.setForwardUserName(user.getUserCN());
        approvalSubmitUtil.approvalSendTodo(instance, handlerDto, todo, approval);
        log.info("approvalSubmitUtil.approvalSendTodo");

        // 更新审批人表
        nodeHandlerService.referral(instance, todoDto.getHandler(), approvalDto.getForwardUser(),
                approvalDto.getForwardUserName());

        // 发布转审事件
        ReferralEvent referralEvent = new ReferralEvent(instance);
        referralEvent.setForwardUser(approvalDto.getForwardUser());
        referralEvent.setForwardUserName(approvalDto.getForwardUserName());
        eventPublisher.publishEvent(referralEvent);

        // 保存转审日志
        logService.save(instance.getFlowInstanceId(), instance.getCurrentNode(), ApprovalEnum.REFERRAL.name(),
                approvalDto.getComment());

        timerAll.print("==========referral end");
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> abort(ApprovalDto approvalDto) {
        CommonUtil.setContext(approvalDto.getW3account(), approvalDto.getUserCn());
        log.info("ApprovalFlow abort start: {}", JSON.toJSONString(approvalDto));
        TimerUtil timerAll = new TimerUtil();

        // 参数校验
        CommonUtil.validate(approvalDto);
        String bizType = approvalDto.getBizType();
        String bizDataId = approvalDto.getBizDataId();

        // 权限校验
        ProApprovalFlowInstanceDto instance = instanceService.loadByBizTypeBizDataId(bizType, bizDataId);
        if (instance.getFlowInstanceId() == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        if (instance.getStatus().equals(ApprovalEnum.ABORT.name())) {
            return ResultDto.fail(ApprovalErrorEnum.ILLEGAL_INSTANCE_STATUS);
        }

        // 完成当前实例的所有待办
        Long flowInstanceId = instance.getFlowInstanceId();
        log.info("flowInstanceId: {}", flowInstanceId);
        List<ProApprovalFlowTodoDto> todoList = toDoService.loadByInstance(flowInstanceId);
        for (ProApprovalFlowTodoDto todoDto : todoList) {
            if (todoDto.getResult().equals(ApprovalEnum.UNHANDLED.name())) {
                todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
                todoDto.setResult(ApprovalEnum.ABORT.name());
            }
        }

        // 把当前实例所有待办的激活状态改为未激活,待办结果置为作废
        toDoService.invalid(todoList);

        // 实例状态置为作废
        instanceService.modifyStatus(flowInstanceId, ApprovalEnum.ABORT.name());

        // 保存作废日志
        logService.save(instance.getFlowInstanceId(), instance.getCurrentNode(), ApprovalEnum.ABORT.name(), "已作废");

        timerAll.print("==========abort end");
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> delete(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        Long flowInstanceId = instanceDto.getFlowInstanceId();
        log.info("flowInstanceId : {}", flowInstanceId);

        // 完成当前实例的所有待办
        List<ProApprovalFlowTodoDto> todoList = toDoService.loadByInstance(flowInstanceId);
        for (ProApprovalFlowTodoDto todoDto : todoList) {
            if (todoDto.getResult().equals(ApprovalEnum.UNHANDLED.name())) {
                todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
            }
        }

        // 删除数据
        instanceService.delete(flowInstanceId);
        nodeHandlerService.deleteByInstanceId(flowInstanceId);
        toDoService.delete(flowInstanceId);
        logService.delete(flowInstanceId);
        log.info("delete end : {}", flowInstanceId);
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> clearLog(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        Long flowInstanceId = instanceDto.getFlowInstanceId();
        log.info("flowInstanceId : {}", flowInstanceId);
        logService.delete(flowInstanceId);
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> modifyOwner(ModifyOwnerDto modifyOwnerDto) {
        CommonUtil.setContext(modifyOwnerDto.getW3account(), modifyOwnerDto.getUserCn());
        log.info("modifyOwnerDto : {}", JSON.toJSONString(modifyOwnerDto));
        ProApprovalFlowInstanceDto instance = getInstance(modifyOwnerDto.getBizType(), modifyOwnerDto.getBizDataId());
        if (instance == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }

        // 修改实例owner
        Long flowInstanceId = instance.getFlowInstanceId();
        modifyOwnerDto.setFlowInstanceId(flowInstanceId);
        instanceService.modifyOwner(modifyOwnerDto);

        // 修改审批人
        ProApprovalFlowNodeDto nodeDto =
                nodeService.loadByFlowIdAndVersion(instance.getFlowId(), instance.getFlowNodeVersion(), SORT_NUM_1);
        nodeHandlerService.deleteNodeHandler(flowInstanceId, nodeDto.getFlowNodeId());
        ProApprovalFlowNodeHandlerEntity handlerEntity = new ProApprovalFlowNodeHandlerEntity();
        handlerEntity.setFlowInstanceId(flowInstanceId);
        handlerEntity.setFlowNodeId(nodeDto.getFlowNodeId());
        handlerEntity.setHandler(modifyOwnerDto.getOwner());
        handlerEntity.setHandlerName(modifyOwnerDto.getOwnerName());
        handlerEntity.setHandlerType(HandlerTypeEnum.APPROVER.name());
        CommonUtil.setUser(handlerEntity);
        nodeHandlerService.save(handlerEntity);

        // 处理驳回待办
        if (ApprovalEnum.REJECT.name().equals(instance.getStatus())) {
            UserVO user = CommonUtil.getCurrentUser();
            Optional<ProApprovalFlowTodoDto> todoOpt = toDoService.loadByHandler(instance.getFlowInstanceId(),
                    instance.getCurrentNode(), user.getUserAccount());
            if (todoOpt.isPresent()) {
                // 完成自己的待办
                ProApprovalFlowTodoDto todoDto = todoOpt.get();
                todoDto.setComment(todoDto.getHandler() + " modifyOwner to " + modifyOwnerDto.getOwner());
                completeSelfTodo(todoDto, user);

                // 给转后owner发待办
                ProApprovalFlowNodeHandlerDto handlerDto = new ProApprovalFlowNodeHandlerDto();
                handlerDto.setHandler(modifyOwnerDto.getOwner());
                handlerDto.setHandlerName(modifyOwnerDto.getOwnerName());
                List<ProApprovalFlowLogDto> logs = logService.loadByFlowInstanceId(instance.getFlowInstanceId());
                ProApprovalFlowLogDto maxLog = logs.stream()
                        .filter(item -> ApprovalEnum.REJECT.name().equals(item.getOpType()))
                        .max(Comparator.comparing(ProApprovalFlowLogDto::getCreateDate))
                        .get();
                ProApprovalFlowNodeDto rejectNode = nodeService.load(maxLog.getFlowNodeId());
                TodoDto todo = ApprovalSubmitUtil.getTodo(instance.getBizData(), rejectNode.getRejectTodoRule());
                ApprovalDto approval = new ApprovalDto();
                approval.setForwardUser(user.getUserAccount());
                approval.setForwardUserName(user.getUserCN());
                approvalSubmitUtil.approvalSendTodo(instance, handlerDto, todo, approval);
            }
        }
        return new ResultDto<>();
    }

    private void completeSelfTodo(ProApprovalFlowTodoDto todoDto, UserVO user) {
        todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
        todoDto.setResult(ApprovalEnum.MODIFY_OWNER.name());
        todoDto.setForwardUser(user.getUserAccount());
        todoDto.setForwardUserName(user.getUserCN());
        toDoService.modify(todoDto);
    }

    @Override
    public ResultDto<String> saveLog(ApprovalLogDto logDto) {
        CommonUtil.setContext(logDto.getW3account(), logDto.getUserCn());
        log.info("ApprovalFlow saveLog : {}", JSON.toJSONString(logDto));
        String bizType = logDto.getBizType();
        String bizDataId = logDto.getBizDataId();
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        Long flowNodeId = instanceDto.getCurrentNode();
        if (StringUtils.hasText(logDto.getFlowNodeCode())) {
            ProApprovalFlowNodeDto nodeDto = nodeService.loadByFlowCodeAndVersion(instanceDto.getFlowId(),
                    logDto.getFlowNodeCode(), instanceDto.getFlowNodeVersion());
            flowNodeId = nodeDto.getFlowNodeId();
        }
        logService.save(instanceDto.getFlowInstanceId(), flowNodeId, logDto.getOpType(), logDto.getRemark());
        return new ResultDto<>();
    }

    @Override
    public ResultDto<String> saveLogAsync(ApprovalLogDto logDto) {
        ApprovalTask.submit(logDto);
        return new ResultDto<>();
    }

    @Override
    public ResultDto<ProApprovalFlowInstanceDto> getInstanceInfo(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        return new ResultDto<>(instanceDto);
    }

    @Override
    public ResultDto<List<ProApprovalFlowLogDto>> getLog(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        return new ResultDto<>(logService.loadByFlowInstanceId(instanceDto.getFlowInstanceId()));
    }

    @Override
    public ResultDto<String> approveSysNode(ApproveSysNodeDto approvalDto) {
        log.info("approvalDto : {}", JSON.toJSONString(approvalDto));
        CommonUtil.setContext();
        Long flowInstanceId = approvalDto.getFlowInstanceId();
        String flowNodeCode = approvalDto.getFlowNodeCode();
        ProApprovalFlowInstanceDto instance = instanceService.load(flowInstanceId);
        if (instance.getFlowInstanceId() == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        ProApprovalFlowNodeDto curNode = nodeService.load(instance.getCurrentNode());
        if (!flowNodeCode.equals(curNode.getFlowNodeCode())) {
            return ResultDto.fail(ApprovalErrorEnum.CURRENT_NODE_ERROR);
        }

        boolean isAgree = AGREE.equals(approvalDto.getResult());
        ResultDto<String> resultDto = new ResultDto<>();
        ProApprovalFlowNodeDto nextNode;
        if (isAgree) {
            if (YES.equals(curNode.getLastFlag())) {
                approvalSubmitUtil.processLastNode(instance, curNode, null);
                return resultDto;
            }
            // 激活下一个流程节点
            nextNode = nodeService.loadByFlowIdAndVersion(instance.getFlowId(), instance.getFlowNodeVersion(),
                    curNode.getSortNum() + 1);
            approvalSubmitUtil.activateNode(instance, nextNode, ApprovalEnum.AGREE.name(), approvalDto.getComment());
            return resultDto;
        }

        // 获取驳回节点
        Long rejectNodeId = approvalRejectUtil.getRejectNode(instance.getBizData(), curNode.getRejectNodeRule());
        nextNode = nodeService.load(rejectNodeId);

        // 实例状态置为驳回
        instanceService.modifyStatus(flowInstanceId, ApprovalEnum.REJECT.name());

        // 激活节点
        approvalSubmitUtil.activateNode(instance, nextNode, ApprovalEnum.REJECT.name(), approvalDto.getComment());

        return new ResultDto<>();
    }

    @Override
    public ResultDto<List<NodeApproverDto>> getApprover(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        List<ProApprovalFlowNodeHandlerDto> list = nodeHandlerService.loadByInstance(instanceDto.getFlowInstanceId());
        List<NodeApproverDto> result = new ArrayList<>();
        list.forEach(item -> {
            NodeApproverDto dto = new NodeApproverDto();
            BeanUtils.copyProperties(item, dto);
            result.add(dto);
        });
        return new ResultDto<>(result);
    }

    @Override
    public ResultDto<List<FlowNodeDto>> getFlow(String bizType, String bizDataId) {
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        List<FlowNodeDto> resultNode = new ArrayList<>();
        List<ProApprovalFlowNodeDto> nodeList = nodeService.getByFlowId(instanceDto);
        for (ProApprovalFlowNodeDto nodeDto : nodeList) {
            FlowNodeDto dto = new FlowNodeDto();
            BeanUtils.copyProperties(nodeDto, dto);
            resultNode.add(dto);
        }
        List<FlowNodeDto> list =
                resultNode.stream().sorted(Comparator.comparing(FlowNodeDto::getSortNum)).collect(Collectors.toList());
        String currentLanguage = RequestContext.getCurrent().getUserLanguage();
        if ("en_US".equals(currentLanguage) && !CollectionUtils.isEmpty(list)) {
            for (FlowNodeDto flowNodeDto : list) {
                flowNodeDto.setFlowNodeNameEn(ApprovalFlowNodeEnum.getNameEn(flowNodeDto.getFlowNodeName()));
            }
        }
        return new ResultDto<>(list);
    }

    @Override
    public ResultDto<String> restart(RestartDto restartDto) {
        CommonUtil.setContext(restartDto.getW3account(), restartDto.getUserCn());
        String bizType = restartDto.getBizType();
        String bizDataId = restartDto.getBizDataId();
        ProApprovalFlowInstanceDto instanceDto = getInstance(bizType, bizDataId);
        if (instanceDto == null) {
            return ResultDto.fail(ApprovalErrorEnum.NOT_FIND_INSTANCE);
        }
        ProApprovalFlowNodeDto nodeDto = nodeService.loadByFlowCodeAndVersion(instanceDto.getFlowId(),
                restartDto.getFlowNodeCode(), instanceDto.getFlowNodeVersion());
        instanceService.modifyStatus(instanceDto.getFlowInstanceId(), ApprovalEnum.RESTART.name());
        logService.save(instanceDto.getFlowInstanceId(), nodeDto.getFlowNodeId(), ApprovalEnum.RESTART.name(),
                restartDto.getRemark());
        UserVO user = CommonUtil.getCurrentUser();
        Optional<ProApprovalFlowTodoDto> todoOpt = toDoService.loadByHandler(instanceDto.getFlowInstanceId(),
                instanceDto.getCurrentNode(), user.getUserAccount());
        todoOpt.ifPresent(todoDto -> {
            todoWelinkService.completeToDoAsync(new TodoCompleteDto(todoDto.getAppTaskId(), todoDto.getHandler()));
            todoDto.setResult(ApprovalEnum.RESTART.name());
            todoDto.setForwardUser(user.getUserAccount());
            todoDto.setForwardUserName(user.getUserCN());
            todoDto.setComment(ApprovalEnum.RESTART.name());
            toDoService.modify(todoDto);
        });
        return new ResultDto<>();
    }

    private ProApprovalFlowInstanceDto getInstance(String bizType, String bizDataId) {
        log.info(COMMON_LOG_MSG, bizType, bizDataId);
        ProApprovalFlowInstanceDto instanceInfo = instanceService.getInstanceInfo(bizType, bizDataId);
        if (ObjectUtils.isEmpty(instanceInfo.getFlowInstanceId())) {
            return null;
        }
        return instanceInfo;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值