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,7 +194,7 @@ public class FlowableUtils {
194 @SuppressWarnings("unchecked") 194 @SuppressWarnings("unchecked")
195 public static Map<String, List<Long>> getStartUserSelectAssignees(Map<String, Object> processVariables) { 195 public static Map<String, List<Long>> getStartUserSelectAssignees(Map<String, Object> processVariables) {
196 if (processVariables == null) { 196 if (processVariables == null) {
197 - return null; 197 + return new HashMap<>();
198 } 198 }
199 return (Map<String, List<Long>>) processVariables.get( 199 return (Map<String, List<Long>>) processVariables.get(
200 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES); 200 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES);
@@ -214,12 +214,12 @@ public class FlowableUtils { @@ -214,12 +214,12 @@ public class FlowableUtils {
214 * 获得流程实例的审批用户选择的下一个节点的审批人 Map 214 * 获得流程实例的审批用户选择的下一个节点的审批人 Map
215 * 215 *
216 * @param processVariables 流程变量 216 * @param processVariables 流程变量
217 - * @return 审批用户选择的下一个节点的审批人Map Map 217 + * @return 审批用户选择的下一个节点的审批人Map
218 */ 218 */
219 @SuppressWarnings("unchecked") 219 @SuppressWarnings("unchecked")
220 public static Map<String, List<Long>> getApproveUserSelectAssignees(Map<String, Object> processVariables) { 220 public static Map<String, List<Long>> getApproveUserSelectAssignees(Map<String, Object> processVariables) {
221 if (processVariables == null) { 221 if (processVariables == null) {
222 - return null; 222 + return new HashMap<>();
223 } 223 }
224 return (Map<String, List<Long>>) processVariables.get( 224 return (Map<String, List<Long>>) processVariables.get(
225 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES); 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,18 +558,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
558 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(), 558 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
559 BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason())); 559 BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason()));
560 // 2.3 调用 BPM complete 去完成任务 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 handleParentTaskIfSign(task.getParentTaskId()); 569 handleParentTaskIfSign(task.getParentTaskId());
@@ -590,51 +584,50 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -590,51 +584,50 @@ public class BpmTaskServiceImpl implements BpmTaskService {
590 */ 584 */
591 private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel, 585 private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel,
592 Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) { 586 Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
593 - // 下一个节点参数为空,不做处理,表示流程正常流转,无需选择下一个节点的审判人  
594 - // TODO @小北:会出现漏选,其实需要的情况哇?  
595 - if (CollUtil.isEmpty(nextAssignees)) {  
596 - return variables;  
597 - }  
598 // 1. 获取下一个将要执行的节点集合 587 // 1. 获取下一个将要执行的节点集合
599 FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey); 588 FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);
600 List<FlowNode> nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables); 589 List<FlowNode> nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables);
601 -  
602 // 2. 循环下一个将要执行的节点集合 590 // 2. 循环下一个将要执行的节点集合
603 - Map<String, List<Long>> processVariables = new HashMap<>(); 591 + Map<String, List<Long>> processVariables;
604 for (FlowNode nextFlowNode : nextFlowNodes) { 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 Integer candidateStrategy = parseCandidateStrategy(nextFlowNode); 594 Integer candidateStrategy = parseCandidateStrategy(nextFlowNode);
  595 + // 2.1 情况一:如果节点中的审批人策略为 发起人自选
611 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())) { 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 if (CollUtil.isEmpty(assignees)) { 599 if (CollUtil.isEmpty(assignees)) {
623 throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); 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 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, processVariables); 612 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, processVariables);
628 } 613 }
629 // 2.2 情况二:如果节点中的审批人策略为 审批人,在审批时选择下一个节点的审批人,并且该节点的审批人为空 614 // 2.2 情况二:如果节点中的审批人策略为 审批人,在审批时选择下一个节点的审批人,并且该节点的审批人为空
630 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) { 615 if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) {
631 // 如果节点存在,但未配置审批人 616 // 如果节点存在,但未配置审批人
  617 + List<Long> assignees = nextAssignees != null ? nextAssignees.get(nextFlowNode.getId()) : null;
632 if (CollUtil.isEmpty(assignees)) { 618 if (CollUtil.isEmpty(assignees)) {
633 throw exception(PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); 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 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, processVariables); 631 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, processVariables);
639 } 632 }
640 } 633 }