diff --git a/cf-framework/cf-spring-boot-starter-biz-id/src/main/java/com/cf/imes/framework/id/config/ChenfengIDAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-biz-id/src/main/java/com/cf/imes/framework/id/config/ChenfengIDAutoConfiguration.java index 7e9a04f88..f641cbac0 100644 --- a/cf-framework/cf-spring-boot-starter-biz-id/src/main/java/com/cf/imes/framework/id/config/ChenfengIDAutoConfiguration.java +++ b/cf-framework/cf-spring-boot-starter-biz-id/src/main/java/com/cf/imes/framework/id/config/ChenfengIDAutoConfiguration.java @@ -13,7 +13,7 @@ import org.springframework.context.annotation.Bean; public class ChenfengIDAutoConfiguration { @Bean - public SnowflakeIdWorker3rd ipQueryService() { + public SnowflakeIdWorker3rd idWorker() { return new SnowflakeIdWorker3rd(); } } \ No newline at end of file diff --git a/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/com/cf/imes/framework/organ/core/mq/rabbitmq/OrganRabbitMQMessagePostProcessor.java b/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/com/cf/imes/framework/organ/core/mq/rabbitmq/OrganRabbitMQMessagePostProcessor.java index 9d858df0c..666d41ff4 100644 --- a/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/com/cf/imes/framework/organ/core/mq/rabbitmq/OrganRabbitMQMessagePostProcessor.java +++ b/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/com/cf/imes/framework/organ/core/mq/rabbitmq/OrganRabbitMQMessagePostProcessor.java @@ -1,6 +1,8 @@ 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 org.apache.commons.lang3.StringUtils; import org.apache.kafka.clients.producer.ProducerInterceptor; import org.springframework.amqp.AmqpException; import org.springframework.amqp.core.Message; @@ -8,6 +10,7 @@ import org.springframework.amqp.core.MessagePostProcessor; 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_PEEK; /** * RabbitMQ 消息队列的多组织 {@link ProducerInterceptor} 实现类 @@ -25,6 +28,11 @@ public class OrganRabbitMQMessagePostProcessor implements MessagePostProcessor { if (organId != null) { 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; } diff --git a/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index 782280514..6b8d61c3c 100644 --- a/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/cf-framework/cf-spring-boot-starter-biz-organ/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -16,6 +16,8 @@ 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.util.OrganUtils; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -33,6 +35,7 @@ import java.lang.reflect.Type; 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_PEEK; /** * Extension of {@link HandlerMethod} that invokes the underlying method with @@ -122,6 +125,7 @@ public class InvocableHandlerMethod extends HandlerMethod { // 注意:如下是本类的改动点!!! // 情况一:无组织编号的情况 Long organId= parseorganId(message); + parsePeek(message); if (organId == null) { return doInvoke(args); } @@ -149,6 +153,18 @@ public class InvocableHandlerMethod extends HandlerMethod { 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 * argument values and falling back to the configured argument resolvers. diff --git a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java index 1d1f2b360..f27361412 100644 --- a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java +++ b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java @@ -1,20 +1,12 @@ package com.cf.imes.framework.mq.rabbitmq.config; -import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants; import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.*; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; 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.condition.ConditionalOnClass; 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 消息队列配置类 * @@ -31,137 +23,4 @@ public class ChenfengRabbitMQAutoConfiguration { public MessageConverter createMessageConverter() { 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 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 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 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(); - } - } diff --git a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java index 91c711a61..f2b3f281d 100644 --- a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java +++ b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java @@ -27,6 +27,17 @@ public class RabbitMqConstants { */ 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"; + /** * 生产单导入死信交换机 */ diff --git a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/util/WebFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/util/WebFrameworkUtils.java index 095bdfa68..a38f8ed11 100644 --- a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/util/WebFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/util/WebFrameworkUtils.java @@ -29,6 +29,8 @@ public class WebFrameworkUtils { public static final String HEADER_ORGAN_ID = "organ-id"; + public static final String HEADER_PEEK = "peek"; + /** * 终端的 Header * diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/orderImport/handler/xml/DefaultXmlOrderImportHandler.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/orderImport/handler/xml/DefaultXmlOrderImportHandler.java index 1ee2241e7..f4eb5c431 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/orderImport/handler/xml/DefaultXmlOrderImportHandler.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/orderImport/handler/xml/DefaultXmlOrderImportHandler.java @@ -119,7 +119,7 @@ public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandl // 创建导入任务 OrderImportTaskDO orderImportTaskDO = OrderImportTaskDO.builder() .id((Long) snowFlakeGenerator.nextId(null)) - .type(OrderImportTypeEnum.EXCEL.getType()) + .type(OrderImportTypeEnum.XML.getType()) .importStatus(OrderImportStatusEnum.IMPORT_NOT_YET.getStatus()) .status(OrderImportTaskStatusEnum.CREATE_NOT_CONSUME.getStatus()) .fileName(fileName) diff --git a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java index dd583345a..283b5189f 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java +++ b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java @@ -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_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_ORDER_PLATENUM_CHECK_ERROR = new ErrorCode(1_005_000_011, "导入失败:生产单【{}】下板件数量已达到20000片,无法继续导入"); - 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_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, "部分导入成功,生产单【{}】下板件数量已达到{}片,本次拆单超出部分不计入生产单"); public static final ErrorCode ORDER_IMPORT_PLATE_GOODS_NOMATCH_ERROR = new ErrorCode(1_005_000_013, "导入失败,板材库中无板材匹配,商品编码:{},商品名称:{},材质:{},颜色:{},厚度:{},品牌:{}"); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/config/ChenfengRabbitMQPlanConfiguration.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/config/ChenfengRabbitMQPlanConfiguration.java new file mode 100644 index 000000000..4621e10c6 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/config/ChenfengRabbitMQPlanConfiguration.java @@ -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 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 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 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); + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java index 698cd8f92..311929d70 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java @@ -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.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 io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; 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.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import javax.validation.Valid; import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.IMPORT; @@ -34,8 +33,8 @@ public class OrderImportController { @PostMapping("/webcad/import") @Operation(summary = "webcad拆单导入生产单") @OperateLog(type = IMPORT) - public CommonResult webCadOrderImport(@RequestBody @Valid WebCadDataReqVO webCadDataReqVO) { - webCadOrderImportService.webCadOrderImport(webCadDataReqVO); + public CommonResult webCadOrderImport(@RequestParam("file") MultipartFile file) { + webCadOrderImportService.webCadOrderImport(file); return CommonResult.success(true); } } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataBlockReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataBlockReqVO.java index 67d57b8e7..4728ddcba 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataBlockReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataBlockReqVO.java @@ -63,59 +63,33 @@ public class WebCadDataBlockReqVO { private Double kaiLiaoWidth; @Valid - private InfoDTO info; +// private InfoDTO info; private String cabinetName; private String roomName; private Double cabinetDepth; private Double cabinetWidth; private Double cabinetHeight; - private BoadrData boardData; private PointInfoDTO pointInfo; - private Long plateGoodsId; - private String goodsId; + private Double sealLeft; + private Double sealRight; + private Double sealUp; + private Double sealDown; + private Boolean isRect; + private String spliteHeight; + private String spliteThickness; + private String spliteWidth; + private boolean has2DModel; + private boolean has3DModel; + private String boardTypeName; + + private List> allRemarkList; + +// private Long plateGoodsId; + private String goodsCode; private List groupIds = new ArrayList<>(); - @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 spliteThickness; - private String spliteWidth; - private Boolean isRect; - private List> remarks; - - @Max(value = 99999, message = "板件开料宽度不能超过99999") - @Min(value = 0, message = "板件开料宽度最小值为0") - private Double kaiLiaoWidth; - - @Max(value = 99999, message = "板件开料高度不能超过99999") - @Min(value = 0, message = "板件开料高度最小值为0") - private Double kaiLiaoHeight; - private Integer openDir; - } - @NoArgsConstructor @Data public static class FrontBackHolesDTO { @@ -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 sealing; - @JsonProperty("boardEdgeRemark") - private List boardEdgeRemark; - @JsonProperty("reservedEdge") - private List reservedEdge; - @JsonProperty("modeling") - private List modeling; - @JsonProperty("curveBoardModeling") - private List curveBoardModeling; - @JsonProperty("holes") - private HolesDTO holes; - @JsonProperty("sideModeling") - private List sideModeling; - @JsonProperty("offsetTanslation") - private OffsetTanslationDTO offsetTanslation; - @JsonProperty("metalsData") - private MetalsDataDTO metalsData; - @JsonProperty("modeling2D") - private List modeling2D; - @JsonProperty("modeling3D") - private List modeling3D; - @JsonProperty("isReverse") - private Boolean isReverse; - - private Object info; - - @NoArgsConstructor - @Data - public static class OriginOutlinDTO { - @JsonProperty("pts") - private List pts; - @JsonProperty("buls") - private List 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 pts; - @JsonProperty("buls") - private List 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 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 pts; - @JsonProperty("buls") - private List 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 pts; - @JsonProperty("buls") - private List 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 pts; - @JsonProperty("buls") - private List 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 items; - - @NoArgsConstructor - @Data - public static class PathDTO { - @JsonProperty("pts") - private List pts; - @JsonProperty("buls") - private List 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 @Data diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataDoubleRoomTreeReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataDoubleRoomTreeReqVO.java index 298ea318f..4ed87ad9c 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataDoubleRoomTreeReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataDoubleRoomTreeReqVO.java @@ -7,6 +7,7 @@ import javax.validation.Valid; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import java.util.List; /** @@ -35,5 +36,9 @@ public class WebCadDataDoubleRoomTreeReqVO { @Max(value = 5000, message = "拆单倍数不能超过5000") @Min(value = 1, message = "拆单倍数最小值为1") private Integer count; + + private List blockList; + + private List objList; } } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataGroupInfoReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataGroupInfoReqVO.java new file mode 100644 index 000000000..1a73182a3 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataGroupInfoReqVO.java @@ -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; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataMaterialReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataMaterialReqVO.java index 32548a802..6e6dec625 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataMaterialReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataMaterialReqVO.java @@ -13,7 +13,11 @@ import java.util.List; @Data public class WebCadDataMaterialReqVO { - private Integer thickness; + private Double height; + + private Double width; + + private Double thickness; private String material; @@ -27,6 +31,14 @@ public class WebCadDataMaterialReqVO { private String name; + private boolean texture; + + public boolean getTexture() { + return texture; + } + + private String spec; + /** * imes板材id */ diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataPartsReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataPartsReqVO.java index 396d72e09..d48598f4f 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataPartsReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataPartsReqVO.java @@ -22,8 +22,6 @@ public class WebCadDataPartsReqVO { private List blockObjectList; - private List leftEdges; - @NoArgsConstructor @Data public static class BlockObjectListDTO { @@ -74,16 +72,6 @@ public class WebCadDataPartsReqVO { 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 @Data public static class GroupDataDTO { @@ -99,37 +87,4 @@ public class WebCadDataPartsReqVO { 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 objectIds; - @JsonProperty("cabinetNames") - private List cabinetNames; - @JsonProperty("roomNames") - private List roomNames; - @JsonProperty("roomName") - private String roomName; - @JsonProperty("cabinetName") - private String cabinetName; - @JsonProperty("num") - private Double num; - } } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataReqVO.java index e507fbaee..6406377af 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/webcad/vo/WebCadDataReqVO.java @@ -5,7 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.Valid; -import javax.validation.constraints.Size; import java.util.List; /** @@ -16,20 +15,14 @@ import java.util.List; @Data public class WebCadDataReqVO { - @JsonProperty(value = "Orders") - @Valid - private WebCadDataOrderReqVO orders; + @JsonProperty(value = "OrderNo") + private String orderNo; @JsonProperty(value = "Materials") private List Materials; - @JsonProperty(value = "Blocks") - @Size(max = 20000, message = "拆单板件片数单次不能超过2万片") - @Valid - private List Blocks; - @JsonProperty(value = "Parts") - private WebCadDataPartsReqVO Parts; + private List Parts; @JsonProperty(value = "ProcessGroup") @Valid @@ -37,4 +30,7 @@ public class WebCadDataReqVO { @Valid private List douleRoomTree; + + @JsonProperty(value = "Blocks") + private List blocks; } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTaskDO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTaskDO.java index 26cca719d..e56f1ddca 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTaskDO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTaskDO.java @@ -64,4 +64,10 @@ public class OrderImportTaskDO extends BaseDO { * 导入结果0 */ private String result; + + + /** + * 导入文件名称 + */ + private String fileName; } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/framework/executor/config/PlanThreadPoolConfiguration.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/framework/executor/config/PlanThreadPoolConfiguration.java index 5c320e019..c8134326b 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/framework/executor/config/PlanThreadPoolConfiguration.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/framework/executor/config/PlanThreadPoolConfiguration.java @@ -17,8 +17,8 @@ public class PlanThreadPoolConfiguration { @Bean(PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR) public ThreadPoolTaskExecutor planThreadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setCorePoolSize(8); // 设置核心线程数 - executor.setMaxPoolSize(16); // 设置最大线程数 + executor.setCorePoolSize(3); // 设置核心线程数 + executor.setMaxPoolSize(6); // 设置最大线程数 executor.setKeepAliveSeconds(60); // 设置空闲时间 executor.setQueueCapacity(100); // 设置队列大小 executor.setThreadNamePrefix("plan-import-Executor-"); // 配置线程池的前缀 diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/order/OrderInputProcessor.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/order/OrderInputProcessor.java index 45ffa8724..31cb867c5 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/order/OrderInputProcessor.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/order/OrderInputProcessor.java @@ -3,6 +3,7 @@ package com.cf.imes.module.plan.service.order; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.IdUtil; +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.ElasticsearchException; import co.elastic.clients.elasticsearch.core.BulkRequest; @@ -35,6 +36,9 @@ public class OrderInputProcessor { @Resource private ElasticsearchClient elasticsearchClient; + @Resource + private ElasticsearchAsyncClient elasticsearchAsyncClient; + private Snowflake snowflake = IdUtil.getSnowflake(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -61,7 +65,21 @@ public class OrderInputProcessor { throw new ServiceException(500, "未知异常"); } } catch (IOException | ElasticsearchException e) { - e.printStackTrace(); + log.error(e.getMessage()); + throw new RuntimeException(e); + } + + } + + /** + * 异步保存生产单造型数据 + * + * @param orderModelDOs + */ + public void batchAsyncSaveModel(List orderModelDOs) { + try { + bulkAsyncCreate(ORDER_PLATE_MODEL, orderModelDOs); + } catch (IOException | ElasticsearchException e) { log.error(e.getMessage()); throw new RuntimeException(e); } @@ -160,4 +178,22 @@ public class OrderInputProcessor { }); return elasticsearchClient.bulk(br.build()); } + + public void bulkAsyncCreate(String idxName, List 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()); + } } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskService.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskService.java new file mode 100644 index 000000000..1d8d462a4 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskService.java @@ -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); +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskServiceImpl.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskServiceImpl.java new file mode 100644 index 000000000..409f5dd8c --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/OrderImportTaskServiceImpl.java @@ -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().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().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())); + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportService.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportService.java index 14dca894e..f1d569b11 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportService.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportService.java @@ -1,6 +1,6 @@ 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 @@ -13,7 +13,7 @@ public interface WebCadOrderImportService { /** * webcad生产单导入 * - * @param webCadDataReqVO + * @param file */ - void webCadOrderImport(WebCadDataReqVO webCadDataReqVO); + void webCadOrderImport(MultipartFile file); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java index 0db96a3d4..1ae1640a9 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java @@ -1,42 +1,63 @@ package com.cf.imes.module.plan.service.orderImport; +import cn.hutool.core.io.FileUtil; 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.ServiceException; 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.organ.core.context.OrganContextHolder; import com.cf.imes.framework.redis.config.ChenfengCacheProperties; 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.executor.enums.OrderImportTypeEnum; 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.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.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.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.factory.WebCadOrderImportFactory; 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.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.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 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 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.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.framework.executor.config.PlanThreadPoolConfiguration.PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR; /** * 生产单导入服务Service实现类 @@ -60,21 +81,12 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService { @Resource private PlateMapper plateMapper; - @Resource - private OrderItemMapper orderItemMapper; - - @Resource - private OrderGroupMapper orderGroupMapper; - @Resource private SnowflakeIdWorker3rd idWorker; @Resource private OrderInputProcessor orderInputProcessor; - @Resource - private OrderPartsMapper orderPartsMapper; - @Resource private CustomPlateNoGenerateService customPlateNoGenerateService; @@ -90,50 +102,219 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService { @Resource private RawGoodsMapper rawGoodsMapper; - @Resource - private PlateGoodMapper plateGoodMapper; - @Resource private DataSourceTransactionManager transactionManager; @Resource private SystemConfigApi systemConfigApi; - @Resource(name = PLAN_IMPOT_THREAD_POOL_TASK_EXECUTOR) - private ThreadPoolTaskExecutor threadPoolTaskExecutor; - - @Value("${chenfeng.plan.impot.cadImportPlateNumThreshold:20000}") + @Value("${chenfeng.plan.webcad.import.cadImportPlateNumThreshold:10000}") private int cadImportPlateNumThreshold; @Resource 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 - public void webCadOrderImport(WebCadDataReqVO webCadDataReqVO) { + public void webCadOrderImport(MultipartFile file) { Long organId = OrganContextHolder.getOrganId(); - String redisUniqueKey = "webcad"; + if (ObjectUtil.isNull(organId)) { throw new ServiceException(WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR); } - try { - String importLockKey = String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId); - // 检查机构导入锁 - boolean lockResult = redisLockUtil.lock(importLockKey, redisUniqueKey, chenfengCacheProperties.getLockTimeout()); - if (!lockResult) { - throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR); + // 上锁 + addLock(organId); + + TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); + // 是否同步处理 + 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; + } + + 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); + } 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(); // 忽略其他字段 + } } - WebCadOrderImportFactory webCadOrderImportFactory = new WebCadOrderImportFactory(organId, orderMapper, snowFlakeGenerator, orderBodyMapper, plateMapper, orderItemMapper, orderGroupMapper, - idWorker, orderInputProcessor, orderPartsMapper, goodsMapper, rawGoodsMapper, plateGoodMapper, customPlateNoGenerateService, transactionManager, systemConfigApi, threadPoolTaskExecutor, cadImportPlateNumThreshold, jdbcTemplate); - webCadOrderImportFactory.analyzeTempData(webCadDataReqVO); + // 事务提交 + transactionManager.commit(transactionStatus); } catch (ServiceException se) { - throw se; + // 事务回滚 + transactionManager.rollback(transactionStatus); + // 移除临时文件 + removeCacheFileWhenException(sync, taskId); + + throw se; } catch (Exception e) { + // 事务回滚 + transactionManager.rollback(transactionStatus); + // 移除临时文件 + removeCacheFileWhenException(sync, taskId); + ErrorCode webcadOrderImportFailed = WEBCAD_ORDER_IMPORT_FAILED; log.error(webcadOrderImportFailed.getMsg(), e); throw new ServiceException(webcadOrderImportFailed); } finally { - // 导入锁解锁 - redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), redisUniqueKey); + if (sync) { + // 导入锁解锁 + 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; + } } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/OrderImportDeadLetterConsumer.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/OrderImportDeadLetterConsumer.java index ab4b4aa36..e79ced481 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/OrderImportDeadLetterConsumer.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/OrderImportDeadLetterConsumer.java @@ -1,7 +1,6 @@ package com.cf.imes.module.plan.service.orderImport.consumer; import cn.hutool.core.util.ObjectUtil; -import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.framework.redis.constants.RedisKeyConstants; @@ -23,7 +22,6 @@ import java.util.List; import java.util.Map; 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"; @RabbitListener(queues = ORDER_IMPORT_DEAD_LETTER_QUEUE) - @DS("imes_prod") public void receive(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, @@ -54,24 +51,28 @@ public class OrderImportDeadLetterConsumer { // 手动确认消息 channel.basicAck(deliveryTag, false); + Long organId = OrganContextHolder.getOrganId(); + String deadLetterReason = getDeadLetterReason(xDeath); long taskId = Long.parseLong(message); if(TTL_REASON.equals(deadLetterReason)) { // 更新状态为消费超时 - orderImportTaskMapper.update(new LambdaUpdateWrapper().eq(OrderImportTaskDO::getId, taskId) + orderImportTaskMapper.update(new LambdaUpdateWrapper() + .eq(OrderImportTaskDO::getId, taskId) + .set(OrderImportTaskDO::getOrganId, organId) .set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_FAIL.getStatus()) ); } else if (ERROR_REASON.equals(deadLetterReason)) { // 更新状态为消费成功、导入失败 - orderImportTaskMapper.update(new LambdaUpdateWrapper().eq(OrderImportTaskDO::getId, taskId) + orderImportTaskMapper.update(new LambdaUpdateWrapper() + .eq(OrderImportTaskDO::getId, taskId) + .set(OrderImportTaskDO::getOrganId, organId) .set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus()) - .set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus()) - .set(OrderImportTaskDO::getResult, ORDER_IMPORT_FAIL.getMsg())); + .set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())); } // 导入锁解锁 - Long organId = OrganContextHolder.getOrganId(); if (ObjectUtil.isNotNull(organId)) { redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/WebCadOrderImportConsumer.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/WebCadOrderImportConsumer.java new file mode 100644 index 000000000..f1d30943f --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/WebCadOrderImportConsumer.java @@ -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().eq(OrderImportTaskDO::getId, taskId).set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())); + } else { + String taskNotExistNotify = String.format("%s不存在的导入任务,消费中止", taskId); + // 更新状态为消费成功,导入失败 + orderImportTaskMapper.update( + new LambdaUpdateWrapper() + .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; + } + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java index a0eb0d9dd..e6adb9014 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java @@ -279,7 +279,7 @@ public class DefaultXmlOrderImportFactory { log.info("====================【生产单默认xml导入处理回显结束】===================="); // 删除临时数据 -// deleteTempData(); + deleteTempData(); // 完成所有流程后更新任务为导入成功 updateTaskSuccess(); } catch (Exception e) { diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportAsyncFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportAsyncFactory.java new file mode 100644 index 000000000..ae9b2d44c --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportAsyncFactory.java @@ -0,0 +1,2037 @@ +package com.cf.imes.module.plan.service.orderImport.factory; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONReader; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.cf.imes.framework.common.exception.ErrorCode; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd; +import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator; +import com.cf.imes.framework.mybatis.core.injector.BaseBatchMapper; +import com.cf.imes.module.executor.enums.DataTypeEnum; +import com.cf.imes.module.executor.enums.OrderImportStatusEnum; +import com.cf.imes.module.executor.enums.OrderItemTypeEnum; +import com.cf.imes.module.executor.enums.OrderStatusEnum; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataBlockRemarkVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataBlockReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataDoubleRoomTreeReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataGroupInfoReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataMaterialReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataPartsReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataProcessGroupReqVO; +import com.cf.imes.module.plan.dal.dataobject.goods.GoodsDO; +import com.cf.imes.module.plan.dal.dataobject.order.OrderDO; +import com.cf.imes.module.plan.dal.dataobject.orderBody.OrderBodyDO; +import com.cf.imes.module.plan.dal.dataobject.orderGroup.OrderGroupDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO; +import com.cf.imes.module.plan.dal.dataobject.orderItem.OrderItemDO; +import com.cf.imes.module.plan.dal.dataobject.orderParts.OrderPartsDO; +import com.cf.imes.module.plan.dal.dataobject.ordermodel.OrderModelDO; +import com.cf.imes.module.plan.dal.dataobject.plate.PlateDO; +import com.cf.imes.module.plan.dal.dataobject.rawgoods.RawGoodsDO; +import com.cf.imes.module.plan.dal.elasticsearch.HoleDetail; +import com.cf.imes.module.plan.dal.elasticsearch.IContourData; +import com.cf.imes.module.plan.dal.elasticsearch.IOriginModelingData; +import com.cf.imes.module.plan.dal.elasticsearch.ModelDetail; +import com.cf.imes.module.plan.dal.elasticsearch.OffSetList; +import com.cf.imes.module.plan.dal.elasticsearch.Point; +import com.cf.imes.module.plan.dal.elasticsearch.PointDetail; +import com.cf.imes.module.plan.dal.elasticsearch.PointList; +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.customplateno.vo.CustomPlateNoGenerateConfigVO; +import com.cf.imes.module.plan.service.order.OrderInputProcessor; +import com.cf.imes.module.system.api.systemconfig.SystemConfigApi; +import com.cf.imes.module.system.api.systemconfig.dto.SystemConfigRespDTO; +import com.cf.imes.module.system.api.systemconfig.dto.SystemConfigSealEdgeRespDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_GET_ORG_SEALEDGE_ERROR; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORG_SEALEDGE_ANALYZE_ERROR; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_NOT_EXISTS_ERROR; +import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL; + +/** + * webcad异步导入生产单工厂服务 + * + * @author Gqr + * @since 2025/3/8 14:39 + */ +@Slf4j +public class WebCadOrderImportAsyncFactory { + /** + * 批量操作阈值 + */ + private static final int BATCH_THRESHOLD_NUMBER = 1000; + + private OrderMapper orderMapper; + + private SnowFlakeGenerator snowFlakeGenerator; + + private OrderBodyMapper orderBodyMapper; + + private PlateMapper plateMapper; + + private OrderGroupMapper orderGroupMapper; + + private SnowflakeIdWorker3rd idWorker; + + private OrderImportTaskMapper orderImportTaskMapper; + + private OrderInputProcessor orderInputProcessor; + + private SystemConfigApi systemConfigApi; + + private GoodsMapper goodsMapper; + + private RawGoodsMapper rawGoodsMapper; + + private CustomPlateNoGenerateService customPlateNoGenerateService; + + private JdbcTemplate jdbcTemplate; + + private Long organId; + + // 批次id + private Long batchId; + + private Long orderId; + + private OrderDO orderDO; + + // 是否入库的第一块板件 + private boolean isFirstPlate; + + // 是否有插入es数据 + private boolean esInsert; + + private CustomPlateNoGenerateConfigVO plateNoGenerateConfigVO; + + // 操作人 + private String operatorName; + + private LocalDateTime now; + + // 柜体成倍信息缓存:{ 房间名+柜体名:count } + private Map roomBodyMap = new HashMap<>(); + + // 柜体缓存 + private Map bodyMap = new HashMap<>(); + + // 房间名+柜体名+加工组名:加工组id + private Map orderGroupMap = new HashMap<>(); + + // 板材缓存:{商品编号:order_goods} + private Map materialMap = new HashMap<>(); + + // 已存在房间缓存:{ roomName: roomId } + private Map existRoomIdMap = new HashMap<>(); + + // IsComposite+ObjectType+Factory+Model+Spec+height+width+depth+unit+brand:orderPartId + private Map orderPartMap = new HashMap<>(); + + // 加工组缓存 + private Map processGroupMap = new HashMap<>(); + + private List plateDOS = new ArrayList<>(); + private List orderItemDOS = new ArrayList<>(); + private List orderGroupDOS = new ArrayList<>(); + private List orderPartsDOS = new ArrayList<>(); + private List orderModelDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List rawGoodsDOS = new ArrayList<>(); + private List goodsDOS = new ArrayList<>(); + private List sealEdgeConfigList; + + + private static final String PART_CATEGORY_ONE = "封边条"; + private static final String PART_CATEGORY_TWO = "五金"; + private static final String PART_CATEGORY_THREE = "组件"; + private static final String EMPTY_STRING = new String(); + + // 当前拆单导入的板件数量(初始包含前n次导入的板件总数) + private int currentPlateNum; + + // cad拆单板件数量阈值 + private int cadImportPlateNumThreshold; + + // 板件数量是否已达到阈值 + private boolean plateNumReachThreshold = false; + + private String tempFilePath; + + public WebCadOrderImportAsyncFactory(Long organId, + OrderMapper orderMapper, + SnowFlakeGenerator snowFlakeGenerator, + OrderBodyMapper orderBodyMapper, + PlateMapper plateMapper, + OrderGroupMapper orderGroupMapper, + SnowflakeIdWorker3rd idWorker, + OrderImportTaskMapper orderImportTaskMapper, + OrderInputProcessor orderInputProcessor, + GoodsMapper goodsMapper, + RawGoodsMapper rawGoodsMapper, + CustomPlateNoGenerateService customPlateNoGenerateService, + SystemConfigApi systemConfigApi, + String operatorName, + int cadImportPlateNumThreshold, + JdbcTemplate jdbcTemplate) { + this.organId = organId; + this.orderMapper = orderMapper; + this.snowFlakeGenerator = snowFlakeGenerator; + this.orderBodyMapper = orderBodyMapper; + this.plateMapper = plateMapper; + this.orderGroupMapper = orderGroupMapper; + this.idWorker = idWorker; + this.orderImportTaskMapper = orderImportTaskMapper; + this.orderInputProcessor = orderInputProcessor; + this.goodsMapper = goodsMapper; + this.rawGoodsMapper = rawGoodsMapper; + this.customPlateNoGenerateService = customPlateNoGenerateService; + this.systemConfigApi = systemConfigApi; + this.operatorName = operatorName; + now = LocalDateTime.now(); + batchId = (Long) snowFlakeGenerator.nextId(null); + sealEdgeConfigList = new ArrayList<>(); + this.cadImportPlateNumThreshold = cadImportPlateNumThreshold; + this.jdbcTemplate = jdbcTemplate; + } + + public void analyzeTempData(Long taskId, String webcadJsonCachePath) throws FileNotFoundException { + tempFilePath = webcadJsonCachePath + File.separator + taskId + ".json"; + try (JSONReader reader = new JSONReader(new FileReader(tempFilePath))) { + reader.startObject(); + while (reader.hasNext()) { + + String name = reader.readString(); + if ("OrderNo".equals(name)) { + log.debug("====================【cad拆单解析生产单开始】===================="); + analyzeOrder(reader.readString()); + log.debug("====================【cad拆单解析生产单结束】===================="); + } + if ("Materials".equals(name)) { + log.debug("====================【cad拆单解析板材开始】===================="); + // 解析板材对应 + analyzeMaterials(reader); + log.debug("====================【cad拆单解析板材结束】===================="); + } + if ("ProcessGroup".equals(name)) { + log.debug("====================【cad拆单解析加工组开始】===================="); + // 解析加工组类型 + analyzeGroups(reader); + log.debug("====================【cad拆单解析加工组结束】===================="); + } + if ("douleRoomTree".equals(name)) { + log.debug("====================【cad拆单解析成倍柜体开始】===================="); + // 缓存柜体成倍信息 + analyzeRoomBody(reader); + log.debug("====================【cad拆单解析成倍柜体结束】===================="); + } + if ("Blocks".equals(name)) { + // 获取自定义板编号配置 + plateNoGenerateConfigVO = customPlateNoGenerateService.getPlateNoGenerateConfig(orderId); + + log.debug("====================【cad拆单解析板件开始】===================="); + analyzeBlockRoomList(reader); + log.debug("====================【cad拆单解析板件结束】===================="); + } + if ("Parts".equals(name)) { + log.debug("====================【cad拆单获取封边配置开始】===================="); + // 获取系统配置-封边对应配置 + getOrgSealEdgeConfig(); + log.debug("====================【cad拆单获取封边配置结束】===================="); + + log.debug("====================【cad拆单解析配件开始】===================="); + analyzePartsRoomList(reader); + log.debug("====================【cad拆单解析配件结束】===================="); + } + } + reader.endObject(); + + orderItemBatchInsertWithinThreshold(orderItemDOS, true); + log.debug("====================【cad拆单全局保存开始】===================="); + // 保存数据柜体、加工组 + saveData(); + log.debug("====================【cad拆单全局保存结束】===================="); + + // 更新导入任务为成功 + updateTaskSuccess(taskId); + } catch (Exception e) { + if (esInsert) { + CompletableFuture.runAsync(() -> { + // 数据库数据回滚,同步删除 ES 里当前批次的数据 + orderInputProcessor.deleteByOrderIdBatch(orderId, batchId, ORDER_PLATE_MODEL); + }); + } + throw e; + } finally { + clearAll(); + deleteTempFile(); + } + } + + /** + * 获取组织封边条对应配置 + */ + private void getOrgSealEdgeConfig() { + CommonResult> orgSealEdgeConfig = systemConfigApi.getOrgSealEdgeConfig(); + boolean success = orgSealEdgeConfig.isSuccess(); + if (success) { + try { + List orgSealEdgeConfigCheckedData = orgSealEdgeConfig.getCheckedData(); + if (CollUtil.isNotEmpty(orgSealEdgeConfigCheckedData)) { + // 默认取第一条为配置 + SystemConfigRespDTO sealEdgeConfig = orgSealEdgeConfigCheckedData.get(0); + String setting = sealEdgeConfig.getSetting(); + // 封边对应配置转列表 + JSONArray jsonArray = JSON.parseArray(setting); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + String widthMin = jsonObject.getString("widthMin"); + String widthMax = jsonObject.getString("widthMax"); + String widthValue = jsonObject.getString("widthValue"); + + if (StringUtils.isNotEmpty(widthMin) && StringUtils.isNotEmpty(widthMax) && StringUtils.isNotEmpty(widthValue)) { + sealEdgeConfigList.add(new SystemConfigSealEdgeRespDTO(NumberUtil.parseDouble(widthMin), NumberUtil.parseDouble(widthMax), NumberUtil.parseDouble(widthValue))); + } + } + } + } catch (Exception e) { + ErrorCode webcadOrderImportOrgSealedgeAnalyzeError = WEBCAD_ORDER_IMPORT_ORG_SEALEDGE_ANALYZE_ERROR; + log.error(webcadOrderImportOrgSealedgeAnalyzeError.getMsg(), e); + throw ServiceExceptionUtil.exception(webcadOrderImportOrgSealedgeAnalyzeError); + } + } else { + throw ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_GET_ORG_SEALEDGE_ERROR); + } + } + + /** + * 解析生产单信息 + * + * @param orderNo + */ + private void analyzeOrder(String orderNo) { + // 查询生产单信息 + OrderDO orderDOFromOrderNo = orderMapper.selectOne(new LambdaUpdateWrapper() + .eq(OrderDO::getId, NumberUtil.parseLong(orderNo)) + .eq(OrderDO::getOrganId, organId) + .eq(OrderDO::getDeleted, false)); + if (ObjectUtil.isNull(orderDOFromOrderNo)) { + throw ServiceExceptionUtil.exception(WEBCAD_ORDER_NOT_EXISTS_ERROR, orderNo); + } else { + Integer status = orderDOFromOrderNo.getStatus(); + // 更新生产单来源为webcad + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper().eq(OrderDO::getId, orderDOFromOrderNo.getId()) + .set(OrderDO::getDataType, DataTypeEnum.API_IMPORT.getStatus()); + // 如果导入生产单为空单,则更新为新单 + if (OrderStatusEnum.EMPTY.getStatus().equals(status)) { + lambdaUpdateWrapper.set(OrderDO::getStatus, OrderStatusEnum.NEW_ORDER.getStatus()); + } + orderMapper.update(lambdaUpdateWrapper); + } + orderDO = orderDOFromOrderNo; + orderId = orderDOFromOrderNo.getId(); + + // 解析已有生产单下板件数量,超过两万不再导入 + Long existPlateCount = plateMapper.selectCount(new LambdaQueryWrapper() + .eq(PlateDO::getOrderId, orderId) + .eq(PlateDO::getOrganId, organId) + .eq(PlateDO::getDeleted, false) + ); + // cadImportPlateNumThreshold片阻止继续拆单 + if (existPlateCount >= cadImportPlateNumThreshold) { + throw ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR, orderId, cadImportPlateNumThreshold); + } else { + currentPlateNum = existPlateCount.intValue(); + } + } + + /** + * 板材id赋值对应板材 + * + * @param reader + */ + private void analyzeMaterials(JSONReader reader) { + reader.startArray(); + while (reader.hasNext()) { + // 读取json内容序列化 + WebCadDataMaterialReqVO materialReqVO = reader.readObject(WebCadDataMaterialReqVO.class); + + String plateGoodsGoodsId = materialReqVO.getGoodsId(); + + Long orderGoodsId; + Long existOrderGoodsId = materialMap.get(plateGoodsGoodsId); + if (ObjectUtil.isNull(existOrderGoodsId)) { + // 检查生产单下是否已经有板材下的order_goods,有不再创建 + List existOrderGoodIds = goodsMapper.selectList(new LambdaQueryWrapper() + .eq(GoodsDO::getGoodsId, plateGoodsGoodsId) + .eq(GoodsDO::getOrderId, orderId) + .eq(GoodsDO::getOrganId, organId) + .eq(GoodsDO::getDeleted, false) + .select(GoodsDO::getId)).stream().map(GoodsDO::getId).toList(); + + if (CollUtil.isNotEmpty(existOrderGoodIds)) { + // 缓存goodCode和orderGoodsId的对应关系 + materialMap.put(plateGoodsGoodsId, existOrderGoodIds.get(0)); + } + + // 创建设计端商品 + Long rawGoodsId = (Long) snowFlakeGenerator.nextId(null); + RawGoodsDO rawGoodsDO = RawGoodsDO.builder() + .id(rawGoodsId) + .orderId(orderId) + .rawGoodsId(plateGoodsGoodsId) + .goodsName(materialReqVO.getName()) + .material(materialReqVO.getMaterial()) + .texture(materialReqVO.getTexture()) + .color(materialReqVO.getColor()) + .colorBlack(EMPTY_STRING) + .thickness(materialReqVO.getThickness()) + .spec(materialReqVO.getSpec()) + .brand(materialReqVO.getBrand()) + .price(0.00) + .deleted(false) + .organId(organId) + .build(); + rawGoodsDO.setCreator(operatorName); + rawGoodsDO.setUpdater(operatorName); + rawGoodsDO.setCreateTime(now); + rawGoodsDO.setUpdateTime(now); + + orderGoodsId = (Long) snowFlakeGenerator.nextId(null); + // 创建生产单商品 + GoodsDO goodsDO = GoodsDO.builder() + .id(orderGoodsId) + .orderId(orderId) + .rawGoodsId(String.valueOf(rawGoodsId)) + .goodsId(plateGoodsGoodsId) + .goodsName(materialReqVO.getName()) + .material(materialReqVO.getMaterial()) + .texture(materialReqVO.getTexture()) + .color(materialReqVO.getColor()) + .colorBlack(EMPTY_STRING) + .width(BigDecimal.valueOf(materialReqVO.getWidth())) + .height(BigDecimal.valueOf(materialReqVO.getHeight())) + .thickness(BigDecimal.valueOf(materialReqVO.getThickness())) + .spec(materialReqVO.getSpec()) + .brand(materialReqVO.getBrand()) + .remark(EMPTY_STRING) + .planId(0L) + .price(0.00) + .deleted(false) + .organId(organId) + .build(); + goodsDO.setCreator(operatorName); + goodsDO.setUpdater(operatorName); + goodsDO.setCreateTime(now); + goodsDO.setUpdateTime(now); + + goodsDOS.add(goodsDO); + rawGoodsDOS.add(rawGoodsDO); + + // 缓存goodCode和orderGoodsId的对应关系 + materialMap.put(plateGoodsGoodsId, orderGoodsId); + } + + } + reader.endArray(); + orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, true); + orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, true); + } + + /** + * 缓存加工组类型 + * + * @param reader + */ + private void analyzeGroups(JSONReader reader) { + reader.startArray(); + while (reader.hasNext()) { + WebCadDataProcessGroupReqVO processGroup = reader.readObject(WebCadDataProcessGroupReqVO.class); + String groupTypeName = processGroup.getType(); + List projects = processGroup.getProjects(); + if (CollUtil.isNotEmpty(projects)) { + for (WebCadDataProcessGroupReqVO.ProjectsDTO project : projects) { + // 缓存加工组信息 + WebCadDataGroupInfoReqVO processGroupInfo = new WebCadDataGroupInfoReqVO(); + processGroupInfo.setGroupName(project.getProjName()); + processGroupInfo.setGroupTypeName(groupTypeName); + processGroupInfo.setHeight(project.getBoxSize().getHeight()); + processGroupInfo.setWidth(project.getBoxSize().getWidth()); + processGroupInfo.setDepth(project.getBoxSize().getDepth()); + processGroupMap.put(project.getGroupID(), processGroupInfo); + } + } + } + reader.endArray(); + } + + /** + * 生成并缓存成倍房间柜体信息 + * + * @param reader + */ + private void analyzeRoomBody(JSONReader reader) { + reader.startArray(); + while (reader.hasNext()) { + reader.startObject(); + + String roomName = null; + while (reader.hasNext()) { + String key = reader.readString(); + if ("name".equals(key)) { + roomName = reader.readString(); + } else if ("count".equals(key)) { + // 无用count + reader.readObject(); + } else if ("children".equals(key)) { + reader.startArray(); + while (reader.hasNext()) { + WebCadDataDoubleRoomTreeReqVO.ChildrenDTO childrenDTO = reader.readObject(WebCadDataDoubleRoomTreeReqVO.ChildrenDTO.class); + // 缓存柜体成倍信息 + roomBodyMap.put(roomName + childrenDTO.getName(), childrenDTO.getCount()); + } + reader.endArray(); + } + } + reader.endObject(); + } + reader.endArray(); + } + + /** + * 解析生产单信息板材列表 + * + * @param reader + */ + private void analyzeBlockRoomList(JSONReader reader) { + // 开始Blocks + reader.startArray(); + while (reader.hasNext()) { + reader.startObject(); + + String roomName = null; + Long roomId = null; + while (reader.hasNext()) { + String key = reader.readString(); + if ("name".equals(key)) { + roomName = reader.readString(); + + // 生产单下已有房间名直接使用roomId + Long existRoomId = existRoomIdMap.get(roomName); + if (ObjectUtil.isNotNull(existRoomId)) { + roomId = existRoomId; + } else { + // 查询生产单下是否已有同名房间 + List existRoomIds = orderBodyMapper.selectList(new LambdaQueryWrapper() + .select(OrderBodyDO::getRoomId) + .eq(OrderBodyDO::getOrderId, orderId) + .eq(OrderBodyDO::getOrganId, organId) + .eq(OrderBodyDO::getDeleted, false) + .eq(OrderBodyDO::getRoomName, roomName)).stream().map(OrderBodyDO::getRoomId).toList(); + if (CollUtil.isNotEmpty(existRoomIds)) { + roomId = existRoomIds.get(0); + existRoomIdMap.put(roomName, roomId); + } else { + roomId = (Long) snowFlakeGenerator.nextId(null); + existRoomIdMap.put(roomName, roomId); + } + } + } else if ("children".equals(key)) { + // 开始Blocks.children + reader.startArray(); + while (reader.hasNext()) { + analyzeBlockBodyList(reader, roomName, roomId); + } + reader.endArray(); + } + } + reader.endObject(); + } + reader.endArray(); + orderPlateBatchInsertWithinThreshold(plateDOS, true); + // 所有自定义板编号生成完成后更新配置到生产单 + customPlateNoGenerateService.updateCustomPlateNoGenerateConfig(plateNoGenerateConfigVO, orderDO); + // 批量插入造型数据 + orderModelsBatchInsertWithinThreshold(true); + } + + private void analyzeBlockBodyList(JSONReader reader, String roomName, Long roomId) { + reader.startObject(); + + String boxName = null; + Integer count = 1; + while (reader.hasNext()) { + String key = reader.readString(); + if ("name".equals(key)) { + boxName = reader.readString(); + + // 获取缓存中的成本数量 + count = roomBodyMap.get(roomName + boxName); + + } else if ("blockList".equals(key)) { + // Blocks.children.blockList开始 + reader.startArray(); + while (reader.hasNext()) { + WebCadDataBlockReqVO block = reader.readObject(WebCadDataBlockReqVO.class); + // 成倍创建 + multiCreateBodyPlate(count, roomId, roomName, boxName, block); + } + reader.endArray(); + } + } + reader.endObject(); + } + + /** + * 成倍创建柜体板件 + * + * @param count + * @param roomId + * @param roomName + * @param block + */ + private void multiCreateBodyPlate(Integer count, Long roomId, String roomName, String boxName, WebCadDataBlockReqVO block) { + for (int i = 0; i < count; i++) { + Long bodyId = (Long) snowFlakeGenerator.nextId(null); + OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) + .roomId(roomId).roomName(roomName).name(boxName).width(0.0).height(0.0) + .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); + + // 缓存成倍的柜体信息 + String multiRoomBodyName = roomName + boxName + i; + orderBodyDO.setMultiRoomBodyName(multiRoomBodyName); + bodyMap.put(multiRoomBodyName, orderBodyDO); + + // 达到阈值了不再创建板件 + if (plateNumReachThreshold) { + continue; + } + + if (!plateNumReachThreshold) { + // 创建板件相关数据:order_plate、order_item、es.orderModels + createPlate(orderBodyDO, block); + } + + } + } + + /** + * 创建板件数据 + * + * @param orderBodyDO + * @param block + */ + private void createPlate(OrderBodyDO orderBodyDO, WebCadDataBlockReqVO block) { + // 是否矩形,不是矩形那就是异形 + Boolean unRegular = !block.getIsRect(); + // 是否造型 + boolean isModel = (block.getFrontModelCount() + block.getBackModelCount()) > 0 || block.isHas2DModel() || block.isHas3DModel(); + // 是否排孔 + boolean isRawHole = (block.getFrontHoleCount() + block.getBackHoleCount()) > 0; + + orderBodyDO.setPlateNum(orderBodyDO.getPlateNum() + 1); + orderBodyDO.setUnregularNum(orderBodyDO.getUnregularNum() + BooleanUtil.toInt(unRegular)); + + // 柜体长宽深 + orderBodyDO.setWidth(block.getCabinetWidth()); + orderBodyDO.setHeight(block.getCabinetHeight()); + orderBodyDO.setDepth(block.getCabinetDepth()); + + Long plateId = (Long) snowFlakeGenerator.nextId(null); + long plateNo = idWorker.nextId(); + long obtainingTime = idWorker.obtainingTime(); + + // 从info.remarks中获取备注相关 + WebCadDataBlockRemarkVO plateRemark = getPlateRemark(block); + List remarks = plateRemark.getRemarks(); + StringBuilder remark = new StringBuilder(); + if (CollUtil.isNotEmpty(remarks)) { + for (String remarkStr : remarks) { + remark.append(remarkStr).append(","); + } + remark.deleteCharAt(remark.length() - 1); + } + + String splitHeight = block.getSpliteHeight(); + String spliteWidth = block.getSpliteWidth(); + // 创建order_plate + PlateDO plateDO = PlateDO.builder() + .id(plateId) + .orderId(orderId) + .name(block.getName()) + .plateNo(obtainingTime + Long.toString(plateNo).substring(2)) + .type(block.getType()) + .goodsId(materialMap.get(block.getGoodsCode())) + .width(BigDecimal.valueOf(block.getWidth())) + .height(BigDecimal.valueOf(block.getHeight())) + .thickness(BigDecimal.valueOf(block.getThickness())) + .splitHeight(BigDecimal.valueOf(NumberUtil.parseDouble(StringUtils.isNotEmpty(splitHeight) ? splitHeight : String.valueOf(block.getKaiLiaoHeight())))) + .splitThickness(BigDecimal.valueOf(NumberUtil.parseDouble(block.getSpliteThickness()))) + .splitWidth(BigDecimal.valueOf(NumberUtil.parseDouble(StringUtils.isNotEmpty(spliteWidth) ? spliteWidth : String.valueOf(block.getKaiLiaoWidth())))) + .area(BigDecimal.valueOf(block.getArea())) + .texture(block.getTexture()) + .holeFace(block.getHoleFace()) + .isDoor(block.getIsDoor()) + .openDoorType(block.getOpenDoorType()) + .isSpecialShaped(unRegular) + .isSculpt(isModel) + .isRowHole(isRawHole) + .customPlateNoBuilder(new StringBuilder()) + .holeArrange(block.getHoleArrange()) + .unregularPointCount(block.getUnregularPointCount()) + .frontHoleCount(block.getFrontHoleCount()) + .backHoleCount(block.getBackHoleCount()) + .sideHoleCount(block.getSideHoleCount()) + .frontModelCount(block.getFrontModelCount()) + .backModelCount(block.getBackModelCount()) + .offsetX(BigDecimal.valueOf(block.getOffsetX())) + .offsetY(BigDecimal.valueOf(block.getOffsetY())) + .isArcAcross(getDefaultFalse(block.getIsArcBase())) + .moduleTypeId(0L) + .isOptimized(false) + .isCutted(0) + .isCancel(false) + .filterType(EMPTY_STRING) + .sealLeft(BigDecimal.valueOf(block.getSealLeft())) + .sealRight(BigDecimal.valueOf(block.getSealRight())) + .sealUp(BigDecimal.valueOf(block.getSealUp())) + .sealDown(BigDecimal.valueOf(block.getSealDown())) + .remark(remark.toString()) + .deleted(false) + .organId(organId) + .build(); + plateDO.setCreator(operatorName); + plateDO.setUpdater(operatorName); + plateDO.setCreateTime(now); + plateDO.setUpdateTime(now); + + // 生成自定义板编号 + generateCustomPlateNo(plateDO, block.getCustBlockNo()); + + //批量保存板件 + // 达到板件数量阈值,停止入库,更新全局参数停止后续入库 + currentPlateNum += 1; + if (currentPlateNum > cadImportPlateNumThreshold) { + plateNumReachThreshold = true; + return; + } + plateDOS.add(plateDO); + orderPlateBatchInsertWithinThreshold(plateDOS, false); + + // 创建es造型数据 + createModel(plateDO, block, plateRemark); + // 批量插入造型数据 + orderModelsBatchInsertWithinThreshold(false); + + // 遍历加工组信息,生成对应的加工组和item + analyzeBlockProcessGroup(orderBodyDO, block, plateId); + } + + /** + * 解析板件加工组 + * + * @param orderBodyDO + * @param block + * @param plateId + */ + private void analyzeBlockProcessGroup(OrderBodyDO orderBodyDO, WebCadDataBlockReqVO block, Long plateId) { + Long bodyId = orderBodyDO.getId(); + Long roomId = orderBodyDO.getRoomId(); + + List groupIds = block.getGroupIds(); + if (CollUtil.isNotEmpty(groupIds)) { + // 加工组缓存存在,一个加工组一个orderGroup+orderItem + for (Integer groupId : groupIds) { + WebCadDataGroupInfoReqVO groupInfo = processGroupMap.get(groupId); + String groupMapKey = orderBodyDO.getMultiRoomBodyName() + groupInfo.getGroupName(); + Long orderGroupId = orderGroupMap.get(groupMapKey); + // 房间+柜体+加工组名称存在累加板件和异形数量,不存在新增groupDO和orderGroupMap缓存 + if (ObjectUtil.isNull(orderGroupId)) { + orderGroupId = (Long) snowFlakeGenerator.nextId(null); + OrderGroupDO orderGroupDO = OrderGroupDO + .builder() + .id(orderGroupId) + .organId(organId) + .orderId(orderId) + .bodyId(bodyId) + .groupTypeId((Long) snowFlakeGenerator.nextId(null)) + .groupTypeName(groupInfo.getGroupTypeName()) + .name(groupInfo.getGroupTypeName()) + .width(groupInfo.getWidth()) + .height(groupInfo.getHeight()) + .depth(groupInfo.getDepth()) + .multiNum(0) + .plateNum(0) + .unregularNum(0) + .filename("无") + .remark("无") + .deleted(false) + .build(); + orderGroupDO.setCreator(operatorName); + orderGroupDO.setUpdater(operatorName); + orderGroupDO.setCreateTime(now); + orderGroupDO.setUpdateTime(now); + + orderGroupMap.put(groupMapKey, orderGroupId); + orderGroupDOS.add(orderGroupDO); + orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, false); + } + + OrderItemDO orderItemDO = OrderItemDO + .builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .roomId(roomId) + .bodyId(bodyId) + .groupId(orderGroupId) + .plateId(plateId) + .packageId(0L) + .partsId(0L) + .num(1.0) + .organId(organId) + .build(); + orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); + } + } else { + // 没有归属的加工组,只创建一个orderItem + OrderItemDO orderItemDO = OrderItemDO + .builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .roomId(roomId) + .bodyId(bodyId) + .groupId(0L) + .plateId(plateId) + .packageId(0L) + .partsId(0L) + .num(1.0) + .organId(organId) + .build(); + orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); + } + } + + /** + * 创建板件造型es数据 + */ + private void createModel(PlateDO plateDO, WebCadDataBlockReqVO block, WebCadDataBlockRemarkVO plateRemark) { + // 点阵信息 + WebCadDataBlockReqVO.PointInfoDTO pointInfo = block.getPointInfo(); + + OrderModelDO orderModelDO = OrderModelDO.builder() + .orderId(orderId) + .plateId(plateDO.getId()) + .batchId(batchId) + .texture(block.getTexture()) + .typographicFace(block.getHoleArrange()) + .openDoorType(block.getOpenDoorType()) + .splitLength(BigDecimal.valueOf(block.getKaiLiaoHeight())) + .splitWidth(BigDecimal.valueOf(block.getKaiLiaoWidth())) + .offsetX(BigDecimal.valueOf(block.getOffsetX())) + .offsetY(BigDecimal.valueOf(block.getOffsetY())) + .pointDetail(getPointDetail(pointInfo.getPointDetail())) + .rawPointDetail(getRawPointDetail(pointInfo.getOrgPointDetail())) + .holeDetail(getHoleDetail(pointInfo.getHoleDetail())) + .sideHoleDetail(getSideHoleDetail(pointInfo.getSideHoleDetail())) + .contourDetail(getContourDetail(pointInfo.getModelDetail())) + .sideDetail(getSideDetail(pointInfo.getSideModelDetail())) + .sideRemark(getSideRemark(plateRemark.getRemarks())) + .boardType(block.getBoardTypeName()) + .has2DModel(block.isHas2DModel()) + .has3DModel(block.isHas3DModel()) + .build(); + + // 处理备注信息 + JSONObject plateExtraRemark = new JSONObject(); + JSONObject extraObject = plateRemark.getExtraObject(); + if (ObjectUtil.isNotNull(extraObject)) { + plateExtraRemark.put("extra", extraObject); + } + + JSONArray drillsObj = plateRemark.getDrillsObj(); + if (ObjectUtil.isNotNull(drillsObj)) { + plateExtraRemark.put("drills", drillsObj); + } + orderModelDO.setPlateExtraRemark(plateExtraRemark); + + orderModelDO.setGoodsId(block.getGoodsCode()); + orderModelDO.setPlateGoodsId(plateDO.getGoodsId()); + orderModelDO.setOrganId(organId); + orderModelDOS.add(orderModelDO); + if (!esInsert) { + esInsert = true; + } + } + + /** + * 获取生产封边备注 + * + * @param remarks + * @return + */ + private Map getSideRemark(List remarks) { + if (CollUtil.isNotEmpty(remarks)) { + Map sideRemarkMap = new HashMap<>(); + for (int i = 1; i <= remarks.size(); i++) { + sideRemarkMap.put("Remark" + i, remarks.get(i - 1)); + } + return sideRemarkMap; + } + return null; + } + + /** + * 获取板件点明细 + * + * @param cadPointDetailList + * @return + */ + private List getPointDetail(List cadPointDetailList) { + List pointDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadPointDetailList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.PointDetailDTO cadPointDetail : cadPointDetailList) { + PointDetail pointDetail = new PointDetail(); + pointDetail.setPointX(cadPointDetail.getPointX()); + pointDetail.setPointY(cadPointDetail.getPointY()); + pointDetail.setCurve(cadPointDetail.getCurve()); + pointDetails.add(pointDetail); + } + } + return pointDetails; + } + + /** + * 获取板件原始点明细 + * + * @param orgPointDetail + * @return + */ + private List getRawPointDetail(List orgPointDetail) { + List pointDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(orgPointDetail)) { + for (WebCadDataBlockReqVO.PointInfoDTO.OrgPointDetailDTO cadPointDetail : orgPointDetail) { + PointDetail pointDetail = new PointDetail(); + pointDetail.setPointX(cadPointDetail.getPointX()); + pointDetail.setPointY(cadPointDetail.getPointY()); + pointDetail.setCurve(cadPointDetail.getCurve()); + pointDetail.setSealSize(BigDecimal.valueOf(cadPointDetail.getSealSize())); + pointDetails.add(pointDetail); + } + } + return pointDetails; + } + + + /** + * 获取板件孔明细列表 + * + * @param cadHoleDetailList + * @return + */ + private List getHoleDetail(List cadHoleDetailList) { + List holeDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadHoleDetailList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.HoleDetailDTO cadHoleDetail : cadHoleDetailList) { + HoleDetail holeDetail = new HoleDetail(); + holeDetail.setId(String.valueOf(cadHoleDetail.getHoleID())); + holeDetail.setFaceType(cadHoleDetail.getFace()); + holeDetail.setHoleType(cadHoleDetail.getHoleType()); + holeDetail.setStartX(cadHoleDetail.getPointX()); + holeDetail.setStartY(cadHoleDetail.getPointY()); + holeDetail.setRadius(cadHoleDetail.getRadius()); + holeDetail.setDepth(cadHoleDetail.getDepth()); + holeDetails.add(holeDetail); + } + } + return holeDetails; + } + + /** + * 获取侧面孔明细 + * + * @param cadSideHoleDetailList + * @return + */ + private List getSideHoleDetail(List cadSideHoleDetailList) { + List holeDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadSideHoleDetailList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.SideHoleDetailDTO cadHoleDetail : cadSideHoleDetailList) { + HoleDetail holeDetail = new HoleDetail(); + holeDetail.setFaceType(cadHoleDetail.getFace()); + holeDetail.setStartX(cadHoleDetail.getPointX()); + holeDetail.setStartY(cadHoleDetail.getPointY()); + holeDetail.setStartZ(cadHoleDetail.getPointZ()); + holeDetail.setRadius(cadHoleDetail.getRadius()); + holeDetail.setEndX(cadHoleDetail.getPointX2()); + holeDetail.setEndY(cadHoleDetail.getPointY2()); + holeDetail.setEndZ(cadHoleDetail.getPointZ()); + holeDetail.setDepth(cadHoleDetail.getDepth()); + holeDetails.add(holeDetail); + } + } + return holeDetails; + } + + /** + * 获取造型明细 + * + * @param cadModelDetailList + * @return + */ + private List getContourDetail(List cadModelDetailList) { + List modelDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadModelDetailList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO cadModelDetail : cadModelDetailList) { + ModelDetail modelDetail = new ModelDetail(); + modelDetail.setModelID(cadModelDetail.getModelID()); + modelDetail.setLineID(cadModelDetail.getLineID()); + modelDetail.setFaceType(cadModelDetail.getFace()); + modelDetail.setDepth(cadModelDetail.getDepth()); + modelDetail.setKnifeName(cadModelDetail.getKnifeName()); + modelDetail.setKnifeRadius(cadModelDetail.getKnifeRadius()); + + WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO cadOriginModeling = cadModelDetail.getOriginModeling(); + if (ObjectUtil.isNotNull(cadOriginModeling)) { + IOriginModelingData originModelingData = new IOriginModelingData(); + originModelingData.setAddLen(cadOriginModeling.getAddLen()); + originModelingData.setAddWidth(cadOriginModeling.getAddWidth()); + originModelingData.setAddDepth(cadOriginModeling.getAddDepth()); + + WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO.OutlineDTO cadOutline = cadOriginModeling.getOutline(); + originModelingData.setOutline(getOriginModelingOutlineList(cadOutline)); + + modelDetail.setOriginModeling(originModelingData); + } + List pointList = cadModelDetail.getPointList(); + modelDetail.setPointList(getModelDetailPointList(pointList)); + + List offSetList = cadModelDetail.getOffSetList(); + modelDetail.setOffSetList(getModelDetailOffsetList(offSetList)); + + modelDetails.add(modelDetail); + } + } + return modelDetails; + } + + /** + * 获取造型偏移量列表 + * + * @param cadOffSetList + * @return + */ + private List getModelDetailOffsetList(List cadOffSetList) { + List offSetLists = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadOffSetList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OffSetListDTO cadOffset : cadOffSetList) { + OffSetList offSet = new OffSetList(); + offSet.setValue(cadOffset.getValue()); + offSet.setDepth(cadOffset.getDeep()); + offSet.setAngle(cadOffset.getAngle()); + offSet.setName(cadOffset.getName()); + offSet.setRadius(cadOffset.getRadius()); + + offSetLists.add(offSet); + } + } + return offSetLists; + } + + /** + * 获取造型点列表 + * + * @param cadPointList + * @return + */ + private List getModelDetailPointList(List cadPointList) { + List pointList = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadPointList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.PointListDTO cadPoint : cadPointList) { + PointList point = new PointList(); + point.setPointX(cadPoint.getPointX()); + point.setPointY(cadPoint.getPointY()); + point.setCurve(cadPoint.getCurve()); + point.setDepth(cadPoint.getDepth()); + point.setRadius(cadPoint.getRadius()); + + pointList.add(point); + } + } + return pointList; + } + + /** + * 获取造型轮廓 + * + * @param cadOutline + * @return + */ + private List getOriginModelingOutlineList(WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO.OutlineDTO cadOutline) { + List outlineList = new ArrayList<>(); + if (ObjectUtil.isNull(cadOutline)) { + return outlineList; + } + + List buls = cadOutline.getBuls(); + List pts = cadOutline.getPts(); + if (CollUtil.isNotEmpty(pts) && CollUtil.isNotEmpty(buls)) { + for (int i = 0; i < pts.size(); i++) { + IContourData iContourData = new IContourData(); + Point point = new Point(); + point.setX(pts.get(i).getX()); + point.setY(pts.get(i).getY()); + iContourData.setPts(point); + iContourData.setBuls(buls.get(i)); + outlineList.add(iContourData); + } + } + return outlineList; + } + + /** + * 获取侧面造型明细 + * + * @param cadSideModelDetailList + * @return + */ + private List getSideDetail(List cadSideModelDetailList) { + List modelDetails = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadSideModelDetailList)) { + for (WebCadDataBlockReqVO.PointInfoDTO.SideModelDetailDTO cadSideModelDetail : cadSideModelDetailList) { + ModelDetail modelDetail = new ModelDetail(); + modelDetail.setModelID(cadSideModelDetail.getModelID()); + modelDetail.setLineID(cadSideModelDetail.getLineID()); + modelDetail.setFaceType(cadSideModelDetail.getFace()); + modelDetail.setDepth(cadSideModelDetail.getDepth()); + modelDetail.setKnifeName(cadSideModelDetail.getKnifeName()); + modelDetail.setKnifeRadius(cadSideModelDetail.getKnifeRadius()); + + WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO cadSideOriginModeling = cadSideModelDetail.getOriginModeling(); + if (ObjectUtil.isNotNull(cadSideOriginModeling)) { + IOriginModelingData originModelingData = new IOriginModelingData(); + originModelingData.setAddLen(cadSideOriginModeling.getAddLen()); + originModelingData.setAddWidth(cadSideOriginModeling.getAddWidth()); + originModelingData.setAddDepth(cadSideOriginModeling.getAddDepth()); + originModelingData.setThickness(cadSideOriginModeling.getThickness()); + originModelingData.setDir(cadSideOriginModeling.getDir()); + originModelingData.setKnifeRadius(cadSideOriginModeling.getKnifeRadius()); + + originModelingData.setOutline(getOriginModelingOutlineList(cadSideOriginModeling.getOutline())); + + originModelingData.setHoles(getSideModelingHoles(cadSideOriginModeling.getHoles())); + + modelDetail.setOriginModeling(originModelingData); + } + modelDetail.setPointList(getModelDetailPointList(cadSideModelDetail.getPointList())); + + modelDetail.setOffSetList(getModelDetailOffsetList(cadSideModelDetail.getOffSetList())); + + modelDetails.add(modelDetail); + } + } + return modelDetails; + } + + /** + * 获取侧面孤岛造型 + * + * @param cadSideHoles + * @return + */ + private List> getSideModelingHoles(List cadSideHoles) { + List> icontourDataList = new ArrayList<>(); + if (CollUtil.isNotEmpty(cadSideHoles)) { + for (WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO.HolesDTO sideHole : cadSideHoles) { + List contourDatas = new ArrayList<>(); + List pts = sideHole.getPts(); + List buls = sideHole.getBuls(); + for (int i = 0; i < pts.size(); i++) { + IContourData iContourData = new IContourData(); + WebCadDataBlockReqVO.PointInfoDTO.ModelDetailDTO.OriginModelingDTO.HolesDTO.PtsDTO ptsDTO = pts.get(i); + Double bul = buls.get(i); + iContourData.setBuls(bul); + iContourData.setPts(new Point(ptsDTO.getX(), ptsDTO.getY(), 0.0)); + contourDatas.add(iContourData); + } + icontourDataList.add(contourDatas); + } + } + return icontourDataList; + } + + /** + * 获取板件备注 + * + * @param block + * @return + */ + private WebCadDataBlockRemarkVO getPlateRemark(WebCadDataBlockReqVO block) { + WebCadDataBlockRemarkVO blockRemark = new WebCadDataBlockRemarkVO(); + + List> remarks = block.getAllRemarkList(); + if (CollUtil.isEmpty(remarks)) { + return blockRemark; + } + + List blockRemarkList = new ArrayList<>(); + for (List remark : remarks) { + if (CollUtil.isNotEmpty(remark) && remark.size() == 2) { + String key = remark.get(0); + String value = remark.get(1); + + if ("#extra".equals(key)) { + blockRemark.setExtraObject(JSON.parseObject(value)); + } else if ("#drills".equals(key)) { + blockRemark.setDrillsObj(JSON.parseArray(value)); + } else { + blockRemarkList.add(value); + } + } + } + blockRemark.setRemarks(blockRemarkList); + return blockRemark; + } + + /** + * 生成自定义板编号 + * + * @param plateDO + * @param cadCustBlockNo cad板号 + */ + private void generateCustomPlateNo(PlateDO plateDO, Integer cadCustBlockNo) { + if (!isFirstPlate) { + isFirstPlate = true; + } + // 配置不为空时,生成自定义板编号 + if (ObjectUtil.isNotNull(plateNoGenerateConfigVO)) { + customPlateNoGenerateService.generateCustomPlateNo(orderId, plateDO, plateNoGenerateConfigVO, isFirstPlate); + } else { + // 配置为空的时候,使用cad的板编号 + if (ObjectUtil.isNotNull(cadCustBlockNo)) { + plateDO.setCustomPlateNo(String.valueOf(cadCustBlockNo)); + } + } + } + + /** + * 解析配件列表 + * + * @param reader + */ + private void analyzePartsRoomList(JSONReader reader) { + reader.startArray(); + while (reader.hasNext()) { + reader.startObject(); + + String roomName = null; + Long roomId = null; + while (reader.hasNext()) { + String key = reader.readString(); + if ("name".equals(key)) { + roomName = reader.readString(); + + // 生产单下已有房间名直接使用roomId + Long existRoomId = existRoomIdMap.get(roomName); + if (ObjectUtil.isNotNull(existRoomId)) { + roomId = existRoomId; + } else { + // 查询生产单下是否已有同名房间 + List existRoomIds = orderBodyMapper.selectList(new LambdaQueryWrapper() + .select(OrderBodyDO::getRoomId) + .eq(OrderBodyDO::getOrderId, orderId) + .eq(OrderBodyDO::getOrganId, organId) + .eq(OrderBodyDO::getDeleted, false) + .eq(OrderBodyDO::getRoomName, roomName)).stream().map(OrderBodyDO::getRoomId).toList(); + if (CollUtil.isNotEmpty(existRoomIds)) { + roomId = existRoomIds.get(0); + existRoomIdMap.put(roomName, roomId); + } else { + roomId = (Long) snowFlakeGenerator.nextId(null); + existRoomIdMap.put(roomName, roomId); + } + } + } else if ("children".equals(key)) { + // 开始Parts.children + reader.startArray(); + while (reader.hasNext()) { + analyzePartsBodyList(reader, roomName, roomId); + } + reader.endArray(); + } + } + reader.endObject(); + } + reader.endArray(); + + orderPartBatchInsertWithinThreshold(orderPartsDOS, true); + } + + + private void analyzePartsBodyList(JSONReader reader, String roomName, Long roomId) { + reader.startObject(); + + String boxName = null; + String roomBoxKey = null; + Integer count = 1; + while (reader.hasNext()) { + String key = reader.readString(); + if ("name".equals(key)) { + boxName = reader.readString(); + + roomBoxKey = roomName + boxName; + // 获取缓存中的成本数量 + count = roomBodyMap.get(roomBoxKey); + + } else if ("objList".equals(key)) { + // Blocks.children.objList开始 + reader.startArray(); + while (reader.hasNext()) { + WebCadDataPartsReqVO.BlockObjectListDTO part = reader.readObject(WebCadDataPartsReqVO.BlockObjectListDTO.class); + // 成倍创建 + if (ObjectUtil.isNull(count)) { + // 房间+柜体不在成倍缓存中, 再检查bodyMap, 再没有创建房间,缓存房间到bodyMap + createPartsUnknownBody(roomId, roomName, boxName, part); + } else { + multipleCreateProcessGroup(count, roomBoxKey, part); + } + } + reader.endArray(); + } + } + reader.endObject(); + } + + /** + * 创建不需要成倍的房间柜体以及其下的板件 + * + * @param roomName + * @param bodyName + * @param part + */ + private void createPartsUnknownBody(Long roomId, String roomName, String bodyName, WebCadDataPartsReqVO.BlockObjectListDTO part) { + String roomBodyKey = roomName + bodyName; + OrderBodyDO orderBodyDO = bodyMap.get(roomBodyKey); + if (ObjectUtil.isNull(orderBodyDO)) { + Long bodyId = (Long) snowFlakeGenerator.nextId(null); + orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) + .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0) + .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); + + // 缓存成倍的柜体信息 + bodyMap.put(roomBodyKey, orderBodyDO); + } + + analyzePartProcessGroup(orderBodyDO, part); + } + + /** + * 成倍创建配件加工组和item + * + * @param count + * @param roomNameKey + * @param part + */ + private void multipleCreateProcessGroup(Integer count, String roomNameKey, WebCadDataPartsReqVO.BlockObjectListDTO part) { + // 成倍数量 + for (int j = 0; j < count; j++) { + // 获取板材已经创建的柜体,缓存key:房间名+柜体名+成倍序号 + OrderBodyDO orderBodyDO = bodyMap.get(roomNameKey + j); + if (ObjectUtil.isNull(orderBodyDO)) { + return; + } + // 解析配件的加工组,创建对应的orderItem + analyzePartProcessGroup(orderBodyDO, part); + } + } + + private void analyzePartProcessGroup(OrderBodyDO orderBodyDO, WebCadDataPartsReqVO.BlockObjectListDTO part) { + Long bodyId = orderBodyDO.getId(); + Long roomId = orderBodyDO.getRoomId(); + + // 获取orderPart + analyzeOrderPart(part); + + // 遍历加工组信息,生成对应的orderItem + List groupIds = part.getGroupIds(); + if (CollUtil.isNotEmpty(groupIds)) { + Double partNum = 0.0; + // 带加工组的配件增加item只记录配件id和数量 + partNum += part.getNum(); + for (Integer groupId : groupIds) { + WebCadDataGroupInfoReqVO groupInfo = processGroupMap.get(groupId); + String groupMapKey = orderBodyDO.getMultiRoomBodyName() + groupInfo.getGroupName(); + Long orderGroupId = orderGroupMap.get(groupMapKey); + // 房间+柜体+加工组名称存在累加配件item,不存在新增groupDO和orderGroupMap缓存 + if (ObjectUtil.isNull(orderGroupId)) { + orderGroupId = (Long) snowFlakeGenerator.nextId(null); + OrderGroupDO orderGroupDO = OrderGroupDO + .builder() + .id(orderGroupId) + .organId(organId) + .orderId(orderId) + .bodyId(bodyId) + .groupTypeId((Long) snowFlakeGenerator.nextId(null)) + .groupTypeName(groupInfo.getGroupTypeName()) + .name(groupInfo.getGroupTypeName()) + .width(groupInfo.getWidth()) + .height(groupInfo.getHeight()) + .depth(groupInfo.getDepth()) + .multiNum(0) + .plateNum(0) + .unregularNum(0) + .filename("无") + .remark("无") + .deleted(false) + .build(); + orderGroupDO.setCreator(operatorName); + orderGroupDO.setUpdater(operatorName); + orderGroupDO.setCreateTime(now); + orderGroupDO.setUpdateTime(now); + + orderGroupMap.put(groupMapKey, orderGroupId); + orderGroupDOS.add(orderGroupDO); + orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, false); + } + + OrderItemDO orderItemDO = OrderItemDO + .builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .roomId(roomId) + .bodyId(bodyId) + .groupId(orderGroupId) + .partsId(part.getImesPartsId()) + .packageId(0L) + .plateId(0L) + .num(part.getNum()) + .organId(organId) + .build(); + orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); + } + OrderItemDO orderItemDO = OrderItemDO + .builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .roomId(roomId) + .bodyId(bodyId) + .groupId(0L) + .partsId(part.getImesPartsId()) + .packageId(0L) + .plateId(0L) + .num(partNum) + .organId(organId) + .build(); + orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); + } else { + OrderItemDO orderItemDO = OrderItemDO + .builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .roomId(roomId) + .bodyId(bodyId) + .groupId(0L) + .partsId(part.getImesPartsId()) + .packageId(0L) + .plateId(0L) + .num(part.getNum()) + .organId(organId) + .build(); + orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); + } + } + + /** + * 分组配件解析出orderParts,id回显到cad配件 + * + * @param part + */ + private void analyzeOrderPart(WebCadDataPartsReqVO.BlockObjectListDTO part) { + boolean composite = part.getIsComposite(); + String partType = part.getType(); + String factory = part.getFactory(); + String model = part.getModel(); + String spec = part.getSpec(); + String height = part.getHeight(); + String width = part.getWidth(); + String thickness = part.getThickness(); + String unit = part.getUnit(); + String brand = part.getBrand(); + + // 分类配件的键组合 + String groupKey = composite + partType + factory + model + spec + height + width + thickness + unit + brand; + + Long orderPartId = orderPartMap.get(groupKey); + if (ObjectUtil.isNull(orderPartId)) { + Long partId = (Long) snowFlakeGenerator.nextId(null); + + String color = null; + String material = null; + if (PART_CATEGORY_ONE.equals(partType)) { + WebCadDataPartsReqVO.BlockObjectListDTO.GroupDataDTO partGroupData = part.getGroupData(); + color = partGroupData.getColor(); + material = partGroupData.getMaterial(); + // 封边条宽度从系统配置中获取宽度对应 + sealEdgeWidthMatch(part); + // 规格可能修改,再获取一次 + spec = part.getSpec(); + } else if (PART_CATEGORY_THREE.equals(partType)) { + color = getFieldFromSpec(part.getSpec(), 2); + material = getFieldFromSpec(part.getSpec(), 1); + } + + String type = changePartType(partType, part.getIsComposite()); + // todo remark、备注信息到es + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id(partId) + .orderId(orderId) + .color(getEmpty(color)) + .category(type) + .type(type) + .goodsId(EMPTY_STRING) + .length(NumberUtil.parseDouble(part.getHeight())) + .width(NumberUtil.parseDouble(part.getWidth())) + .thickness(NumberUtil.parseDouble(part.getThickness())) + .isComposite(part.getIsComposite()) + .name(part.getName()) + .material(getEmpty(material)) + .model(getEmpty(model)) + .spec(getEmpty(spec)) + .brand(getEmpty(brand)) + .factory(getEmpty(factory)) + .unit(part.getUnit()) + .price(0.0) + .subparts(EMPTY_STRING) + .remark(getEmpty(part.getRemark())) + .organId(organId) + .deleted(false) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + orderPartsDOS.add(orderPartsDO); + orderPartBatchInsertWithinThreshold(orderPartsDOS, false); + + // orderpart id回显到配件 + part.setImesPartsId(partId); + + orderPartMap.put(groupKey, partId); + } else { + // orderpart id回显到配件 + part.setImesPartsId(orderPartId); + } + } + + /** + * 从规格中获取属性,例:material、color + * + * @return + */ + private String getFieldFromSpec(String spec, int index) { + if (StringUtils.isNotEmpty(spec)) { + String[] specSplit = spec.split("\\|"); + if (specSplit.length > index) { + return specSplit[index]; + } + } + return null; + } + + + /** + * 封边条宽度匹配,获取厚度 + * + * @param part + */ + private void sealEdgeWidthMatch(WebCadDataPartsReqVO.BlockObjectListDTO part) { + // 获取宽度、厚度 + WebCadDataPartsReqVO.BlockObjectListDTO.GroupDataDTO partGroupData = part.getGroupData(); + + if (ObjectUtil.isNotNull(partGroupData)) { + part.setThickness(String.valueOf(partGroupData.getSize())); + Integer thickness = partGroupData.getThickness(); + + // 是否匹配上系统配置的封边条宽度配置,对应上了需要同步修改spec的中的内容 + boolean sealEdgeConfigMatch = false; + String matchWidth = null; + for (SystemConfigSealEdgeRespDTO configSealEdgeRespDTO : sealEdgeConfigList) { + // 宽度处于配置范围,宽取值作为最终配件宽度 + if (thickness >= configSealEdgeRespDTO.getWidthMin() && thickness <= configSealEdgeRespDTO.getWidthMax()) { + matchWidth = String.valueOf(configSealEdgeRespDTO.getWidthValue()); + part.setWidth(matchWidth); + sealEdgeConfigMatch = true; + break; + } + } + if (sealEdgeConfigMatch) { + part.setSpec(modifySealEdgeSpec(part.getSpec(), matchWidth)); + } else { + // 没有匹配的对应直接使用板厚做宽度 + part.setWidth(String.valueOf(thickness)); + } + } + } + + /** + * 根据对应的宽度修改spec规格中的第二段宽度 + * + * @param spec + * @param width + * @return + */ + private String modifySealEdgeSpec(String spec, String width) { + if (StringUtils.isNotEmpty(spec)) { + String[] specSplit = spec.split("-"); + // 例:15mm-18mm + if (specSplit.length == 2) { + return specSplit[0] + "-" + width + "mm"; + } + // 例:9mm-18mm-经典檀木 + if (specSplit.length == 3) { + return specSplit[0] + "-" + width + "mm-" + specSplit[2]; + } + } + return spec; + } + + /** + * value为空返回EMPTY_STRING + * + * @param value + * @return + */ + private String getEmpty(String value) { + return StringUtils.defaultIfEmpty(value, EMPTY_STRING); + } + + /** + * value为空返回false + * + * @param value + * @return + */ + private Boolean getDefaultFalse(Boolean value) { + return ObjectUtil.defaultIfNull(value, false); + } + + /** + * 配件类型转换 + * + * @param objectType + * @param isComposite + * @return + */ + private String changePartType(String objectType, boolean isComposite) { + if (PART_CATEGORY_ONE.equals(objectType)) { + return PART_CATEGORY_ONE; + } else { + if (isComposite) { + return PART_CATEGORY_THREE; + } else { + return PART_CATEGORY_TWO; + } + } + } + + /** + * 每达到阈值就批量插入一次 + * + * @param baseBatchMapper + * @param list + * @param isLast 是否最后一次插入,不是就需要清理list + */ + private void orderInfoBatchInsertWithinThreshold(BaseBatchMapper baseBatchMapper, List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + baseBatchMapper.insertBatchSomeColumn(list); + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + private void orderPlateBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + String sql = "INSERT INTO order_plate (id,organ_id,order_id,name,plate_no,type,goods_id,width,height,thickness,split_width,split_height,split_thickness,seal_left,seal_right,seal_up,seal_down,area,texture,hole_face,hole_arrange,unregular_point_count,front_hole_count,back_hole_count,side_hole_count,front_model_count,back_model_count,is_door,open_door_type,offset_x,offset_y,is_arc_across,module_type_id,is_special_shaped,is_sculpt,is_row_hole,is_optimized,is_cutted,filter_type,remark,is_cancel,deleted,custom_plate_no,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + PlateDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrganId()); + ps.setLong(3, item.getOrderId()); + ps.setString(4, item.getName()); + ps.setString(5, item.getPlateNo()); + ps.setInt(6, item.getType()); + ps.setLong(7, item.getGoodsId()); + ps.setBigDecimal(8, item.getWidth()); + ps.setBigDecimal(9, item.getHeight()); + ps.setBigDecimal(10, item.getThickness()); + ps.setBigDecimal(11, item.getSplitWidth()); + ps.setBigDecimal(12, item.getSplitHeight()); + ps.setBigDecimal(13, item.getSplitThickness()); + ps.setBigDecimal(14, item.getSealLeft()); + ps.setBigDecimal(15, item.getSealRight()); + ps.setBigDecimal(16, item.getSealUp()); + ps.setBigDecimal(17, item.getSealDown()); + ps.setBigDecimal(18, item.getArea()); + ps.setInt(19, item.getTexture()); + ps.setInt(20, item.getHoleFace()); + ps.setInt(21, item.getHoleArrange()); + ps.setInt(22, item.getUnregularPointCount()); + ps.setInt(23, item.getFrontHoleCount()); + ps.setInt(24, item.getBackHoleCount()); + ps.setInt(25, item.getSideHoleCount()); + ps.setInt(26, item.getFrontModelCount()); + ps.setInt(27, item.getBackModelCount()); + ps.setBoolean(28, item.getIsDoor()); + ps.setInt(29, item.getOpenDoorType()); + ps.setBigDecimal(30, item.getOffsetX()); + ps.setBigDecimal(31, item.getOffsetY()); + ps.setBoolean(32, item.getIsArcAcross()); + ps.setLong(33, item.getModuleTypeId()); + ps.setBoolean(34, item.getIsSpecialShaped()); + ps.setBoolean(35, item.getIsSculpt()); + ps.setBoolean(36, item.getIsRowHole()); + ps.setBoolean(37, item.getIsOptimized()); + ps.setInt(38, item.getIsCutted()); + ps.setString(39, item.getFilterType()); + ps.setString(40, item.getRemark()); + ps.setBoolean(41, item.getIsCancel()); + ps.setBoolean(42, item.getDeleted()); + ps.setString(43, item.getCustomPlateNo()); + ps.setTimestamp(44, Timestamp.valueOf(item.getCreateTime())); + ps.setTimestamp(45, Timestamp.valueOf(item.getUpdateTime())); + ps.setString(46, item.getCreator()); + ps.setString(47, item.getUpdater()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + private void orderItemBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + + String sql = "INSERT INTO order_item (id,order_id,type,room_id,body_id,package_id,group_id,plate_id,parts_id,num,organ_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderItemDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrderId()); + ps.setInt(3, item.getType()); + ps.setLong(4, item.getRoomId()); + ps.setLong(5, item.getBodyId()); + ps.setLong(6, item.getPackageId()); + ps.setLong(7, item.getGroupId()); + ps.setLong(8, item.getPlateId()); + ps.setLong(9, item.getPartsId()); + ps.setDouble(10, item.getNum()); + ps.setLong(11, item.getOrganId()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + private void orderPartBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + + String sql = "INSERT INTO order_parts (id,organ_id,order_id,goods_id,name,color,material,category,type,width,length,thickness,model,spec,brand,factory,unit,price,is_composite,subparts,remark,deleted,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderPartsDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrganId()); + ps.setLong(3, item.getOrderId()); + ps.setString(4, item.getGoodsId()); + ps.setString(5, item.getName()); + ps.setString(6, item.getColor()); + ps.setString(7, item.getMaterial()); + ps.setString(8, item.getCategory()); + ps.setString(9, item.getType()); + ps.setDouble(10, item.getWidth()); + ps.setDouble(11, item.getLength()); + ps.setDouble(12, item.getThickness()); + ps.setString(13, item.getModel()); + ps.setString(14, item.getSpec()); + ps.setString(15, item.getBrand()); + ps.setString(16, item.getFactory()); + ps.setString(17, item.getUnit()); + ps.setDouble(18, item.getPrice()); + ps.setBoolean(19, item.getIsComposite()); + ps.setString(20, item.getSubparts()); + ps.setString(21, item.getRemark()); + ps.setBoolean(22, item.getDeleted()); + ps.setTimestamp(23, Timestamp.valueOf(item.getCreateTime())); + ps.setTimestamp(24, Timestamp.valueOf(item.getUpdateTime())); + ps.setString(25, item.getCreator()); + ps.setString(26, item.getUpdater()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + /** + * 每达到阈值就批量插入一次生产单造型数据和压缩数据 + * + * @param isLast 是否最后一次插入,不是就需要清理list + */ + private void orderModelsBatchInsertWithinThreshold(boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(orderModelDOS) && (orderModelDOS.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + // 保存生产单造型数据 + orderInputProcessor.batchAsyncSaveModel(orderModelDOS); + if (!isLast) { + // 存储完成清理 list + orderModelDOS.clear(); + } + } + } + + /** + * 每batchSize条拆分dataList + * + * @param dataList + */ + private List> batchProcess(List dataList) { + List> resultList = new ArrayList<>(); + if (CollUtil.isEmpty(dataList)) { + return resultList; + } + + int total = dataList.size(); + for (int i = 0; i < total; i += BATCH_THRESHOLD_NUMBER) { + int end = Math.min(i + BATCH_THRESHOLD_NUMBER, total); + List subList = dataList.subList(i, end); + + if (!subList.isEmpty()) { + resultList.add(subList); + } + } + return resultList; + } + + /** + * 保存数据 + * orderBody、orderGroup + */ + private void saveData() { + // 分成1000一组 + List> bodyList = batchProcess(bodyMap.values().stream().toList()); + List> groupList = batchProcess(orderGroupDOS); + + // 保存 + saveBody(bodyList); + saveGroup(groupList); + } + + /** + * 插入柜体 + * + * @param bodyList + */ + private void saveBody(List> bodyList) { + for (List bodys : bodyList) { + String sql = "INSERT INTO order_body (id, organ_id, order_id, room_id, room_name, name, width, height, depth, multi_num, plate_num, unregular_num, filename, remark, deleted,create_time,update_time,creator,updater) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderBodyDO orderBodyDO = bodys.get(index); + ps.setLong(1, orderBodyDO.getId()); + ps.setLong(2, orderBodyDO.getOrganId()); + ps.setLong(3, orderBodyDO.getOrderId()); + ps.setLong(4, orderBodyDO.getRoomId()); + ps.setString(5, orderBodyDO.getRoomName()); + ps.setString(6, orderBodyDO.getName()); + ps.setDouble(7, orderBodyDO.getWidth()); + ps.setDouble(8, orderBodyDO.getHeight()); + ps.setDouble(9, orderBodyDO.getDepth()); + ps.setInt(10, orderBodyDO.getMultiNum()); + ps.setInt(11, orderBodyDO.getPlateNum()); + ps.setInt(12, orderBodyDO.getUnregularNum()); + ps.setString(13, orderBodyDO.getFilename()); + ps.setString(14, orderBodyDO.getRemark()); + ps.setBoolean(15, orderBodyDO.getDeleted()); + ps.setTimestamp(16, Timestamp.valueOf(orderBodyDO.getCreateTime())); + ps.setTimestamp(17, Timestamp.valueOf(orderBodyDO.getUpdateTime())); + ps.setString(18, orderBodyDO.getCreator()); + ps.setString(19, orderBodyDO.getUpdater()); + } + + @Override + public int getBatchSize() { + return bodys.size(); + } + }); + } + } + + /** + * 插入加工组 + * + * @param groupList + */ + private void saveGroup(List> groupList) { + for (List groups : groupList) { + String sql = "INSERT INTO order_group (id, organ_id, order_id, body_id, group_type_id, group_type_name, name, width, height, depth, multi_num, plate_num, unregular_num, filename, remark, deleted,create_time,update_time,creator,updater) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderGroupDO orderGroupDO = groups.get(index); + ps.setLong(1, orderGroupDO.getId()); + ps.setLong(2, orderGroupDO.getOrganId()); + ps.setLong(3, orderGroupDO.getOrderId()); + ps.setLong(4, orderGroupDO.getBodyId()); + ps.setLong(5, orderGroupDO.getGroupTypeId()); + ps.setString(6, orderGroupDO.getGroupTypeName()); + ps.setString(7, orderGroupDO.getName()); + ps.setDouble(8, orderGroupDO.getWidth()); + ps.setDouble(9, orderGroupDO.getHeight()); + ps.setDouble(10, orderGroupDO.getDepth()); + ps.setInt(11, orderGroupDO.getMultiNum()); + ps.setInt(12, orderGroupDO.getPlateNum()); + ps.setInt(13, orderGroupDO.getUnregularNum()); + ps.setString(14, orderGroupDO.getFilename()); + ps.setString(15, orderGroupDO.getRemark()); + ps.setBoolean(16, orderGroupDO.getDeleted()); + ps.setTimestamp(17, Timestamp.valueOf(orderGroupDO.getCreateTime())); + ps.setTimestamp(18, Timestamp.valueOf(orderGroupDO.getUpdateTime())); + ps.setString(19, orderGroupDO.getCreator()); + ps.setString(20, orderGroupDO.getUpdater()); + } + + @Override + public int getBatchSize() { + return groups.size(); + } + }); + } + } + + /** + * 清空所有列表 + */ + private void clearAll() { + roomBodyMap.clear(); + bodyMap.clear(); + orderGroupMap.clear(); + materialMap.clear(); + processGroupMap.clear(); + existRoomIdMap.clear(); + orderPartMap.clear(); + + plateDOS.clear(); + orderItemDOS.clear(); + orderGroupDOS.clear(); + orderPartsDOS.clear(); + orderModelDOS.clear(); + rawGoodsDOS.clear(); + goodsDOS.clear(); + sealEdgeConfigList.clear(); + } + + /** + * 移除缓存的临时文件 + */ + private void deleteTempFile() { + FileUtil.del(tempFilePath); + } + + /** + * 更新为导入成功 + */ + private void updateTaskSuccess(Long taskId) { + orderImportTaskMapper.update(new LambdaUpdateWrapper().eq(OrderImportTaskDO::getId, taskId).set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_SUCCESS.getStatus())); + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java index b620ccdad..99ab8fd41 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java @@ -8,11 +8,9 @@ import com.alibaba.excel.util.ListUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.ErrorCode; -import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd; @@ -25,8 +23,8 @@ import com.cf.imes.module.executor.enums.OrderStatusEnum; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataBlockRemarkVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataBlockReqVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataDoubleRoomTreeReqVO; +import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataGroupInfoReqVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataMaterialReqVO; -import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataOrderReqVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataPartsReqVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataProcessGroupReqVO; import com.cf.imes.module.plan.controller.admin.orderImport.webcad.vo.WebCadDataReqVO; @@ -38,7 +36,6 @@ import com.cf.imes.module.plan.dal.dataobject.orderItem.OrderItemDO; import com.cf.imes.module.plan.dal.dataobject.orderParts.OrderPartsDO; import com.cf.imes.module.plan.dal.dataobject.ordermodel.OrderModelDO; import com.cf.imes.module.plan.dal.dataobject.plate.PlateDO; -import com.cf.imes.module.plan.dal.dataobject.plate.PlateGoodDO; import com.cf.imes.module.plan.dal.dataobject.rawgoods.RawGoodsDO; import com.cf.imes.module.plan.dal.elasticsearch.HoleDetail; import com.cf.imes.module.plan.dal.elasticsearch.IContourData; @@ -52,9 +49,6 @@ 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.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.rawgoods.RawGoodsMapper; import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService; @@ -67,10 +61,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionStatus; import java.math.BigDecimal; import java.sql.PreparedStatement; @@ -78,24 +68,16 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_GET_ORG_SEALEDGE_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORG_SEALEDGE_ANALYZE_ERROR; -import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_PLATE_NOT_EXIST_ERROR; -import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_NOT_EXISTS_ERROR; import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL; @@ -110,7 +92,7 @@ public class WebCadOrderImportFactory { /** * 批量操作阈值 */ - private static final int BATCH_THRESHOLD_NUMBER = 800; + private static final int BATCH_THRESHOLD_NUMBER = 1000; private OrderMapper orderMapper; @@ -120,30 +102,18 @@ public class WebCadOrderImportFactory { private PlateMapper plateMapper; - private OrderItemMapper orderItemMapper; - - private OrderGroupMapper orderGroupMapper; - private SnowflakeIdWorker3rd idWorker; private OrderInputProcessor orderInputProcessor; private SystemConfigApi systemConfigApi; - private OrderPartsMapper orderPartsMapper; - private GoodsMapper goodsMapper; private RawGoodsMapper rawGoodsMapper; - private PlateGoodMapper plateGoodMapper; - private CustomPlateNoGenerateService customPlateNoGenerateService; - private DataSourceTransactionManager transactionManager; - - private ThreadPoolTaskExecutor threadPoolTaskExecutor; - private JdbcTemplate jdbcTemplate; private Long organId; @@ -168,31 +138,34 @@ public class WebCadOrderImportFactory { private LocalDateTime now; - // 柜体成倍信息缓存:{ 房间名+柜体名:childrenDTO } - private Map roomBodyMap = new HashMap<>(); + // 柜体成倍信息缓存:{ 房间名+柜体名:count } + private Map roomBodyMap = new HashMap<>(); // 柜体缓存 private Map bodyMap = new HashMap<>(); - // 房间名+柜体名+加工组名 - private Map orderGroupMap = new HashMap<>(); + // 房间名+柜体名+加工组名:加工组id + private Map orderGroupMap = new HashMap<>(); // 板材缓存:{商品编号:order_goods} - private Map materialMap = new HashMap<>(); + private Map materialMap = new HashMap<>(); - // 已存在的房间缓存 - private Map existRoomMap = new HashMap(); + // 已存在房间缓存:{ roomName: roomId } + private Map existRoomIdMap = new HashMap<>(); + + // IsComposite+ObjectType+Factory+Model+Spec+height+width+depth+unit+brand:orderPartId + private Map orderPartMap = new HashMap<>(); // 加工组缓存 - private Map processGroupMap = new HashMap<>(); + private Map processGroupMap = new HashMap<>(); - private List plateDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); - private List orderItemDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); - private List orderGroupDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); - private List orderPartsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List plateDOS = new ArrayList<>(); + private List orderItemDOS = new ArrayList<>(); + private List orderGroupDOS = new ArrayList<>(); + private List orderPartsDOS = new ArrayList<>(); private List orderModelDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); - private List rawGoodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); - private List goodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List rawGoodsDOS = new ArrayList<>(); + private List goodsDOS = new ArrayList<>(); private List sealEdgeConfigList; @@ -201,9 +174,6 @@ public class WebCadOrderImportFactory { private static final String PART_CATEGORY_THREE = "组件"; private static final String EMPTY_STRING = new String(); - // 主线程的data_code - private String peek; - // 当前拆单导入的板件数量(初始包含前n次导入的板件总数) private int currentPlateNum; @@ -218,18 +188,12 @@ public class WebCadOrderImportFactory { SnowFlakeGenerator snowFlakeGenerator, OrderBodyMapper orderBodyMapper, PlateMapper plateMapper, - OrderItemMapper orderItemMapper, - OrderGroupMapper orderGroupMapper, SnowflakeIdWorker3rd idWorker, OrderInputProcessor orderInputProcessor, - OrderPartsMapper orderPartsMapper, GoodsMapper goodsMapper, RawGoodsMapper rawGoodsMapper, - PlateGoodMapper plateGoodMapper, CustomPlateNoGenerateService customPlateNoGenerateService, - DataSourceTransactionManager transactionManager, SystemConfigApi systemConfigApi, - ThreadPoolTaskExecutor threadPoolTaskExecutor, int cadImportPlateNumThreshold, JdbcTemplate jdbcTemplate) { this.organId = organId; @@ -237,23 +201,16 @@ public class WebCadOrderImportFactory { this.snowFlakeGenerator = snowFlakeGenerator; this.orderBodyMapper = orderBodyMapper; this.plateMapper = plateMapper; - this.orderItemMapper = orderItemMapper; - this.orderGroupMapper = orderGroupMapper; this.idWorker = idWorker; this.orderInputProcessor = orderInputProcessor; - this.orderPartsMapper = orderPartsMapper; this.goodsMapper = goodsMapper; this.rawGoodsMapper = rawGoodsMapper; - this.plateGoodMapper = plateGoodMapper; this.customPlateNoGenerateService = customPlateNoGenerateService; - this.transactionManager = transactionManager; this.systemConfigApi = systemConfigApi; - this.threadPoolTaskExecutor = threadPoolTaskExecutor; operatorName = SecurityFrameworkUtils.getLoginUser().getNickname(); now = LocalDateTime.now(); batchId = (Long) snowFlakeGenerator.nextId(null); sealEdgeConfigList = new ArrayList<>(); - peek = DynamicDataSourceContextHolder.peek(); this.cadImportPlateNumThreshold = cadImportPlateNumThreshold; this.jdbcTemplate = jdbcTemplate; } @@ -270,17 +227,17 @@ public class WebCadOrderImportFactory { log.debug("====================【cad拆单解析生产单开始】===================="); // 解析生产单信息 - analyzeOrder(webCadDataReqVO.getOrders()); + analyzeOrder(webCadDataReqVO.getOrderNo()); log.debug("====================【cad拆单解析生产单结束】===================="); log.debug("====================【cad拆单解析板材开始】===================="); // 板材id对应板件 - analyzeMaterials(webCadDataReqVO.getMaterials(), webCadDataReqVO.getBlocks()); + analyzeMaterials(webCadDataReqVO.getMaterials()); log.debug("====================【cad拆单解析板材结束】===================="); log.debug("====================【cad拆单解析加工组开始】===================="); // 解析加工组类型 - analyzeGroups(webCadDataReqVO.getProcessGroup(), webCadDataReqVO.getBlocks(), webCadDataReqVO.getParts()); + analyzeGroups(webCadDataReqVO.getProcessGroup()); log.debug("====================【cad拆单解析加工组结束】===================="); log.debug("====================【cad拆单解析成倍柜体开始】===================="); @@ -298,30 +255,14 @@ public class WebCadOrderImportFactory { analyzeParts(webCadDataReqVO.getParts()); log.debug("====================【cad拆单解析配件结束】===================="); - // 清理引用 - webCadDataReqVO.setBlocks(null); - webCadDataReqVO.setParts(null); - webCadDataReqVO.setMaterials(null); - webCadDataReqVO.setProcessGroup(null); - webCadDataReqVO.setDouleRoomTree(null); - webCadDataReqVO.setOrders(null); - - log.debug("====================【cad拆单同步保存开始】===================="); - // 同步保存板件 - savePlateSync(); - // 同步保存配件 - savePartSync(); - // 同步保存item - saveItemSync(); - log.debug("====================【cad拆单同步保存开始】===================="); - - log.debug("====================【cad拆单异步保存开始】===================="); - // 异步保存数据 - saveDataAsync(); - log.debug("====================【cad拆单异步保存结束】===================="); + orderItemBatchInsertWithinThreshold(orderItemDOS, true); + log.debug("====================【cad拆单全局保存开始】===================="); + // 保存数据柜体、加工组 + saveData(); + log.debug("====================【cad拆单全局保存结束】===================="); if (plateNumReachThreshold) { - log.warn(ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR, orderId).getMessage()); + log.warn(ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR, orderId, cadImportPlateNumThreshold).getMessage()); } } catch (Exception e) { @@ -377,11 +318,10 @@ public class WebCadOrderImportFactory { /** * 解析生产单信息 * - * @param orderReqVO + * @param orderNo */ - private void analyzeOrder(WebCadDataOrderReqVO orderReqVO) { + private void analyzeOrder(String orderNo) { // 查询生产单信息 - String orderNo = orderReqVO.getOrderNo(); OrderDO orderDOFromOrderNo = orderMapper.selectOne(new LambdaUpdateWrapper() .eq(OrderDO::getId, NumberUtil.parseLong(orderNo)) .eq(OrderDO::getOrganId, organId) @@ -408,9 +348,9 @@ public class WebCadOrderImportFactory { .eq(PlateDO::getOrganId, organId) .eq(PlateDO::getDeleted, false) ); - // 2万片阻止继续拆单 + // cadImportPlateNumThreshold万片阻止继续拆单 if (existPlateCount >= cadImportPlateNumThreshold) { - throw ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR, orderId); + throw ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_CHECK_ERROR, orderId, cadImportPlateNumThreshold); } else { currentPlateNum = existPlateCount.intValue(); } @@ -421,60 +361,49 @@ public class WebCadOrderImportFactory { * * @param materialReqVOS */ - private void analyzeMaterials(List materialReqVOS, List blockReqVOS) { + private void analyzeMaterials(List materialReqVOS) { if (CollUtil.isEmpty(materialReqVOS)) { return; } + + // 检查生产单下是否已经有goodsId下的order_goods,有不再创建 + materialMap = goodsMapper.selectMaps( + new LambdaQueryWrapper() + .select(GoodsDO::getGoodsId, GoodsDO::getId) + .eq(GoodsDO::getOrderId, orderId) + .eq(GoodsDO::getOrganId, organId) + .eq(GoodsDO::getDeleted, false) + .in(GoodsDO::getGoodsId, materialReqVOS.stream().map(WebCadDataMaterialReqVO::getGoodsId).collect(Collectors.toList())) + .groupBy(GoodsDO::getGoodsId)).stream() + .collect(Collectors.toMap( + m -> String.valueOf(m.get("goods_id")), + m -> ((Number) m.get("id")).longValue() + )); + for (WebCadDataMaterialReqVO materialReqVO : materialReqVOS) { - String plateGoodsId = materialReqVO.getId(); String plateGoodsGoodsId = materialReqVO.getGoodsId(); - List orginIds = materialReqVO.getOrginIds(); - PlateGoodDO plateGoodDO = plateGoodMapper.selectOne(new LambdaQueryWrapper() - .eq(PlateGoodDO::getId, NumberUtil.parseLong(plateGoodsId)) - .eq(PlateGoodDO::getOrganId, organId) - .eq(PlateGoodDO::getDeleted, false)); - // 检查板材库 - if (ObjectUtil.isNull(plateGoodDO)) { - throw ServiceExceptionUtil.exception(WEBCAD_ORDER_IMPORT_PLATE_NOT_EXIST_ERROR, plateGoodsId); - } - // 获取缓存的orderGoods - GoodsDO cacheOrderPlate = materialMap.get(plateGoodsGoodsId); - // 缓存没有才创建 - if (ObjectUtil.isNotNull(cacheOrderPlate)) { - Long cacheOrderPlateId = cacheOrderPlate.getId(); - // 使用缓存中的order_goods信息赋值到板件 - setGoodsInfoToBlock(plateGoodsGoodsId, cacheOrderPlateId, orginIds, blockReqVOS); - continue; - } - // 检查生产单下是否已经有板材下的order_goods,有不再创建 - List existOrderGoods = goodsMapper.selectList(new LambdaUpdateWrapper() - .eq(GoodsDO::getGoodsId, plateGoodsGoodsId) - .eq(GoodsDO::getOrderId, orderId) - .eq(GoodsDO::getOrganId, organId) - .eq(GoodsDO::getDeleted, false)); - Long orderGoodsId; - if (CollUtil.isNotEmpty(existOrderGoods)) { - orderGoodsId = existOrderGoods.get(0).getId(); - } else { + + Long existOrderGoodsId = materialMap.get(plateGoodsGoodsId); + if (ObjectUtil.isNull(existOrderGoodsId)) { // 创建设计端商品 Long rawGoodsId = (Long) snowFlakeGenerator.nextId(null); RawGoodsDO rawGoodsDO = RawGoodsDO.builder() .id(rawGoodsId) .orderId(orderId) .rawGoodsId(plateGoodsGoodsId) - .goodsName(plateGoodDO.getGoodsName()) - .material(plateGoodDO.getMaterial()) - .texture(plateGoodDO.getTexture()) - .color(plateGoodDO.getColor()) - .colorBlack(StringUtils.isNotEmpty(plateGoodDO.getColorBlack()) ? plateGoodDO.getColorBlack() : EMPTY_STRING) - .thickness(plateGoodDO.getThickness()) - .spec(plateGoodDO.getSpec()) - .brand(plateGoodDO.getBrand()) + .goodsName(materialReqVO.getName()) + .material(materialReqVO.getMaterial()) + .texture(materialReqVO.getTexture()) + .color(materialReqVO.getColor()) + .colorBlack(EMPTY_STRING) + .thickness(materialReqVO.getThickness()) + .spec(materialReqVO.getSpec()) + .brand(materialReqVO.getBrand()) .price(0.00) .deleted(false) .organId(organId) .build(); - orderGoodsId = (Long) snowFlakeGenerator.nextId(null); + Long orderGoodsId = (Long) snowFlakeGenerator.nextId(null); // 创建生产单商品 GoodsDO goodsDO = GoodsDO.builder() @@ -482,16 +411,16 @@ public class WebCadOrderImportFactory { .orderId(orderId) .rawGoodsId(String.valueOf(rawGoodsId)) .goodsId(plateGoodsGoodsId) - .goodsName(plateGoodDO.getGoodsName()) - .material(plateGoodDO.getMaterial()) - .texture(plateGoodDO.getTexture()) - .color(plateGoodDO.getColor()) - .colorBlack(StringUtils.isNotEmpty(plateGoodDO.getColorBlack()) ? plateGoodDO.getColorBlack() : EMPTY_STRING) - .width(BigDecimal.valueOf(plateGoodDO.getWidth())) - .height(BigDecimal.valueOf(plateGoodDO.getHeight())) - .thickness(BigDecimal.valueOf(plateGoodDO.getThickness())) - .spec(plateGoodDO.getSpec()) - .brand(plateGoodDO.getBrand()) + .goodsName(materialReqVO.getName()) + .material(materialReqVO.getMaterial()) + .texture(materialReqVO.getTexture()) + .color(materialReqVO.getColor()) + .colorBlack(EMPTY_STRING) + .width(BigDecimal.valueOf(materialReqVO.getWidth())) + .height(BigDecimal.valueOf(materialReqVO.getHeight())) + .thickness(BigDecimal.valueOf(materialReqVO.getThickness())) + .spec(materialReqVO.getSpec()) + .brand(materialReqVO.getBrand()) .remark(EMPTY_STRING) .planId(0L) .price(0.00) @@ -502,101 +431,40 @@ public class WebCadOrderImportFactory { goodsDOS.add(goodsDO); rawGoodsDOS.add(rawGoodsDO); - // 缓存板材 - materialMap.put(plateGoodsGoodsId, goodsDO); + // 缓存goodCode和orderGoodsId的对应关系 + materialMap.put(plateGoodsGoodsId, orderGoodsId); } - setGoodsInfoToBlock(plateGoodsGoodsId, orderGoodsId, orginIds, blockReqVOS); } orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, true); orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, true); } - /** - * 板件信息映射到对应的cad板材中 - * - * @param plateGoodsGoodsId - * @param orderGoodsId - * @param orginIds - * @param blockReqVOS - */ - private void setGoodsInfoToBlock(String plateGoodsGoodsId, Long orderGoodsId, List orginIds, List blockReqVOS) { - if (CollUtil.isEmpty(orginIds)) { - return; - } - for (Integer blockIndex : orginIds) { - // blockIndex序号获取对应板件a - WebCadDataBlockReqVO webCadDataBlockReqVO = blockReqVOS.get(blockIndex - 1); - // 把板材的id和goodsId赋给cad板件 - webCadDataBlockReqVO.setGoodsId(plateGoodsGoodsId); - webCadDataBlockReqVO.setPlateGoodsId(orderGoodsId); - } - } - /** * 缓存加工组类型 * * @param processGroupList */ - private void analyzeGroups(List processGroupList, List blockReqVOS, WebCadDataPartsReqVO partsReqVO) { + private void analyzeGroups(List processGroupList) { if (CollUtil.isNotEmpty(processGroupList)) { for (WebCadDataProcessGroupReqVO processGroup : processGroupList) { String groupTypeName = processGroup.getType(); List projects = processGroup.getProjects(); - // 加工组信息缓存到cad block和part上 if (CollUtil.isNotEmpty(projects)) { for (WebCadDataProcessGroupReqVO.ProjectsDTO project : projects) { // 缓存加工组信息 - WebCadDataBlockReqVO.GroupInfo processGroupInfo = new WebCadDataBlockReqVO.GroupInfo(); + WebCadDataGroupInfoReqVO processGroupInfo = new WebCadDataGroupInfoReqVO(); processGroupInfo.setGroupName(project.getProjName()); processGroupInfo.setGroupTypeName(groupTypeName); processGroupInfo.setHeight(project.getBoxSize().getHeight()); processGroupInfo.setWidth(project.getBoxSize().getWidth()); processGroupInfo.setDepth(project.getBoxSize().getDepth()); processGroupMap.put(project.getGroupID(), processGroupInfo); - // 板件 - processBlocksGroup(project, blockReqVOS); - // 配件 - processPartsGroup(project, partsReqVO); } } } } } - /** - * 加工组缓存到对应的板件下 - * - * @param project - * @param blockReqVOS - */ - private void processBlocksGroup(WebCadDataProcessGroupReqVO.ProjectsDTO project, List blockReqVOS) { - List brIds = project.getBrIds(); - if (CollUtil.isNotEmpty(brIds)) { - for (Integer brId : brIds) { - // brId 板件序号获取板件 - WebCadDataBlockReqVO webCadDataBlockReqVO = blockReqVOS.get(brId - 1); - webCadDataBlockReqVO.getGroupIds().add(project.getGroupID()); - } - } - } - - /** - * 加工组缓存到对应的配件下 - * - * @param project - * @param partsReqVO - */ - private void processPartsGroup(WebCadDataProcessGroupReqVO.ProjectsDTO project, WebCadDataPartsReqVO partsReqVO) { - List objIds = project.getObjIds(); - if (CollUtil.isNotEmpty(objIds)) { - for (Integer objId : objIds) { - // objId 配件序号获取配件 - WebCadDataPartsReqVO.BlockObjectListDTO part = partsReqVO.getBlockObjectList().get(objId - 1); - part.getGroupIds().add(project.getGroupID()); - } - } - } - /** * 生成并缓存成倍房间柜体信息 * @@ -613,7 +481,7 @@ public class WebCadOrderImportFactory { for (WebCadDataDoubleRoomTreeReqVO.ChildrenDTO body : bodys) { String bodyName = body.getName(); // 缓存柜体成倍信息 - roomBodyMap.put(roomName + bodyName, body); + roomBodyMap.put(roomName + bodyName, body.getCount()); } } } @@ -622,56 +490,60 @@ public class WebCadOrderImportFactory { /** * 解析生产单信息板材列表 * - * @param blockList + * @param douleRoomTree */ - private void analyzeBlockList(List blockList) { - if (CollUtil.isEmpty(blockList)) { + private void analyzeBlockList(List douleRoomTree) { + if (CollUtil.isEmpty(douleRoomTree)) { return; } - // 基于房间名分组 - Map> roomCollect = blockList.stream() - .collect(Collectors.groupingBy(WebCadDataBlockReqVO::getRoomName, Collectors.toList())); - for (Map.Entry> roomEntry : roomCollect.entrySet()) { - String roomName = roomEntry.getKey(); - List listRoom = roomEntry.getValue(); + // 所有房间名 + List roomNames = douleRoomTree.stream().map(WebCadDataDoubleRoomTreeReqVO::getName).collect(Collectors.toList()); + // 查询当前生产单的所有房间 + existRoomIdMap = orderBodyMapper.selectMaps( + new LambdaQueryWrapper() + .select(OrderBodyDO::getRoomName, OrderBodyDO::getRoomId) + .eq(OrderBodyDO::getOrderId, orderId) + .eq(OrderBodyDO::getOrganId, organId) + .eq(OrderBodyDO::getDeleted, false) + .in(OrderBodyDO::getRoomName, roomNames) + .groupBy(OrderBodyDO::getRoomName)).stream() + .collect(Collectors.toMap( + m -> String.valueOf(m.get("room_name")), + m -> ((Number) m.get("room_id")).longValue() + )); + + for (WebCadDataDoubleRoomTreeReqVO room : douleRoomTree) { + // 房间名 + String roomName = room.getName(); + + // 同步房间直接使用roomId Long roomId; - Long existRoomId = existRoomMap.get(roomName); + Long existRoomId = existRoomIdMap.get(roomName); if (ObjectUtil.isNotNull(existRoomId)) { roomId = existRoomId; } else { roomId = (Long) snowFlakeGenerator.nextId(null); - // 检查当前单子中是否已有房间,是则使用相同房间id - List existRoomNameBodys = orderBodyMapper.selectList(new LambdaUpdateWrapper() - .eq(OrderBodyDO::getOrderId, orderId) - .eq(OrderBodyDO::getRoomName, roomName) - .eq(OrderBodyDO::getOrganId, organId) - .eq(OrderBodyDO::getDeleted, false)); - if (CollUtil.isNotEmpty(existRoomNameBodys)) { - roomId = existRoomNameBodys.get(0).getRoomId(); - existRoomMap.put(roomName, roomId); - } + existRoomIdMap.put(roomName, roomId); } - // 基于柜体名分组 - Map> bodyCollect = listRoom.stream() - .collect(Collectors.groupingBy(WebCadDataBlockReqVO::getCabinetName, Collectors.toList())); - for (Map.Entry> bodyEntry : bodyCollect.entrySet()) { - String bodyName = bodyEntry.getKey(); - List listBody = bodyEntry.getValue(); + // 柜体列表 + List roomBoxs = room.getChildren(); + for (WebCadDataDoubleRoomTreeReqVO.ChildrenDTO box : roomBoxs) { + String boxName = box.getName(); - String roomBodyKey = roomName + bodyName; - WebCadDataDoubleRoomTreeReqVO.ChildrenDTO cadBody = roomBodyMap.get(roomBodyKey); + // 柜体下的板件 + List listBody = box.getBlockList(); - if (ObjectUtil.isNull(cadBody)) { - // 房间+柜体不在成倍缓存中, 再检查bodyMap, 再没有创建房间,缓存房间到bodyMap - createBlockUnknownBody(roomId, roomName, bodyName, listBody); - } else { - // 成倍数量 - multiCreateBodyPlate(cadBody, roomId, roomName, roomBodyKey, listBody); - } + String roomNameKey = roomName + boxName; + // 获取缓存中的成本数量 + Integer count = roomBodyMap.get(roomNameKey); + + // 成倍创建 + multiCreateBodyPlate(count, roomId, roomName, boxName, listBody); } } + orderPlateBatchInsertWithinThreshold(plateDOS, true); // 所有自定义板编号生成完成后更新配置到生产单 customPlateNoGenerateService.updateCustomPlateNoGenerateConfig(plateNoGenerateConfigVO, orderDO); // 批量插入造型数据 @@ -684,15 +556,13 @@ public class WebCadOrderImportFactory { * @param cadBody * @param roomId * @param roomName - * @param roomBodyKey * @param listBody */ - private void multiCreateBodyPlate(WebCadDataDoubleRoomTreeReqVO.ChildrenDTO cadBody, Long roomId, String roomName, String roomBodyKey, List listBody) { - Integer bodyMultipleNum = cadBody.getCount(); - for (int i = 0; i < bodyMultipleNum; i++) { + private void multiCreateBodyPlate(Integer count, Long roomId, String roomName, String boxName, List listBody) { + for (int i = 0; i < count; i++) { Long bodyId = (Long) snowFlakeGenerator.nextId(null); OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) - .roomId(roomId).roomName(roomName).name(cadBody.getName()).width(0.0).height(0.0) + .roomId(roomId).roomName(roomName).name(boxName).width(0.0).height(0.0) .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); orderBodyDO.setCreator(operatorName); orderBodyDO.setUpdater(operatorName); @@ -700,7 +570,7 @@ public class WebCadOrderImportFactory { orderBodyDO.setUpdateTime(now); // 缓存成倍的柜体信息 - String multiRoomBodyName = roomBodyKey + i; + String multiRoomBodyName = roomName + boxName + i; orderBodyDO.setMultiRoomBodyName(multiRoomBodyName); bodyMap.put(multiRoomBodyName, orderBodyDO); @@ -721,36 +591,6 @@ public class WebCadOrderImportFactory { } } - /** - * 创建不需要成倍的房间柜体以及其下的板件 - * - * @param roomName - * @param bodyName - * @param bodyCollect - */ - private void createBlockUnknownBody(Long roomId, String roomName, String bodyName, List bodyCollect) { - String roomBodyKey = roomName + bodyName; - OrderBodyDO orderBodyDO = bodyMap.get(roomBodyKey); - if (ObjectUtil.isNull(orderBodyDO)) { - Long bodyId = (Long) snowFlakeGenerator.nextId(null); - orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) - .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0) - .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); - orderBodyDO.setCreator(operatorName); - orderBodyDO.setUpdater(operatorName); - orderBodyDO.setCreateTime(now); - orderBodyDO.setUpdateTime(now); - - // 缓存成倍的柜体信息 - bodyMap.put(roomBodyKey, orderBodyDO); - } - - for (WebCadDataBlockReqVO block : bodyCollect) { - // 创建板件相关数据:order_plate、order_item、es.orderModels - createPlate(orderBodyDO, block); - } - } - /** * 创建板件数据 * @@ -758,11 +598,10 @@ public class WebCadOrderImportFactory { * @param block */ private void createPlate(OrderBodyDO orderBodyDO, WebCadDataBlockReqVO block) { - WebCadDataBlockReqVO.InfoDTO blockInfo = block.getInfo(); // 是否矩形,不是矩形那就是异形 - Boolean unRegular = !blockInfo.getIsRect(); + Boolean unRegular = !block.getIsRect(); // 是否造型 - boolean isModel = (block.getFrontModelCount() + block.getBackModelCount()) > 0; + boolean isModel = (block.getFrontModelCount() + block.getBackModelCount()) > 0 || block.isHas2DModel() || block.isHas3DModel(); // 是否排孔 boolean isRawHole = (block.getFrontHoleCount() + block.getBackHoleCount()) > 0; @@ -779,7 +618,7 @@ public class WebCadOrderImportFactory { long obtainingTime = idWorker.obtainingTime(); // 从info.remarks中获取备注相关 - WebCadDataBlockRemarkVO plateRemark = getPlateRemark(blockInfo); + WebCadDataBlockRemarkVO plateRemark = getPlateRemark(block); List remarks = plateRemark.getRemarks(); StringBuilder remark = new StringBuilder(); if (CollUtil.isNotEmpty(remarks)) { @@ -789,8 +628,8 @@ public class WebCadOrderImportFactory { remark.deleteCharAt(remark.length() - 1); } - String splitHeight = blockInfo.getSpliteHeight(); - String spliteWidth = blockInfo.getSpliteWidth(); + String splitHeight = block.getSpliteHeight(); + String spliteWidth = block.getSpliteWidth(); // 创建order_plate PlateDO plateDO = PlateDO.builder() .id(plateId) @@ -798,12 +637,12 @@ public class WebCadOrderImportFactory { .name(block.getName()) .plateNo(obtainingTime + Long.toString(plateNo).substring(2)) .type(block.getType()) - .goodsId(block.getPlateGoodsId()) + .goodsId(materialMap.get(block.getGoodsCode())) .width(BigDecimal.valueOf(block.getWidth())) .height(BigDecimal.valueOf(block.getHeight())) .thickness(BigDecimal.valueOf(block.getThickness())) .splitHeight(BigDecimal.valueOf(NumberUtil.parseDouble(StringUtils.isNotEmpty(splitHeight) ? splitHeight : String.valueOf(block.getKaiLiaoHeight())))) - .splitThickness(BigDecimal.valueOf(NumberUtil.parseDouble(blockInfo.getSpliteThickness()))) + .splitThickness(BigDecimal.valueOf(NumberUtil.parseDouble(block.getSpliteThickness()))) .splitWidth(BigDecimal.valueOf(NumberUtil.parseDouble(StringUtils.isNotEmpty(spliteWidth) ? spliteWidth : String.valueOf(block.getKaiLiaoWidth())))) .area(BigDecimal.valueOf(block.getArea())) .texture(block.getTexture()) @@ -829,10 +668,10 @@ public class WebCadOrderImportFactory { .isCutted(0) .isCancel(false) .filterType(EMPTY_STRING) - .sealLeft(BigDecimal.ZERO) - .sealRight(BigDecimal.ZERO) - .sealUp(BigDecimal.ZERO) - .sealDown(BigDecimal.ZERO) + .sealLeft(BigDecimal.valueOf(block.getSealLeft())) + .sealRight(BigDecimal.valueOf(block.getSealRight())) + .sealUp(BigDecimal.valueOf(block.getSealUp())) + .sealDown(BigDecimal.valueOf(block.getSealDown())) .remark(remark.toString()) .deleted(false) .organId(organId) @@ -845,11 +684,6 @@ public class WebCadOrderImportFactory { // 生成自定义板编号 generateCustomPlateNo(plateDO, block.getCustBlockNo()); - WebCadDataBlockReqVO.BoadrData boardData = block.getBoardData(); - boardData.setInfo(blockInfo); - // 获取封边厚度 - calculateSealThickness(plateDO, boardData.getSealing()); - //批量保存板件 // 达到板件数量阈值,停止入库,更新全局参数停止后续入库 currentPlateNum += 1; @@ -858,20 +692,21 @@ public class WebCadOrderImportFactory { return; } plateDOS.add(plateDO); +// orderPlateBatchInsertWithinThreshold(plateMapper, plateDOS, false); // 创建es造型数据 - createModel(plateDO, block, blockInfo, plateRemark); + createModel(plateDO, block, plateRemark); // 批量插入造型数据 orderModelsBatchInsertWithinThreshold(false); // 遍历加工组信息,生成对应的加工组和item - analyzeBlockProcessGroup(orderBodyDO, block, blockInfo, plateId); + analyzeBlockProcessGroup(orderBodyDO, block, plateId); } /** * 创建板件造型es数据 */ - private void createModel(PlateDO plateDO, WebCadDataBlockReqVO block, WebCadDataBlockReqVO.InfoDTO blockInfo, WebCadDataBlockRemarkVO plateRemark) { + private void createModel(PlateDO plateDO, WebCadDataBlockReqVO block, WebCadDataBlockRemarkVO plateRemark) { // 点阵信息 WebCadDataBlockReqVO.PointInfoDTO pointInfo = block.getPointInfo(); @@ -882,8 +717,8 @@ public class WebCadOrderImportFactory { .texture(block.getTexture()) .typographicFace(block.getHoleArrange()) .openDoorType(block.getOpenDoorType()) - .splitLength(BigDecimal.valueOf(blockInfo.getKaiLiaoHeight())) - .splitWidth(BigDecimal.valueOf(blockInfo.getKaiLiaoWidth())) + .splitLength(BigDecimal.valueOf(block.getKaiLiaoHeight())) + .splitWidth(BigDecimal.valueOf(block.getKaiLiaoWidth())) .offsetX(BigDecimal.valueOf(block.getOffsetX())) .offsetY(BigDecimal.valueOf(block.getOffsetY())) .pointDetail(getPointDetail(pointInfo.getPointDetail())) @@ -893,15 +728,15 @@ public class WebCadOrderImportFactory { .contourDetail(getContourDetail(pointInfo.getModelDetail())) .sideDetail(getSideDetail(pointInfo.getSideModelDetail())) .sideRemark(getSideRemark(plateRemark.getRemarks())) + .boardType(block.getBoardTypeName()) + .has2DModel(block.isHas2DModel()) + .has3DModel(block.isHas3DModel()) .build(); // 处理备注信息 JSONObject plateExtraRemark = new JSONObject(); JSONObject extraObject = plateRemark.getExtraObject(); if (ObjectUtil.isNotNull(extraObject)) { - orderModelDO.setBoardType(extraObject.getString("boardType")); - orderModelDO.setHas2DModel(extraObject.getBoolean("has2DModel")); - orderModelDO.setHas3DModel(extraObject.getBoolean("has3DModel")); plateExtraRemark.put("extra", extraObject); } @@ -911,11 +746,9 @@ public class WebCadOrderImportFactory { } orderModelDO.setPlateExtraRemark(plateExtraRemark); - orderModelDO.setGoodsId(block.getGoodsId()); + orderModelDO.setGoodsId(block.getGoodsCode()); orderModelDO.setPlateGoodsId(plateDO.getGoodsId()); orderModelDO.setOrganId(organId); - orderModelDO.setCreator(operatorName); - orderModelDO.setUpdater(operatorName); orderModelDOS.add(orderModelDO); if (!esInsert) { esInsert = true; @@ -1221,16 +1054,13 @@ public class WebCadOrderImportFactory { /** * 获取板件备注 * - * @param infoDTO + * @param block * @return */ - private WebCadDataBlockRemarkVO getPlateRemark(WebCadDataBlockReqVO.InfoDTO infoDTO) { + private WebCadDataBlockRemarkVO getPlateRemark(WebCadDataBlockReqVO block) { WebCadDataBlockRemarkVO blockRemark = new WebCadDataBlockRemarkVO(); - if (ObjectUtil.isNull(infoDTO)) { - return blockRemark; - } - List> remarks = infoDTO.getRemarks(); + List> remarks = block.getAllRemarkList(); if (CollUtil.isEmpty(remarks)) { return blockRemark; } @@ -1282,24 +1112,23 @@ public class WebCadOrderImportFactory { * @param block * @param plateId */ - private void analyzeBlockProcessGroup(OrderBodyDO orderBodyDO, WebCadDataBlockReqVO block, WebCadDataBlockReqVO.InfoDTO infoDTO, Long plateId) { + private void analyzeBlockProcessGroup(OrderBodyDO orderBodyDO, WebCadDataBlockReqVO block, Long plateId) { Long bodyId = orderBodyDO.getId(); Long roomId = orderBodyDO.getRoomId(); - // 是否矩形,不是矩形那就是异形 - Boolean unRegular = !infoDTO.getIsRect(); List groupIds = block.getGroupIds(); if (CollUtil.isNotEmpty(groupIds)) { // 加工组缓存存在,一个加工组一个orderGroup+orderItem for (Integer groupId : groupIds) { - WebCadDataBlockReqVO.GroupInfo groupInfo = processGroupMap.get(groupId); + WebCadDataGroupInfoReqVO groupInfo = processGroupMap.get(groupId); String groupMapKey = orderBodyDO.getMultiRoomBodyName() + groupInfo.getGroupName(); - OrderGroupDO orderGroupDO = orderGroupMap.get(groupMapKey); + Long orderGroupId = orderGroupMap.get(groupMapKey); // 房间+柜体+加工组名称存在累加板件和异形数量,不存在新增groupDO和orderGroupMap缓存 - if (ObjectUtil.isNull(orderGroupDO)) { - orderGroupDO = OrderGroupDO + if (ObjectUtil.isNull(orderGroupId)) { + orderGroupId = (Long) snowFlakeGenerator.nextId(null); + OrderGroupDO orderGroupDO = OrderGroupDO .builder() - .id((Long) snowFlakeGenerator.nextId(null)) + .id(orderGroupId) .organId(organId) .orderId(orderId) .bodyId(bodyId) @@ -1310,8 +1139,8 @@ public class WebCadOrderImportFactory { .height(groupInfo.getHeight()) .depth(groupInfo.getDepth()) .multiNum(0) - .plateNum(1) - .unregularNum(BooleanUtil.toInt(unRegular)) + .plateNum(0) + .unregularNum(0) .filename("无") .remark("无") .deleted(false) @@ -1321,11 +1150,8 @@ public class WebCadOrderImportFactory { orderGroupDO.setCreateTime(now); orderGroupDO.setUpdateTime(now); - orderGroupMap.put(groupMapKey, orderGroupDO); + orderGroupMap.put(groupMapKey, orderGroupId); orderGroupDOS.add(orderGroupDO); - } else { - orderGroupDO.setPlateNum(orderGroupDO.getPlateNum() + 1); - orderGroupDO.setUnregularNum(orderGroupDO.getUnregularNum() + BooleanUtil.toInt(unRegular)); } OrderItemDO orderItemDO = OrderItemDO @@ -1335,7 +1161,7 @@ public class WebCadOrderImportFactory { .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) .roomId(roomId) .bodyId(bodyId) - .groupId(orderGroupDO.getId()) + .groupId(orderGroupId) .plateId(plateId) .packageId(0L) .partsId(0L) @@ -1343,6 +1169,7 @@ public class WebCadOrderImportFactory { .organId(organId) .build(); orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); } } else { // 没有归属的加工组,只创建一个orderItem @@ -1361,6 +1188,7 @@ public class WebCadOrderImportFactory { .organId(organId) .build(); orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); } } @@ -1369,67 +1197,85 @@ public class WebCadOrderImportFactory { * * @param parts */ - private void analyzeParts(WebCadDataPartsReqVO parts) { + private void analyzeParts(List parts) { if (ObjectUtil.isNull(parts)) { return; } - List blockObjectList = parts.getBlockObjectList(); - if (CollUtil.isEmpty(blockObjectList)) { - return; - } - // 解析orderParts - analyzeOrderParts(blockObjectList); + for (WebCadDataDoubleRoomTreeReqVO room : parts) { + // 房间名 + String roomName = room.getName(); - // 解析配件的orderItem - // 基于房间名分组 - Map> roomCollect = blockObjectList.stream() - .collect(Collectors.groupingBy(WebCadDataPartsReqVO.BlockObjectListDTO::getRoomName, Collectors.toList())); - roomCollect.forEach((roomName, listRoom) -> { - Long roomId = (Long) snowFlakeGenerator.nextId(null); - // 检查当前单子中是否已有房间,是则使用相同房间id - List existRoomNameBodys = orderBodyMapper.selectList(new LambdaUpdateWrapper() - .eq(OrderBodyDO::getOrderId, orderId) - .eq(OrderBodyDO::getRoomName, roomName) - .eq(OrderBodyDO::getOrganId, organId) - .eq(OrderBodyDO::getDeleted, false)); - if (CollUtil.isNotEmpty(existRoomNameBodys)) { - roomId = existRoomNameBodys.get(0).getRoomId(); - } + // 同步房间直接使用roomId + Long roomId; + Long existRoomId = existRoomIdMap.get(roomName); - // 基于柜体名分组 - Map> bodyCollect = listRoom.stream() - .collect(Collectors.groupingBy(WebCadDataPartsReqVO.BlockObjectListDTO::getCabinetName, Collectors.toList())); - for (Map.Entry> entry : bodyCollect.entrySet()) { - String bodyName = entry.getKey(); - List listBody = entry.getValue(); + if (ObjectUtil.isNotNull(existRoomId)) { + roomId = existRoomId; + } else { + // 可能有配件房间柜体不在板件的情况,再查一次 + // 查询当前生产单的所有房间 + List roomNames = parts.stream().map(WebCadDataDoubleRoomTreeReqVO::getName).collect(Collectors.toList()); - String roomNameKey = roomName + bodyName; - WebCadDataDoubleRoomTreeReqVO.ChildrenDTO cadBody = roomBodyMap.get(roomNameKey); - - if (ObjectUtil.isNull(cadBody)) { - // 房间+柜体不在成倍缓存中, 再检查bodyMap, 再没有创建房间,缓存房间到bodyMap - createPartsUnknownBody(roomId, roomName, bodyName, listBody); + Map existPartsRoomIdMap = orderBodyMapper.selectMaps( + new LambdaQueryWrapper() + .select(OrderBodyDO::getRoomName, OrderBodyDO::getRoomId) + .eq(OrderBodyDO::getOrderId, orderId) + .eq(OrderBodyDO::getOrganId, organId) + .eq(OrderBodyDO::getDeleted, false) + .in(OrderBodyDO::getRoomName, roomNames) + .groupBy(OrderBodyDO::getRoomName)).stream() + .collect(Collectors.toMap( + m -> String.valueOf(m.get("room_name")), + m -> ((Number) m.get("room_id")).longValue() + )); + Long existPartRoomId = existPartsRoomIdMap.get(roomName); + if (ObjectUtil.isNotNull(existPartRoomId)) { + roomId = existPartRoomId; } else { - multipleCreateProcessGroup(cadBody, roomNameKey, listBody); + roomId = (Long) snowFlakeGenerator.nextId(null); + existRoomIdMap.put(roomName, roomId); } } - }); + + // 柜体列表 + List roomBoxs = room.getChildren(); + for (WebCadDataDoubleRoomTreeReqVO.ChildrenDTO box : roomBoxs) { + String boxName = box.getName(); + + // 柜体下的板件 + List listBody = box.getObjList(); + + String roomNameKey = roomName + boxName; + // 获取缓存中的成本数量 + Integer count = roomBodyMap.get(roomNameKey); + + if (ObjectUtil.isNull(count)) { + // 房间+柜体不在成倍缓存中, 再检查bodyMap, 再没有创建房间,缓存房间到bodyMap + createPartsUnknownBody(roomId, roomName, boxName, listBody); + } else { + multipleCreateProcessGroup(count, roomNameKey, listBody); + } + } + } + orderPartBatchInsertWithinThreshold(orderPartsDOS, true); } /** * 成倍创建配件加工组和item * - * @param cadBody + * @param count * @param roomNameKey * @param listBody */ - private void multipleCreateProcessGroup(WebCadDataDoubleRoomTreeReqVO.ChildrenDTO cadBody, String roomNameKey, List listBody) { + private void multipleCreateProcessGroup(Integer count , String roomNameKey, List listBody) { // 成倍数量 - Integer bodyMultipleNum = cadBody.getCount(); - for (int j = 0; j < bodyMultipleNum; j++) { + for (int j = 0; j < count; j++) { // 获取板材已经创建的柜体,缓存key:房间名+柜体名+成倍序号 OrderBodyDO orderBodyDO = bodyMap.get(roomNameKey + j); + if (ObjectUtil.isNull(orderBodyDO)) { + return; + } // 解析配件的加工组,创建对应的orderItem for (WebCadDataPartsReqVO.BlockObjectListDTO part : listBody) { analyzePartProcessGroup(orderBodyDO, part); @@ -1470,6 +1316,9 @@ public class WebCadOrderImportFactory { Long bodyId = orderBodyDO.getId(); Long roomId = orderBodyDO.getRoomId(); + // 获取orderPart + analyzeOrderPart(part); + // 遍历加工组信息,生成对应的orderItem List groupIds = part.getGroupIds(); if (CollUtil.isNotEmpty(groupIds)) { @@ -1477,14 +1326,15 @@ public class WebCadOrderImportFactory { // 带加工组的配件增加item只记录配件id和数量 partNum += part.getNum(); for (Integer groupId : groupIds) { - WebCadDataBlockReqVO.GroupInfo groupInfo = processGroupMap.get(groupId); + WebCadDataGroupInfoReqVO groupInfo = processGroupMap.get(groupId); String groupMapKey = orderBodyDO.getMultiRoomBodyName() + groupInfo.getGroupName(); - OrderGroupDO orderGroupDO = orderGroupMap.get(groupMapKey); + Long orderGroupId = orderGroupMap.get(groupMapKey); // 房间+柜体+加工组名称存在累加配件item,不存在新增groupDO和orderGroupMap缓存 - if (ObjectUtil.isNull(orderGroupDO)) { - orderGroupDO = OrderGroupDO + if (ObjectUtil.isNull(orderGroupId)) { + orderGroupId = (Long) snowFlakeGenerator.nextId(null); + OrderGroupDO orderGroupDO = OrderGroupDO .builder() - .id((Long) snowFlakeGenerator.nextId(null)) + .id(orderGroupId) .organId(organId) .orderId(orderId) .bodyId(bodyId) @@ -1506,7 +1356,7 @@ public class WebCadOrderImportFactory { orderGroupDO.setCreateTime(now); orderGroupDO.setUpdateTime(now); - orderGroupMap.put(groupMapKey, orderGroupDO); + orderGroupMap.put(groupMapKey, orderGroupId); orderGroupDOS.add(orderGroupDO); } @@ -1517,7 +1367,7 @@ public class WebCadOrderImportFactory { .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) .roomId(roomId) .bodyId(bodyId) - .groupId(orderGroupDO.getId()) + .groupId(orderGroupId) .partsId(part.getImesPartsId()) .packageId(0L) .plateId(0L) @@ -1525,6 +1375,7 @@ public class WebCadOrderImportFactory { .organId(organId) .build(); orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); } OrderItemDO orderItemDO = OrderItemDO .builder() @@ -1541,6 +1392,7 @@ public class WebCadOrderImportFactory { .organId(organId) .build(); orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); } else { OrderItemDO orderItemDO = OrderItemDO .builder() @@ -1557,129 +1409,104 @@ public class WebCadOrderImportFactory { .organId(organId) .build(); orderItemDOS.add(orderItemDO); + orderItemBatchInsertWithinThreshold(orderItemDOS, false); } } /** * 分组配件解析出orderParts,id回显到cad配件 * - * @param blockObjectList + * @param part */ - private void analyzeOrderParts(List blockObjectList) { - if (CollUtil.isEmpty(blockObjectList)) { - return; - } - // 筛选出组件配件 - List moduleCollect = blockObjectList.stream().filter(p -> PART_CATEGORY_THREE.equals(p.getType())).collect(Collectors.toList()); - // 基于以下属性分组非组件的配件 - Map, List> partsMap = blockObjectList.stream().filter(p -> !PART_CATEGORY_THREE.equals(p.getType())).collect(Collectors.groupingBy( - p -> Arrays.asList( - p.getIsComposite(), - p.getType(), - p.getFactory(), - p.getModel(), - p.getSpec(), - p.getHeight(), - p.getWidth(), - p.getThickness(), - p.getUnit(), - p.getBrand()), - Collectors.toList() - )); - partsMap.forEach((partKey, partValue) -> { - Long partId = (Long) snowFlakeGenerator.nextId(null); - WebCadDataPartsReqVO.BlockObjectListDTO part = partValue.get(0); - + private void analyzeOrderPart(WebCadDataPartsReqVO.BlockObjectListDTO part) { + boolean composite = part.getIsComposite(); String partType = part.getType(); + String factory = part.getFactory(); String model = part.getModel(); String spec = part.getSpec(); + String height = part.getHeight(); + String width = part.getWidth(); + String thickness = part.getThickness(); + String unit = part.getUnit(); String brand = part.getBrand(); - String factory = part.getFactory(); - String color = null; - String material = null; - if (PART_CATEGORY_ONE.equals(partType)) { - WebCadDataPartsReqVO.BlockObjectListDTO.GroupDataDTO partGroupData = part.getGroupData(); - color = partGroupData.getColor(); - material = partGroupData.getMaterial(); - // 封边条宽度从系统配置中获取宽度对应 - sealEdgeWidthMatch(part); - // 规格可能修改,再获取一次 - spec = part.getSpec(); + + // 分类配件的键组合 + String groupKey = composite + partType + factory + model + spec + height + width + thickness + unit + brand; + + Long orderPartId = orderPartMap.get(groupKey); + if(ObjectUtil.isNull(orderPartId)) { + Long partId = (Long) snowFlakeGenerator.nextId(null); + + String color = null; + String material = null; + if (PART_CATEGORY_ONE.equals(partType)) { + WebCadDataPartsReqVO.BlockObjectListDTO.GroupDataDTO partGroupData = part.getGroupData(); + color = partGroupData.getColor(); + material = partGroupData.getMaterial(); + // 封边条宽度从系统配置中获取宽度对应 + sealEdgeWidthMatch(part); + // 规格可能修改,再获取一次 + spec = part.getSpec(); + } else if (PART_CATEGORY_THREE.equals(partType)) { + color = getFieldFromSpec(part.getSpec(), 2); + material = getFieldFromSpec(part.getSpec(), 1); + } + + String type = changePartType(partType, part.getIsComposite()); + // todo remark、备注信息到es + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id(partId) + .orderId(orderId) + .color(getEmpty(color)) + .category(type) + .type(type) + .goodsId(EMPTY_STRING) + .length(NumberUtil.parseDouble(part.getHeight())) + .width(NumberUtil.parseDouble(part.getWidth())) + .thickness(NumberUtil.parseDouble(part.getThickness())) + .isComposite(part.getIsComposite()) + .name(part.getName()) + .material(getEmpty(material)) + .model(getEmpty(model)) + .spec(getEmpty(spec)) + .brand(getEmpty(brand)) + .factory(getEmpty(factory)) + .unit(part.getUnit()) + .price(0.0) + .subparts(EMPTY_STRING) + .remark(getEmpty(part.getRemark())) + .organId(organId) + .deleted(false) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + orderPartsDOS.add(orderPartsDO); + orderPartBatchInsertWithinThreshold(orderPartsDOS, false); + + // orderpart id回显到配件 + part.setImesPartsId(partId); + + orderPartMap.put(groupKey, partId); + } else { + // orderpart id回显到配件 + part.setImesPartsId(orderPartId); } + } - String type = changePartType(partType, part.getIsComposite()); - // todo remark、备注信息到es - OrderPartsDO orderPartsDO = OrderPartsDO.builder() - .id(partId) - .orderId(orderId) - .color(getEmpty(color)) - .category(type) - .type(type) - .goodsId(EMPTY_STRING) - .length(NumberUtil.parseDouble(part.getHeight())) - .width(NumberUtil.parseDouble(part.getWidth())) - .thickness(NumberUtil.parseDouble(part.getThickness())) - .isComposite(part.getIsComposite()) - .name(part.getName()) - .material(getEmpty(material)) - .model(getEmpty(model)) - .spec(getEmpty(spec)) - .brand(getEmpty(brand)) - .factory(getEmpty(factory)) - .unit(part.getUnit()) - .price(0.0) - .subparts(EMPTY_STRING) - .remark("") - .organId(organId) - .deleted(false) - .build(); - orderPartsDO.setCreator(operatorName); - orderPartsDO.setUpdater(operatorName); - orderPartsDO.setCreateTime(now); - orderPartsDO.setUpdateTime(now); - orderPartsDOS.add(orderPartsDO); - - // 配件id回显到列表 - partValue.forEach(p -> p.setImesPartsId(partId)); - }); - // 组件不分组,每一个组件认为是一种组件 - for (WebCadDataPartsReqVO.BlockObjectListDTO module : moduleCollect) { - Long partId = (Long) snowFlakeGenerator.nextId(null); - String type = changePartType(module.getType(), module.getIsComposite()); - // todo color、remark、备注信息到es - OrderPartsDO orderPartsDO = OrderPartsDO.builder() - .id(partId) - .orderId(orderId) - .goodsId(EMPTY_STRING) - .color(EMPTY_STRING) - .category(type) - .type(type) - .length(NumberUtil.parseDouble(module.getHeight())) - .width(NumberUtil.parseDouble(module.getWidth())) - .thickness(NumberUtil.parseDouble(module.getThickness())) - .isComposite(module.getIsComposite()) - .name(module.getName()) - .material(EMPTY_STRING) - .model(module.getModel()) - .spec(module.getSpec()) - .brand(module.getBrand()) - .factory(module.getFactory()) - .unit(module.getUnit()) - .price(0.0) - .subparts(EMPTY_STRING) - .remark("") - .organId(organId) - .deleted(false) - .build(); - orderPartsDO.setCreator(operatorName); - orderPartsDO.setUpdater(operatorName); - orderPartsDO.setCreateTime(now); - orderPartsDO.setUpdateTime(now); - orderPartsDOS.add(orderPartsDO); - - // 配件id回显到列表 - module.setImesPartsId(partId); + /** + * 从规格中获取属性,例:material、color + * @return + */ + private String getFieldFromSpec(String spec, int index) { + if (StringUtils.isNotEmpty(spec)) { + String[] specSplit = spec.split("\\|"); + if (specSplit.length > index) { + return specSplit[index]; + } } + return null; } @@ -1806,6 +1633,164 @@ public class WebCadOrderImportFactory { } } + private void orderPlateBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + String sql = "INSERT INTO order_plate (id,organ_id,order_id,name,plate_no,type,goods_id,width,height,thickness,split_width,split_height,split_thickness,seal_left,seal_right,seal_up,seal_down,area,texture,hole_face,hole_arrange,unregular_point_count,front_hole_count,back_hole_count,side_hole_count,front_model_count,back_model_count,is_door,open_door_type,offset_x,offset_y,is_arc_across,module_type_id,is_special_shaped,is_sculpt,is_row_hole,is_optimized,is_cutted,filter_type,remark,is_cancel,deleted,custom_plate_no,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + PlateDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrganId()); + ps.setLong(3, item.getOrderId()); + ps.setString(4, item.getName()); + ps.setString(5, item.getPlateNo()); + ps.setInt(6, item.getType()); + ps.setLong(7, item.getGoodsId()); + ps.setBigDecimal(8, item.getWidth()); + ps.setBigDecimal(9, item.getHeight()); + ps.setBigDecimal(10, item.getThickness()); + ps.setBigDecimal(11, item.getSplitWidth()); + ps.setBigDecimal(12, item.getSplitHeight()); + ps.setBigDecimal(13, item.getSplitThickness()); + ps.setBigDecimal(14, item.getSealLeft()); + ps.setBigDecimal(15, item.getSealRight()); + ps.setBigDecimal(16, item.getSealUp()); + ps.setBigDecimal(17, item.getSealDown()); + ps.setBigDecimal(18, item.getArea()); + ps.setInt(19, item.getTexture()); + ps.setInt(20, item.getHoleFace()); + ps.setInt(21, item.getHoleArrange()); + ps.setInt(22, item.getUnregularPointCount()); + ps.setInt(23, item.getFrontHoleCount()); + ps.setInt(24, item.getBackHoleCount()); + ps.setInt(25, item.getSideHoleCount()); + ps.setInt(26, item.getFrontModelCount()); + ps.setInt(27, item.getBackModelCount()); + ps.setBoolean(28, item.getIsDoor()); + ps.setInt(29, item.getOpenDoorType()); + ps.setBigDecimal(30, item.getOffsetX()); + ps.setBigDecimal(31, item.getOffsetY()); + ps.setBoolean(32, item.getIsArcAcross()); + ps.setLong(33, item.getModuleTypeId()); + ps.setBoolean(34, item.getIsSpecialShaped()); + ps.setBoolean(35, item.getIsSculpt()); + ps.setBoolean(36, item.getIsRowHole()); + ps.setBoolean(37, item.getIsOptimized()); + ps.setInt(38, item.getIsCutted()); + ps.setString(39, item.getFilterType()); + ps.setString(40, item.getRemark()); + ps.setBoolean(41, item.getIsCancel()); + ps.setBoolean(42, item.getDeleted()); + ps.setString(43, item.getCustomPlateNo()); + ps.setTimestamp(44, Timestamp.valueOf(item.getCreateTime())); + ps.setTimestamp(45, Timestamp.valueOf(item.getUpdateTime())); + ps.setString(46, item.getCreator()); + ps.setString(47, item.getUpdater()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + private void orderItemBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + + String sql = "INSERT INTO order_item (id,order_id,type,room_id,body_id,package_id,group_id,plate_id,parts_id,num,organ_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderItemDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrderId()); + ps.setInt(3, item.getType()); + ps.setLong(4, item.getRoomId()); + ps.setLong(5, item.getBodyId()); + ps.setLong(6, item.getPackageId()); + ps.setLong(7, item.getGroupId()); + ps.setLong(8, item.getPlateId()); + ps.setLong(9, item.getPartsId()); + ps.setDouble(10, item.getNum()); + ps.setLong(11, item.getOrganId()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + + private void orderPartBatchInsertWithinThreshold(List list, boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + + String sql = "INSERT INTO order_parts (id,organ_id,order_id,goods_id,name,color,material,category,type,width,length,thickness,model,spec,brand,factory,unit,price,is_composite,subparts,remark,deleted,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderPartsDO item = list.get(index); + ps.setLong(1, item.getId()); + ps.setLong(2, item.getOrganId()); + ps.setLong(3, item.getOrderId()); + ps.setString(4, item.getGoodsId()); + ps.setString(5, item.getName()); + ps.setString(6, item.getColor()); + ps.setString(7, item.getMaterial()); + ps.setString(8, item.getCategory()); + ps.setString(9, item.getType()); + ps.setDouble(10, item.getWidth()); + ps.setDouble(11, item.getLength()); + ps.setDouble(12, item.getThickness()); + ps.setString(13, item.getModel()); + ps.setString(14, item.getSpec()); + ps.setString(15, item.getBrand()); + ps.setString(16, item.getFactory()); + ps.setString(17, item.getUnit()); + ps.setDouble(18, item.getPrice()); + ps.setBoolean(19, item.getIsComposite()); + ps.setString(20, item.getSubparts()); + ps.setString(21, item.getRemark()); + ps.setBoolean(22, item.getDeleted()); + ps.setTimestamp(23, Timestamp.valueOf(item.getCreateTime())); + ps.setTimestamp(24, Timestamp.valueOf(item.getUpdateTime())); + ps.setString(25, item.getCreator()); + ps.setString(26, item.getUpdater()); + } + + @Override + public int getBatchSize() { + return list.size(); + } + }); + + + if (!isLast) { + // 存储完成清理 list + list.clear(); + } + } + } + /** * 每达到阈值就批量插入一次生产单造型数据和压缩数据 * @@ -1815,7 +1800,7 @@ public class WebCadOrderImportFactory { // 达到批量的阈值就做一次插入 if (CollUtil.isNotEmpty(orderModelDOS) && (orderModelDOS.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { // 保存生产单造型数据 - orderInputProcessor.batchSaveModel(orderModelDOS); + orderInputProcessor.batchAsyncSaveModel(orderModelDOS); if (!isLast) { // 存储完成清理 list orderModelDOS.clear(); @@ -1824,342 +1809,97 @@ public class WebCadOrderImportFactory { } /** - * 获取板件封边厚度 - * cad封边列表的顺序:下右上左 - * - * @param plateDO - * @param sealingList + * 保存数据 + * orderBody、orderGroup */ - private void calculateSealThickness(PlateDO plateDO, List sealingList) { - if (CollUtil.isNotEmpty(sealingList) && sealingList.size() == 4) { - plateDO.setSealDown(BigDecimal.valueOf(sealingList.get(0).getSize())); - plateDO.setSealLeft(BigDecimal.valueOf(sealingList.get(1).getSize())); - plateDO.setSealUp(BigDecimal.valueOf(sealingList.get(2).getSize())); - plateDO.setSealRight(BigDecimal.valueOf(sealingList.get(3).getSize())); - } - } - - /** - * 同步保存板件 - */ - private void savePlateSync() { - TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); - - try { - List> plateList = batchProcess(plateDOS); - - // 同步插入order_plate - batchSavePlate(plateList); - // 清理order_plate相关的列表 - plateList.clear(); - - } catch (Exception e) { - log.error("WEBCAD import savePlate error", e); - // 事务回滚 - transactionManager.rollback(transactionStatus); - // 抛出异常回滚 - throw new ServiceException(WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR); - } finally { - // 清理order_plate相关的列表 - plateDOS.clear(); - } - - // 事务提交 - transactionManager.commit(transactionStatus); - } - - /** - * 批次插入板件 - * - * @param plateList 分批次后的板件列表 - */ - private void batchSavePlate(List> plateList) { - for (List plates : plateList) { - String sql = "INSERT INTO order_plate (id,organ_id,order_id,name,plate_no,type,goods_id,width,height,thickness,split_width,split_height,split_thickness,seal_left,seal_right,seal_up,seal_down,area,texture,hole_face,hole_arrange,unregular_point_count,front_hole_count,back_hole_count,side_hole_count,front_model_count,back_model_count,is_door,open_door_type,offset_x,offset_y,is_arc_across,module_type_id,is_special_shaped,is_sculpt,is_row_hole,is_optimized,is_cutted,filter_type,remark,is_cancel,deleted,custom_plate_no,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; - jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps, int index) throws SQLException { - PlateDO item = plates.get(index); - ps.setLong(1, item.getId()); - ps.setLong(2, item.getOrganId()); - ps.setLong(3, item.getOrderId()); - ps.setString(4, item.getName()); - ps.setString(5, item.getPlateNo()); - ps.setInt(6, item.getType()); - ps.setLong(7, item.getGoodsId()); - ps.setBigDecimal(8, item.getWidth()); - ps.setBigDecimal(9, item.getHeight()); - ps.setBigDecimal(10, item.getThickness()); - ps.setBigDecimal(11, item.getSplitWidth()); - ps.setBigDecimal(12, item.getSplitHeight()); - ps.setBigDecimal(13, item.getSplitThickness()); - ps.setBigDecimal(14, item.getSealLeft()); - ps.setBigDecimal(15, item.getSealRight()); - ps.setBigDecimal(16, item.getSealUp()); - ps.setBigDecimal(17, item.getSealDown()); - ps.setBigDecimal(18, item.getArea()); - ps.setInt(19, item.getTexture()); - ps.setInt(20, item.getHoleFace()); - ps.setInt(21, item.getHoleArrange()); - ps.setInt(22, item.getUnregularPointCount()); - ps.setInt(23, item.getFrontHoleCount()); - ps.setInt(24, item.getBackHoleCount()); - ps.setInt(25, item.getSideHoleCount()); - ps.setInt(26, item.getFrontModelCount()); - ps.setInt(27, item.getBackModelCount()); - ps.setBoolean(28, item.getIsDoor()); - ps.setInt(29, item.getOpenDoorType()); - ps.setBigDecimal(30, item.getOffsetX()); - ps.setBigDecimal(31, item.getOffsetY()); - ps.setBoolean(32, item.getIsArcAcross()); - ps.setLong(33, item.getModuleTypeId()); - ps.setBoolean(34, item.getIsSpecialShaped()); - ps.setBoolean(35, item.getIsSculpt()); - ps.setBoolean(36, item.getIsRowHole()); - ps.setBoolean(37, item.getIsOptimized()); - ps.setInt(38, item.getIsCutted()); - ps.setString(39, item.getFilterType()); - ps.setString(40, item.getRemark()); - ps.setBoolean(41, item.getIsCancel()); - ps.setBoolean(42, item.getDeleted()); - ps.setString(43, item.getCustomPlateNo()); - ps.setTimestamp(44, Timestamp.valueOf(item.getCreateTime())); - ps.setTimestamp(45, Timestamp.valueOf(item.getUpdateTime())); - ps.setString(46, item.getCreator()); - ps.setString(47, item.getUpdater()); - } - - @Override - public int getBatchSize() { - return plates.size(); - } - }); - } - } - - /** - * 同步保存配件 - */ - private void savePartSync() { - TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); - - try { - List> partList = batchProcess(orderPartsDOS); - - // 同步插入order_plate - batchSavePart(partList); - // 清理order_plate相关的列表 - partList.clear(); - - } catch (Exception e) { - log.error("WEBCAD import savePart error", e); - // 事务回滚 - transactionManager.rollback(transactionStatus); - // 抛出异常回滚 - throw new ServiceException(WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR); - } finally { - // 清理order_plate相关的列表 - orderPartsDOS.clear(); - } - - // 事务提交 - transactionManager.commit(transactionStatus); - } - - /** - * 批次插入配件 - * - * @param partList 分批次后的配件列表 - */ - private void batchSavePart(List> partList) { - for (List plates : partList) { - String sql = "INSERT INTO order_parts (id,organ_id,order_id,goods_id,name,color,material,category,type,width,length,thickness,model,spec,brand,factory,unit,price,is_composite,subparts,remark,deleted,create_time,update_time,creator,updater) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; - jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps, int index) throws SQLException { - OrderPartsDO item = plates.get(index); - ps.setLong(1, item.getId()); - ps.setLong(2, item.getOrganId()); - ps.setLong(3, item.getOrderId()); - ps.setString(4, item.getGoodsId()); - ps.setString(5, item.getName()); - ps.setString(6, item.getColor()); - ps.setString(7, item.getMaterial()); - ps.setString(8, item.getCategory()); - ps.setString(9, item.getType()); - ps.setDouble(10, item.getWidth()); - ps.setDouble(11, item.getLength()); - ps.setDouble(12, item.getThickness()); - ps.setString(13, item.getModel()); - ps.setString(14, item.getSpec()); - ps.setString(15, item.getBrand()); - ps.setString(16, item.getFactory()); - ps.setString(17, item.getUnit()); - ps.setDouble(18, item.getPrice()); - ps.setBoolean(19, item.getIsComposite()); - ps.setString(20, item.getSubparts()); - ps.setString(21, item.getRemark()); - ps.setBoolean(22, item.getDeleted()); - ps.setTimestamp(23, Timestamp.valueOf(item.getCreateTime())); - ps.setTimestamp(24, Timestamp.valueOf(item.getUpdateTime())); - ps.setString(25, item.getCreator()); - ps.setString(26, item.getUpdater()); - } - - @Override - public int getBatchSize() { - return plates.size(); - } - }); - } - } - - /** - * 同步保存item - */ - private void saveItemSync() { - TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); - - try { - List> itemList = batchProcess(orderItemDOS); - - // 同步插入order_plate - batchSaveItem(itemList); - // 清理order_plate相关的列表 - itemList.clear(); - - } catch (Exception e) { - log.error("WEBCAD import saveItem error", e); - // 事务回滚 - transactionManager.rollback(transactionStatus); - // 抛出异常回滚 - throw new ServiceException(WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR); - } finally { - // 清理order_plate相关的列表 - orderItemDOS.clear(); - } - - // 事务提交 - transactionManager.commit(transactionStatus); - } - - /** - * 批次插入item - * - * @param itemList 分批次后的item列表 - */ - private void batchSaveItem(List> itemList) { - for (List items : itemList) { - String sql = "INSERT INTO order_item (id,order_id,type,room_id,body_id,package_id,group_id,plate_id,parts_id,num,organ_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)"; - jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps, int index) throws SQLException { - OrderItemDO item = items.get(index); - ps.setLong(1, item.getId()); - ps.setLong(2, item.getOrderId()); - ps.setInt(3, item.getType()); - ps.setLong(4, item.getRoomId()); - ps.setLong(5, item.getBodyId()); - ps.setLong(6, item.getPackageId()); - ps.setLong(7, item.getGroupId()); - ps.setLong(8, item.getPlateId()); - ps.setLong(9, item.getPartsId()); - ps.setDouble(10, item.getNum()); - ps.setLong(11, item.getOrganId()); - } - - @Override - public int getBatchSize() { - return items.size(); - } - }); - } - } - - /** - * 异步保存数据 - * orderBody、orderItem、orderGroup - */ - private void saveDataAsync() { - TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); - AtomicBoolean hasError = new AtomicBoolean(false); - + private void saveData() { + // 分成1000一组 List> bodyList = batchProcess(bodyMap.values().stream().toList()); List> groupList = batchProcess(orderGroupDOS); - // 计数器 - CountDownLatch latch = new CountDownLatch(bodyList.size() + groupList.size()); // 保存 - saveBodyAsync(bodyList, latch, hasError); - saveGroupAsync(groupList, latch, hasError); - - try { - // 等待所有任务完成,30s没有完成就主动终止 - latch.await(30, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - hasError.set(true); - log.error("WEBCAD import saveData Thread interrupted", e); - } - - if (hasError.get()) { - // 事务回滚 - transactionManager.rollback(transactionStatus); - // 抛出异常回滚主线程的数据 - throw new ServiceException(WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR); - } else { - // 事务提交 - transactionManager.commit(transactionStatus); - } + saveBody(bodyList); + saveGroup(groupList); } /** - * 异步插入柜体 + * 插入柜体 * - * @param latch - * @param hasError + * @param bodyList */ - private void saveBodyAsync(List> bodyList, CountDownLatch latch, AtomicBoolean hasError) { - for (List bodyDOS : bodyList) { - threadPoolTaskExecutor.submit(() -> { - try { - // 子线程同步主线程的多数据源 - DynamicDataSourceContextHolder.push(peek); - orderBodyMapper.insertBatchSomeColumn(bodyDOS); - } catch (Exception e) { - log.error("WEBCAD import saveBodyAsync error", e); - boolean b = hasError.get(); - if (!b) { - hasError.set(true); - } - } finally { - latch.countDown(); // 任务完成,计数器减1 + private void saveBody(List> bodyList) { + for (List bodys : bodyList) { + String sql = "INSERT INTO order_body (id, organ_id, order_id, room_id, room_name, name, width, height, depth, multi_num, plate_num, unregular_num, filename, remark, deleted,create_time,update_time,creator,updater) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderBodyDO orderBodyDO = bodys.get(index); + ps.setLong(1, orderBodyDO.getId()); + ps.setLong(2, orderBodyDO.getOrganId()); + ps.setLong(3, orderBodyDO.getOrderId()); + ps.setLong(4, orderBodyDO.getRoomId()); + ps.setString(5, orderBodyDO.getRoomName()); + ps.setString(6, orderBodyDO.getName()); + ps.setDouble(7, orderBodyDO.getWidth()); + ps.setDouble(8, orderBodyDO.getHeight()); + ps.setDouble(9, orderBodyDO.getDepth()); + ps.setInt(10, orderBodyDO.getMultiNum()); + ps.setInt(11, orderBodyDO.getPlateNum()); + ps.setInt(12, orderBodyDO.getUnregularNum()); + ps.setString(13, orderBodyDO.getFilename()); + ps.setString(14, orderBodyDO.getRemark()); + ps.setBoolean(15, orderBodyDO.getDeleted()); + ps.setTimestamp(16, Timestamp.valueOf(orderBodyDO.getCreateTime())); + ps.setTimestamp(17, Timestamp.valueOf(orderBodyDO.getUpdateTime())); + ps.setString(18, orderBodyDO.getCreator()); + ps.setString(19, orderBodyDO.getUpdater()); + } + + @Override + public int getBatchSize() { + return bodys.size(); } }); } } /** - * 异步插入加工组 + * 插入加工组 * - * @param latch - * @param hasError + * @param groupList */ - private void saveGroupAsync(List> groupList, CountDownLatch latch, AtomicBoolean hasError) { - for (List orderGroupDOS : groupList) { - threadPoolTaskExecutor.submit(() -> { - try { - // 子线程同步主线程的多数据源 - DynamicDataSourceContextHolder.push(peek); - orderGroupMapper.insertBatchSomeColumn(orderGroupDOS); - } catch (Exception e) { - log.error("WEBCAD import saveGroupAsync error", e); - boolean b = hasError.get(); - if (!b) { - hasError.set(true); - } - } finally { - latch.countDown(); // 任务完成,计数器减1 + private void saveGroup(List> groupList) { + for (List groups : groupList) { + String sql = "INSERT INTO order_group (id, organ_id, order_id, body_id, group_type_id, group_type_name, name, width, height, depth, multi_num, plate_num, unregular_num, filename, remark, deleted,create_time,update_time,creator,updater) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?)"; + jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int index) throws SQLException { + OrderGroupDO orderGroupDO = groups.get(index); + ps.setLong(1, orderGroupDO.getId()); + ps.setLong(2, orderGroupDO.getOrganId()); + ps.setLong(3, orderGroupDO.getOrderId()); + ps.setLong(4, orderGroupDO.getBodyId()); + ps.setLong(5, orderGroupDO.getGroupTypeId()); + ps.setString(6, orderGroupDO.getGroupTypeName()); + ps.setString(7, orderGroupDO.getName()); + ps.setDouble(8, orderGroupDO.getWidth()); + ps.setDouble(9, orderGroupDO.getHeight()); + ps.setDouble(10, orderGroupDO.getDepth()); + ps.setInt(11, orderGroupDO.getMultiNum()); + ps.setInt(12, orderGroupDO.getPlateNum()); + ps.setInt(13, orderGroupDO.getUnregularNum()); + ps.setString(14, orderGroupDO.getFilename()); + ps.setString(15, orderGroupDO.getRemark()); + ps.setBoolean(16, orderGroupDO.getDeleted()); + ps.setTimestamp(17, Timestamp.valueOf(orderGroupDO.getCreateTime())); + ps.setTimestamp(18, Timestamp.valueOf(orderGroupDO.getUpdateTime())); + ps.setString(19, orderGroupDO.getCreator()); + ps.setString(20, orderGroupDO.getUpdater()); + } + + @Override + public int getBatchSize() { + return groups.size(); } }); } @@ -2196,8 +1936,9 @@ public class WebCadOrderImportFactory { bodyMap.clear(); orderGroupMap.clear(); materialMap.clear(); - existRoomMap.clear(); processGroupMap.clear(); + existRoomIdMap.clear(); + orderPartMap.clear(); plateDOS.clear(); orderItemDOS.clear(); diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml index aba6d2e11..06fb0e8dc 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml @@ -72,6 +72,12 @@ spring: port: 5672 # RabbitMQ 服务的端口 username: guest # RabbitMQ 服务的账号 password: guest # RabbitMQ 服务的密码 + listener: + simple: + concurrency: 2 + max-concurrency: 5 + prefetch: 5 + acknowledge-mode: manual # Kafka 配置项,对应 KafkaProperties 配置类 kafka: bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application.yaml b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application.yaml index 2b8f5b916..191b1c9c6 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application.yaml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application.yaml @@ -172,4 +172,11 @@ chenfeng: ignore-tables: encrypt: enable: false - publicKey: cfimes \ No newline at end of file + publicKey: cfimes + plan: + webcad: + import: + node: 1 + async-plate-threshold: 5000 + cadImportPlateNumThreshold: 20000 + temp-file-path: /data/imes-server/cf-prod-plan/local \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/config/ChenfengRabbitMQSystemConfiguration.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/config/ChenfengRabbitMQSystemConfiguration.java new file mode 100644 index 000000000..92d407f12 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/config/ChenfengRabbitMQSystemConfiguration.java @@ -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 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(); + } +}