|
@@ -1,310 +0,0 @@
|
|
|
-package cn.iocoder.yudao.module.bpm.service.task;
|
|
|
-
|
|
|
-import cn.hutool.core.collection.CollUtil;
|
|
|
-import cn.hutool.core.lang.Assert;
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
|
|
|
-import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
|
|
|
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
|
|
-import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
|
|
|
-import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
|
|
|
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
|
|
|
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
|
|
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
|
|
|
-import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
|
|
|
-import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
|
|
-import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
|
|
|
-import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
|
|
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
-import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
|
|
-import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
|
|
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
|
|
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
|
|
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.activiti.engine.HistoryService;
|
|
|
-import org.activiti.engine.RuntimeService;
|
|
|
-import org.activiti.engine.history.HistoricProcessInstance;
|
|
|
-import org.activiti.engine.repository.ProcessDefinition;
|
|
|
-import org.activiti.engine.runtime.ProcessInstance;
|
|
|
-import org.activiti.engine.task.Task;
|
|
|
-import org.springframework.context.annotation.Lazy;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
-import org.springframework.validation.annotation.Validated;
|
|
|
-
|
|
|
-import javax.annotation.Resource;
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
|
|
-import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
|
|
-
|
|
|
-/**
|
|
|
- * 流程实例 Service 实现类
|
|
|
- *
|
|
|
- * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
|
|
|
- * 1. https://blog.csdn.net/bobozai86/article/details/105210414
|
|
|
- *
|
|
|
- * HistoricProcessInstance & ProcessInstance 的关系:
|
|
|
- * 1.https://my.oschina.net/843294669/blog/719024
|
|
|
- * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
|
|
|
- *
|
|
|
- * @author 芋道源码
|
|
|
- */
|
|
|
-@Service
|
|
|
-@Validated
|
|
|
-@Slf4j
|
|
|
-public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
|
|
|
-
|
|
|
- @Resource
|
|
|
- private RuntimeService runtimeService;
|
|
|
- @Resource
|
|
|
- private HistoryService historyService;
|
|
|
-
|
|
|
- @Resource
|
|
|
- private AdminUserApi adminUserApi;
|
|
|
- @Resource
|
|
|
- private DeptApi deptApi;
|
|
|
- @Resource
|
|
|
- @Lazy // 解决循环依赖
|
|
|
- private BpmTaskService taskService;
|
|
|
- @Resource
|
|
|
- private BpmProcessDefinitionService processDefinitionService;
|
|
|
- @Resource
|
|
|
- private BpmMessageService messageService;
|
|
|
-
|
|
|
- @Resource
|
|
|
- private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
|
|
|
-
|
|
|
- @Resource
|
|
|
- private BpmProcessInstanceExtMapper processInstanceExtMapper;
|
|
|
-
|
|
|
- @Override
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqVO createReqVO) {
|
|
|
- // 获得流程定义
|
|
|
- ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
|
|
|
- // 发起流程
|
|
|
- return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqDTO createReqDTO) {
|
|
|
- // 获得流程定义
|
|
|
- ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
|
|
|
- // 发起流程
|
|
|
- return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
|
|
|
- }
|
|
|
-
|
|
|
- private String createProcessInstance0(Long userId, ProcessDefinition definition,
|
|
|
- Map<String, Object> variables, String businessKey) {
|
|
|
- // 校验流程定义
|
|
|
- if (definition == null) {
|
|
|
- throw exception(PROCESS_DEFINITION_NOT_EXISTS);
|
|
|
- }
|
|
|
- if (definition.isSuspended()) {
|
|
|
- throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
|
|
|
- }
|
|
|
-
|
|
|
- // 创建流程实例
|
|
|
- ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
|
|
|
- // 设置流程名字
|
|
|
- runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
|
|
|
-
|
|
|
- // 补全流程实例的拓展表
|
|
|
- processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
|
|
|
- .setFormVariables(variables));
|
|
|
-
|
|
|
- // 添加初始的评论 TODO 芋艿:在思考下
|
|
|
-// Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
|
|
|
-// if (task != null) {
|
|
|
-// SysUserDO user = userService.getUser(userId);
|
|
|
-// Assert.notNull(user, "用户({})不存在", userId);
|
|
|
-// String type = "normal";
|
|
|
-// taskService.addComment(task.getId(), instance.getProcessInstanceId(), type,
|
|
|
-// String.format("%s 发起流程申请", user.getNickname()));
|
|
|
-// }
|
|
|
- return instance.getId();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public void cancelProcessInstance(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO) {
|
|
|
- // 校验流程实例存在
|
|
|
- ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
|
|
|
- if (instance == null) {
|
|
|
- throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
|
|
|
- }
|
|
|
- // 只能取消自己的
|
|
|
- if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
|
|
|
- throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
|
|
|
- }
|
|
|
-
|
|
|
- // 通过删除流程实例,实现流程实例的取消
|
|
|
- runtimeService.deleteProcessInstance(cancelReqVO.getId(),
|
|
|
- BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void deleteProcessInstance(String id, String reason) {
|
|
|
- runtimeService.deleteProcessInstance(id, reason);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,
|
|
|
- BpmProcessInstanceMyPageReqVO pageReqVO) {
|
|
|
- // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
|
|
|
- PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
|
|
|
- if (CollUtil.isEmpty(pageResult.getList())) {
|
|
|
- return new PageResult<>(pageResult.getTotal());
|
|
|
- }
|
|
|
-
|
|
|
- // 获得流程 Task Map
|
|
|
- List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
|
|
|
- Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
|
|
|
- // 转换返回
|
|
|
- return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
|
|
|
- // 获得流程实例
|
|
|
- HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
|
|
|
- if (processInstance == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
|
|
|
- Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
|
|
|
-
|
|
|
- // 获得流程定义
|
|
|
- ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(
|
|
|
- processInstance.getProcessDefinitionId());
|
|
|
- Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
|
|
|
- BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
|
|
|
- processInstance.getProcessDefinitionId());
|
|
|
- Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
|
|
|
- String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
|
|
|
-
|
|
|
- // 获得 User
|
|
|
- AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
|
|
|
- DeptRespDTO dept = null;
|
|
|
- if (startUser != null) {
|
|
|
- dept = deptApi.getDept(startUser.getDeptId());
|
|
|
- }
|
|
|
-
|
|
|
- // 拼接结果
|
|
|
- return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
|
|
|
- processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<ProcessInstance> getProcessInstances(Set<String> ids) {
|
|
|
- return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ProcessInstance getProcessInstance(String id) {
|
|
|
- return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获得历史的流程实例
|
|
|
- *
|
|
|
- * @param id 流程实例的编号
|
|
|
- * @return 历史的流程实例
|
|
|
- */
|
|
|
- @Override
|
|
|
- public HistoricProcessInstance getHistoricProcessInstance(String id) {
|
|
|
- return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
|
|
|
- return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void createProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance) {
|
|
|
- // 获得流程定义
|
|
|
- ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
|
|
|
- // 插入 BpmProcessInstanceExtDO 对象
|
|
|
- BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
|
|
|
- .setCategory(definition.getCategory())
|
|
|
- .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
|
|
|
- .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
|
|
- processInstanceExtMapper.insert(instanceExtDO);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void updateProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance) {
|
|
|
- BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance);
|
|
|
- processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void updateProcessInstanceExtCancel(org.activiti.api.process.model.ProcessInstance instance, String reason) {
|
|
|
- // 判断是否为 Reject 不通过。如果是,则不进行更新
|
|
|
- if (BpmProcessInstanceDeleteReasonEnum.isRejectReason(reason)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 需要主动查询,因为 instance 只有 id 属性
|
|
|
- // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
|
|
|
- HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
|
|
|
- // 更新拓展表
|
|
|
- BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
|
|
|
- .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
|
|
|
- .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
|
|
|
- .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
|
|
|
- processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
|
|
|
-
|
|
|
- // 发送流程实例的状态事件
|
|
|
- processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
|
|
|
- BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void updateProcessInstanceExtComplete(org.activiti.api.process.model.ProcessInstance instance) {
|
|
|
- // 需要主动查询,因为 instance 只有 id 属性
|
|
|
- // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
|
|
|
- HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
|
|
|
- // 更新拓展表
|
|
|
- BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
|
|
|
- .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
|
|
|
- .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
|
|
|
- .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
|
|
|
- processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
|
|
|
-
|
|
|
- // 发送流程被通过的消息
|
|
|
- messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2(instance));
|
|
|
-
|
|
|
- // 发送流程实例的状态事件
|
|
|
- processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
|
|
|
- BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
|
|
|
- }
|
|
|
-
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public void updateProcessInstanceExtReject(String id, String reason) {
|
|
|
- // 需要主动查询,因为 instance 只有 id 属性
|
|
|
- ProcessInstance processInstance = getProcessInstance(id);
|
|
|
- // 删除流程实例,以实现驳回任务时,取消整个审批流程
|
|
|
- deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
|
|
|
-
|
|
|
- // 更新 status + result
|
|
|
- // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
|
|
|
- // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
|
|
|
- BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
|
|
|
- .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
|
|
|
- .setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
|
|
|
- processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
|
|
|
-
|
|
|
- // 发送流程被不通过的消息
|
|
|
- messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert(processInstance, reason));
|
|
|
-
|
|
|
- // 发送流程实例的状态事件
|
|
|
- processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
|
|
|
- BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
|
|
|
- }
|
|
|
-
|
|
|
-}
|