Commit b766f8d820a13ec12a25f02485570b7e50a10df2

Authored by YunaiV
1 parent 7ba084bc

fix:【BPM 工作流】子流程支持流程 title 自定义标题

yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; 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 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 4 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
4 import com.google.common.collect.ImmutableSet; 5 import com.google.common.collect.ImmutableSet;
5 import jakarta.annotation.Resource; 6 import jakarta.annotation.Resource;
@@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
37 38
38 @Override 39 @Override
39 protected void processCreated(FlowableEngineEntityEvent event) { 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 @Override 46 @Override
44 protected void processCompleted(FlowableEngineEntityEvent event) { 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 protected void processCancelled(FlowableCancelledEvent event) { 54 protected void processCancelled(FlowableCancelledEvent event) {
  55 + // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法
50 ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId()); 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,10 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
5 import cn.hutool.core.date.DateUtil; 5 import cn.hutool.core.date.DateUtil;
6 import cn.hutool.core.lang.Assert; 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 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
12 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 9 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
13 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 10 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -61,6 +58,8 @@ import org.flowable.task.api.history.HistoricTaskInstance; @@ -61,6 +58,8 @@ import org.flowable.task.api.history.HistoricTaskInstance;
61 import org.springframework.context.annotation.Lazy; 58 import org.springframework.context.annotation.Lazy;
62 import org.springframework.stereotype.Service; 59 import org.springframework.stereotype.Service;
63 import org.springframework.transaction.annotation.Transactional; 60 import org.springframework.transaction.annotation.Transactional;
  61 +import org.springframework.transaction.support.TransactionSynchronization;
  62 +import org.springframework.transaction.support.TransactionSynchronizationManager;
64 import org.springframework.validation.annotation.Validated; 63 import org.springframework.validation.annotation.Validated;
65 64
66 import java.util.*; 65 import java.util.*;
@@ -244,7 +243,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -244,7 +243,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
244 if (historicProcessInstance == null) { 243 if (historicProcessInstance == null) {
245 throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); 244 throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
246 } 245 }
247 - // 1.3 校验 BpmnModel 246 + // 1.3 校验BpmnModel
248 BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId()); 247 BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
249 if (bpmnModel == null) { 248 if (bpmnModel == null) {
250 return null; 249 return null;
@@ -449,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -449,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
449 .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) 448 .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
450 .setStartTime(DateUtils.of(activity.getStartTime())) 449 .setStartTime(DateUtils.of(activity.getStartTime()))
451 .setEndTime(DateUtils.of(activity.getEndTime())) 450 .setEndTime(DateUtils.of(activity.getEndTime()))
452 - .setProcessInstanceId(activity.getCalledProcessInstanceId()); 451 + .setProcessInstanceId(activity.getProcessInstanceId());
453 approvalNodes.add(callActivity); 452 approvalNodes.add(callActivity);
454 } 453 }
455 }); 454 });
@@ -521,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -521,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
521 activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); 520 activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
522 } 521 }
523 if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { 522 if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
524 - activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId()); 523 + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId());
525 } 524 }
526 return activityNode; 525 return activityNode;
527 }); 526 });
@@ -771,17 +770,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -771,17 +770,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
771 processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule)); 770 processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
772 } 771 }
773 // 3.2 流程名称 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 // 3.3 发起流程实例 774 // 3.3 发起流程实例
786 ProcessInstance instance = processInstanceBuilder.start(); 775 ProcessInstance instance = processInstanceBuilder.start();
787 return instance.getId(); 776 return instance.getId();
@@ -817,6 +806,25 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -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 @Override 828 @Override
821 public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { 829 public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
822 // 1.1 校验流程实例存在 830 // 1.1 校验流程实例存在
@@ -833,7 +841,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -833,7 +841,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
833 .getProcessDefinitionInfo(instance.getProcessDefinitionId()); 841 .getProcessDefinitionInfo(instance.getProcessDefinitionId());
834 Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); 842 Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
835 if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 843 if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
836 - && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { 844 + && BooleanUtil.isFalse(processDefinitionInfo.getAllowCancelRunningProcess())) {
837 throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); 845 throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
838 } 846 }
839 // 1.4 子流程不允许取消 847 // 1.4 子流程不允许取消
@@ -900,64 +908,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -900,64 +908,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
900 908
901 @Override 909 @Override
902 public void processProcessInstanceCompleted(ProcessInstance instance) { 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 }