From 8eea97add40df7a84b127127b31d8aca4fdf624d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 30 Jul 2025 18:46:32 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E3=80=90bpm=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E3=80=91=E8=B7=A8=E8=BF=9B=E7=A8=8B=E8=B0=83=E7=94=A8?= =?UTF-8?q?=EF=BC=8C=E6=97=A0=E6=B3=95=E5=9B=9E=E8=B0=83=20crm=20=E7=9A=84?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=BB=93=E6=9E=9C=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/config/YudaoWebAutoConfiguration.java | 2 + .../event/BpmProcessInstanceStatusEvent.java | 5 ++ .../module/bpm/enums/ErrorCodeConstants.java | 2 +- .../event/CrmReceivableStatusListener.java | 27 ++++++++++ .../core/util/BpmHttpRequestUtils.java | 50 +++++++++++++++---- .../rpc/config/RpcConfiguration.java | 12 +++++ .../listener/CrmReceivableStatusListener.java | 17 +++++-- 7 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/event/CrmReceivableStatusListener.java diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index a70fe9684..5e033b124 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.util.AntPathMatcher; import org.springframework.web.bind.annotation.RestController; @@ -124,6 +125,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { */ @Bean @ConditionalOnMissingBean + @LoadBalanced public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder.build(); } diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEvent.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEvent.java index 5522d01b3..17947d24b 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEvent.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEvent.java @@ -34,6 +34,11 @@ public class BpmProcessInstanceStatusEvent extends ApplicationEvent { */ private String businessKey; + public BpmProcessInstanceStatusEvent() { + // new Object() 保证非空 + super(new Object()); + } + public BpmProcessInstanceStatusEvent(Object source) { super(source); } diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index 4f7d7bf7c..c9f9ab530 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -40,7 +40,7 @@ public interface ErrorCodeConstants { ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在"); ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程"); ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消"); - ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败"); + ErrorCode PROCESS_INSTANCE_HTTP_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 请求调用失败"); ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置"); ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消"); diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/event/CrmReceivableStatusListener.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/event/CrmReceivableStatusListener.java new file mode 100644 index 000000000..69769058d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/event/CrmReceivableStatusListener.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.bpm.api.event; + +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils; +import jakarta.validation.Valid; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 回款审批的结果的监听器实现类 + * + * @author 芋道源码 + */ +public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener { + + @Override + public String getProcessDefinitionKey() { + return "crm-receivable-audit"; + } + + @Override + public void onEvent(@RequestBody @Valid BpmProcessInstanceStatusEvent event) { + BpmHttpRequestUtils.executeBpmHttpRequest(event, + "http://crm-server/rpc-api/crm/receivable/update-audit-status"); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java index 014b5e3f0..358ee9f4d 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java @@ -6,15 +6,15 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import com.fasterxml.jackson.core.type.TypeReference; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.runtime.ProcessInstance; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; @@ -26,7 +26,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_CALL_ERROR; /** * 工作流发起 HTTP 请求工具类 @@ -42,7 +42,6 @@ public class BpmHttpRequestUtils { List bodyParams, Boolean handleResponse, List> response) { - RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); // 1.1 设置请求头 @@ -51,6 +50,7 @@ public class BpmHttpRequestUtils { MultiValueMap body = buildHttpBody(processInstance, bodyParams); // 2. 发起请求 + RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); ResponseEntity responseEntity = sendHttpRequest(url, headers, body, restTemplate); // 3. 处理返回 @@ -78,27 +78,55 @@ public class BpmHttpRequestUtils { } } + public static void executeBpmHttpRequest(BpmProcessInstanceStatusEvent event, + String url) { + // 1.1 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + if (TenantContextHolder.getTenantId() != null) { + headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); + } else { + BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); + ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getId()); + if (processInstance != null) { + headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); + } + } + // 1.2 设置请求体 +// MultiValueMap body = new LinkedMultiValueMap<>(); +// body.add("id", event.getId()); +// body.add("processDefinitionKey", event.getProcessDefinitionKey()); +// body.add("status", event.getStatus().toString()); +// if (StrUtil.isNotEmpty(event.getBusinessKey())) { +// body.add("businessKey", event.getBusinessKey()); +// } + + // 2. 发起请求 + RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); + sendHttpRequest(url, headers, event, restTemplate); + } + public static ResponseEntity sendHttpRequest(String url, MultiValueMap headers, - MultiValueMap body, + Object body, RestTemplate restTemplate) { - HttpEntity> requestEntity = new HttpEntity<>(body, headers); + HttpEntity requestEntity = new HttpEntity<>(body, headers); ResponseEntity responseEntity; try { responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); - log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); + log.info("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); } catch (RestClientException e) { - log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); - throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR); + log.error("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); + throw exception(PROCESS_INSTANCE_HTTP_CALL_ERROR); } return responseEntity; } public static MultiValueMap buildHttpHeaders(ProcessInstance processInstance, List headerSettings) { - Map processVariables = processInstance.getProcessVariables(); MultiValueMap headers = new LinkedMultiValueMap<>(); headers.add(HEADER_TENANT_ID, processInstance.getTenantId()); + Map processVariables = processInstance.getProcessVariables(); addHttpRequestParam(headers, headerSettings, processVariables); return headers; } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java index ea99eac82..90ffa4eca 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.rpc.config; +import cn.iocoder.yudao.module.bpm.api.event.CrmReceivableStatusListener; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; @@ -7,11 +8,22 @@ import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.permission.RoleApi; import cn.iocoder.yudao.module.system.api.sms.SmsSendApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(value = "bpmRpcConfiguration", proxyBeanMethods = false) @EnableFeignClients(clients = {RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, PermissionApi.class}) public class RpcConfiguration { + + // ========== 特殊:解决微 yudao-cloud 微服务场景下,跨服务(进程)无法 Listener 的问题 ========== + + @Bean + @ConditionalOnMissingBean(name = "crmReceivableStatusListener") + public CrmReceivableStatusListener crmReceivableStatusListener() { + return new CrmReceivableStatusListener(); + } + } diff --git a/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java b/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java index f0ddd86e5..dcb963bf0 100644 --- a/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java +++ b/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java @@ -1,20 +1,30 @@ package cn.iocoder.yudao.module.crm.service.receivable.listener; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; +import cn.iocoder.yudao.module.crm.enums.ApiConstants; import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl; import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; /** * 回款审批的结果的监听器实现类 * * @author HUIHUI */ -@Component +@RestController +@Validated +@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener { + private static final String PREFIX = ApiConstants.PREFIX + "/receivable"; + @Resource private CrmReceivableService receivableService; @@ -24,7 +34,8 @@ public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventLi } @Override - public void onEvent(BpmProcessInstanceStatusEvent event) { + @PostMapping(PREFIX + "/update-audit-status") // 目的:提供给 bpm-server rpc 调用 + public void onEvent(@RequestBody BpmProcessInstanceStatusEvent event) { receivableService.updateReceivableAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus()); }