Commit 254b55778f839de4639c4831ca0110f89bbbaf36
1 parent
10bbe741
【代码评审】BPM:子流程
Showing
8 changed files
with
81 additions
and
55 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java
| @@ -30,7 +30,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable<Integer> { | @@ -30,7 +30,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable<Integer> { | ||
| 30 | DELAY_TIMER_NODE(14, "延迟器", "receiveTask"), | 30 | DELAY_TIMER_NODE(14, "延迟器", "receiveTask"), |
| 31 | TRIGGER_NODE(15, "触发器", "serviceTask"), | 31 | TRIGGER_NODE(15, "触发器", "serviceTask"), |
| 32 | 32 | ||
| 33 | - CHILD_PROCESS(20, "子流程", "callActivity"), | 33 | + CHILD_PROCESS(20, "子流程", "callActivity"), // TODO @lesan:CHILD_PROCESS、ASYNC_CHILD_PROCESS 可以合并为一个么? |
| 34 | ASYNC_CHILD_PROCESS(21, "异步子流程", "callActivity"), | 34 | ASYNC_CHILD_PROCESS(21, "异步子流程", "callActivity"), |
| 35 | 35 | ||
| 36 | // 50 ~ 条件分支 | 36 | // 50 ~ 条件分支 |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
| @@ -26,7 +26,7 @@ public enum BpmReasonEnum { | @@ -26,7 +26,7 @@ public enum BpmReasonEnum { | ||
| 26 | TIMEOUT_REJECT("审批超时,系统自动不通过"), | 26 | TIMEOUT_REJECT("审批超时,系统自动不通过"), |
| 27 | ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"), | 27 | ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"), |
| 28 | ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"), | 28 | ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"), |
| 29 | - ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), | 29 | + ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), // 目前仅“子流程”使用 |
| 30 | ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND("审批人与提交人为同一人时,找不到部门负责人,自动通过"), | 30 | ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND("审批人与提交人为同一人时,找不到部门负责人,自动通过"), |
| 31 | ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"), | 31 | ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"), |
| 32 | ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"), | 32 | ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"), |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| @@ -124,6 +124,9 @@ public class BpmSimpleModelNodeVO { | @@ -124,6 +124,9 @@ public class BpmSimpleModelNodeVO { | ||
| 124 | */ | 124 | */ |
| 125 | private TriggerSetting triggerSetting; | 125 | private TriggerSetting triggerSetting; |
| 126 | 126 | ||
| 127 | + /** | ||
| 128 | + * 子流程设置 | ||
| 129 | + */ | ||
| 127 | private ChildProcessSetting childProcessSetting; | 130 | private ChildProcessSetting childProcessSetting; |
| 128 | 131 | ||
| 129 | @Schema(description = "任务监听器") | 132 | @Schema(description = "任务监听器") |
| @@ -410,21 +413,24 @@ public class BpmSimpleModelNodeVO { | @@ -410,21 +413,24 @@ public class BpmSimpleModelNodeVO { | ||
| 410 | @Valid | 413 | @Valid |
| 411 | public static class ChildProcessSetting { | 414 | public static class ChildProcessSetting { |
| 412 | 415 | ||
| 413 | - @Schema(description = "被调用流程", example = "xxx") | 416 | + // TODO @lesan:calledElement => calledProcessDefinitionKey ? 这样更容易理解?不过如果一个流程多次发起,key 变了,好像会有问题? |
| 417 | + @Schema(description = "被调用流程", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") | ||
| 414 | @NotEmpty(message = "被调用流程不能为空") | 418 | @NotEmpty(message = "被调用流程不能为空") |
| 415 | private String calledElement; | 419 | private String calledElement; |
| 416 | 420 | ||
| 417 | - @Schema(description = "被调用流程名称", example = "xxx") | 421 | + @Schema(description = "被调用流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") |
| 418 | @NotEmpty(message = "被调用流程名称不能为空") | 422 | @NotEmpty(message = "被调用流程名称不能为空") |
| 419 | private String calledElementName; | 423 | private String calledElementName; |
| 420 | 424 | ||
| 421 | - @Schema(description = "是否异步", example = "false") | 425 | + @Schema(description = "是否异步", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") |
| 422 | @NotNull(message = "是否异步不能为空") | 426 | @NotNull(message = "是否异步不能为空") |
| 423 | private Boolean async; | 427 | private Boolean async; |
| 424 | 428 | ||
| 425 | - @Schema(description = "输入参数(主->子)", example = "[]") | 429 | + // TODO @lesan:inVariables |
| 430 | + @Schema(description = "输入参数(主->子)", requiredMode = Schema.RequiredMode.REQUIRED, example = "[]") | ||
| 426 | private List<IOParameter> inVariable; | 431 | private List<IOParameter> inVariable; |
| 427 | 432 | ||
| 433 | + // TODO @lesan:outVariables | ||
| 428 | @Schema(description = "输出参数(子->主)", example = "[]") | 434 | @Schema(description = "输出参数(子->主)", example = "[]") |
| 429 | private List<IOParameter> outVariable; | 435 | private List<IOParameter> outVariable; |
| 430 | 436 | ||
| @@ -432,7 +438,8 @@ public class BpmSimpleModelNodeVO { | @@ -432,7 +438,8 @@ public class BpmSimpleModelNodeVO { | ||
| 432 | @NotNull(message = "是否自动跳过子流程发起节点不能为空") | 438 | @NotNull(message = "是否自动跳过子流程发起节点不能为空") |
| 433 | private Boolean skipStartUserNode; | 439 | private Boolean skipStartUserNode; |
| 434 | 440 | ||
| 435 | - @Schema(description = "子流程发起人配置", example = "{}") | 441 | + @Schema(description = "子流程发起人配置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") |
| 442 | + // TODO @lesan:这个应该也必须填写? | ||
| 436 | private StartUserSetting startUserSetting; | 443 | private StartUserSetting startUserSetting; |
| 437 | 444 | ||
| 438 | @Schema(description = "子流程发起人配置") | 445 | @Schema(description = "子流程发起人配置") |
| @@ -448,7 +455,9 @@ public class BpmSimpleModelNodeVO { | @@ -448,7 +455,9 @@ public class BpmSimpleModelNodeVO { | ||
| 448 | @Schema(description = "表单", example = "xxx") | 455 | @Schema(description = "表单", example = "xxx") |
| 449 | private String formField; | 456 | private String formField; |
| 450 | 457 | ||
| 458 | + // TODO @lesan:emptyHandleType => emptyType,和 type 对上? | ||
| 451 | @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 459 | @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 460 | + @NotNull(message = "当子流程发起人为空时类型不能为空") | ||
| 452 | @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class) | 461 | @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class) |
| 453 | private Integer emptyHandleType; | 462 | private Integer emptyHandleType; |
| 454 | 463 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
| @@ -25,7 +25,10 @@ import org.flowable.engine.impl.util.CommandContextUtil; | @@ -25,7 +25,10 @@ import org.flowable.engine.impl.util.CommandContextUtil; | ||
| 25 | import org.flowable.engine.runtime.ProcessInstance; | 25 | import org.flowable.engine.runtime.ProcessInstance; |
| 26 | import org.flowable.task.api.TaskInfo; | 26 | import org.flowable.task.api.TaskInfo; |
| 27 | 27 | ||
| 28 | -import java.util.*; | 28 | +import java.util.HashMap; |
| 29 | +import java.util.List; | ||
| 30 | +import java.util.Map; | ||
| 31 | +import java.util.Objects; | ||
| 29 | import java.util.concurrent.Callable; | 32 | import java.util.concurrent.Callable; |
| 30 | import java.util.stream.Collectors; | 33 | import java.util.stream.Collectors; |
| 31 | 34 | ||
| @@ -241,6 +244,7 @@ public class FlowableUtils { | @@ -241,6 +244,7 @@ public class FlowableUtils { | ||
| 241 | return formFieldsMap.entrySet().stream() | 244 | return formFieldsMap.entrySet().stream() |
| 242 | .limit(3) | 245 | .limit(3) |
| 243 | .map(entry -> new KeyValue<>(entry.getValue().getTitle(), | 246 | .map(entry -> new KeyValue<>(entry.getValue().getTitle(), |
| 247 | + // TODO @lesan: MapUtil.getStr 可以更简单? | ||
| 244 | StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), "")))) | 248 | StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), "")))) |
| 245 | .collect(Collectors.toList()); | 249 | .collect(Collectors.toList()); |
| 246 | } | 250 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -11,8 +11,11 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B | @@ -11,8 +11,11 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B | ||
| 11 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 11 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 12 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | 12 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
| 13 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; | 13 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; |
| 14 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; | ||
| 14 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; | 15 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; |
| 15 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmTriggerTaskDelegate; | 16 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmTriggerTaskDelegate; |
| 17 | +import cn.iocoder.yudao.module.bpm.service.task.listener.BpmCallActivityListener; | ||
| 18 | +import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener; | ||
| 16 | import org.flowable.bpmn.BpmnAutoLayout; | 19 | import org.flowable.bpmn.BpmnAutoLayout; |
| 17 | import org.flowable.bpmn.constants.BpmnXMLConstants; | 20 | import org.flowable.bpmn.constants.BpmnXMLConstants; |
| 18 | import org.flowable.bpmn.model.Process; | 21 | import org.flowable.bpmn.model.Process; |
| @@ -24,10 +27,7 @@ import org.springframework.util.MultiValueMap; | @@ -24,10 +27,7 @@ import org.springframework.util.MultiValueMap; | ||
| 24 | import java.util.*; | 27 | import java.util.*; |
| 25 | 28 | ||
| 26 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; | 29 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; |
| 27 | -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE; | ||
| 28 | -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS; | ||
| 29 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; | 30 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; |
| 30 | -import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; | ||
| 31 | import static java.util.Arrays.asList; | 31 | import static java.util.Arrays.asList; |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| @@ -462,7 +462,7 @@ public class SimpleModelUtils { | @@ -462,7 +462,7 @@ public class SimpleModelUtils { | ||
| 462 | FlowableListener flowableListener = new FlowableListener(); | 462 | FlowableListener flowableListener = new FlowableListener(); |
| 463 | flowableListener.setEvent(TaskListener.EVENTNAME_CREATE); | 463 | flowableListener.setEvent(TaskListener.EVENTNAME_CREATE); |
| 464 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); | 464 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 465 | - flowableListener.setImplementation(DELEGATE_EXPRESSION); | 465 | + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); |
| 466 | addListenerConfig(flowableListener, node.getTaskCreateListener()); | 466 | addListenerConfig(flowableListener, node.getTaskCreateListener()); |
| 467 | flowableListeners.add(flowableListener); | 467 | flowableListeners.add(flowableListener); |
| 468 | } | 468 | } |
| @@ -471,7 +471,7 @@ public class SimpleModelUtils { | @@ -471,7 +471,7 @@ public class SimpleModelUtils { | ||
| 471 | FlowableListener flowableListener = new FlowableListener(); | 471 | FlowableListener flowableListener = new FlowableListener(); |
| 472 | flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT); | 472 | flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT); |
| 473 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); | 473 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 474 | - flowableListener.setImplementation(DELEGATE_EXPRESSION); | 474 | + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); |
| 475 | addListenerConfig(flowableListener, node.getTaskAssignListener()); | 475 | addListenerConfig(flowableListener, node.getTaskAssignListener()); |
| 476 | flowableListeners.add(flowableListener); | 476 | flowableListeners.add(flowableListener); |
| 477 | } | 477 | } |
| @@ -480,7 +480,7 @@ public class SimpleModelUtils { | @@ -480,7 +480,7 @@ public class SimpleModelUtils { | ||
| 480 | FlowableListener flowableListener = new FlowableListener(); | 480 | FlowableListener flowableListener = new FlowableListener(); |
| 481 | flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE); | 481 | flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE); |
| 482 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); | 482 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 483 | - flowableListener.setImplementation(DELEGATE_EXPRESSION); | 483 | + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); |
| 484 | addListenerConfig(flowableListener, node.getTaskCompleteListener()); | 484 | addListenerConfig(flowableListener, node.getTaskCompleteListener()); |
| 485 | flowableListeners.add(flowableListener); | 485 | flowableListeners.add(flowableListener); |
| 486 | } | 486 | } |
| @@ -788,48 +788,56 @@ public class SimpleModelUtils { | @@ -788,48 +788,56 @@ public class SimpleModelUtils { | ||
| 788 | CallActivity callActivity = new CallActivity(); | 788 | CallActivity callActivity = new CallActivity(); |
| 789 | callActivity.setId(node.getId()); | 789 | callActivity.setId(node.getId()); |
| 790 | callActivity.setName(node.getName()); | 790 | callActivity.setName(node.getName()); |
| 791 | - callActivity.setCalledElementType("key"); | 791 | + callActivity.setCalledElementType("key"); // TODO @lesan:这里为啥是 key 哈? |
| 792 | // 1. 是否异步 | 792 | // 1. 是否异步 |
| 793 | callActivity.setAsynchronous(node.getChildProcessSetting().getAsync()); | 793 | callActivity.setAsynchronous(node.getChildProcessSetting().getAsync()); |
| 794 | + | ||
| 794 | // 2. 调用的子流程 | 795 | // 2. 调用的子流程 |
| 795 | callActivity.setCalledElement(childProcessSetting.getCalledElement()); | 796 | callActivity.setCalledElement(childProcessSetting.getCalledElement()); |
| 796 | callActivity.setProcessInstanceName(childProcessSetting.getCalledElementName()); | 797 | callActivity.setProcessInstanceName(childProcessSetting.getCalledElementName()); |
| 798 | + | ||
| 797 | // 3. 是否自动跳过子流程发起节点 | 799 | // 3. 是否自动跳过子流程发起节点 |
| 800 | + // TODO @lesan:貌似只有 SourceExpression 的区别,直接通过 valueOf childProcessSetting.getSkipStartUserNode()??? | ||
| 798 | if (Boolean.TRUE.equals(childProcessSetting.getSkipStartUserNode())) { | 801 | if (Boolean.TRUE.equals(childProcessSetting.getSkipStartUserNode())) { |
| 799 | IOParameter ioParameter = new IOParameter(); | 802 | IOParameter ioParameter = new IOParameter(); |
| 800 | ioParameter.setSourceExpression("true"); | 803 | ioParameter.setSourceExpression("true"); |
| 801 | - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); | 804 | + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); |
| 802 | inVariable.add(ioParameter); | 805 | inVariable.add(ioParameter); |
| 803 | } else { | 806 | } else { |
| 804 | IOParameter ioParameter = new IOParameter(); | 807 | IOParameter ioParameter = new IOParameter(); |
| 805 | ioParameter.setSourceExpression("false"); | 808 | ioParameter.setSourceExpression("false"); |
| 806 | - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); | 809 | + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); |
| 807 | inVariable.add(ioParameter); | 810 | inVariable.add(ioParameter); |
| 808 | } | 811 | } |
| 812 | + | ||
| 809 | // 4. 主→子变量传递 | 813 | // 4. 主→子变量传递 |
| 810 | - // 默认需要传递的一些变量 | ||
| 811 | - // 4.1 流程状态 | 814 | + // 4.1 【默认需要传递的一些变量】流程状态 |
| 815 | + // TODO @lesan:4.1 这个要不,单独一个序号,类似 3. 这个。然后下面,就是把 主→子变量传递、子→主变量传递;这样逻辑连贯点哈 | ||
| 812 | IOParameter ioParameter = new IOParameter(); | 816 | IOParameter ioParameter = new IOParameter(); |
| 813 | - ioParameter.setSource(PROCESS_INSTANCE_VARIABLE_STATUS); | ||
| 814 | - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_STATUS); | 817 | + ioParameter.setSource(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); |
| 818 | + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); | ||
| 815 | inVariable.add(ioParameter); | 819 | inVariable.add(ioParameter); |
| 816 | callActivity.setInParameters(inVariable); | 820 | callActivity.setInParameters(inVariable); |
| 821 | + | ||
| 817 | // 5. 子→主变量传递 | 822 | // 5. 子→主变量传递 |
| 823 | + // TODO @lesan:通过 isNotEmpty 这种哈 | ||
| 818 | if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { | 824 | if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { |
| 819 | callActivity.setOutParameters(childProcessSetting.getOutVariable()); | 825 | callActivity.setOutParameters(childProcessSetting.getOutVariable()); |
| 820 | } | 826 | } |
| 827 | + | ||
| 821 | // 6. 子流程发起人配置 | 828 | // 6. 子流程发起人配置 |
| 822 | List<FlowableListener> executionListeners = new ArrayList<>(); | 829 | List<FlowableListener> executionListeners = new ArrayList<>(); |
| 823 | FlowableListener flowableListener = new FlowableListener(); | 830 | FlowableListener flowableListener = new FlowableListener(); |
| 824 | flowableListener.setEvent(ExecutionListener.EVENTNAME_START); | 831 | flowableListener.setEvent(ExecutionListener.EVENTNAME_START); |
| 825 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); | 832 | flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 826 | - flowableListener.setImplementation("${bpmCallActivityListener}"); | 833 | + flowableListener.setImplementation(BpmCallActivityListener.DELEGATE_EXPRESSION); |
| 827 | FieldExtension fieldExtension = new FieldExtension(); | 834 | FieldExtension fieldExtension = new FieldExtension(); |
| 828 | fieldExtension.setFieldName("listenerConfig"); | 835 | fieldExtension.setFieldName("listenerConfig"); |
| 829 | fieldExtension.setStringValue(JsonUtils.toJsonString(childProcessSetting.getStartUserSetting())); | 836 | fieldExtension.setStringValue(JsonUtils.toJsonString(childProcessSetting.getStartUserSetting())); |
| 830 | flowableListener.getFieldExtensions().add(fieldExtension); | 837 | flowableListener.getFieldExtensions().add(fieldExtension); |
| 831 | executionListeners.add(flowableListener); | 838 | executionListeners.add(flowableListener); |
| 832 | callActivity.setExecutionListeners(executionListeners); | 839 | callActivity.setExecutionListeners(executionListeners); |
| 840 | + | ||
| 833 | // 添加节点类型 | 841 | // 添加节点类型 |
| 834 | addNodeType(node.getType(), callActivity); | 842 | addNodeType(node.getType(), callActivity); |
| 835 | return callActivity; | 843 | return callActivity; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -320,7 +320,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -320,7 +320,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 320 | // 遍历 tasks 列表,只处理已结束的 UserTask | 320 | // 遍历 tasks 列表,只处理已结束的 UserTask |
| 321 | // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities | 321 | // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities |
| 322 | // 的话,它无法成为一个节点 | 322 | // 的话,它无法成为一个节点 |
| 323 | - // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程 | 323 | + // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程;TODO @lesan:这个会有啥影响?微信聊? |
| 324 | List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null); | 324 | List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null); |
| 325 | List<ActivityNode> approvalNodes = convertList(endTasks, task -> { | 325 | List<ActivityNode> approvalNodes = convertList(endTasks, task -> { |
| 326 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); | 326 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); |
| @@ -389,7 +389,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -389,7 +389,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 389 | Map<String, Object> processVariables, | 389 | Map<String, Object> processVariables, |
| 390 | List<HistoricActivityInstance> activities, | 390 | List<HistoricActivityInstance> activities, |
| 391 | List<HistoricTaskInstance> tasks) { | 391 | List<HistoricTaskInstance> tasks) { |
| 392 | - // 构建运行中的任务,基于 activityId 分组 | 392 | + // 构建运行中的任务、子流程,基于 activityId 分组 |
| 393 | List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null | 393 | List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null |
| 394 | && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); | 394 | && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); |
| 395 | Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities, | 395 | Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities, |
| @@ -414,6 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -414,6 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 414 | // 处理每个任务的 tasks 属性 | 414 | // 处理每个任务的 tasks 属性 |
| 415 | for (HistoricActivityInstance activity : taskActivities) { | 415 | for (HistoricActivityInstance activity : taskActivities) { |
| 416 | HistoricTaskInstance task = taskMap.get(activity.getTaskId()); | 416 | HistoricTaskInstance task = taskMap.get(activity.getTaskId()); |
| 417 | + // TODO @lesan:这里为啥 continue 哈? | ||
| 417 | if (task == null) { | 418 | if (task == null) { |
| 418 | continue; | 419 | continue; |
| 419 | } | 420 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -1214,7 +1214,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1214,7 +1214,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1214 | } | 1214 | } |
| 1215 | } | 1215 | } |
| 1216 | 1216 | ||
| 1217 | - // 发起人节点 | 1217 | + // 获取发起人节点 |
| 1218 | BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); | 1218 | BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); |
| 1219 | if (bpmnModel == null) { | 1219 | if (bpmnModel == null) { |
| 1220 | log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); | 1220 | log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); |
| @@ -1227,16 +1227,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1227,16 +1227,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1227 | String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); | 1227 | String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); |
| 1228 | Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(), | 1228 | Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(), |
| 1229 | PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); | 1229 | PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); |
| 1230 | - if (userTaskElement.getId().equals(START_USER_NODE_ID) && | ||
| 1231 | - (skipStartUserNodeFlag == null || Boolean.TRUE.equals(skipStartUserNodeFlag)) && | ||
| 1232 | - !Boolean.TRUE.equals(returnTaskFlag)) { | 1230 | + if (userTaskElement.getId().equals(START_USER_NODE_ID) |
| 1231 | + && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 | ||
| 1232 | + || Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 | ||
| 1233 | + && !Boolean.TRUE.equals(returnTaskFlag)) { // TODO @lesan:ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE) 改成这个有问题么?尽量不用 ! 取反 | ||
| 1233 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) | 1234 | getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) |
| 1234 | .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); | 1235 | .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); |
| 1235 | return; | 1236 | return; |
| 1236 | } | 1237 | } |
| 1237 | // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理 | 1238 | // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理 |
| 1238 | - if (!userTaskElement.getId().equals(START_USER_NODE_ID) && | ||
| 1239 | - StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { | 1239 | + if (ObjectUtil.notEqual(userTaskElement.getId(), START_USER_NODE_ID) |
| 1240 | + && StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { | ||
| 1240 | if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { | 1241 | if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { |
| 1241 | Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement); | 1242 | Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement); |
| 1242 | 1243 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java
| 1 | package cn.iocoder.yudao.module.bpm.service.task.listener; | 1 | package cn.iocoder.yudao.module.bpm.service.task.listener; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.convert.Convert; | ||
| 4 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 5 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 5 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| @@ -22,7 +21,7 @@ import org.springframework.stereotype.Component; | @@ -22,7 +21,7 @@ import org.springframework.stereotype.Component; | ||
| 22 | import java.util.List; | 21 | import java.util.List; |
| 23 | 22 | ||
| 24 | /** | 23 | /** |
| 25 | - * BPM 子流程监听器 | 24 | + * BPM 子流程监听器:设置流程的发起人 |
| 26 | * | 25 | * |
| 27 | * @author Lesan | 26 | * @author Lesan |
| 28 | */ | 27 | */ |
| @@ -42,47 +41,51 @@ public class BpmCallActivityListener implements ExecutionListener { | @@ -42,47 +41,51 @@ public class BpmCallActivityListener implements ExecutionListener { | ||
| 42 | public void notify(DelegateExecution execution) { | 41 | public void notify(DelegateExecution execution) { |
| 43 | String expressionText = listenerConfig.getExpressionText(); | 42 | String expressionText = listenerConfig.getExpressionText(); |
| 44 | Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); | 43 | Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); |
| 45 | - BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject(expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); | ||
| 46 | - // 1. 当发起人来源为表单时 | ||
| 47 | - if (startUserSetting != null && | ||
| 48 | - startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { | 44 | + BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject( |
| 45 | + expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); | ||
| 46 | + | ||
| 47 | + // 1. 当发起人来源为主流程发起人时,并兜底 startUserSetting 为空时 | ||
| 48 | + if (startUserSetting == null | ||
| 49 | + || startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { | ||
| 50 | + ExecutionEntity parent = (ExecutionEntity) execution.getParent(); | ||
| 51 | + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | ||
| 52 | + return; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + // 2. 当发起人来源为表单时 | ||
| 56 | + if (startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { | ||
| 49 | ExecutionEntity parent = (ExecutionEntity) execution.getParent(); | 57 | ExecutionEntity parent = (ExecutionEntity) execution.getParent(); |
| 50 | - String formField = parent.getVariable(startUserSetting.getFormField(), String.class); | ||
| 51 | - // 1.1 当表单值为空时 | ||
| 52 | - if (StrUtil.isEmpty(formField)) { | ||
| 53 | - // 1.1.1 来自主流程发起人 | ||
| 54 | - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())){ | 58 | + String formFieldValue = parent.getVariable(startUserSetting.getFormField(), String.class); |
| 59 | + // 2.1 当表单值为空时 | ||
| 60 | + if (StrUtil.isEmpty(formFieldValue)) { | ||
| 61 | + // 2.1.1 来自主流程发起人 | ||
| 62 | + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { | ||
| 55 | FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | 63 | FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); |
| 56 | return; | 64 | return; |
| 57 | } | 65 | } |
| 58 | - // 1.1.2 来自子流程管理员 | ||
| 59 | - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())){ | 66 | + // 2.1.2 来自子流程管理员 |
| 67 | + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())) { | ||
| 60 | BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId()); | 68 | BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId()); |
| 61 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); | 69 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); |
| 62 | - FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); | 70 | + FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); |
| 63 | return; | 71 | return; |
| 64 | } | 72 | } |
| 65 | - // 1.1.3 来自主流程管理员 | ||
| 66 | - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())){ | 73 | + // 2.1.3 来自主流程管理员 |
| 74 | + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { | ||
| 67 | BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); | 75 | BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); |
| 68 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); | 76 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); |
| 69 | - FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); | 77 | + FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); |
| 70 | return; | 78 | return; |
| 71 | } | 79 | } |
| 72 | } | 80 | } |
| 73 | - // 1.2 使用表单值,并兜底字符串转Long失败时使用主流程发起人 | 81 | + // 2.2 使用表单值,并兜底字符串转 Long 失败时使用主流程发起人 |
| 74 | try { | 82 | try { |
| 75 | - FlowableUtils.setAuthenticatedUserId(Long.parseLong(formField)); | 83 | + FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); |
| 76 | } catch (Exception e) { | 84 | } catch (Exception e) { |
| 85 | + // todo @lesan:打个日志,方便排查 | ||
| 77 | FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | 86 | FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); |
| 78 | } | 87 | } |
| 79 | } | 88 | } |
| 80 | - // 2. 当发起人来源为主流程发起人时,并兜底startUserSetting为空时 | ||
| 81 | - if (startUserSetting == null || | ||
| 82 | - startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { | ||
| 83 | - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); | ||
| 84 | - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | ||
| 85 | - } | ||
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | } | 91 | } |
| 89 | \ No newline at end of file | 92 | \ No newline at end of file |