Commit b496ec3fd00031335298983875969885ebe1562d

Authored by 芋道源码
Committed by Gitee
2 parents 243ce1ff eaa15b24

!1238 fix: 修复流程预测节点错误问题

Merge pull request !1238 from SamllNorth_Lee/fix/bpm
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
1 1 package cn.iocoder.yudao.module.bpm.controller.admin.task;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  9 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
7 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
8 11 import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
9 12 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
... ... @@ -163,6 +166,9 @@ public class BpmProcessInstanceController {
163 166 @Parameter(name = "id", description = "流程实例的编号", required = true)
164 167 @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
165 168 public CommonResult<BpmApprovalDetailRespVO> getApprovalDetail(@Valid BpmApprovalDetailReqVO reqVO) {
  169 + if (StrUtil.isNotEmpty(reqVO.getProcessVariablesStr())){
  170 + reqVO.setProcessVariables(JsonUtils.parseObject(reqVO.getProcessVariablesStr(),Map.class));
  171 + }
166 172 return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
167 173 }
168 174  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailReqVO.java
... ... @@ -18,6 +18,9 @@ public class BpmApprovalDetailReqVO {
18 18 @Schema(description = "流程变量")
19 19 private Map<String, Object> processVariables; // 使用场景:同 processDefinitionId,用于流程预测
20 20  
  21 + @Schema(description = "流程变量")
  22 + private String processVariablesStr; // 解决 GET 无法传递对象的问题,最终转换成 processVariables 变量
  23 +
21 24 @Schema(description = "流程实例的编号", example = "1024")
22 25 private String processInstanceId; // 使用场景:流程已发起时候传流程实例 ID
23 26  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
... ... @@ -799,8 +799,8 @@ public class BpmnModelUtils {
799 799 // 查找满足条件的 SequenceFlow 路径
800 800 Gateway gateway = (Gateway) currentElement;
801 801 SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
802   - flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
803   - && evalConditionExpress(variables, flow.getConditionExpression()));
  802 + flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
  803 + && (evalConditionExpress(variables, flow.getConditionExpression())));
804 804 if (matchSequenceFlow == null) {
805 805 matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
806 806 flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
... ... @@ -821,8 +821,8 @@ public class BpmnModelUtils {
821 821 // 查找满足条件的 SequenceFlow 路径
822 822 Gateway gateway = (Gateway) currentElement;
823 823 Collection<SequenceFlow> matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
824   - flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
825   - && evalConditionExpress(variables, flow.getConditionExpression()));
  824 + flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
  825 + && evalConditionExpress(variables, flow.getConditionExpression()));
826 826 if (CollUtil.isEmpty(matchSequenceFlows)) {
827 827 matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
828 828 flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
... ... @@ -857,6 +857,9 @@ public class BpmnModelUtils {
857 857 if (express == null) {
858 858 return Boolean.FALSE;
859 859 }
  860 + if (variables == null) {
  861 + return Boolean.FALSE;
  862 + }
860 863 try {
861 864 Object result = FlowableUtils.getExpressionValue(variables, express);
862 865 return Boolean.TRUE.equals(result);
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
... ... @@ -811,8 +811,8 @@ public class SimpleModelUtils {
811 811 if (nodeType == BpmSimpleModelNodeTypeEnum.CONDITION_BRANCH_NODE) {
812 812 // 查找满足条件的 BpmSimpleModelNodeVO 节点
813 813 BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
814   - conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
815   - && evalConditionExpress(variables, conditionNode.getConditionSetting()));
  814 + conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
  815 + && evalConditionExpress(variables, conditionNode.getConditionSetting()));
816 816 if (matchConditionNode == null) {
817 817 matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
818 818 conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
... ... @@ -826,8 +826,8 @@ public class SimpleModelUtils {
826 826 if (nodeType == BpmSimpleModelNodeTypeEnum.INCLUSIVE_BRANCH_NODE) {
827 827 // 查找满足条件的 BpmSimpleModelNodeVO 节点
828 828 Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
829   - conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
830   - && evalConditionExpress(variables, conditionNode.getConditionSetting()));
  829 + conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
  830 + && evalConditionExpress(variables, conditionNode.getConditionSetting()));
831 831 if (CollUtil.isEmpty(matchConditionNodes)) {
832 832 matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
833 833 conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
... ... @@ -29,7 +29,7 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
29 29 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
30 30 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
31 31 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
32   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept.BpmTaskCandidateStartUserSelectStrategy;
  32 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
33 33 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
34 34 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
35 35 import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
... ... @@ -210,7 +210,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
210 210 // TODO @jason:有一个极端情况,如果一个用户有 2 个 task A 和 B,A 已经通过,B 需要审核。这个时,通过 A 进来,todo 拿到
211 211 // B,会不会表单权限不一致哈。
212 212 BpmTaskRespVO todoTask = taskService.getFirstTodoTask(loginUserId, reqVO.getProcessInstanceId());
213   -
214 213 // 3.2 预测未运行节点的审批信息
215 214 List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
216 215 processDefinitionInfo,
... ... @@ -651,7 +650,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
651 650 throw exception(PROCESS_INSTANCE_START_USER_CAN_START);
652 651 }
653 652 // 1.3 校验发起人自选审批人
654   - validateStartUserSelectAssignees(definition, startUserSelectAssignees);
  653 + validateStartUserSelectAssignees(userId, definition, startUserSelectAssignees, variables);
655 654  
656 655 // 2. 创建流程实例
657 656 if (variables == null) {
... ... @@ -696,17 +695,20 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
696 695 return instance.getId();
697 696 }
698 697  
699   - private void validateStartUserSelectAssignees(ProcessDefinition definition,
700   - Map<String, List<Long>> startUserSelectAssignees) {
701   - // 1. 获得发起人自选审批人的 UserTask/ServiceTask 列表
702   - BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId());
703   - List<Task> tasks = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectTaskList(bpmnModel);
704   - if (CollUtil.isEmpty(tasks)) {
  698 + private void validateStartUserSelectAssignees(Long userId, ProcessDefinition definition,
  699 + Map<String, List<Long>> startUserSelectAssignees, Map<String,Object> variables) {
  700 + // 1.获取预测的节点信息
  701 + BpmApprovalDetailRespVO detailRespVO = getApprovalDetail(userId, new BpmApprovalDetailReqVO()
  702 + .setProcessDefinitionId(definition.getId())
  703 + .setProcessVariables(variables));
  704 + List<ActivityNode> activityNodes = detailRespVO.getActivityNodes();
  705 + if (CollUtil.isEmpty(activityNodes)){
705 706 return;
706 707 }
707   -
708   - // 2. 校验发起人自选审批人的审批人和抄送人是否都配置了
709   - tasks.forEach(task -> {
  708 + // 2.移除掉不是发起人自选审批人节点
  709 + activityNodes.removeIf(task -> !Objects.equals(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()));
  710 + // 3.流程发起时要先获取当前流程的预测走向节点,发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了
  711 + activityNodes.forEach(task -> {
710 712 List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null;
711 713 if (CollUtil.isEmpty(assignees)) {
712 714 throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, task.getName());
... ...