mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
新增webcad生产单导入:1、cad拆单同步新结构优化适配;2、cad拆单支持基于配置限制板件数量和是否异步拆单,新增异步拆单;
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
public class ChenfengIDAutoConfiguration {
|
public class ChenfengIDAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SnowflakeIdWorker3rd ipQueryService() {
|
public SnowflakeIdWorker3rd idWorker() {
|
||||||
return new SnowflakeIdWorker3rd();
|
return new SnowflakeIdWorker3rd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
@@ -1,6 +1,8 @@
|
|||||||
package com.cf.imes.framework.organ.core.mq.rabbitmq;
|
package com.cf.imes.framework.organ.core.mq.rabbitmq;
|
||||||
|
|
||||||
|
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.kafka.clients.producer.ProducerInterceptor;
|
import org.apache.kafka.clients.producer.ProducerInterceptor;
|
||||||
import org.springframework.amqp.AmqpException;
|
import org.springframework.amqp.AmqpException;
|
||||||
import org.springframework.amqp.core.Message;
|
import org.springframework.amqp.core.Message;
|
||||||
@@ -8,6 +10,7 @@ import org.springframework.amqp.core.MessagePostProcessor;
|
|||||||
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
|
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
|
||||||
|
|
||||||
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_ORGAN_ID;
|
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_ORGAN_ID;
|
||||||
|
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_PEEK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RabbitMQ 消息队列的多组织 {@link ProducerInterceptor} 实现类
|
* RabbitMQ 消息队列的多组织 {@link ProducerInterceptor} 实现类
|
||||||
@@ -25,6 +28,11 @@ public class OrganRabbitMQMessagePostProcessor implements MessagePostProcessor {
|
|||||||
if (organId != null) {
|
if (organId != null) {
|
||||||
message.getMessageProperties().getHeaders().put(HEADER_ORGAN_ID, organId);
|
message.getMessageProperties().getHeaders().put(HEADER_ORGAN_ID, organId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String peek = DynamicDataSourceContextHolder.peek();
|
||||||
|
if (StringUtils.isNotEmpty(peek)) {
|
||||||
|
message.getMessageProperties().getHeaders().put(HEADER_PEEK, peek);
|
||||||
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.messaging.handler.invocation;
|
package org.springframework.messaging.handler.invocation;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
import com.cf.imes.framework.organ.core.util.OrganUtils;
|
import com.cf.imes.framework.organ.core.util.OrganUtils;
|
||||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
@@ -33,6 +35,7 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_ORGAN_ID;
|
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_ORGAN_ID;
|
||||||
|
import static com.cf.imes.framework.web.core.util.WebFrameworkUtils.HEADER_PEEK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link HandlerMethod} that invokes the underlying method with
|
* Extension of {@link HandlerMethod} that invokes the underlying method with
|
||||||
@@ -122,6 +125,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||||||
// 注意:如下是本类的改动点!!!
|
// 注意:如下是本类的改动点!!!
|
||||||
// 情况一:无组织编号的情况
|
// 情况一:无组织编号的情况
|
||||||
Long organId= parseorganId(message);
|
Long organId= parseorganId(message);
|
||||||
|
parsePeek(message);
|
||||||
if (organId == null) {
|
if (organId == null) {
|
||||||
return doInvoke(args);
|
return doInvoke(args);
|
||||||
}
|
}
|
||||||
@@ -149,6 +153,18 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||||||
throw new IllegalArgumentException("未知的数据类型:" + organId);
|
throw new IllegalArgumentException("未知的数据类型:" + organId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头部带有多数据源,透传
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
private void parsePeek(Message<?> message) {
|
||||||
|
Object peek = message.getHeaders().get(HEADER_PEEK);
|
||||||
|
if (ObjectUtil.isNotNull(peek)) {
|
||||||
|
DynamicDataSourceContextHolder.push(peek.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the method argument values for the current message, checking the provided
|
* Get the method argument values for the current message, checking the provided
|
||||||
* argument values and falling back to the configured argument resolvers.
|
* argument values and falling back to the configured argument resolvers.
|
||||||
|
|||||||
-141
@@ -1,20 +1,12 @@
|
|||||||
package com.cf.imes.framework.mq.rabbitmq.config;
|
package com.cf.imes.framework.mq.rabbitmq.config;
|
||||||
|
|
||||||
import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.amqp.core.*;
|
|
||||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RabbitMQ 消息队列配置类
|
* RabbitMQ 消息队列配置类
|
||||||
*
|
*
|
||||||
@@ -31,137 +23,4 @@ public class ChenfengRabbitMQAutoConfiguration {
|
|||||||
public MessageConverter createMessageConverter() {
|
public MessageConverter createMessageConverter() {
|
||||||
return new Jackson2JsonMessageConverter();
|
return new Jackson2JsonMessageConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单excel导入交换机、队列、绑定声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public FanoutExchange orderImportDefaultExcelFanoutExchange() {
|
|
||||||
return new FanoutExchange(RabbitMqConstants.ORDER_IMPORT_DEFAULT_EXCEL_EXCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单excel导入队列声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Queue orderImportDefaultExcelQueue() {
|
|
||||||
Map<String, Object> args = new HashMap<>(1);
|
|
||||||
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
|
|
||||||
args.put("x-dead-letter-exchange", ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
|
||||||
// 设置死信路由键
|
|
||||||
args.put("x-dead-letter-routing-key", ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
|
||||||
return QueueBuilder.durable(RabbitMqConstants.ORDER_IMPORT_DEFAULT_EXCEL_QUEUE).withArguments(args).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单excel导入交换机声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Binding orderImportDefaultExcelBinding() {
|
|
||||||
return BindingBuilder.bind(orderImportDefaultExcelQueue()).to(orderImportDefaultExcelFanoutExchange());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单xml导入交换机、队列、绑定声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public FanoutExchange orderImportDefaultXmlFanoutExchange() {
|
|
||||||
return new FanoutExchange(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_EXCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单xml导入队列声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Queue orderImportDefaultXmlQueue() {
|
|
||||||
Map<String, Object> args = new HashMap<>(1);
|
|
||||||
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
|
|
||||||
args.put("x-dead-letter-exchange", ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
|
||||||
// 设置死信路由键
|
|
||||||
args.put("x-dead-letter-routing-key", ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
|
||||||
return QueueBuilder.durable(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_QUEUE).withArguments(args).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单xml导入交换机声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Binding orderImportDefaultXmlBinding() {
|
|
||||||
return BindingBuilder.bind(orderImportDefaultXmlQueue()).to(orderImportDefaultXmlFanoutExchange());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单导入死信交换机声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public DirectExchange orderImportDeadLetterExchange() {
|
|
||||||
return new DirectExchange(ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单导入死信队列声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Queue orderImportDeadLetterQueue() {
|
|
||||||
return new Queue(ORDER_IMPORT_DEAD_LETTER_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产单导入死信队列、交换机、绑定声明
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Binding deadLetterBindingA() {
|
|
||||||
return BindingBuilder.bind(orderImportDeadLetterQueue()).to(orderImportDeadLetterExchange()).with(ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广告状态修改 延迟队列
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Queue advertisementUpdateDelayedQueue(){
|
|
||||||
return QueueBuilder.durable(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广告状态修改 定义延迟交换机
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public CustomExchange advertisementUpdateDelayExchange() {
|
|
||||||
Map<String, Object> args = new HashMap<>();
|
|
||||||
args.put("x-delayed-type", "direct");
|
|
||||||
return new CustomExchange(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广告状态修改 队列与交换机绑定
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Binding advertisementUpdateQueueABindingX(@Qualifier("advertisementUpdateDelayedQueue") Queue queue,
|
|
||||||
@Qualifier("advertisementUpdateDelayExchange") CustomExchange delayedExchange){
|
|
||||||
return BindingBuilder.bind(queue)
|
|
||||||
.to(delayedExchange)
|
|
||||||
.with(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY)
|
|
||||||
.noargs();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -27,6 +27,17 @@ public class RabbitMqConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String ORDER_IMPORT_DEFAULT_XML_QUEUE = "order_import_default_xml_queue";
|
public static final String ORDER_IMPORT_DEFAULT_XML_QUEUE = "order_import_default_xml_queue";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webcad拆单交换机
|
||||||
|
*/
|
||||||
|
public static final String ORDER_IMPORT_WEBCAD_EXCHANGE = "order_import_webcad_exchange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webcad拆单队列
|
||||||
|
*/
|
||||||
|
public static final String ORDER_IMPORT_WEBCAD_QUEUE = "order_import_webcad_queue_%s";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生产单导入死信交换机
|
* 生产单导入死信交换机
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
@@ -29,6 +29,8 @@ public class WebFrameworkUtils {
|
|||||||
|
|
||||||
public static final String HEADER_ORGAN_ID = "organ-id";
|
public static final String HEADER_ORGAN_ID = "organ-id";
|
||||||
|
|
||||||
|
public static final String HEADER_PEEK = "peek";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终端的 Header
|
* 终端的 Header
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -119,7 +119,7 @@ public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandl
|
|||||||
// 创建导入任务
|
// 创建导入任务
|
||||||
OrderImportTaskDO orderImportTaskDO = OrderImportTaskDO.builder()
|
OrderImportTaskDO orderImportTaskDO = OrderImportTaskDO.builder()
|
||||||
.id((Long) snowFlakeGenerator.nextId(null))
|
.id((Long) snowFlakeGenerator.nextId(null))
|
||||||
.type(OrderImportTypeEnum.EXCEL.getType())
|
.type(OrderImportTypeEnum.XML.getType())
|
||||||
.importStatus(OrderImportStatusEnum.IMPORT_NOT_YET.getStatus())
|
.importStatus(OrderImportStatusEnum.IMPORT_NOT_YET.getStatus())
|
||||||
.status(OrderImportTaskStatusEnum.CREATE_NOT_CONSUME.getStatus())
|
.status(OrderImportTaskStatusEnum.CREATE_NOT_CONSUME.getStatus())
|
||||||
.fileName(fileName)
|
.fileName(fileName)
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ public class ErrorCodeConstants {
|
|||||||
public static final ErrorCode WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR = new ErrorCode(1_005_000_008, "导入失败:数据保存异常,请检查拆单数据");
|
public static final ErrorCode WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR = new ErrorCode(1_005_000_008, "导入失败:数据保存异常,请检查拆单数据");
|
||||||
public static final ErrorCode WEBCAD_ORDER_IMPORT_GET_ORG_SEALEDGE_ERROR = new ErrorCode(1_005_000_009, "导入失败:获取组织封边对应配置异常,请检查服务");
|
public static final ErrorCode WEBCAD_ORDER_IMPORT_GET_ORG_SEALEDGE_ERROR = new ErrorCode(1_005_000_009, "导入失败:获取组织封边对应配置异常,请检查服务");
|
||||||
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORG_SEALEDGE_ANALYZE_ERROR = new ErrorCode(1_005_000_010, "导入失败:组织封边对应配置解析异常,请检查配置");
|
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORG_SEALEDGE_ANALYZE_ERROR = new ErrorCode(1_005_000_010, "导入失败:组织封边对应配置解析异常,请检查配置");
|
||||||
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR = new ErrorCode(1_005_000_011, "导入失败:生产单【{}】下板件数量已达到20000片,无法继续导入");
|
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR = new ErrorCode(1_005_000_011, "导入失败:生产单【{}】下板件数量已达到{}片,无法继续导入");
|
||||||
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR = new ErrorCode(1_005_000_012, "部分导入成功,生产单【{}】下板件数量已达到20000片,本次拆单超出部分不计入生产单");
|
public static final ErrorCode WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR = new ErrorCode(1_005_000_012, "部分导入成功,生产单【{}】下板件数量已达到{}片,本次拆单超出部分不计入生产单");
|
||||||
public static final ErrorCode ORDER_IMPORT_PLATE_GOODS_NOMATCH_ERROR = new ErrorCode(1_005_000_013, "导入失败,板材库中无板材匹配,商品编码:{},商品名称:{},材质:{},颜色:{},厚度:{},品牌:{}");
|
public static final ErrorCode ORDER_IMPORT_PLATE_GOODS_NOMATCH_ERROR = new ErrorCode(1_005_000_013, "导入失败,板材库中无板材匹配,商品编码:{},商品名称:{},材质:{},颜色:{},厚度:{},品牌:{}");
|
||||||
}
|
}
|
||||||
|
|||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
package com.cf.imes.module.plan.config;
|
||||||
|
|
||||||
|
import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants;
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.DirectExchange;
|
||||||
|
import org.springframework.amqp.core.FanoutExchange;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.amqp.core.QueueBuilder;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_EXCHANGE;
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_QUEUE;
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY;
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_WEBCAD_QUEUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/5/12 12:00
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class ChenfengRabbitMQPlanConfiguration {
|
||||||
|
@Value("${chenfeng.plan.webcad.import.node:1}")
|
||||||
|
private String instanceId;
|
||||||
|
|
||||||
|
private static final String X_DEAD_LETTER_EXCHANGE_KEY = "x-dead-letter-exchange";
|
||||||
|
private static final String X_DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webcad拆单导入交换机、队列、绑定声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DirectExchange orderImportWebCadFanoutExchange() {
|
||||||
|
return new DirectExchange(RabbitMqConstants.ORDER_IMPORT_WEBCAD_EXCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("orderImportWebCadQueueName")
|
||||||
|
public String dynamicOrderImportWebCadQueueName() {
|
||||||
|
return String.format(ORDER_IMPORT_WEBCAD_QUEUE, instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webcad拆单导入队列声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue orderImportWebCadQueue() {
|
||||||
|
Map<String, Object> args = new HashMap<>(1);
|
||||||
|
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
|
||||||
|
args.put(X_DEAD_LETTER_EXCHANGE_KEY, ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
||||||
|
// 设置死信路由键
|
||||||
|
args.put(X_DEAD_LETTER_ROUTING_KEY, ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
||||||
|
return QueueBuilder.durable(dynamicOrderImportWebCadQueueName()).withArguments(args).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单xml导入交换机声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding orderImportWebCadBinding() {
|
||||||
|
return BindingBuilder.bind(orderImportWebCadQueue()).to(orderImportWebCadFanoutExchange()).with(instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单excel导入交换机、队列、绑定声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FanoutExchange orderImportDefaultExcelFanoutExchange() {
|
||||||
|
return new FanoutExchange(RabbitMqConstants.ORDER_IMPORT_DEFAULT_EXCEL_EXCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单excel导入队列声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue orderImportDefaultExcelQueue() {
|
||||||
|
Map<String, Object> args = new HashMap<>(1);
|
||||||
|
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
|
||||||
|
args.put(X_DEAD_LETTER_EXCHANGE_KEY, ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
||||||
|
// 设置死信路由键
|
||||||
|
args.put(X_DEAD_LETTER_ROUTING_KEY, ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
||||||
|
return QueueBuilder.durable(RabbitMqConstants.ORDER_IMPORT_DEFAULT_EXCEL_QUEUE).withArguments(args).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单excel导入交换机声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding orderImportDefaultExcelBinding() {
|
||||||
|
return BindingBuilder.bind(orderImportDefaultExcelQueue()).to(orderImportDefaultExcelFanoutExchange());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单xml导入交换机、队列、绑定声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FanoutExchange orderImportDefaultXmlFanoutExchange() {
|
||||||
|
return new FanoutExchange(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_EXCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单xml导入队列声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue orderImportDefaultXmlQueue() {
|
||||||
|
Map<String, Object> args = new HashMap<>(1);
|
||||||
|
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
|
||||||
|
args.put(X_DEAD_LETTER_EXCHANGE_KEY, ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
||||||
|
// 设置死信路由键
|
||||||
|
args.put(X_DEAD_LETTER_ROUTING_KEY, ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
||||||
|
return QueueBuilder.durable(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_QUEUE).withArguments(args).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单xml导入交换机声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding orderImportDefaultXmlBinding() {
|
||||||
|
return BindingBuilder.bind(orderImportDefaultXmlQueue()).to(orderImportDefaultXmlFanoutExchange());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单导入死信交换机声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DirectExchange orderImportDeadLetterExchange() {
|
||||||
|
return new DirectExchange(ORDER_IMPORT_DEAD_LETTER_EXCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单导入死信队列声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue orderImportDeadLetterQueue() {
|
||||||
|
return new Queue(ORDER_IMPORT_DEAD_LETTER_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产单导入死信队列、交换机、绑定声明
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding deadLetterBindingA() {
|
||||||
|
return BindingBuilder.bind(orderImportDeadLetterQueue()).to(orderImportDeadLetterExchange()).with(ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-5
@@ -2,19 +2,18 @@ package com.cf.imes.module.plan.controller.admin.orderImport;
|
|||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||||
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
|
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
|
||||||
import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataReqVO;
|
|
||||||
import com.cf.imes.module.plan.service.orderImport.WebCadOrderImportService;
|
import com.cf.imes.module.plan.service.orderImport.WebCadOrderImportService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.IMPORT;
|
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.IMPORT;
|
||||||
|
|
||||||
@@ -34,8 +33,8 @@ public class OrderImportController {
|
|||||||
@PostMapping("/webcad/import")
|
@PostMapping("/webcad/import")
|
||||||
@Operation(summary = "webcad拆单导入生产单")
|
@Operation(summary = "webcad拆单导入生产单")
|
||||||
@OperateLog(type = IMPORT)
|
@OperateLog(type = IMPORT)
|
||||||
public CommonResult<Boolean> webCadOrderImport(@RequestBody @Valid WebCadDataReqVO webCadDataReqVO) {
|
public CommonResult<Boolean> webCadOrderImport(@RequestParam("file") MultipartFile file) {
|
||||||
webCadOrderImportService.webCadOrderImport(webCadDataReqVO);
|
webCadOrderImportService.webCadOrderImport(file);
|
||||||
return CommonResult.success(true);
|
return CommonResult.success(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-329
@@ -63,58 +63,32 @@ public class WebCadDataBlockReqVO {
|
|||||||
private Double kaiLiaoWidth;
|
private Double kaiLiaoWidth;
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
private InfoDTO info;
|
// private InfoDTO info;
|
||||||
private String cabinetName;
|
private String cabinetName;
|
||||||
private String roomName;
|
private String roomName;
|
||||||
private Double cabinetDepth;
|
private Double cabinetDepth;
|
||||||
private Double cabinetWidth;
|
private Double cabinetWidth;
|
||||||
private Double cabinetHeight;
|
private Double cabinetHeight;
|
||||||
private BoadrData boardData;
|
|
||||||
private PointInfoDTO pointInfo;
|
private PointInfoDTO pointInfo;
|
||||||
|
|
||||||
private Long plateGoodsId;
|
private Double sealLeft;
|
||||||
private String goodsId;
|
private Double sealRight;
|
||||||
|
private Double sealUp;
|
||||||
private List<Integer> groupIds = new ArrayList<>();
|
private Double sealDown;
|
||||||
|
private Boolean isRect;
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class GroupInfo {
|
|
||||||
private String groupTypeName;
|
|
||||||
private String groupName;
|
|
||||||
private Double width;
|
|
||||||
private Double height;
|
|
||||||
private Double depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class InfoDTO {
|
|
||||||
private Integer id;
|
|
||||||
private String name;
|
|
||||||
private String roomName;
|
|
||||||
private String cabinetName;
|
|
||||||
private String material;
|
|
||||||
private String boardName;
|
|
||||||
private String color;
|
|
||||||
private Integer lines;
|
|
||||||
private String drillType;
|
|
||||||
private Integer thickness;
|
|
||||||
private String spliteHeight;
|
private String spliteHeight;
|
||||||
private String spliteThickness;
|
private String spliteThickness;
|
||||||
private String spliteWidth;
|
private String spliteWidth;
|
||||||
private Boolean isRect;
|
private boolean has2DModel;
|
||||||
private List<List<String>> remarks;
|
private boolean has3DModel;
|
||||||
|
private String boardTypeName;
|
||||||
|
|
||||||
@Max(value = 99999, message = "板件开料宽度不能超过99999")
|
private List<List<String>> allRemarkList;
|
||||||
@Min(value = 0, message = "板件开料宽度最小值为0")
|
|
||||||
private Double kaiLiaoWidth;
|
|
||||||
|
|
||||||
@Max(value = 99999, message = "板件开料高度不能超过99999")
|
// private Long plateGoodsId;
|
||||||
@Min(value = 0, message = "板件开料高度最小值为0")
|
private String goodsCode;
|
||||||
private Double kaiLiaoHeight;
|
|
||||||
private Integer openDir;
|
private List<Integer> groupIds = new ArrayList<>();
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
@@ -166,295 +140,6 @@ public class WebCadDataBlockReqVO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class BoadrData {
|
|
||||||
@JsonProperty("originOutlin")
|
|
||||||
private OriginOutlinDTO originOutlin;
|
|
||||||
@JsonProperty("outline")
|
|
||||||
private OutlineDTO outline;
|
|
||||||
@JsonProperty("sealing")
|
|
||||||
private List<SealingDTO> sealing;
|
|
||||||
@JsonProperty("boardEdgeRemark")
|
|
||||||
private List<BoardEdgeRemarkDTO> boardEdgeRemark;
|
|
||||||
@JsonProperty("reservedEdge")
|
|
||||||
private List<ReservedEdgeDTO> reservedEdge;
|
|
||||||
@JsonProperty("modeling")
|
|
||||||
private List<ModelingDTO> modeling;
|
|
||||||
@JsonProperty("curveBoardModeling")
|
|
||||||
private List<?> curveBoardModeling;
|
|
||||||
@JsonProperty("holes")
|
|
||||||
private HolesDTO holes;
|
|
||||||
@JsonProperty("sideModeling")
|
|
||||||
private List<SideModelingDTO> sideModeling;
|
|
||||||
@JsonProperty("offsetTanslation")
|
|
||||||
private OffsetTanslationDTO offsetTanslation;
|
|
||||||
@JsonProperty("metalsData")
|
|
||||||
private MetalsDataDTO metalsData;
|
|
||||||
@JsonProperty("modeling2D")
|
|
||||||
private List<Modeling2DDTO> modeling2D;
|
|
||||||
@JsonProperty("modeling3D")
|
|
||||||
private List<?> modeling3D;
|
|
||||||
@JsonProperty("isReverse")
|
|
||||||
private Boolean isReverse;
|
|
||||||
|
|
||||||
private Object info;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OriginOutlinDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Integer y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OutlineDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Integer y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class HolesDTO {
|
|
||||||
@JsonProperty("frontBackHoles")
|
|
||||||
private List<?> frontBackHoles;
|
|
||||||
@JsonProperty("sideHoles")
|
|
||||||
private List<?> sideHoles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OffsetTanslationDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
@JsonProperty("z")
|
|
||||||
private Integer z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class MetalsDataDTO {
|
|
||||||
@JsonProperty("metals")
|
|
||||||
private Integer metals;
|
|
||||||
@JsonProperty("comp")
|
|
||||||
private Integer comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class SealingDTO {
|
|
||||||
@JsonProperty("length")
|
|
||||||
private Double length;
|
|
||||||
@JsonProperty("size")
|
|
||||||
private Integer size;
|
|
||||||
@JsonProperty("sealColor")
|
|
||||||
private String sealColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class BoardEdgeRemarkDTO {
|
|
||||||
@JsonProperty("description")
|
|
||||||
private String description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class ReservedEdgeDTO {
|
|
||||||
@JsonProperty("size")
|
|
||||||
private Integer size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class ModelingDTO {
|
|
||||||
@JsonProperty("feeding")
|
|
||||||
private List<FeedingDTO> feeding;
|
|
||||||
@JsonProperty("thickness")
|
|
||||||
private Integer thickness;
|
|
||||||
@JsonProperty("dir")
|
|
||||||
private Integer dir;
|
|
||||||
@JsonProperty("knifeRadius")
|
|
||||||
private Integer knifeRadius;
|
|
||||||
@JsonProperty("origin")
|
|
||||||
private OriginDTO origin;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OriginDTO {
|
|
||||||
@JsonProperty("outline")
|
|
||||||
private OutlineDTO outline;
|
|
||||||
@JsonProperty("holes")
|
|
||||||
private List<?> holes;
|
|
||||||
@JsonProperty("addLen")
|
|
||||||
private Integer addLen;
|
|
||||||
@JsonProperty("addWidth")
|
|
||||||
private Integer addWidth;
|
|
||||||
@JsonProperty("addDepth")
|
|
||||||
private Integer addDepth;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OutlineDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class FeedingDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class SideModelingDTO {
|
|
||||||
@JsonProperty("thickness")
|
|
||||||
private Integer thickness;
|
|
||||||
@JsonProperty("dir")
|
|
||||||
private Integer dir;
|
|
||||||
@JsonProperty("knifeRadius")
|
|
||||||
private Integer knifeRadius;
|
|
||||||
@JsonProperty("outline")
|
|
||||||
private OutlineDTO outline;
|
|
||||||
@JsonProperty("holes")
|
|
||||||
private List<?> holes;
|
|
||||||
@JsonProperty("addLen")
|
|
||||||
private Integer addLen;
|
|
||||||
@JsonProperty("addWidth")
|
|
||||||
private Integer addWidth;
|
|
||||||
@JsonProperty("addDepth")
|
|
||||||
private Integer addDepth;
|
|
||||||
@JsonProperty("chaiDanName")
|
|
||||||
private String chaiDanName;
|
|
||||||
@JsonProperty("modelType")
|
|
||||||
private Integer modelType;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class OutlineDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class Modeling2DDTO {
|
|
||||||
@JsonProperty("path")
|
|
||||||
private PathDTO path;
|
|
||||||
@JsonProperty("dir")
|
|
||||||
private Integer dir;
|
|
||||||
@JsonProperty("items")
|
|
||||||
private List<ItemsDTO> items;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PathDTO {
|
|
||||||
@JsonProperty("pts")
|
|
||||||
private List<PtsDTO> pts;
|
|
||||||
@JsonProperty("buls")
|
|
||||||
private List<Integer> buls;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class PtsDTO {
|
|
||||||
@JsonProperty("x")
|
|
||||||
private Double x;
|
|
||||||
@JsonProperty("y")
|
|
||||||
private Double y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class ItemsDTO {
|
|
||||||
@JsonProperty("depth")
|
|
||||||
private Integer depth;
|
|
||||||
@JsonProperty("offset")
|
|
||||||
private Integer offset;
|
|
||||||
@JsonProperty("knife")
|
|
||||||
private KnifeDTO knife;
|
|
||||||
@JsonProperty("depthExpr")
|
|
||||||
private String depthExpr;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class KnifeDTO {
|
|
||||||
@JsonProperty("id")
|
|
||||||
private String id;
|
|
||||||
@JsonProperty("radius")
|
|
||||||
private Integer radius;
|
|
||||||
@JsonProperty("angle")
|
|
||||||
private Double angle;
|
|
||||||
@JsonProperty("name")
|
|
||||||
private String name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
+5
@@ -7,6 +7,7 @@ import javax.validation.Valid;
|
|||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,5 +36,9 @@ public class WebCadDataDoubleRoomTreeReqVO {
|
|||||||
@Max(value = 5000, message = "拆单倍数不能超过5000")
|
@Max(value = 5000, message = "拆单倍数不能超过5000")
|
||||||
@Min(value = 1, message = "拆单倍数最小值为1")
|
@Min(value = 1, message = "拆单倍数最小值为1")
|
||||||
private Integer count;
|
private Integer count;
|
||||||
|
|
||||||
|
private List<WebCadDataBlockReqVO> blockList;
|
||||||
|
|
||||||
|
private List<WebCadDataPartsReqVO.BlockObjectListDTO> objList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/5/6 15:27
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class WebCadDataGroupInfoReqVO {
|
||||||
|
private String groupTypeName;
|
||||||
|
private String groupName;
|
||||||
|
private Double width;
|
||||||
|
private Double height;
|
||||||
|
private Double depth;
|
||||||
|
}
|
||||||
+13
-1
@@ -13,7 +13,11 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class WebCadDataMaterialReqVO {
|
public class WebCadDataMaterialReqVO {
|
||||||
|
|
||||||
private Integer thickness;
|
private Double height;
|
||||||
|
|
||||||
|
private Double width;
|
||||||
|
|
||||||
|
private Double thickness;
|
||||||
|
|
||||||
private String material;
|
private String material;
|
||||||
|
|
||||||
@@ -27,6 +31,14 @@ public class WebCadDataMaterialReqVO {
|
|||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
private boolean texture;
|
||||||
|
|
||||||
|
public boolean getTexture() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String spec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* imes板材id
|
* imes板材id
|
||||||
*/
|
*/
|
||||||
|
|||||||
-45
@@ -22,8 +22,6 @@ public class WebCadDataPartsReqVO {
|
|||||||
|
|
||||||
private List<BlockObjectListDTO> blockObjectList;
|
private List<BlockObjectListDTO> blockObjectList;
|
||||||
|
|
||||||
private List<LeftEdgesDTO> leftEdges;
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
public static class BlockObjectListDTO {
|
public static class BlockObjectListDTO {
|
||||||
@@ -74,16 +72,6 @@ public class WebCadDataPartsReqVO {
|
|||||||
|
|
||||||
private GroupDataDTO groupData;
|
private GroupDataDTO groupData;
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class GroupInfo {
|
|
||||||
private String groupTypeName;
|
|
||||||
private String groupName;
|
|
||||||
private Double width;
|
|
||||||
private Double height;
|
|
||||||
private Double depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
public static class GroupDataDTO {
|
public static class GroupDataDTO {
|
||||||
@@ -99,37 +87,4 @@ public class WebCadDataPartsReqVO {
|
|||||||
private String color;
|
private String color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
public static class LeftEdgesDTO {
|
|
||||||
@JsonProperty("thickness")
|
|
||||||
private Double thickness;
|
|
||||||
@JsonProperty("width")
|
|
||||||
private Double width;
|
|
||||||
@JsonProperty("height")
|
|
||||||
private Double height;
|
|
||||||
@JsonProperty("color")
|
|
||||||
private String color;
|
|
||||||
@JsonProperty("material")
|
|
||||||
private String material;
|
|
||||||
@JsonProperty("name")
|
|
||||||
private String name;
|
|
||||||
@JsonProperty("goodsId")
|
|
||||||
private String goodsId;
|
|
||||||
@JsonProperty("id")
|
|
||||||
private String id;
|
|
||||||
@JsonProperty("objectIds")
|
|
||||||
private List<Integer> objectIds;
|
|
||||||
@JsonProperty("cabinetNames")
|
|
||||||
private List<String> cabinetNames;
|
|
||||||
@JsonProperty("roomNames")
|
|
||||||
private List<String> roomNames;
|
|
||||||
@JsonProperty("roomName")
|
|
||||||
private String roomName;
|
|
||||||
@JsonProperty("cabinetName")
|
|
||||||
private String cabinetName;
|
|
||||||
@JsonProperty("num")
|
|
||||||
private Double num;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -5,7 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.Size;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,20 +15,14 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class WebCadDataReqVO {
|
public class WebCadDataReqVO {
|
||||||
|
|
||||||
@JsonProperty(value = "Orders")
|
@JsonProperty(value = "OrderNo")
|
||||||
@Valid
|
private String orderNo;
|
||||||
private WebCadDataOrderReqVO orders;
|
|
||||||
|
|
||||||
@JsonProperty(value = "Materials")
|
@JsonProperty(value = "Materials")
|
||||||
private List<WebCadDataMaterialReqVO> Materials;
|
private List<WebCadDataMaterialReqVO> Materials;
|
||||||
|
|
||||||
@JsonProperty(value = "Blocks")
|
|
||||||
@Size(max = 20000, message = "拆单板件片数单次不能超过2万片")
|
|
||||||
@Valid
|
|
||||||
private List<WebCadDataBlockReqVO> Blocks;
|
|
||||||
|
|
||||||
@JsonProperty(value = "Parts")
|
@JsonProperty(value = "Parts")
|
||||||
private WebCadDataPartsReqVO Parts;
|
private List<WebCadDataDoubleRoomTreeReqVO> Parts;
|
||||||
|
|
||||||
@JsonProperty(value = "ProcessGroup")
|
@JsonProperty(value = "ProcessGroup")
|
||||||
@Valid
|
@Valid
|
||||||
@@ -37,4 +30,7 @@ public class WebCadDataReqVO {
|
|||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
private List<WebCadDataDoubleRoomTreeReqVO> douleRoomTree;
|
private List<WebCadDataDoubleRoomTreeReqVO> douleRoomTree;
|
||||||
|
|
||||||
|
@JsonProperty(value = "Blocks")
|
||||||
|
private List<WebCadDataDoubleRoomTreeReqVO> blocks;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -64,4 +64,10 @@ public class OrderImportTaskDO extends BaseDO {
|
|||||||
* 导入结果0
|
* 导入结果0
|
||||||
*/
|
*/
|
||||||
private String result;
|
private String result;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入文件名称
|
||||||
|
*/
|
||||||
|
private String fileName;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -17,8 +17,8 @@ public class PlanThreadPoolConfiguration {
|
|||||||
@Bean(PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR)
|
@Bean(PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR)
|
||||||
public ThreadPoolTaskExecutor planThreadPoolTaskExecutor() {
|
public ThreadPoolTaskExecutor planThreadPoolTaskExecutor() {
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
executor.setCorePoolSize(8); // 设置核心线程数
|
executor.setCorePoolSize(3); // 设置核心线程数
|
||||||
executor.setMaxPoolSize(16); // 设置最大线程数
|
executor.setMaxPoolSize(6); // 设置最大线程数
|
||||||
executor.setKeepAliveSeconds(60); // 设置空闲时间
|
executor.setKeepAliveSeconds(60); // 设置空闲时间
|
||||||
executor.setQueueCapacity(100); // 设置队列大小
|
executor.setQueueCapacity(100); // 设置队列大小
|
||||||
executor.setThreadNamePrefix("plan-import-Executor-"); // 配置线程池的前缀
|
executor.setThreadNamePrefix("plan-import-Executor-"); // 配置线程池的前缀
|
||||||
|
|||||||
+37
-1
@@ -3,6 +3,7 @@ package com.cf.imes.module.plan.service.order;
|
|||||||
import cn.hutool.core.lang.Snowflake;
|
import cn.hutool.core.lang.Snowflake;
|
||||||
import cn.hutool.core.text.CharSequenceUtil;
|
import cn.hutool.core.text.CharSequenceUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
|
||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
||||||
import co.elastic.clients.elasticsearch.core.BulkRequest;
|
import co.elastic.clients.elasticsearch.core.BulkRequest;
|
||||||
@@ -35,6 +36,9 @@ public class OrderInputProcessor {
|
|||||||
@Resource
|
@Resource
|
||||||
private ElasticsearchClient elasticsearchClient;
|
private ElasticsearchClient elasticsearchClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ElasticsearchAsyncClient elasticsearchAsyncClient;
|
||||||
|
|
||||||
private Snowflake snowflake = IdUtil.getSnowflake();
|
private Snowflake snowflake = IdUtil.getSnowflake();
|
||||||
|
|
||||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
@@ -61,7 +65,21 @@ public class OrderInputProcessor {
|
|||||||
throw new ServiceException(500, "未知异常");
|
throw new ServiceException(500, "未知异常");
|
||||||
}
|
}
|
||||||
} catch (IOException | ElasticsearchException e) {
|
} catch (IOException | ElasticsearchException e) {
|
||||||
e.printStackTrace();
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步保存生产单造型数据
|
||||||
|
*
|
||||||
|
* @param orderModelDOs
|
||||||
|
*/
|
||||||
|
public void batchAsyncSaveModel(List<OrderModelDO> orderModelDOs) {
|
||||||
|
try {
|
||||||
|
bulkAsyncCreate(ORDER_PLATE_MODEL, orderModelDOs);
|
||||||
|
} catch (IOException | ElasticsearchException e) {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -160,4 +178,22 @@ public class OrderInputProcessor {
|
|||||||
});
|
});
|
||||||
return elasticsearchClient.bulk(br.build());
|
return elasticsearchClient.bulk(br.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bulkAsyncCreate(String idxName, List<? extends ESDocument> documents) throws IOException, ElasticsearchException {
|
||||||
|
BulkRequest.Builder br = new BulkRequest.Builder();
|
||||||
|
Date date = new Date();
|
||||||
|
documents.forEach(esDocument -> {
|
||||||
|
if (CharSequenceUtil.isBlank(esDocument.getId())) {
|
||||||
|
esDocument.setId(snowflake.nextIdStr());
|
||||||
|
}
|
||||||
|
esDocument.setCreateTime(simpleDateFormat.format(date));
|
||||||
|
|
||||||
|
esDocument.setUpdateTime(simpleDateFormat.format(date));
|
||||||
|
br.operations(op -> op.index(idx -> idx
|
||||||
|
.index(idxName)
|
||||||
|
.id(esDocument.getId())
|
||||||
|
.document(esDocument)));
|
||||||
|
});
|
||||||
|
elasticsearchAsyncClient.bulk(br.build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.cf.imes.module.plan.service.orderImport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/5/13 16:41
|
||||||
|
*/
|
||||||
|
public interface OrderImportTaskService {
|
||||||
|
/**
|
||||||
|
* 更新业务异常状态
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
* @param organId
|
||||||
|
* @param serviceExceptionMessage
|
||||||
|
*/
|
||||||
|
void updateServiceExceptionTaskStatus(Long taskId, Long organId, String serviceExceptionMessage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新异常状态
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
* @param organId
|
||||||
|
*/
|
||||||
|
void updateExceptionTaskStatus(Long taskId, Long organId);
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
package com.cf.imes.module.plan.service.orderImport;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
|
||||||
|
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTaskMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_FAIL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/5/13 16:41
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class OrderImportTaskServiceImpl implements OrderImportTaskService {
|
||||||
|
@Resource
|
||||||
|
private OrderImportTaskMapper orderImportTaskMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||||
|
public void updateServiceExceptionTaskStatus(Long taskId, Long organId, String serviceExceptionMessage) {
|
||||||
|
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId)
|
||||||
|
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getOrganId, organId)
|
||||||
|
.set(OrderImportTaskDO::getResult, serviceExceptionMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||||
|
public void updateExceptionTaskStatus(Long taskId, Long organId) {
|
||||||
|
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId)
|
||||||
|
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getOrganId, organId)
|
||||||
|
.set(OrderImportTaskDO::getResult, ORDER_IMPORT_FAIL.getMsg()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
package com.cf.imes.module.plan.service.orderImport;
|
package com.cf.imes.module.plan.service.orderImport;
|
||||||
|
|
||||||
import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataReqVO;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生产单导入服务Service
|
* 生产单导入服务Service
|
||||||
@@ -13,7 +13,7 @@ public interface WebCadOrderImportService {
|
|||||||
/**
|
/**
|
||||||
* webcad生产单导入
|
* webcad生产单导入
|
||||||
*
|
*
|
||||||
* @param webCadDataReqVO
|
* @param file
|
||||||
*/
|
*/
|
||||||
void webCadOrderImport(WebCadDataReqVO webCadDataReqVO);
|
void webCadOrderImport(MultipartFile file);
|
||||||
}
|
}
|
||||||
|
|||||||
+214
-33
@@ -1,42 +1,63 @@
|
|||||||
package com.cf.imes.module.plan.service.orderImport;
|
package com.cf.imes.module.plan.service.orderImport;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||||
import com.cf.imes.framework.common.exception.ErrorCode;
|
import com.cf.imes.framework.common.exception.ErrorCode;
|
||||||
import com.cf.imes.framework.common.exception.ServiceException;
|
import com.cf.imes.framework.common.exception.ServiceException;
|
||||||
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
|
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
|
||||||
|
import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants;
|
||||||
import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
|
import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
|
||||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
import com.cf.imes.framework.redis.config.ChenfengCacheProperties;
|
import com.cf.imes.framework.redis.config.ChenfengCacheProperties;
|
||||||
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
|
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
|
||||||
import com.cf.imes.framework.redis.util.RedisLockUtil;
|
import com.cf.imes.framework.redis.util.RedisLockUtil;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportTypeEnum;
|
||||||
import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataReqVO;
|
import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataReqVO;
|
||||||
|
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO;
|
||||||
import com.cf.imes.module.plan.dal.mysql.goods.GoodsMapper;
|
import com.cf.imes.module.plan.dal.mysql.goods.GoodsMapper;
|
||||||
import com.cf.imes.module.plan.dal.mysql.order.OrderMapper;
|
import com.cf.imes.module.plan.dal.mysql.order.OrderMapper;
|
||||||
import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper;
|
import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper;
|
||||||
import com.cf.imes.module.plan.dal.mysql.orderGroup.OrderGroupMapper;
|
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTaskMapper;
|
||||||
import com.cf.imes.module.plan.dal.mysql.orderItem.OrderItemMapper;
|
|
||||||
import com.cf.imes.module.plan.dal.mysql.orderParts.OrderPartsMapper;
|
|
||||||
import com.cf.imes.module.plan.dal.mysql.plate.PlateGoodMapper;
|
|
||||||
import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper;
|
import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper;
|
||||||
import com.cf.imes.module.plan.dal.mysql.rawgoods.RawGoodsMapper;
|
import com.cf.imes.module.plan.dal.mysql.rawgoods.RawGoodsMapper;
|
||||||
import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService;
|
import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService;
|
||||||
import com.cf.imes.module.plan.service.order.OrderInputProcessor;
|
import com.cf.imes.module.plan.service.order.OrderInputProcessor;
|
||||||
import com.cf.imes.module.plan.service.orderImport.factory.WebCadOrderImportFactory;
|
import com.cf.imes.module.plan.service.orderImport.factory.WebCadOrderImportFactory;
|
||||||
import com.cf.imes.module.system.api.systemconfig.SystemConfigApi;
|
import com.cf.imes.module.system.api.systemconfig.SystemConfigApi;
|
||||||
|
import com.fasterxml.jackson.core.JsonFactory;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonToken;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.core.MessageBuilder;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORGAN_LOCK_ERROR;
|
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORGAN_LOCK_ERROR;
|
||||||
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_FAILED;
|
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_FAILED;
|
||||||
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR;
|
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR;
|
||||||
import static com.cf.imes.module.plan.framework.executor.config.PlanThreadPoolConfiguration.PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生产单导入服务Service实现类
|
* 生产单导入服务Service实现类
|
||||||
@@ -60,21 +81,12 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PlateMapper plateMapper;
|
private PlateMapper plateMapper;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private OrderItemMapper orderItemMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private OrderGroupMapper orderGroupMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SnowflakeIdWorker3rd idWorker;
|
private SnowflakeIdWorker3rd idWorker;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private OrderInputProcessor orderInputProcessor;
|
private OrderInputProcessor orderInputProcessor;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private OrderPartsMapper orderPartsMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CustomPlateNoGenerateService customPlateNoGenerateService;
|
private CustomPlateNoGenerateService customPlateNoGenerateService;
|
||||||
|
|
||||||
@@ -90,50 +102,219 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService {
|
|||||||
@Resource
|
@Resource
|
||||||
private RawGoodsMapper rawGoodsMapper;
|
private RawGoodsMapper rawGoodsMapper;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private PlateGoodMapper plateGoodMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DataSourceTransactionManager transactionManager;
|
private DataSourceTransactionManager transactionManager;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SystemConfigApi systemConfigApi;
|
private SystemConfigApi systemConfigApi;
|
||||||
|
|
||||||
@Resource(name = PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR)
|
@Value("${chenfeng.plan.webcad.import.cadImportPlateNumThreshold:10000}")
|
||||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
|
||||||
|
|
||||||
@Value("${chenfeng.plan.impot.cadImportPlateNumThreshold:20000}")
|
|
||||||
private int cadImportPlateNumThreshold;
|
private int cadImportPlateNumThreshold;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private JdbcTemplate jdbcTemplate;
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderImportTaskMapper orderImportTaskMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cad拆单请求缓存地址
|
||||||
|
*/
|
||||||
|
@Value("${chenfeng.plan.webcad.import.temp-file-path}")
|
||||||
|
private String webcadJsonCachePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cad拆单是否使用异步方式的板件阈值
|
||||||
|
*/
|
||||||
|
@Value("${chenfeng.plan.webcad.import.async-plate-threshold:5000}")
|
||||||
|
private int webcadAsyncPlateThreshold;
|
||||||
|
|
||||||
|
@Value("${chenfeng.plan.webcad.import.node:1}")
|
||||||
|
private String instanceId;
|
||||||
|
|
||||||
|
private static final String REDIS_UNIQUEKEY = "webcad";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void webCadOrderImport(WebCadDataReqVO webCadDataReqVO) {
|
public void webCadOrderImport(MultipartFile file) {
|
||||||
Long organId = OrganContextHolder.getOrganId();
|
Long organId = OrganContextHolder.getOrganId();
|
||||||
String redisUniqueKey = "webcad";
|
|
||||||
if (ObjectUtil.isNull(organId)) {
|
if (ObjectUtil.isNull(organId)) {
|
||||||
throw new ServiceException(WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR);
|
throw new ServiceException(WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR);
|
||||||
}
|
}
|
||||||
try {
|
// 上锁
|
||||||
String importLockKey = String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId);
|
addLock(organId);
|
||||||
// 检查机构导入锁
|
|
||||||
boolean lockResult = redisLockUtil.lock(importLockKey, redisUniqueKey, chenfengCacheProperties.getLockTimeout());
|
TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults());
|
||||||
if (!lockResult) {
|
// 是否同步处理
|
||||||
throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR);
|
boolean sync = true;
|
||||||
|
Long taskId = null;
|
||||||
|
JsonFactory factory = new JsonFactory();
|
||||||
|
try (GZIPInputStream gzipInputStream = new GZIPInputStream(file.getInputStream());
|
||||||
|
JsonParser parser = factory.createParser(gzipInputStream)) {
|
||||||
|
factory.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
|
||||||
|
|
||||||
|
int plateCount = 0;
|
||||||
|
String fileName = null;
|
||||||
|
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||||
|
String fieldName = parser.getCurrentName();
|
||||||
|
if (StringUtils.isEmpty(fieldName)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
WebCadOrderImportFactory webCadOrderImportFactory = new WebCadOrderImportFactory(organId, orderMapper, snowFlakeGenerator, orderBodyMapper, plateMapper, orderItemMapper, orderGroupMapper,
|
|
||||||
idWorker, orderInputProcessor, orderPartsMapper, goodsMapper, rawGoodsMapper, plateGoodMapper, customPlateNoGenerateService, transactionManager, systemConfigApi, threadPoolTaskExecutor, cadImportPlateNumThreshold, jdbcTemplate);
|
parser.nextToken(); // 移动到字段值位置
|
||||||
|
|
||||||
|
if ("plateCount".equals(fieldName)) {
|
||||||
|
plateCount = parser.getIntValue();
|
||||||
|
} else if ("fileName".equals(fieldName)) {
|
||||||
|
fileName = parser.getText();
|
||||||
|
} else if ("blockData".equals(fieldName)) {
|
||||||
|
if (plateCount < webcadAsyncPlateThreshold) {
|
||||||
|
|
||||||
|
// 在异步阈值范围内,直接解析整个对象
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
WebCadDataReqVO webCadDataReqVO = mapper.readValue(parser, WebCadDataReqVO.class);
|
||||||
|
WebCadOrderImportFactory webCadOrderImportFactory = new WebCadOrderImportFactory(organId, orderMapper, snowFlakeGenerator, orderBodyMapper, plateMapper,
|
||||||
|
idWorker, orderInputProcessor, goodsMapper, rawGoodsMapper, customPlateNoGenerateService, systemConfigApi, cadImportPlateNumThreshold, jdbcTemplate);
|
||||||
webCadOrderImportFactory.analyzeTempData(webCadDataReqVO);
|
webCadOrderImportFactory.analyzeTempData(webCadDataReqVO);
|
||||||
|
} else {
|
||||||
|
sync = false;
|
||||||
|
|
||||||
|
// plateCount 大于阈值时将 blockData 写入文件
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
|
||||||
|
// 读取结构
|
||||||
|
JsonNode node = mapper.readTree(parser);
|
||||||
|
|
||||||
|
// 缓存请求,创建导入任务
|
||||||
|
taskId = initiateTask(node, organId, fileName);
|
||||||
|
|
||||||
|
// 发送异步消息
|
||||||
|
sendMessage(taskId, organId);
|
||||||
|
|
||||||
|
// 跳过当前 blockData 解析步骤
|
||||||
|
parser.skipChildren(); // 忽略 blockData
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parser.skipChildren(); // 忽略其他字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 事务提交
|
||||||
|
transactionManager.commit(transactionStatus);
|
||||||
} catch (ServiceException se) {
|
} catch (ServiceException se) {
|
||||||
|
// 事务回滚
|
||||||
|
transactionManager.rollback(transactionStatus);
|
||||||
|
// 移除临时文件
|
||||||
|
removeCacheFileWhenException(sync, taskId);
|
||||||
|
|
||||||
throw se;
|
throw se;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// 事务回滚
|
||||||
|
transactionManager.rollback(transactionStatus);
|
||||||
|
// 移除临时文件
|
||||||
|
removeCacheFileWhenException(sync, taskId);
|
||||||
|
|
||||||
ErrorCode webcadOrderImportFailed = WEBCAD_ORDER_IMPORT_FAILED;
|
ErrorCode webcadOrderImportFailed = WEBCAD_ORDER_IMPORT_FAILED;
|
||||||
log.error(webcadOrderImportFailed.getMsg(), e);
|
log.error(webcadOrderImportFailed.getMsg(), e);
|
||||||
throw new ServiceException(webcadOrderImportFailed);
|
throw new ServiceException(webcadOrderImportFailed);
|
||||||
} finally {
|
} finally {
|
||||||
|
if (sync) {
|
||||||
// 导入锁解锁
|
// 导入锁解锁
|
||||||
redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), redisUniqueKey);
|
redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), REDIS_UNIQUEKEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存请求,发起异步
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
* @param organId
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private Long initiateTask(JsonNode node, Long organId, String fileName) throws IOException {
|
||||||
|
// 创建任务
|
||||||
|
Long taskId = createImportTask(organId, fileName);
|
||||||
|
// 缓存请求到本地磁盘
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
File file = new File(webcadJsonCachePath + File.separator + taskId + ".json");
|
||||||
|
objectMapper.writeValue(file, node);
|
||||||
|
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送异步消息
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
*/
|
||||||
|
private void sendMessage(Long taskId, Long organId) {
|
||||||
|
Message message = MessageBuilder
|
||||||
|
.withBody(taskId.toString().getBytes())
|
||||||
|
.setHeader("peek", DynamicDataSourceContextHolder.peek())
|
||||||
|
.setExpiration("60000") // 设置消息级 TTL(60 秒)
|
||||||
|
.build();
|
||||||
|
//如果处于事务中,待事务提交成功了再执行后续操作,防止事务未提交完成导致消费端查不到数据
|
||||||
|
if (TransactionSynchronizationManager.isActualTransactionActive()) {
|
||||||
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
|
@Override
|
||||||
|
public void afterCommit() {
|
||||||
|
// 数据库操作全部完成发送消息
|
||||||
|
rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_IMPORT_WEBCAD_EXCHANGE, instanceId, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 数据库操作全部完成发送消息
|
||||||
|
rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_IMPORT_WEBCAD_EXCHANGE, instanceId, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加导入锁
|
||||||
|
*
|
||||||
|
* @param organId
|
||||||
|
*/
|
||||||
|
private void addLock(Long organId) {
|
||||||
|
String importLockKey = String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId);
|
||||||
|
// 检查机构导入锁
|
||||||
|
boolean lockResult = redisLockUtil.lock(importLockKey, REDIS_UNIQUEKEY, chenfengCacheProperties.getLockTimeout());
|
||||||
|
if (!lockResult) {
|
||||||
|
throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常时移除临时文件
|
||||||
|
*/
|
||||||
|
private void removeCacheFileWhenException(boolean sync, Long taskId) {
|
||||||
|
if (!sync && ObjectUtil.isNotNull(taskId)) {
|
||||||
|
FileUtil.del(webcadJsonCachePath + File.separator + taskId + ".json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建导入任务
|
||||||
|
*
|
||||||
|
* @return taskId
|
||||||
|
*/
|
||||||
|
private Long createImportTask(Long organId, String fileName) {
|
||||||
|
Long taskId = (Long) snowFlakeGenerator.nextId(null);
|
||||||
|
// 创建导入任务
|
||||||
|
OrderImportTaskDO orderImportTaskDO = OrderImportTaskDO.builder()
|
||||||
|
.id(taskId)
|
||||||
|
.type(OrderImportTypeEnum.API.getType())
|
||||||
|
.importStatus(OrderImportStatusEnum.IMPORT_NOT_YET.getStatus())
|
||||||
|
.status(OrderImportTaskStatusEnum.CREATE_NOT_CONSUME.getStatus())
|
||||||
|
.fileName(fileName)
|
||||||
|
.organId(organId)
|
||||||
|
.build();
|
||||||
|
orderImportTaskMapper.insert(orderImportTaskDO);
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+9
-8
@@ -1,7 +1,6 @@
|
|||||||
package com.cf.imes.module.plan.service.orderImport.consumer;
|
package com.cf.imes.module.plan.service.orderImport.consumer;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
|
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
|
||||||
@@ -23,7 +22,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_QUEUE;
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_QUEUE;
|
||||||
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_FAIL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生产单导入死信队列消费
|
* 生产单导入死信队列消费
|
||||||
@@ -45,7 +43,6 @@ public class OrderImportDeadLetterConsumer {
|
|||||||
private static final String ERROR_REASON = "rejected";
|
private static final String ERROR_REASON = "rejected";
|
||||||
|
|
||||||
@RabbitListener(queues = ORDER_IMPORT_DEAD_LETTER_QUEUE)
|
@RabbitListener(queues = ORDER_IMPORT_DEAD_LETTER_QUEUE)
|
||||||
@DS("imes_prod")
|
|
||||||
public void receive(String message,
|
public void receive(String message,
|
||||||
Channel channel,
|
Channel channel,
|
||||||
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
|
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
|
||||||
@@ -54,24 +51,28 @@ public class OrderImportDeadLetterConsumer {
|
|||||||
// 手动确认消息
|
// 手动确认消息
|
||||||
channel.basicAck(deliveryTag, false);
|
channel.basicAck(deliveryTag, false);
|
||||||
|
|
||||||
|
Long organId = OrganContextHolder.getOrganId();
|
||||||
|
|
||||||
String deadLetterReason = getDeadLetterReason(xDeath);
|
String deadLetterReason = getDeadLetterReason(xDeath);
|
||||||
long taskId = Long.parseLong(message);
|
long taskId = Long.parseLong(message);
|
||||||
|
|
||||||
if(TTL_REASON.equals(deadLetterReason)) {
|
if(TTL_REASON.equals(deadLetterReason)) {
|
||||||
// 更新状态为消费超时
|
// 更新状态为消费超时
|
||||||
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId)
|
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>()
|
||||||
|
.eq(OrderImportTaskDO::getId, taskId)
|
||||||
|
.set(OrderImportTaskDO::getOrganId, organId)
|
||||||
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_FAIL.getStatus())
|
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_FAIL.getStatus())
|
||||||
);
|
);
|
||||||
} else if (ERROR_REASON.equals(deadLetterReason)) {
|
} else if (ERROR_REASON.equals(deadLetterReason)) {
|
||||||
// 更新状态为消费成功、导入失败
|
// 更新状态为消费成功、导入失败
|
||||||
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId)
|
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>()
|
||||||
|
.eq(OrderImportTaskDO::getId, taskId)
|
||||||
|
.set(OrderImportTaskDO::getOrganId, organId)
|
||||||
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
|
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
|
||||||
.set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())
|
.set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus()));
|
||||||
.set(OrderImportTaskDO::getResult, ORDER_IMPORT_FAIL.getMsg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入锁解锁
|
// 导入锁解锁
|
||||||
Long organId = OrganContextHolder.getOrganId();
|
|
||||||
if (ObjectUtil.isNotNull(organId)) {
|
if (ObjectUtil.isNotNull(organId)) {
|
||||||
redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message);
|
redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message);
|
||||||
}
|
}
|
||||||
|
|||||||
+216
@@ -0,0 +1,216 @@
|
|||||||
|
package com.cf.imes.module.plan.service.orderImport.consumer;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.cf.imes.framework.common.exception.ServiceException;
|
||||||
|
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||||
|
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
|
||||||
|
import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
|
||||||
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
|
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
|
||||||
|
import com.cf.imes.framework.redis.util.RedisLockUtil;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
|
||||||
|
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
|
||||||
|
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.goods.GoodsMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.order.OrderMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.orderGroup.OrderGroupMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTaskMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper;
|
||||||
|
import com.cf.imes.module.plan.dal.mysql.rawgoods.RawGoodsMapper;
|
||||||
|
import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService;
|
||||||
|
import com.cf.imes.module.plan.service.order.OrderInputProcessor;
|
||||||
|
import com.cf.imes.module.plan.service.orderImport.OrderImportTaskService;
|
||||||
|
import com.cf.imes.module.plan.service.orderImport.factory.WebCadOrderImportAsyncFactory;
|
||||||
|
import com.cf.imes.module.system.api.systemconfig.SystemConfigApi;
|
||||||
|
import com.rabbitmq.client.Channel;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.amqp.support.AmqpHeaders;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
|
import org.springframework.messaging.handler.annotation.Header;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_FAIL;
|
||||||
|
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_ORGANID_NOT_EXISTS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webcad拆单消费者
|
||||||
|
*
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/4/21 13:46
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class WebCadOrderImportConsumer {
|
||||||
|
@Resource
|
||||||
|
private OrderMapper orderMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SnowFlakeGenerator snowFlakeGenerator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderBodyMapper orderBodyMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PlateMapper plateMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderGroupMapper orderGroupMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SnowflakeIdWorker3rd idWorker;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderInputProcessor orderInputProcessor;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CustomPlateNoGenerateService customPlateNoGenerateService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisLockUtil redisLockUtil;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private GoodsMapper goodsMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RawGoodsMapper rawGoodsMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SystemConfigApi systemConfigApi;
|
||||||
|
|
||||||
|
@Value("${chenfeng.plan.webcad.import.cadImportPlateNumThreshold:10000}")
|
||||||
|
private int cadImportPlateNumThreshold;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderImportTaskMapper orderImportTaskMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderImportTaskService orderImportTaskService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cad拆单请求缓存地址
|
||||||
|
*/
|
||||||
|
@Value("${chenfeng.plan.webcad.import.temp-file-path}")
|
||||||
|
private String webcadJsonCachePath;
|
||||||
|
|
||||||
|
private static final String REDIS_UNIQUEKEY = "webcad";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataSourceTransactionManager transactionManager;
|
||||||
|
|
||||||
|
@RabbitListener(queues = "#{@orderImportWebCadQueueName}")
|
||||||
|
public void orderImport(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception {
|
||||||
|
log.info("====================【webcad异步拆单收到消息:{}】====================", message);
|
||||||
|
|
||||||
|
Long organId = null;
|
||||||
|
Long taskId = Long.parseLong(message);
|
||||||
|
boolean nackSent = false;
|
||||||
|
TransactionStatus transactionStatus = null;
|
||||||
|
try {
|
||||||
|
transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults());
|
||||||
|
|
||||||
|
organId = OrganContextHolder.getOrganId();
|
||||||
|
if (ObjectUtil.isNull(organId)) {
|
||||||
|
throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORGANID_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 确认任务,更新状态为消费成功,没有找到任务中断后续消费
|
||||||
|
OrderImportTaskDO orderImportTaskDO = confirmOrderImport(taskId);
|
||||||
|
if (ObjectUtil.isNull(orderImportTaskDO)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("====================【webcad异步拆单处理临时数据开始】====================");
|
||||||
|
WebCadOrderImportAsyncFactory webCadOrderImportAsyncFactory =
|
||||||
|
new WebCadOrderImportAsyncFactory(organId, orderMapper, snowFlakeGenerator, orderBodyMapper, plateMapper, orderGroupMapper, idWorker,
|
||||||
|
orderImportTaskMapper, orderInputProcessor, goodsMapper, rawGoodsMapper, customPlateNoGenerateService, systemConfigApi, orderImportTaskDO.getCreator(), cadImportPlateNumThreshold, jdbcTemplate);
|
||||||
|
webCadOrderImportAsyncFactory.analyzeTempData(taskId, webcadJsonCachePath);
|
||||||
|
log.info("====================【webcad异步拆单处理临时数据结束】====================");
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
|
transactionManager.commit(transactionStatus);
|
||||||
|
} catch (ServiceException se) {
|
||||||
|
// 回滚事务
|
||||||
|
if (transactionStatus != null) {
|
||||||
|
transactionManager.rollback(transactionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新任务状态
|
||||||
|
orderImportTaskService.updateServiceExceptionTaskStatus(taskId, organId, se.getMessage());
|
||||||
|
|
||||||
|
nackSent = true;
|
||||||
|
// 确认消息进入死信队列
|
||||||
|
channel.basicNack(deliveryTag, false, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 回滚事务
|
||||||
|
if (transactionStatus != null) {
|
||||||
|
transactionManager.rollback(transactionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新任务状态
|
||||||
|
orderImportTaskService.updateExceptionTaskStatus(taskId, organId);
|
||||||
|
|
||||||
|
nackSent = true;
|
||||||
|
// 确认消息进入死信队列
|
||||||
|
channel.basicNack(deliveryTag, false, false);
|
||||||
|
log.error(ORDER_IMPORT_FAIL.getMsg(), e);
|
||||||
|
} finally {
|
||||||
|
// 手动确认消息接收
|
||||||
|
if (!nackSent) {
|
||||||
|
channel.basicAck(deliveryTag, false);
|
||||||
|
}
|
||||||
|
// 导入锁解锁
|
||||||
|
redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), REDIS_UNIQUEKEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认导入任务,更新任务状态
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
*/
|
||||||
|
private OrderImportTaskDO confirmOrderImport(Long taskId) {
|
||||||
|
boolean taskExist = false;
|
||||||
|
OrderImportTaskDO orderImportTaskDO = null;
|
||||||
|
// 线程每1s查询一次,查三次没有就提示任务不存在
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
orderImportTaskDO = orderImportTaskMapper.selectById(taskId);
|
||||||
|
if (ObjectUtil.isNotNull(orderImportTaskDO)) {
|
||||||
|
taskExist = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("====================【线程中断异常】====================");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (taskExist) {
|
||||||
|
// 更新状态为消费成功
|
||||||
|
orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId).set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus()));
|
||||||
|
} else {
|
||||||
|
String taskNotExistNotify = String.format("%s不存在的导入任务,消费中止", taskId);
|
||||||
|
// 更新状态为消费成功,导入失败
|
||||||
|
orderImportTaskMapper.update(
|
||||||
|
new LambdaUpdateWrapper<OrderImportTaskDO>()
|
||||||
|
.eq(OrderImportTaskDO::getId, taskId)
|
||||||
|
.set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())
|
||||||
|
.set(OrderImportTaskDO::getResult, taskNotExistNotify)
|
||||||
|
);
|
||||||
|
log.error(String.format("====================【%s】====================", taskNotExistNotify));
|
||||||
|
}
|
||||||
|
return orderImportTaskDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -279,7 +279,7 @@ public class DefaultXmlOrderImportFactory {
|
|||||||
log.info("====================【生产单默认xml导入处理回显结束】====================");
|
log.info("====================【生产单默认xml导入处理回显结束】====================");
|
||||||
|
|
||||||
// 删除临时数据
|
// 删除临时数据
|
||||||
// deleteTempData();
|
deleteTempData();
|
||||||
// 完成所有流程后更新任务为导入成功
|
// 完成所有流程后更新任务为导入成功
|
||||||
updateTaskSuccess();
|
updateTaskSuccess();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
+2037
File diff suppressed because it is too large
Load Diff
+413
-672
File diff suppressed because it is too large
Load Diff
@@ -72,6 +72,12 @@ spring:
|
|||||||
port: 5672 # RabbitMQ 服务的端口
|
port: 5672 # RabbitMQ 服务的端口
|
||||||
username: guest # RabbitMQ 服务的账号
|
username: guest # RabbitMQ 服务的账号
|
||||||
password: guest # RabbitMQ 服务的密码
|
password: guest # RabbitMQ 服务的密码
|
||||||
|
listener:
|
||||||
|
simple:
|
||||||
|
concurrency: 2
|
||||||
|
max-concurrency: 5
|
||||||
|
prefetch: 5
|
||||||
|
acknowledge-mode: manual
|
||||||
# Kafka 配置项,对应 KafkaProperties 配置类
|
# Kafka 配置项,对应 KafkaProperties 配置类
|
||||||
kafka:
|
kafka:
|
||||||
bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
|
bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
|
||||||
|
|||||||
@@ -173,3 +173,10 @@ chenfeng:
|
|||||||
encrypt:
|
encrypt:
|
||||||
enable: false
|
enable: false
|
||||||
publicKey: cfimes
|
publicKey: cfimes
|
||||||
|
plan:
|
||||||
|
webcad:
|
||||||
|
import:
|
||||||
|
node: 1
|
||||||
|
async-plate-threshold: 5000
|
||||||
|
cadImportPlateNumThreshold: 20000
|
||||||
|
temp-file-path: /data/imes-server/cf-prod-plan/local
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package com.cf.imes.module.system.config;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.CustomExchange;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.amqp.core.QueueBuilder;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE;
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE;
|
||||||
|
import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/5/13 11:42
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class ChenfengRabbitMQSystemConfiguration {
|
||||||
|
/**
|
||||||
|
* 广告状态修改 延迟队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue advertisementUpdateDelayedQueue(){
|
||||||
|
return QueueBuilder.durable(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告状态修改 定义延迟交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CustomExchange advertisementUpdateDelayExchange() {
|
||||||
|
Map<String, Object> args = new HashMap<>();
|
||||||
|
args.put("x-delayed-type", "direct");
|
||||||
|
return new CustomExchange(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告状态修改 队列与交换机绑定
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding advertisementUpdateQueueABindingX(@Qualifier("advertisementUpdateDelayedQueue") Queue queue,
|
||||||
|
@Qualifier("advertisementUpdateDelayExchange") CustomExchange delayedExchange){
|
||||||
|
return BindingBuilder.bind(queue)
|
||||||
|
.to(delayedExchange)
|
||||||
|
.with(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY)
|
||||||
|
.noargs();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user