!1238 fix: 修复流程预测节点错误问题
Merge pull request !1238 from SamllNorth_Lee/fix/bpm
This commit is contained in:
commit
b496ec3fd0
|
@ -1,9 +1,12 @@
|
||||||
package cn.iocoder.yudao.module.bpm.controller.admin.task;
|
package cn.iocoder.yudao.module.bpm.controller.admin.task;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
|
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.convert.task.BpmProcessInstanceConvert;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||||
|
@ -163,6 +166,9 @@ public class BpmProcessInstanceController {
|
||||||
@Parameter(name = "id", description = "流程实例的编号", required = true)
|
@Parameter(name = "id", description = "流程实例的编号", required = true)
|
||||||
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
|
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
|
||||||
public CommonResult<BpmApprovalDetailRespVO> getApprovalDetail(@Valid BpmApprovalDetailReqVO reqVO) {
|
public CommonResult<BpmApprovalDetailRespVO> getApprovalDetail(@Valid BpmApprovalDetailReqVO reqVO) {
|
||||||
|
if (StrUtil.isNotEmpty(reqVO.getProcessVariablesStr())){
|
||||||
|
reqVO.setProcessVariables(JsonUtils.parseObject(reqVO.getProcessVariablesStr(),Map.class));
|
||||||
|
}
|
||||||
return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
|
return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ public class BpmApprovalDetailReqVO {
|
||||||
@Schema(description = "流程变量")
|
@Schema(description = "流程变量")
|
||||||
private Map<String, Object> processVariables; // 使用场景:同 processDefinitionId,用于流程预测
|
private Map<String, Object> processVariables; // 使用场景:同 processDefinitionId,用于流程预测
|
||||||
|
|
||||||
|
@Schema(description = "流程变量")
|
||||||
|
private String processVariablesStr; // 解决 GET 无法传递对象的问题,最终转换成 processVariables 变量
|
||||||
|
|
||||||
@Schema(description = "流程实例的编号", example = "1024")
|
@Schema(description = "流程实例的编号", example = "1024")
|
||||||
private String processInstanceId; // 使用场景:流程已发起时候传流程实例 ID
|
private String processInstanceId; // 使用场景:流程已发起时候传流程实例 ID
|
||||||
|
|
||||||
|
|
|
@ -799,8 +799,8 @@ public class BpmnModelUtils {
|
||||||
// 查找满足条件的 SequenceFlow 路径
|
// 查找满足条件的 SequenceFlow 路径
|
||||||
Gateway gateway = (Gateway) currentElement;
|
Gateway gateway = (Gateway) currentElement;
|
||||||
SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
||||||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
&& (evalConditionExpress(variables, flow.getConditionExpression())));
|
||||||
if (matchSequenceFlow == null) {
|
if (matchSequenceFlow == null) {
|
||||||
matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||||
|
@ -821,8 +821,8 @@ public class BpmnModelUtils {
|
||||||
// 查找满足条件的 SequenceFlow 路径
|
// 查找满足条件的 SequenceFlow 路径
|
||||||
Gateway gateway = (Gateway) currentElement;
|
Gateway gateway = (Gateway) currentElement;
|
||||||
Collection<SequenceFlow> matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
Collection<SequenceFlow> matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
||||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
||||||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
||||||
if (CollUtil.isEmpty(matchSequenceFlows)) {
|
if (CollUtil.isEmpty(matchSequenceFlows)) {
|
||||||
matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
||||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||||
|
@ -857,6 +857,9 @@ public class BpmnModelUtils {
|
||||||
if (express == null) {
|
if (express == null) {
|
||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
if (variables == null) {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Object result = FlowableUtils.getExpressionValue(variables, express);
|
Object result = FlowableUtils.getExpressionValue(variables, express);
|
||||||
return Boolean.TRUE.equals(result);
|
return Boolean.TRUE.equals(result);
|
||||||
|
|
|
@ -811,8 +811,8 @@ public class SimpleModelUtils {
|
||||||
if (nodeType == BpmSimpleModelNodeTypeEnum.CONDITION_BRANCH_NODE) {
|
if (nodeType == BpmSimpleModelNodeTypeEnum.CONDITION_BRANCH_NODE) {
|
||||||
// 查找满足条件的 BpmSimpleModelNodeVO 节点
|
// 查找满足条件的 BpmSimpleModelNodeVO 节点
|
||||||
BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
|
BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
|
||||||
conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
|
conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
|
||||||
&& evalConditionExpress(variables, conditionNode.getConditionSetting()));
|
&& evalConditionExpress(variables, conditionNode.getConditionSetting()));
|
||||||
if (matchConditionNode == null) {
|
if (matchConditionNode == null) {
|
||||||
matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
|
matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
|
||||||
conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
|
conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
|
||||||
|
@ -826,8 +826,8 @@ public class SimpleModelUtils {
|
||||||
if (nodeType == BpmSimpleModelNodeTypeEnum.INCLUSIVE_BRANCH_NODE) {
|
if (nodeType == BpmSimpleModelNodeTypeEnum.INCLUSIVE_BRANCH_NODE) {
|
||||||
// 查找满足条件的 BpmSimpleModelNodeVO 节点
|
// 查找满足条件的 BpmSimpleModelNodeVO 节点
|
||||||
Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
|
Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
|
||||||
conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
|
conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
|
||||||
&& evalConditionExpress(variables, conditionNode.getConditionSetting()));
|
&& evalConditionExpress(variables, conditionNode.getConditionSetting()));
|
||||||
if (CollUtil.isEmpty(matchConditionNodes)) {
|
if (CollUtil.isEmpty(matchConditionNodes)) {
|
||||||
matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
|
matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
|
||||||
conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
|
conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
|
||||||
|
|
|
@ -29,7 +29,7 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept.BpmTaskCandidateStartUserSelectStrategy;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
|
||||||
|
@ -210,7 +210,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
// TODO @jason:有一个极端情况,如果一个用户有 2 个 task A 和 B,A 已经通过,B 需要审核。这个时,通过 A 进来,todo 拿到
|
// TODO @jason:有一个极端情况,如果一个用户有 2 个 task A 和 B,A 已经通过,B 需要审核。这个时,通过 A 进来,todo 拿到
|
||||||
// B,会不会表单权限不一致哈。
|
// B,会不会表单权限不一致哈。
|
||||||
BpmTaskRespVO todoTask = taskService.getFirstTodoTask(loginUserId, reqVO.getProcessInstanceId());
|
BpmTaskRespVO todoTask = taskService.getFirstTodoTask(loginUserId, reqVO.getProcessInstanceId());
|
||||||
|
|
||||||
// 3.2 预测未运行节点的审批信息
|
// 3.2 预测未运行节点的审批信息
|
||||||
List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
|
List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
|
||||||
processDefinitionInfo,
|
processDefinitionInfo,
|
||||||
|
@ -651,7 +650,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
throw exception(PROCESS_INSTANCE_START_USER_CAN_START);
|
throw exception(PROCESS_INSTANCE_START_USER_CAN_START);
|
||||||
}
|
}
|
||||||
// 1.3 校验发起人自选审批人
|
// 1.3 校验发起人自选审批人
|
||||||
validateStartUserSelectAssignees(definition, startUserSelectAssignees);
|
validateStartUserSelectAssignees(userId, definition, startUserSelectAssignees, variables);
|
||||||
|
|
||||||
// 2. 创建流程实例
|
// 2. 创建流程实例
|
||||||
if (variables == null) {
|
if (variables == null) {
|
||||||
|
@ -696,17 +695,20 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
return instance.getId();
|
return instance.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateStartUserSelectAssignees(ProcessDefinition definition,
|
private void validateStartUserSelectAssignees(Long userId, ProcessDefinition definition,
|
||||||
Map<String, List<Long>> startUserSelectAssignees) {
|
Map<String, List<Long>> startUserSelectAssignees, Map<String,Object> variables) {
|
||||||
// 1. 获得发起人自选审批人的 UserTask/ServiceTask 列表
|
// 1.获取预测的节点信息
|
||||||
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId());
|
BpmApprovalDetailRespVO detailRespVO = getApprovalDetail(userId, new BpmApprovalDetailReqVO()
|
||||||
List<Task> tasks = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectTaskList(bpmnModel);
|
.setProcessDefinitionId(definition.getId())
|
||||||
if (CollUtil.isEmpty(tasks)) {
|
.setProcessVariables(variables));
|
||||||
|
List<ActivityNode> activityNodes = detailRespVO.getActivityNodes();
|
||||||
|
if (CollUtil.isEmpty(activityNodes)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 2.移除掉不是发起人自选审批人节点
|
||||||
// 2. 校验发起人自选审批人的审批人和抄送人是否都配置了
|
activityNodes.removeIf(task -> !Objects.equals(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()));
|
||||||
tasks.forEach(task -> {
|
// 3.流程发起时要先获取当前流程的预测走向节点,发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了
|
||||||
|
activityNodes.forEach(task -> {
|
||||||
List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null;
|
List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null;
|
||||||
if (CollUtil.isEmpty(assignees)) {
|
if (CollUtil.isEmpty(assignees)) {
|
||||||
throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, task.getName());
|
throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, task.getName());
|
||||||
|
|
Loading…
Reference in New Issue