|
|
|
|
@@ -1,22 +1,27 @@
|
|
|
|
|
package com.njcn.bpm.service.task.impl;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.util.ArrayUtil;
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import com.njcn.bpm.constant.BpmConstants;
|
|
|
|
|
import com.njcn.bpm.enums.BpmProcessInstanceStatusEnum;
|
|
|
|
|
import com.njcn.bpm.enums.BpmResponseEnum;
|
|
|
|
|
import com.njcn.bpm.pojo.dto.BpmProcessInstanceCreateReqDTO;
|
|
|
|
|
import com.njcn.bpm.service.IBpmProcessDefinitionService;
|
|
|
|
|
import com.njcn.bpm.service.task.IBpmProcessInstanceService;
|
|
|
|
|
import com.njcn.bpm.strategy.BpmTaskCandidateStartUserSelectStrategy;
|
|
|
|
|
import com.njcn.bpm.utils.CollectionUtils;
|
|
|
|
|
import com.njcn.common.pojo.exception.BusinessException;
|
|
|
|
|
import com.njcn.user.api.UserFeignClient;
|
|
|
|
|
import com.njcn.user.pojo.po.User;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.flowable.bpmn.model.BpmnModel;
|
|
|
|
|
import org.flowable.bpmn.model.UserTask;
|
|
|
|
|
import org.flowable.engine.HistoryService;
|
|
|
|
|
import org.flowable.engine.RuntimeService;
|
|
|
|
|
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
|
|
|
|
|
import org.flowable.engine.history.HistoricProcessInstance;
|
|
|
|
|
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
|
|
|
|
import org.flowable.engine.repository.ProcessDefinition;
|
|
|
|
|
import org.flowable.engine.runtime.ProcessInstance;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
import com.njcn.bpm.utils.FlowableUtils;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import javax.validation.Valid;
|
|
|
|
|
@@ -25,13 +30,13 @@ import java.util.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 流程实例 Service 实现类
|
|
|
|
|
*
|
|
|
|
|
* <p>
|
|
|
|
|
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
|
|
|
|
|
* 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
|
|
|
|
|
*
|
|
|
|
|
* 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
|
|
|
|
|
* <p>
|
|
|
|
|
* HistoricProcessInstance & ProcessInstance 的关系:
|
|
|
|
|
* 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
|
|
|
|
|
*
|
|
|
|
|
* 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
|
|
|
|
|
* <p>
|
|
|
|
|
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
|
|
|
|
|
*
|
|
|
|
|
* @author 芋道源码
|
|
|
|
|
@@ -43,16 +48,18 @@ public class BpmProcessInstanceServiceImpl implements IBpmProcessInstanceService
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private RuntimeService runtimeService;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private HistoryService historyService;
|
|
|
|
|
|
|
|
|
|
// @Resource
|
|
|
|
|
// private BpmProcessDefinitionService processDefinitionService;
|
|
|
|
|
@Resource
|
|
|
|
|
private IBpmProcessDefinitionService processDefinitionService;
|
|
|
|
|
|
|
|
|
|
// @Resource
|
|
|
|
|
// private BpmMessageService messageService;
|
|
|
|
|
//
|
|
|
|
|
// @Resource
|
|
|
|
|
// private AdminUserApi adminUserApi;
|
|
|
|
|
@Resource
|
|
|
|
|
private UserFeignClient userFeignClient;
|
|
|
|
|
//
|
|
|
|
|
// @Resource
|
|
|
|
|
// private BpmProcessInstanceEventPublisher processInstanceEventPublisher;
|
|
|
|
|
@@ -64,6 +71,8 @@ public class BpmProcessInstanceServiceImpl implements IBpmProcessInstanceService
|
|
|
|
|
.processInstanceId(id)
|
|
|
|
|
.singleResult();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// @Override
|
|
|
|
|
// public List<ProcessInstance> getProcessInstances(Set<String> ids) {
|
|
|
|
|
@@ -128,70 +137,72 @@ public class BpmProcessInstanceServiceImpl implements IBpmProcessInstanceService
|
|
|
|
|
// return createProcessInstance0(userId, definition, createReqVO.getVariables(), null,
|
|
|
|
|
// createReqVO.getStartUserSelectAssignees());
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Override
|
|
|
|
|
// public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
|
|
|
|
|
// // 获得流程定义
|
|
|
|
|
// ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
|
|
|
|
|
// // 发起流程
|
|
|
|
|
// return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(),
|
|
|
|
|
// createReqDTO.getStartUserSelectAssignees());
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// private String createProcessInstance0(Long userId, ProcessDefinition definition,
|
|
|
|
|
// Map<String, Object> variables, String businessKey,
|
|
|
|
|
// Map<String, List<Long>> startUserSelectAssignees) {
|
|
|
|
|
// // 1.1 校验流程定义
|
|
|
|
|
// if (definition == null) {
|
|
|
|
|
// throw exception(PROCESS_DEFINITION_NOT_EXISTS);
|
|
|
|
|
// }
|
|
|
|
|
// if (definition.isSuspended()) {
|
|
|
|
|
// throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
|
|
|
|
|
// }
|
|
|
|
|
// // 1.2 校验发起人自选审批人
|
|
|
|
|
// validateStartUserSelectAssignees(definition, startUserSelectAssignees);
|
|
|
|
|
//
|
|
|
|
|
// // 2. 创建流程实例
|
|
|
|
|
// if (variables == null) {
|
|
|
|
|
// variables = new HashMap<>();
|
|
|
|
|
// }
|
|
|
|
|
// FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
|
|
|
|
|
// variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
|
|
|
|
|
// BpmProcessInstanceStatusEnum.RUNNING.getStatus());
|
|
|
|
|
// if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
|
|
|
|
|
// variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
|
|
|
|
|
// }
|
|
|
|
|
// ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
|
|
|
|
|
// .processDefinitionId(definition.getId())
|
|
|
|
|
// .businessKey(businessKey)
|
|
|
|
|
// .name(definition.getName().trim())
|
|
|
|
|
// .variables(variables)
|
|
|
|
|
// .start();
|
|
|
|
|
// return instance.getId();
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// private void validateStartUserSelectAssignees(ProcessDefinition definition, Map<String, List<Long>> startUserSelectAssignees) {
|
|
|
|
|
// // 1. 获得发起人自选审批人的 UserTask 列表
|
|
|
|
|
// BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId());
|
|
|
|
|
// List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
|
|
|
|
|
// if (CollUtil.isEmpty(userTaskList)) {
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // 2. 校验发起人自选审批人的 UserTask 是否都配置了
|
|
|
|
|
// userTaskList.forEach(userTask -> {
|
|
|
|
|
// List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(userTask.getId()) : null;
|
|
|
|
|
// if (CollUtil.isEmpty(assignees)) {
|
|
|
|
|
// throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, userTask.getName());
|
|
|
|
|
// }
|
|
|
|
|
// Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assignees);
|
|
|
|
|
// assignees.forEach(assignee -> {
|
|
|
|
|
// if (userMap.get(assignee) == null) {
|
|
|
|
|
// throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS, userTask.getName(), assignee);
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String createProcessInstance(String userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
|
|
|
|
|
// 获得流程定义
|
|
|
|
|
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
|
|
|
|
|
// 发起流程
|
|
|
|
|
return createProcessInstance(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(),
|
|
|
|
|
createReqDTO.getStartUserSelectAssignees());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String createProcessInstance(String userId, ProcessDefinition definition,
|
|
|
|
|
Map<String, Object> variables, String businessKey,
|
|
|
|
|
Map<String, List<String>> startUserSelectAssignees) {
|
|
|
|
|
// 1.1 校验流程定义
|
|
|
|
|
if (definition == null) {
|
|
|
|
|
throw new BusinessException(BpmResponseEnum.PROCESS_DEFINITION_NOT_EXISTS);
|
|
|
|
|
}
|
|
|
|
|
if (definition.isSuspended()) {
|
|
|
|
|
throw new BusinessException(BpmResponseEnum.PROCESS_DEFINITION_IS_SUSPENDED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1.2 校验发起人自选审批人
|
|
|
|
|
validateStartUserSelectAssignees(definition, startUserSelectAssignees);
|
|
|
|
|
|
|
|
|
|
// 2. 创建流程实例
|
|
|
|
|
if (variables == null) {
|
|
|
|
|
variables = new HashMap<>();
|
|
|
|
|
}
|
|
|
|
|
FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
|
|
|
|
|
variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
|
|
|
|
|
BpmProcessInstanceStatusEnum.RUNNING.getStatus());
|
|
|
|
|
if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
|
|
|
|
|
variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
|
|
|
|
|
}
|
|
|
|
|
ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
|
|
|
|
|
.processDefinitionId(definition.getId())
|
|
|
|
|
.businessKey(businessKey)
|
|
|
|
|
.name(definition.getName().trim())
|
|
|
|
|
.variables(variables)
|
|
|
|
|
.start();
|
|
|
|
|
return instance.getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void validateStartUserSelectAssignees(ProcessDefinition definition, Map<String, List<String>> startUserSelectAssignees) {
|
|
|
|
|
// 1. 获得发起人自选审批人的 UserTask 列表
|
|
|
|
|
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId());
|
|
|
|
|
List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
|
|
|
|
|
if (CollUtil.isEmpty(userTaskList)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 校验发起人自选审批人的 UserTask 是否都配置了
|
|
|
|
|
userTaskList.forEach(userTask -> {
|
|
|
|
|
List<String> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(userTask.getId()) : null;
|
|
|
|
|
if (CollUtil.isEmpty(assignees)) {
|
|
|
|
|
throw new BusinessException("审批任务(" + userTask.getName() + ")的审批人未配置");
|
|
|
|
|
}
|
|
|
|
|
List<User> userList = userFeignClient.getUserByIdList(assignees).getData();
|
|
|
|
|
Map<String, User> userMap = CollectionUtils.convertMap(userList, User::getId);
|
|
|
|
|
assignees.forEach(assignee -> {
|
|
|
|
|
if (userMap.get(assignee) == null) {
|
|
|
|
|
throw new BusinessException("审批任务(" + userTask.getName() + ")的审批人(" + assignee + ")不存在");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
// @Override
|
|
|
|
|
// public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
|
|
|
|
|
|