fix:【bpm 工作流】跨进程调用,无法回调 crm 的工作流结果的问题
parent
b46f29e45f
commit
8eea97add4
|
|
@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
@ -124,6 +125,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
|
@LoadBalanced
|
||||||
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
|
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
|
||||||
return restTemplateBuilder.build();
|
return restTemplateBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ public class BpmProcessInstanceStatusEvent extends ApplicationEvent {
|
||||||
*/
|
*/
|
||||||
private String businessKey;
|
private String businessKey;
|
||||||
|
|
||||||
|
public BpmProcessInstanceStatusEvent() {
|
||||||
|
// new Object() 保证非空
|
||||||
|
super(new Object());
|
||||||
|
}
|
||||||
|
|
||||||
public BpmProcessInstanceStatusEvent(Object source) {
|
public BpmProcessInstanceStatusEvent(Object source) {
|
||||||
super(source);
|
super(source);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_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_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_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_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, "子流程取消失败,子流程不允许取消");
|
ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
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.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.*;
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.client.RestClientException;
|
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.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
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 请求工具类
|
* 工作流发起 HTTP 请求工具类
|
||||||
|
|
@ -42,7 +42,6 @@ public class BpmHttpRequestUtils {
|
||||||
List<BpmSimpleModelNodeVO.HttpRequestParam> bodyParams,
|
List<BpmSimpleModelNodeVO.HttpRequestParam> bodyParams,
|
||||||
Boolean handleResponse,
|
Boolean handleResponse,
|
||||||
List<KeyValue<String, String>> response) {
|
List<KeyValue<String, String>> response) {
|
||||||
RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class);
|
|
||||||
BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class);
|
BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class);
|
||||||
|
|
||||||
// 1.1 设置请求头
|
// 1.1 设置请求头
|
||||||
|
|
@ -51,6 +50,7 @@ public class BpmHttpRequestUtils {
|
||||||
MultiValueMap<String, String> body = buildHttpBody(processInstance, bodyParams);
|
MultiValueMap<String, String> body = buildHttpBody(processInstance, bodyParams);
|
||||||
|
|
||||||
// 2. 发起请求
|
// 2. 发起请求
|
||||||
|
RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class);
|
||||||
ResponseEntity<String> responseEntity = sendHttpRequest(url, headers, body, restTemplate);
|
ResponseEntity<String> responseEntity = sendHttpRequest(url, headers, body, restTemplate);
|
||||||
|
|
||||||
// 3. 处理返回
|
// 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<String, String> 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<String> sendHttpRequest(String url,
|
public static ResponseEntity<String> sendHttpRequest(String url,
|
||||||
MultiValueMap<String, String> headers,
|
MultiValueMap<String, String> headers,
|
||||||
MultiValueMap<String, String> body,
|
Object body,
|
||||||
RestTemplate restTemplate) {
|
RestTemplate restTemplate) {
|
||||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
HttpEntity<Object> requestEntity = new HttpEntity<>(body, headers);
|
||||||
ResponseEntity<String> responseEntity;
|
ResponseEntity<String> responseEntity;
|
||||||
try {
|
try {
|
||||||
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
|
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) {
|
} catch (RestClientException e) {
|
||||||
log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
log.error("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
||||||
throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);
|
throw exception(PROCESS_INSTANCE_HTTP_CALL_ERROR);
|
||||||
}
|
}
|
||||||
return responseEntity;
|
return responseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
|
public static MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
|
||||||
List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
|
List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
|
||||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
|
||||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||||
headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
|
headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
|
||||||
|
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||||
addHttpRequestParam(headers, headerSettings, processVariables);
|
addHttpRequestParam(headers, headerSettings, processVariables);
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.bpm.framework.rpc.config;
|
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.DeptApi;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
||||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
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.permission.RoleApi;
|
||||||
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
|
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
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.cloud.openfeign.EnableFeignClients;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Configuration(value = "bpmRpcConfiguration", proxyBeanMethods = false)
|
@Configuration(value = "bpmRpcConfiguration", proxyBeanMethods = false)
|
||||||
@EnableFeignClients(clients = {RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class,
|
@EnableFeignClients(clients = {RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class,
|
||||||
PermissionApi.class})
|
PermissionApi.class})
|
||||||
public class RpcConfiguration {
|
public class RpcConfiguration {
|
||||||
|
|
||||||
|
// ========== 特殊:解决微 yudao-cloud 微服务场景下,跨服务(进程)无法 Listener 的问题 ==========
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(name = "crmReceivableStatusListener")
|
||||||
|
public CrmReceivableStatusListener crmReceivableStatusListener() {
|
||||||
|
return new CrmReceivableStatusListener();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,30 @@
|
||||||
package cn.iocoder.yudao.module.crm.service.receivable.listener;
|
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.BpmProcessInstanceStatusEvent;
|
||||||
import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener;
|
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.CrmReceivableService;
|
||||||
import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl;
|
import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
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
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@Component
|
@RestController
|
||||||
|
@Validated
|
||||||
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener {
|
public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener {
|
||||||
|
|
||||||
|
private static final String PREFIX = ApiConstants.PREFIX + "/receivable";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CrmReceivableService receivableService;
|
private CrmReceivableService receivableService;
|
||||||
|
|
||||||
|
|
@ -24,7 +34,8 @@ public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventLi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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());
|
receivableService.updateReceivableAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue