|
@@ -0,0 +1,167 @@
|
|
|
+package cn.iocoder.yudao.module.bpm.service.task;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.lang.Assert;
|
|
|
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
|
|
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO;
|
|
|
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
|
|
|
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
|
|
|
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
|
|
|
+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.service.definition.BpmProcessDefinitionService;
|
|
|
+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.flowable.engine.HistoryService;
|
|
|
+import org.flowable.engine.RuntimeService;
|
|
|
+import org.flowable.engine.history.HistoricProcessInstance;
|
|
|
+import org.flowable.engine.repository.ProcessDefinition;
|
|
|
+import org.flowable.engine.runtime.ProcessInstance;
|
|
|
+import org.flowable.task.api.Task;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import javax.validation.Valid;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+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.PROCESS_DEFINITION_IS_SUSPENDED;
|
|
|
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NOT_EXISTS;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 流程实例 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 BpmProcessInstanceExtMapper processInstanceExtMapper;
|
|
|
+ @Resource
|
|
|
+ @Lazy // 解决循环依赖
|
|
|
+ private BpmTaskService taskService;
|
|
|
+ @Resource
|
|
|
+ private BpmProcessDefinitionService processDefinitionService;
|
|
|
+ @Resource
|
|
|
+ private HistoryService historyService;
|
|
|
+ @Resource
|
|
|
+ private AdminUserApi adminUserApi;
|
|
|
+ @Resource
|
|
|
+ private DeptApi deptApi;
|
|
|
+ @Override
|
|
|
+ public List<ProcessInstance> getProcessInstances(Set<String> ids) {
|
|
|
+ return runtimeService.createProcessInstanceQuery().processDefinitionIds(ids).list();
|
|
|
+ }
|
|
|
+
|
|
|
+ @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 String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
|
|
|
+ // 获得流程定义
|
|
|
+ ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
|
|
|
+ // 发起流程
|
|
|
+ return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
|
|
|
+ }
|
|
|
+
|
|
|
+ @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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得历史的流程实例
|
|
|
+ *
|
|
|
+ * @param id 流程实例的编号
|
|
|
+ * @return 历史的流程实例
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public HistoricProcessInstance getHistoricProcessInstance(String id) {
|
|
|
+ return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
|
|
|
+ }
|
|
|
+
|
|
|
+ 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));
|
|
|
+
|
|
|
+
|
|
|
+ return instance.getId();
|
|
|
+ }
|
|
|
+}
|