Commit 13c2d36eeea6455d65c4b1262fccfdf816e0558c

Authored by lizhixian
1 parent 37b2fd47

feat:添加流程审批时校验,是否为下一个流程审批的节点

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
... ... @@ -57,6 +57,7 @@ public interface ErrorCodeConstants {
57 57 ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
58 58 ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
59 59 ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");
  60 + ErrorCode TASK_START_USER_SELECT_NODE_NOT_EXISTS = new ErrorCode(1_009_004_007, "({})不是下一个执行的流程节点!");
60 61  
61 62 // ========== 动态表单模块 1-009-010-000 ==========
62 63 ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
... ... @@ -176,14 +176,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
176 176 // 如果流程变量不为空,则用前端传递的新变量值覆盖历史的流程变量
177 177 Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables();
178 178 if (null != processVariables) {
179   - // 遍历新变量值,仅更新历史变量中存在的键
180   - for (Map.Entry<String, Object> entry : processVariables.entrySet()) {
181   - String key = entry.getKey();
182   - if (historicVariables.containsKey(key)) {
183   - // 如果历史变量中存在该键,则用新值覆盖
184   - historicVariables.put(key, entry.getValue());
185   - }
186   - }
  179 + historicVariables.putAll(processVariables);
187 180 }
188 181 processVariables = historicVariables;
189 182 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -10,15 +10,19 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
10 10 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
11 11 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
12 12 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
  13 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailReqVO;
  14 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO;
13 15 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
14 16 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
15 17 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
16 18 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
  19 +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
17 20 import cn.iocoder.yudao.module.bpm.enums.definition.*;
18 21 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
19 22 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
20 23 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
21 24 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
  25 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
22 26 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
23 27 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
24 28 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
... ... @@ -56,6 +60,7 @@ import org.springframework.transaction.support.TransactionSynchronization;
56 60 import org.springframework.transaction.support.TransactionSynchronizationManager;
57 61  
58 62 import java.util.*;
  63 +import java.util.stream.Collectors;
59 64 import java.util.stream.Stream;
60 65  
61 66 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -519,6 +524,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
519 524 // 其中,variables 是存储动态表单到 local 任务级别。过滤一下,避免 ProcessInstance 系统级的变量被占用
520 525 if (CollUtil.isNotEmpty(reqVO.getVariables())) {
521 526 Map<String, Object> variables = FlowableUtils.filterTaskFormVariable(reqVO.getVariables());
  527 + // 校验传递的参数中是否存在不是下一个执行的节点
  528 + checkNextActivityNodes(userId, reqVO.getVariables(), task.getProcessInstanceId(), reqVO.getNextAssignees());
522 529 // 下个节点审批人如果不存在,则由前端传递
523 530 if (CollUtil.isNotEmpty(reqVO.getNextAssignees())) {
524 531 // 获取实例中的全部节点数据,避免后续节点的审批人被覆盖
... ... @@ -537,6 +544,35 @@ public class BpmTaskServiceImpl implements BpmTaskService {
537 544 }
538 545  
539 546 /**
  547 + * 校验传递的参数中是否存在不是下一个执行的节点
  548 + *
  549 + * @param loginUserId 流程发起人
  550 + * @param processInstanceId 流程实例id
  551 + * @param nextActivityNodes 下一个执行节点信息 {节点id : [审批人id,审批人id]}
  552 + */
  553 + private void checkNextActivityNodes(Long loginUserId, Map<String, Object> variables,String processInstanceId,
  554 + Map<String, List<Long>> nextActivityNodes){
  555 + // 1、查询流程【预测】的全部信息
  556 + BpmApprovalDetailRespVO approvalDetail = processInstanceService.getApprovalDetail(loginUserId,
  557 + new BpmApprovalDetailReqVO().setProcessVariables(variables).setProcessInstanceId(processInstanceId));
  558 + // 2、获取预测节点的信息
  559 + List<BpmApprovalDetailRespVO.ActivityNode> activityNodes = approvalDetail.getActivityNodes();
  560 + if (CollUtil.isNotEmpty(activityNodes)) {
  561 + // 2.1、获取节点中的审批人策略为【发起人自选】且状态为【未执行】的节点
  562 + List<BpmApprovalDetailRespVO.ActivityNode> notStartActivityNodes = activityNodes.stream().filter(node ->
  563 + BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy().equals(node.getCandidateStrategy())
  564 + && BpmTaskStatusEnum.NOT_START.getStatus().equals(node.getStatus())).toList();
  565 + // 3、校验传递的参数中是否存在不是下一节点的信息
  566 + for (Map.Entry<String, List<Long>> nextActivityNode : nextActivityNodes.entrySet()) {
  567 + if (notStartActivityNodes.stream().noneMatch(taskNode -> taskNode.getId().equals(nextActivityNode.getKey()))) {
  568 + log.error("[checkNextActivityNodes][ ({}) 不是下一个执行的流程节点!]", nextActivityNode.getKey());
  569 + throw exception(TASK_START_USER_SELECT_NODE_NOT_EXISTS, nextActivityNode.getKey());
  570 + }
  571 + }
  572 + }
  573 + }
  574 +
  575 + /**
540 576 * 审批通过存在“后加签”的任务。
541 577 * <p>
542 578 * 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理
... ...