Commit b766f8d820a13ec12a25f02485570b7e50a10df2
1 parent
7ba084bc
fix:【BPM 工作流】子流程支持流程 title 自定义标题
Showing
2 changed files
with
102 additions
and
72 deletions
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | |
| 3 | 4 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 4 | 5 | import com.google.common.collect.ImmutableSet; |
| 5 | 6 | import jakarta.annotation.Resource; |
| ... | ... | @@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent |
| 37 | 38 | |
| 38 | 39 | @Override |
| 39 | 40 | protected void processCreated(FlowableEngineEntityEvent event) { |
| 40 | - processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity()); | |
| 41 | + ProcessInstance processInstance = (ProcessInstance) event.getEntity(); | |
| 42 | + FlowableUtils.execute(processInstance.getTenantId(), | |
| 43 | + () -> processInstanceService.processProcessInstanceCreated(processInstance)); | |
| 41 | 44 | } |
| 42 | 45 | |
| 43 | 46 | @Override |
| 44 | 47 | protected void processCompleted(FlowableEngineEntityEvent event) { |
| 45 | - processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity()); | |
| 48 | + ProcessInstance processInstance = (ProcessInstance) event.getEntity(); | |
| 49 | + FlowableUtils.execute(processInstance.getTenantId(), | |
| 50 | + () -> processInstanceService.processProcessInstanceCompleted(processInstance)); | |
| 46 | 51 | } |
| 47 | 52 | |
| 48 | - @Override // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法 | |
| 53 | + @Override | |
| 49 | 54 | protected void processCancelled(FlowableCancelledEvent event) { |
| 55 | + // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法 | |
| 50 | 56 | ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId()); |
| 51 | - processInstanceService.processProcessInstanceCompleted(processInstance); | |
| 57 | + if (processInstance != null) { | |
| 58 | + FlowableUtils.execute(processInstance.getTenantId(), | |
| 59 | + () -> processInstanceService.processProcessInstanceCompleted(processInstance)); | |
| 60 | + } | |
| 52 | 61 | } |
| 53 | 62 | |
| 54 | 63 | } | ... | ... |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| ... | ... | @@ -4,10 +4,7 @@ import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | 5 | import cn.hutool.core.date.DateUtil; |
| 6 | 6 | import cn.hutool.core.lang.Assert; |
| 7 | -import cn.hutool.core.util.ArrayUtil; | |
| 8 | -import cn.hutool.core.util.ObjUtil; | |
| 9 | -import cn.hutool.core.util.ObjectUtil; | |
| 10 | -import cn.hutool.core.util.StrUtil; | |
| 7 | +import cn.hutool.core.util.*; | |
| 11 | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 12 | 9 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| 13 | 10 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| ... | ... | @@ -61,6 +58,8 @@ import org.flowable.task.api.history.HistoricTaskInstance; |
| 61 | 58 | import org.springframework.context.annotation.Lazy; |
| 62 | 59 | import org.springframework.stereotype.Service; |
| 63 | 60 | import org.springframework.transaction.annotation.Transactional; |
| 61 | +import org.springframework.transaction.support.TransactionSynchronization; | |
| 62 | +import org.springframework.transaction.support.TransactionSynchronizationManager; | |
| 64 | 63 | import org.springframework.validation.annotation.Validated; |
| 65 | 64 | |
| 66 | 65 | import java.util.*; |
| ... | ... | @@ -244,7 +243,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 244 | 243 | if (historicProcessInstance == null) { |
| 245 | 244 | throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); |
| 246 | 245 | } |
| 247 | - // 1.3 校验 BpmnModel | |
| 246 | + // 1.3 校验BpmnModel | |
| 248 | 247 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId()); |
| 249 | 248 | if (bpmnModel == null) { |
| 250 | 249 | return null; |
| ... | ... | @@ -449,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 449 | 448 | .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) |
| 450 | 449 | .setStartTime(DateUtils.of(activity.getStartTime())) |
| 451 | 450 | .setEndTime(DateUtils.of(activity.getEndTime())) |
| 452 | - .setProcessInstanceId(activity.getCalledProcessInstanceId()); | |
| 451 | + .setProcessInstanceId(activity.getProcessInstanceId()); | |
| 453 | 452 | approvalNodes.add(callActivity); |
| 454 | 453 | } |
| 455 | 454 | }); |
| ... | ... | @@ -521,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 521 | 520 | activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); |
| 522 | 521 | } |
| 523 | 522 | if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { |
| 524 | - activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId()); | |
| 523 | + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); | |
| 525 | 524 | } |
| 526 | 525 | return activityNode; |
| 527 | 526 | }); |
| ... | ... | @@ -771,17 +770,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 771 | 770 | processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule)); |
| 772 | 771 | } |
| 773 | 772 | // 3.2 流程名称 |
| 774 | - BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting(); | |
| 775 | - if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) { | |
| 776 | - AdminUserRespDTO user = adminUserApi.getUser(userId); | |
| 777 | - Map<String, Object> cloneVariables = new HashMap<>(variables); | |
| 778 | - cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname()); | |
| 779 | - cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now()); | |
| 780 | - cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim()); | |
| 781 | - processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables)); | |
| 782 | - } else { | |
| 783 | - processInstanceBuilder.name(definition.getName().trim()); | |
| 784 | - } | |
| 773 | + processInstanceBuilder.name(generateProcessInstanceName(userId, definition, processDefinitionInfo, variables)); | |
| 785 | 774 | // 3.3 发起流程实例 |
| 786 | 775 | ProcessInstance instance = processInstanceBuilder.start(); |
| 787 | 776 | return instance.getId(); |
| ... | ... | @@ -817,6 +806,25 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 817 | 806 | }); |
| 818 | 807 | } |
| 819 | 808 | |
| 809 | + private String generateProcessInstanceName(Long userId, | |
| 810 | + ProcessDefinition definition, | |
| 811 | + BpmProcessDefinitionInfoDO definitionInfo, | |
| 812 | + Map<String, Object> variables) { | |
| 813 | + if (definition == null || definitionInfo == null) { | |
| 814 | + return null; | |
| 815 | + } | |
| 816 | + BpmModelMetaInfoVO.TitleSetting titleSetting = definitionInfo.getTitleSetting(); | |
| 817 | + if (titleSetting == null || !BooleanUtil.isTrue(titleSetting.getEnable())) { | |
| 818 | + return definition.getName(); | |
| 819 | + } | |
| 820 | + AdminUserRespDTO user = adminUserApi.getUser(userId); | |
| 821 | + Map<String, Object> cloneVariables = new HashMap<>(variables); | |
| 822 | + cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname()); | |
| 823 | + cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now()); | |
| 824 | + cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim()); | |
| 825 | + return StrUtil.format(definitionInfo.getTitleSetting().getTitle(), cloneVariables); | |
| 826 | + } | |
| 827 | + | |
| 820 | 828 | @Override |
| 821 | 829 | public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { |
| 822 | 830 | // 1.1 校验流程实例存在 |
| ... | ... | @@ -833,7 +841,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 833 | 841 | .getProcessDefinitionInfo(instance.getProcessDefinitionId()); |
| 834 | 842 | Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); |
| 835 | 843 | if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 |
| 836 | - && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { | |
| 844 | + && BooleanUtil.isFalse(processDefinitionInfo.getAllowCancelRunningProcess())) { | |
| 837 | 845 | throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); |
| 838 | 846 | } |
| 839 | 847 | // 1.4 子流程不允许取消 |
| ... | ... | @@ -900,64 +908,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 900 | 908 | |
| 901 | 909 | @Override |
| 902 | 910 | public void processProcessInstanceCompleted(ProcessInstance instance) { |
| 903 | - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 | |
| 904 | - FlowableUtils.execute(instance.getTenantId(), () -> { | |
| 905 | - // 1.1 获取当前状态 | |
| 906 | - Integer status = (Integer) instance.getProcessVariables() | |
| 907 | - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); | |
| 908 | - String reason = (String) instance.getProcessVariables() | |
| 909 | - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); | |
| 910 | - // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 | |
| 911 | - // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 | |
| 912 | - if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { | |
| 913 | - status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); | |
| 914 | - runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, | |
| 915 | - status); | |
| 916 | - } | |
| 911 | + // 1.1 获取当前状态 | |
| 912 | + Integer status = (Integer) instance.getProcessVariables() | |
| 913 | + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); | |
| 914 | + String reason = (String) instance.getProcessVariables() | |
| 915 | + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); | |
| 916 | + // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 | |
| 917 | + // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 | |
| 918 | + if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { | |
| 919 | + status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); | |
| 920 | + runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, | |
| 921 | + status); | |
| 922 | + } | |
| 923 | + | |
| 924 | + // 2. 发送对应的消息通知 | |
| 925 | + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { | |
| 926 | + messageService.sendMessageWhenProcessInstanceApprove( | |
| 927 | + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); | |
| 928 | + } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { | |
| 929 | + messageService.sendMessageWhenProcessInstanceReject( | |
| 930 | + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); | |
| 931 | + } | |
| 932 | + | |
| 933 | + // 3. 发送流程实例的状态事件 | |
| 934 | + processInstanceEventPublisher.sendProcessInstanceResultEvent( | |
| 935 | + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status)); | |
| 936 | + | |
| 937 | + // 4. 流程后置通知 | |
| 938 | + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { | |
| 939 | + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. | |
| 940 | + getProcessDefinitionInfo(instance.getProcessDefinitionId()); | |
| 941 | + if (ObjUtil.isNotNull(processDefinitionInfo) && | |
| 942 | + ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) { | |
| 943 | + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); | |
| 917 | 944 | |
| 918 | - // 2. 发送对应的消息通知 | |
| 919 | - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { | |
| 920 | - messageService.sendMessageWhenProcessInstanceApprove( | |
| 921 | - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); | |
| 922 | - } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { | |
| 923 | - messageService.sendMessageWhenProcessInstanceReject( | |
| 924 | - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); | |
| 945 | + BpmHttpRequestUtils.executeBpmHttpRequest(instance, | |
| 946 | + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | |
| 925 | 947 | } |
| 948 | + } | |
| 949 | + } | |
| 926 | 950 | |
| 927 | - // 3. 发送流程实例的状态事件 | |
| 928 | - processInstanceEventPublisher.sendProcessInstanceResultEvent( | |
| 929 | - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status)); | |
| 951 | + @Override | |
| 952 | + public void processProcessInstanceCreated(ProcessInstance instance) { | |
| 953 | + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. | |
| 954 | + getProcessDefinitionInfo(instance.getProcessDefinitionId()); | |
| 955 | + ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(instance.getProcessDefinitionId()); | |
| 956 | + if (processDefinition == null || processDefinitionInfo == null) { | |
| 957 | + return; | |
| 958 | + } | |
| 930 | 959 | |
| 931 | - // 4. 流程后置通知 | |
| 932 | - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { | |
| 933 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. | |
| 934 | - getProcessDefinitionInfo(instance.getProcessDefinitionId()); | |
| 935 | - if (ObjUtil.isNotNull(processDefinitionInfo) && | |
| 936 | - ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) { | |
| 937 | - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); | |
| 960 | + // 自定义标题。目的:主要处理子流程的标题无法处理 | |
| 961 | + // 注意:必须使用 TransactionSynchronizationManager 事务提交后,否则不生效!!! | |
| 962 | + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { | |
| 938 | 963 | |
| 939 | - BpmHttpRequestUtils.executeBpmHttpRequest(instance, | |
| 940 | - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | |
| 964 | + @Override | |
| 965 | + public void afterCommit() { | |
| 966 | + String name = generateProcessInstanceName(Long.valueOf(instance.getStartUserId()), | |
| 967 | + processDefinition, processDefinitionInfo, instance.getProcessVariables()); | |
| 968 | + if (ObjUtil.notEqual(instance.getName(), name)) { | |
| 969 | + runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name); | |
| 941 | 970 | } |
| 942 | 971 | } |
| 943 | - }); | |
| 944 | - } | |
| 945 | 972 | |
| 946 | - @Override | |
| 947 | - public void processProcessInstanceCreated(ProcessInstance instance) { | |
| 948 | - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 | |
| 949 | - FlowableUtils.execute(instance.getTenantId(), () -> { | |
| 950 | - // 流程前置通知 | |
| 951 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. | |
| 952 | - getProcessDefinitionInfo(instance.getProcessDefinitionId()); | |
| 953 | - if (ObjUtil.isNull(processDefinitionInfo) || | |
| 954 | - ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) { | |
| 955 | - return; | |
| 956 | - } | |
| 957 | - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); | |
| 958 | - BpmHttpRequestUtils.executeBpmHttpRequest(instance, | |
| 959 | - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | |
| 960 | 973 | }); |
| 974 | + | |
| 975 | + // 流程前置通知 | |
| 976 | + if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) { | |
| 977 | + return; | |
| 978 | + } | |
| 979 | + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); | |
| 980 | + BpmHttpRequestUtils.executeBpmHttpRequest(instance, | |
| 981 | + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); | |
| 961 | 982 | } |
| 962 | 983 | |
| 963 | 984 | } | ... | ... |