Commit 26dd8b66702230129ba48a6d87bcda399c06a974

Authored by lizhixian
1 parent b6a9b5dd

fix:获取下一个节点审批人为空时,返回new HashMap<>(),避免下级使用空指针

review: 优化审批时,校验选择的下一个节点的审批人,是否合法
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
... ... @@ -194,7 +194,7 @@ public class FlowableUtils {
194 194 @SuppressWarnings("unchecked")
195 195 public static Map<String, List<Long>> getStartUserSelectAssignees(Map<String, Object> processVariables) {
196 196 if (processVariables == null) {
197   - return null;
  197 + return new HashMap<>();
198 198 }
199 199 return (Map<String, List<Long>>) processVariables.get(
200 200 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES);
... ... @@ -214,12 +214,12 @@ public class FlowableUtils {
214 214 * 获得流程实例的审批用户选择的下一个节点的审批人 Map
215 215 *
216 216 * @param processVariables 流程变量
217   - * @return 审批用户选择的下一个节点的审批人Map Map
  217 + * @return 审批用户选择的下一个节点的审批人Map
218 218 */
219 219 @SuppressWarnings("unchecked")
220 220 public static Map<String, List<Long>> getApproveUserSelectAssignees(Map<String, Object> processVariables) {
221 221 if (processVariables == null) {
222   - return null;
  222 + return new HashMap<>();
223 223 }
224 224 return (Map<String, List<Long>>) processVariables.get(
225 225 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES);
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -558,18 +558,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
558 558 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
559 559 BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason()));
560 560 // 2.3 调用 BPM complete 去完成任务
561   - // 其中,variables 是存储动态表单到 local 任务级别。过滤一下,避免 ProcessInstance 系统级的变量被占用
562   - if (CollUtil.isNotEmpty(reqVO.getVariables())) {
563   - // 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑
564   - Map<String, Object> variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(),
565   - bpmnModel, reqVO.getNextAssignees(), instance);
566   - // 完成任务
567   - runtimeService.setVariables(task.getProcessInstanceId(), variables);
568   - taskService.complete(task.getId(), variables, true);
569   - } else {
570   - // 完成任务
571   - taskService.complete(task.getId());
572   - }
  561 + // 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑
  562 + Map<String, Object> variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(),
  563 + bpmnModel, reqVO.getNextAssignees(), instance);
  564 + // 完成任务
  565 + runtimeService.setVariables(task.getProcessInstanceId(), variables);
  566 + taskService.complete(task.getId(), variables, true);
573 567  
574 568 // 【加签专属】处理加签任务
575 569 handleParentTaskIfSign(task.getParentTaskId());
... ... @@ -590,51 +584,50 @@ public class BpmTaskServiceImpl implements BpmTaskService {
590 584 */
591 585 private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel,
592 586 Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
593   - // 下一个节点参数为空,不做处理,表示流程正常流转,无需选择下一个节点的审判人
594   - // TODO @小北:会出现漏选,其实需要的情况哇?
595   - if (CollUtil.isEmpty(nextAssignees)) {
596   - return variables;
597   - }
598 587 // 1. 获取下一个将要执行的节点集合
599 588 FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);
600 589 List<FlowNode> nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables);
601   -
602 590 // 2. 循环下一个将要执行的节点集合
603   - Map<String, List<Long>> processVariables = new HashMap<>();
  591 + Map<String, List<Long>> processVariables;
604 592 for (FlowNode nextFlowNode : nextFlowNodes) {
605   - if (!nextAssignees.containsKey(nextFlowNode.getId())) {
606   - throw exception(TASK_TARGET_NODE_NOT_EXISTS, nextFlowNode.getName());
607   - }
608   - List<Long> assignees = nextAssignees.get(nextFlowNode.getId());
609   - // 2.1 情况一:如果节点中的审批人策略为 发起人自选
  593 + // 获取任务节点中的审批人策略
610 594 Integer candidateStrategy = parseCandidateStrategy(nextFlowNode);
  595 + // 2.1 情况一:如果节点中的审批人策略为 发起人自选
611 596 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())) {
612   - processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables());
613   - if (processVariables == null) {
614   - processVariables = new HashMap<>();
615   - }
616   - List<Long> startUserSelectAssignee = processVariables.get(nextFlowNode.getId());
617   - // 特殊:如果当前节点已经存在审批人,则不允许覆盖
618   - if (CollUtil.isNotEmpty(startUserSelectAssignee)) {
619   - continue;
620   - }
621 597 // 如果节点存在,但未配置审批人
  598 + List<Long> assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null;
622 599 if (CollUtil.isEmpty(assignees)) {
623 600 throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName());
624 601 }
  602 + processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables());
  603 + if (CollUtil.isNotEmpty(processVariables)) {
  604 + List<Long> startUserSelectAssignee = processVariables.get(nextFlowNode.getId());
  605 + // 特殊:如果当前节点已经存在审批人,则不允许覆盖
  606 + if (CollUtil.isNotEmpty(startUserSelectAssignee)) {
  607 + continue;
  608 + }
  609 + }
625 610 // 校验通过的全部节点和审批人
626   - processVariables.put(nextFlowNode.getId(), assignees);
  611 + processVariables.put(nextFlowNode.getId(), nextAssignees.get(nextFlowNode.getId()));
627 612 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, processVariables);
628 613 }
629 614 // 2.2 情况二:如果节点中的审批人策略为 审批人,在审批时选择下一个节点的审批人,并且该节点的审批人为空
630 615 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) {
631 616 // 如果节点存在,但未配置审批人
  617 + List<Long> assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null;
632 618 if (CollUtil.isEmpty(assignees)) {
633 619 throw exception(PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName());
634 620 }
  621 + processVariables = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables());
  622 + if (CollUtil.isNotEmpty(processVariables)) {
  623 + List<Long> approveUserSelectAssignee = processVariables.get(nextFlowNode.getId());
  624 + // 特殊:如果当前节点已经存在审批人,则不允许覆盖
  625 + if (CollUtil.isNotEmpty(approveUserSelectAssignee)) {
  626 + continue;
  627 + }
  628 + }
635 629 // 校验通过的全部节点和审批人
636   - processVariables.put(nextFlowNode.getId(), assignees);
637   - // TODO @小北:是不是要类似情况一的做法,通过 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES 拿一下?因为如果 task1 是审批人自选,task2 是审批人自选,看着会覆盖?
  630 + processVariables.put(nextFlowNode.getId(), nextAssignees.get(nextFlowNode.getId()));
638 631 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, processVariables);
639 632 }
640 633 }
... ...