# Conflicts:
#	yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java
#	yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
pull/150/MERGE
YunaiV 2025-07-30 19:07:02 +08:00
commit 02ddf5a5a7
17 changed files with 286 additions and 59 deletions

View File

@ -17,6 +17,7 @@ uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql
import argparse import argparse
import pathlib import pathlib
import re import re
import sys
import time import time
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Dict, Generator, Optional, Tuple, Union from typing import Dict, Generator, Optional, Tuple, Union
@ -293,8 +294,10 @@ class Convertor(ABC):
# 将parse失败的脚本打印出来 # 将parse失败的脚本打印出来
if error_scripts: if error_scripts:
print("!!! 以下内容无法正常解析", file=sys.stderr)
for script in error_scripts: for script in error_scripts:
print(script) # print to stderr
print(script, file=sys.stderr)
class PostgreSQLConvertor(Convertor): class PostgreSQLConvertor(Convertor):

View File

@ -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();
} }

View File

@ -25,6 +25,7 @@ import org.springframework.util.Assert;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.validation.FieldError; import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError; import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.MissingServletRequestParameterException;
@ -100,6 +101,9 @@ public class GlobalExceptionHandler {
if (ex instanceof HttpRequestMethodNotSupportedException) { if (ex instanceof HttpRequestMethodNotSupportedException) {
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
} }
if (ex instanceof HttpMediaTypeNotSupportedException) {
return httpMediaTypeNotSupportedExceptionHandler((HttpMediaTypeNotSupportedException) ex);
}
if (ex instanceof ServiceException) { if (ex instanceof ServiceException) {
return serviceExceptionHandler((ServiceException) ex); return serviceExceptionHandler((ServiceException) ex);
} }
@ -178,9 +182,11 @@ public class GlobalExceptionHandler {
if (ex.getCause() instanceof InvalidFormatException) { if (ex.getCause() instanceof InvalidFormatException) {
InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
}else {
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
} }
if (StrUtil.startWith(ex.getMessage(), "Required request body is missing")) {
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数类型错误: request body 缺失");
}
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
} }
/** /**
@ -236,6 +242,17 @@ public class GlobalExceptionHandler {
return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage())); return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
} }
/**
* SpringMVC Content-Type
*
* A Content-Type application/json Content-Type application/octet-stream
*/
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public CommonResult<?> httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException ex) {
log.warn("[httpMediaTypeNotSupportedExceptionHandler]", ex);
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求类型不正确:%s", ex.getMessage()));
}
/** /**
* Spring Security * Spring Security
* *
@ -394,7 +411,7 @@ public class GlobalExceptionHandler {
return CommonResult.error(NOT_IMPLEMENTED.getCode(), return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]"); "[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
} }
// 9. IOT 物联网 // 9. IoT 物联网
if (message.contains("iot_")) { if (message.contains("iot_")) {
log.error("[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]"); log.error("[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(), return CommonResult.error(NOT_IMPLEMENTED.getCode(),

View File

@ -35,6 +35,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);
} }

View File

@ -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, "子流程取消失败,子流程不允许取消");
@ -58,7 +58,6 @@ public interface ErrorCodeConstants {
ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务"); ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人"); ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");

View File

@ -14,6 +14,7 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum BpmTaskStatusEnum { public enum BpmTaskStatusEnum {
SKIP(-2, "跳过"),
NOT_START(-1, "未开始"), NOT_START(-1, "未开始"),
RUNNING(1, "审批中"), RUNNING(1, "审批中"),
APPROVE(2, "审批通过"), APPROVE(2, "审批通过"),

View File

@ -0,0 +1,25 @@
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.web.bind.annotation.RequestBody;
/**
*
*
* @author
*/
public class CrmContractStatusListener extends BpmProcessInstanceStatusEventListener {
@Override
public String getProcessDefinitionKey() {
return "crm-contract-audit";
}
@Override
public void onEvent(@RequestBody @Valid BpmProcessInstanceStatusEvent event) {
BpmHttpRequestUtils.executeBpmHttpRequest(event,
"http://crm-server/rpc-api/crm/contract/update-audit-status");
}
}

View File

@ -0,0 +1,25 @@
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.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");
}
}

View File

@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "是否填写审批意见", example = "false") @Schema(description = "是否填写审批意见", example = "false")
private Boolean reasonRequire; private Boolean reasonRequire;
@Schema(description = "跳过表达式", example = "{true}")
private String skipExpression; // 用于审批节点
/** /**
* *
*/ */

View File

@ -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;
} }

View File

@ -800,9 +800,10 @@ public class BpmnModelUtils {
|| currentElement instanceof EndEvent || currentElement instanceof EndEvent
|| currentElement instanceof UserTask || currentElement instanceof UserTask
|| currentElement instanceof ServiceTask) { || currentElement instanceof ServiceTask) {
// 添加元素 // 添加节点
FlowNode flowNode = (FlowNode) currentElement; FlowNode flowNode = (FlowNode) currentElement;
resultElements.add(flowNode); resultElements.add(flowNode);
// 遍历子节点 // 遍历子节点
flowNode.getOutgoingFlows().forEach( flowNode.getOutgoingFlows().forEach(
nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements));
@ -835,6 +836,31 @@ public class BpmnModelUtils {
} }
} }
/**
*
*
* @param flowNode
* @param variables
*/
public static boolean isSkipNode(FlowElement flowNode, Map<String, Object> variables) {
// 1. 检查节点是否有跳过表达式(支持多种任务节点类型)
String skipExpression = null;
if (flowNode instanceof UserTask) {
skipExpression = ((UserTask) flowNode).getSkipExpression();
} else if (flowNode instanceof ServiceTask) {
skipExpression = ((ServiceTask) flowNode).getSkipExpression();
} else if (flowNode instanceof ScriptTask) {
skipExpression = ((ScriptTask) flowNode).getSkipExpression();
}
if (StrUtil.isEmpty(skipExpression)) {
return false;
}
// 2. 计算跳过表达式的值
return evalConditionExpress(variables, skipExpression);
}
/** /**
* *
* *
@ -997,7 +1023,7 @@ public class BpmnModelUtils {
* @return * @return
*/ */
public static boolean evalConditionExpress(Map<String, Object> variables, String expression) { public static boolean evalConditionExpress(Map<String, Object> variables, String expression) {
if (expression == null) { if (StrUtil.isEmpty(expression)) {
return Boolean.FALSE; return Boolean.FALSE;
} }
// 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.*; import cn.hutool.core.util.*;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
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.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
@ -17,13 +16,14 @@ import cn.iocoder.yudao.module.bpm.service.task.listener.BpmCallActivityListener
import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener; import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener;
import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.constants.BpmnXMLConstants; import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.delegate.ExecutionListener; import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.delegate.TaskListener; import org.flowable.engine.delegate.TaskListener;
import java.util.*; import java.util.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@ -239,13 +239,13 @@ public class SimpleModelUtils {
// 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况 // 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况
if (isValidNode(conditionChildNode)) { if (isValidNode(conditionChildNode)) {
// 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线 // 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), item); SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), nodeType, item);
process.addFlowElement(sequenceFlow); process.addFlowElement(sequenceFlow);
// 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线 // 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线
traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId); traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId);
} else { } else {
// 3.2 分支没有后续节点。例如说,建立 A->D 的连线 // 3.2 分支没有后续节点。例如说,建立 A->D 的连线
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, item); SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, nodeType, item);
process.addFlowElement(sequenceFlow); process.addFlowElement(sequenceFlow);
} }
} }
@ -464,6 +464,10 @@ public class SimpleModelUtils {
addReasonRequire(node.getReasonRequire(), userTask); addReasonRequire(node.getReasonRequire(), userTask);
// 节点类型 // 节点类型
addNodeType(node.getType(), userTask); addNodeType(node.getType(), userTask);
// 添加跳过表达式
if (StrUtil.isNotEmpty(node.getSkipExpression())) {
userTask.setSkipExpression(node.getSkipExpression());
}
return userTask; return userTask;
} }
@ -591,17 +595,23 @@ public class SimpleModelUtils {
private static class ParallelBranchNodeConvert implements NodeConvert { private static class ParallelBranchNodeConvert implements NodeConvert {
/**
* 使 true https://t.zsxq.com/m6GXh 反馈问题
*
* @see {@link ConditionNodeConvert#buildSequenceFlow}
*/
@Override @Override
public List<ParallelGateway> convertList(BpmSimpleModelNodeVO node) { public List<InclusiveGateway> convertList(BpmSimpleModelNodeVO node) {
ParallelGateway parallelGateway = new ParallelGateway();
parallelGateway.setId(node.getId()); InclusiveGateway inclusiveGateway = new InclusiveGateway();
inclusiveGateway.setId(node.getId());
// TODO @jasonsetName // TODO @jasonsetName
// 行聚合网关由程序创建,前端不需要传入 // 并网关 由程序创建,前端不需要传入
ParallelGateway joinParallelGateway = new ParallelGateway(); InclusiveGateway joinParallelGateway = new InclusiveGateway();
joinParallelGateway.setId(buildGatewayJoinId(node.getId())); joinParallelGateway.setId(buildGatewayJoinId(node.getId()));
// TODO @jasonsetName // TODO @jasonsetName
return CollUtil.newArrayList(parallelGateway, joinParallelGateway); return CollUtil.newArrayList(inclusiveGateway, joinParallelGateway);
} }
@Override @Override
@ -652,8 +662,14 @@ public class SimpleModelUtils {
} }
public static SequenceFlow buildSequenceFlow(String sourceId, String targetId, public static SequenceFlow buildSequenceFlow(String sourceId, String targetId,
BpmSimpleModelNodeVO node) { BpmSimpleModelNodeTypeEnum nodeType, BpmSimpleModelNodeVO node) {
String conditionExpression = buildConditionExpression(node.getConditionSetting()); String conditionExpression;
// 并行分支,使用包容网关实现,强制设置条件表达式为 true
if (BpmSimpleModelNodeTypeEnum.PARALLEL_BRANCH_NODE == nodeType) {
conditionExpression ="${true}";
} else {
conditionExpression = buildConditionExpression(node.getConditionSetting());
}
return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression); return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression);
} }
} }
@ -662,7 +678,6 @@ public class SimpleModelUtils {
* *
*/ */
public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
// 并行网关不需要设置条件
if (conditionSetting == null) { if (conditionSetting == null) {
return null; return null;
} }
@ -684,15 +699,18 @@ public class SimpleModelUtils {
if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) {
return null; return null;
} }
List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { List<String> strConditionGroups = convertList(conditionGroups.getConditions(), item -> {
if (CollUtil.isEmpty(item.getRules())) { if (CollUtil.isEmpty(item.getRules())) {
return ""; return "";
} }
// 构造规则表达式 // 构造规则表达式
List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> { List<String> list = convertList(item.getRules(), (rule) -> {
String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide()
: "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号
return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); return String.format(" vars:getOrDefault(%s, null) %s var:convertByType(%s,%s) ",
rule.getLeftSide(), // 左侧:读取变量
rule.getOpCode(), // 中间:操作符,比较
rule.getLeftSide(), rightSide); // 右侧转换变量VariableConvertByTypeExpressionFunction
}); });
// 构造条件组的表达式 // 构造条件组的表达式
Boolean and = item.getAnd(); Boolean and = item.getAnd();
@ -954,7 +972,7 @@ public class SimpleModelUtils {
|| nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
|| nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS
|| nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
// 添加元素 // 添加此节点
resultNodes.add(currentNode); resultNodes.add(currentNode);
} }
@ -1000,6 +1018,16 @@ public class SimpleModelUtils {
simulateNextNode(currentNode.getChildNode(), variables, resultNodes); simulateNextNode(currentNode.getChildNode(), variables, resultNodes);
} }
/**
*
*/
public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map<String, Object> variables) {
if (StrUtil.isEmpty(currentNode.getSkipExpression())) {
return false;
}
return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression());
}
public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
} }

View File

@ -1,5 +1,7 @@
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.CrmContractStatusListener;
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 +9,28 @@ 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();
}
@Bean
@ConditionalOnMissingBean(name = "crmContractStatusListener")
public CrmContractStatusListener crmContractStatusListener() {
return new CrmContractStatusListener();
}
} }

View File

@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
: ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
.setStatus(FlowableUtils.getTaskStatus(task)) .setStatus(getEndActivityNodeStatus(task))
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
.setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
.setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
@ -462,6 +462,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return approvalNodes; return approvalNodes;
} }
/**
*
*/
private Integer getEndActivityNodeStatus(HistoricTaskInstance task) {
Integer status = FlowableUtils.getTaskStatus(task);
if (status != null) {
return status;
}
// 结束节点未获取到状态,为跳过状态。可见 bpmn 或者 simple 的 skipExpression
return BpmTaskStatusEnum.SKIP.getStatus();
}
/** /**
* *
*/ */
@ -565,10 +577,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
if (runActivityIds.contains(node.getId())) { if (runActivityIds.contains(node.getId())) {
return null; return null;
} }
Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
// 如果节点被跳过。设置状态为跳过
if (SimpleModelUtils.isSkipNode(node, processVariables)) {
status = BpmTaskStatusEnum.SKIP.getStatus();
}
ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
.setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
.setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); .setStatus(status);
// 1. 开始节点/审批节点 // 1. 开始节点/审批节点
if (ObjectUtils.equalsAny(node.getType(), if (ObjectUtils.equalsAny(node.getType(),
@ -608,8 +624,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
if (runActivityIds.contains(node.getId())) { if (runActivityIds.contains(node.getId())) {
return null; return null;
} }
Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
// 如果节点被跳过,状态设置为跳过
if(BpmnModelUtils.isSkipNode(node, processVariables)){
status = BpmTaskStatusEnum.SKIP.getStatus();
}
ActivityNode activityNode = new ActivityNode().setId(node.getId()) ActivityNode activityNode = new ActivityNode().setId(node.getId())
.setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); .setStatus(status);
// 1. 开始节点 // 1. 开始节点
if (node instanceof StartEvent) { if (node instanceof StartEvent) {

View File

@ -947,7 +947,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason())); BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason()));
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
// 特殊如果已经被委派owner 非空),则不需要更新 ownerhttps://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153
if (StrUtil.isEmpty(task.getOwner())) {
taskService.setOwner(taskId, task.getAssignee()); taskService.setOwner(taskId, task.getAssignee());
}
// 3.2 执行委派,将任务委派给 delegateUser // 3.2 执行委派,将任务委派给 delegateUser
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString()); taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
// 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中 // 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中
@ -973,7 +976,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason())); BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason()));
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
// 特殊如果已经被转派owner 非空),则不需要更新 ownerhttps://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153
if (StrUtil.isEmpty(task.getOwner())) {
taskService.setOwner(taskId, task.getAssignee()); taskService.setOwner(taskId, task.getAssignee());
}
// 3.2 执行转派(审批人),将任务转派给 assigneeUser // 3.2 执行转派(审批人),将任务转派给 assigneeUser
// 委托( delegate和转派transfer的差别就在这块的调用 // 委托( delegate和转派transfer的差别就在这块的调用
taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString()); taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString());

View File

@ -2,20 +2,28 @@ package cn.iocoder.yudao.module.crm.service.contract.listener;
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.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl;
import org.springframework.stereotype.Component; import jakarta.annotation.Resource;
import org.springframework.cloud.openfeign.FeignClient;
import javax.annotation.Resource; 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 CrmContractStatusListener extends BpmProcessInstanceStatusEventListener { public class CrmContractStatusListener extends BpmProcessInstanceStatusEventListener {
private static final String PREFIX = ApiConstants.PREFIX + "/contract";
@Resource @Resource
private CrmContractService contractService; private CrmContractService contractService;
@ -25,7 +33,8 @@ public class CrmContractStatusListener extends BpmProcessInstanceStatusEventList
} }
@Override @Override
protected void onEvent(BpmProcessInstanceStatusEvent event) { @PostMapping(PREFIX + "/update-audit-status") // 目的:提供给 bpm-server rpc 调用
protected void onEvent(@RequestBody BpmProcessInstanceStatusEvent event) {
contractService.updateContractAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus()); contractService.updateContractAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
} }

View File

@ -1,21 +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 org.springframework.stereotype.Component; import jakarta.annotation.Resource;
import org.springframework.cloud.openfeign.FeignClient;
import javax.annotation.Resource; 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;
@ -25,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());
} }