From 38054f58f9b8fe21f6567dc66d2f08ebf727e32f Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 28 Feb 2025 16:27:34 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E7=94=9F=E4=BA=A7?= =?UTF-8?q?=E5=8D=95xml=E5=AF=BC=E5=85=A5=E5=BC=82=E6=AD=A5=E5=A4=84?= =?UTF-8?q?=E7=90=86=EF=BC=9B2=E3=80=81excel=E5=AF=BC=E5=85=A5=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dict/core/util/DictFrameworkUtils.java | 4 +- .../ChenfengRabbitMQAutoConfiguration.java | 45 +- .../rabbitmq/constant/RabbitMqConstants.java | 14 +- .../executor/enums/ErrorCodeConstants.java | 3 + .../executor/enums/OrderImportConstants.java | 5 + .../enums/OrderImportTmpDataTypeEnum.java | 7 +- .../orderImport/OrderImportTempDataDO.java | 25 + .../xml/DefaultXmlOrderImportHandler.java | 103 +- .../DefaultOrderImportExcelListener.java | 50 +- .../DefaultOrderImportXmlParserHandler.java | 2049 +++++++++++++++++ .../admin/files/xml/VO/RoomBoxXmlVO.java | 72 + .../cf-module-prod-plan-biz/pom.xml | 20 +- .../vo/OrderImportTempDataReqVO.java | 15 + .../orderImport/xml/vo/AssemblyXmlVO.java | 92 + .../orderImport/xml/vo/BlockXmlVO.java | 138 ++ .../orderImport/xml/vo/CorrelationXmlVO.java | 55 + .../xml/vo/CuttingOutlineXmlVO.java | 20 + .../orderImport/xml/vo/EdgingXmlVO.java | 92 + .../orderImport/xml/vo/ExtraVO.java | 44 + .../orderImport/xml/vo/GrooveXmlVO.java | 73 + .../orderImport/xml/vo/GrooveXmlVOS.java | 53 + .../orderImport/xml/vo/GroupXmlVO.java | 33 + .../orderImport/xml/vo/HardwareXmlVO.java | 92 + .../orderImport/xml/vo/HoleXmlVO.java | 91 + .../orderImport/xml/vo/HoleXmlVOS.java | 53 + .../orderImport/xml/vo/IsletXmlVO.java | 23 + .../orderImport/xml/vo/OffsetLineXmlVO.java | 32 + .../orderImport/xml/vo/PlateXmlVO.java | 89 + .../orderImport/xml/vo/PointXmlVO.java | 71 + .../orderImport/xml/vo/RectSealVO.java | 30 + .../orderImport/xml/vo/RemarkXmlVO.java | 19 + .../orderImport/xml/vo/RoomBoxXmlVO.java | 76 + .../orderImport/OrderImportTempDataDO.java | 62 + ...rderImportTempDataPartItemCodeGroupDO.java | 38 + ...mportTempDataPartRoomBodyGroupGroupDO.java | 42 + .../OrderImportTempDataMapper.java | 18 + .../DefaultExcelOrderImportConsumer.java | 3 + .../DefaultXmlOrderImportConsumer.java | 260 +++ .../DefaultExcelOrderImportFactory.java | 19 +- .../factory/DefaultXmlOrderImportFactory.java | 2005 ++++++++++++++++ .../orderImport/OrderImportTempDataMapper.xml | 15 + 41 files changed, 6007 insertions(+), 43 deletions(-) create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/DefaultOrderImportXmlParserHandler.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/VO/RoomBoxXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/AssemblyXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/BlockXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CorrelationXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CuttingOutlineXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/EdgingXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/ExtraVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVOS.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GroupXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HardwareXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVOS.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/IsletXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/OffsetLineXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PlateXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PointXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RectSealVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RemarkXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RoomBoxXmlVO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartItemCodeGroupDO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartRoomBodyGroupGroupDO.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultXmlOrderImportConsumer.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java diff --git a/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java index 69335d8ee..49a669bc9 100644 --- a/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java @@ -28,7 +28,7 @@ public class DictFrameworkUtils { * 针对 {@link #getDictDataLabel(String, String)} 的缓存 */ private static final LoadingCache, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( - Duration.ofMinutes(1L), // 过期时间 1 分钟 + Duration.ofMinutes(10L), // 过期时间 1 分钟 new CacheLoader<>() { @Override @@ -43,7 +43,7 @@ public class DictFrameworkUtils { * 针对 {@link #parseDictDataValue(String, String)} 的缓存 */ private static final LoadingCache, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( - Duration.ofMinutes(1L), // 过期时间 1 分钟 + Duration.ofMinutes(10L), // 过期时间 1 分钟 new CacheLoader<>() { @Override 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 bf52fd5c0..191a84c2e 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 @@ -41,22 +41,22 @@ public class ChenfengRabbitMQAutoConfiguration { /** - * 生产单导入交换机、队列、绑定声明 + * 生产单excel导入交换机、队列、绑定声明 * * @return */ @Bean - public FanoutExchange orderImportFanoutExchange() { + public FanoutExchange orderImportDefaultExcelFanoutExchange() { return new FanoutExchange(RabbitMqConstants.ORDER_IMPORT_DEFAULT_EXCEL_EXCHANGE); } /** - * 生产单导入队列声明 + * 生产单excel导入队列声明 * * @return */ @Bean - public Queue orderImportQueue() { + public Queue orderImportDefaultExcelQueue() { Map args = new HashMap<>(1); // x-dead-letter-exchange 这里声明当前队列绑定的死信交换机 args.put("x-dead-letter-exchange", ORDER_IMPORT_DEAD_LETTER_EXCHANGE); @@ -72,7 +72,42 @@ public class ChenfengRabbitMQAutoConfiguration { */ @Bean public Binding orderImportDefaultExcelBinding() { - return BindingBuilder.bind(orderImportQueue()).to(orderImportFanoutExchange()); + 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()); } /** 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 f136772b3..553315086 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 @@ -8,15 +8,25 @@ package com.cf.imes.framework.mq.rabbitmq.constant; */ public class RabbitMqConstants { /** - * 生产单导入交换机 + * 生产单导入excel交换机 */ public static final String ORDER_IMPORT_DEFAULT_EXCEL_EXCHANGE = "order_import_default_excel_exchange"; /** - * 生产单导入队列 + * 生产单导入excel队列 */ public static final String ORDER_IMPORT_DEFAULT_EXCEL_QUEUE = "order_import_default_excel_queue"; + /** + * 生产单导入xml交换机 + */ + public static final String ORDER_IMPORT_DEFAULT_XML_EXCHANGE = "order_import_default_xml_exchange"; + + /** + * 生产单导入xml队列 + */ + public static final String ORDER_IMPORT_DEFAULT_XML_QUEUE = "order_import_default_xml_queue"; + /** * 生产单导入死信交换机 */ diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java index a6a52dcce..18ff2044c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java @@ -91,4 +91,7 @@ public class ErrorCodeConstants { public static final ErrorCode ORDER_IMPORT_DETAIL_FIELD_EMPTY = new ErrorCode(1_002_031_010, "导入校验异常:第{}行,导入明细【{}】不能为空"); public static final ErrorCode ORDER_IMPORT_DETAIL_FIELD_LENGTH_ERROR = new ErrorCode(1_002_031_011, "导入校验异常:第{}行,导入明细【{}】长度不能超过【{}】个字符"); public static final ErrorCode ORDER_IMPORT_DETAIL_VALID_ERROR = new ErrorCode(1_002_031_012, "导入校验异常:{}"); + public static final ErrorCode ORDER_IMPORT_GROUPCODE_NOT_EXIST_VALID_ERROR = new ErrorCode(1_002_031_013, "导入校验异常:板件{}下加工组编码{}不存在于加工组编码列表中"); + public static final ErrorCode ORDER_IMPORT_ROOMCODE_NOT_EXIST_VALID_ERROR = new ErrorCode(1_002_031_014, "导入校验异常:板件{}下房间编码{}不存在于房间编码列表中"); + public static final ErrorCode ORDER_IMPORT_BODYCODE_NOT_EXIST_VALID_ERROR = new ErrorCode(1_002_031_015, "导入校验异常:板件{}下柜体编码{}不存在于柜体编码列表中"); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportConstants.java index e3c9bb05d..4c4b7f9a2 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportConstants.java @@ -16,4 +16,9 @@ public class OrderImportConstants { * 房间、柜体缺省name */ public static final String NOT_ASSIGNED = "未命名"; + + /** + * 房间柜体缺省code + */ + public static final String NOT_ASSIGNED_CODE = "未命编号"; } diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportTmpDataTypeEnum.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportTmpDataTypeEnum.java index 00238d511..d9a2c9ee4 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportTmpDataTypeEnum.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/OrderImportTmpDataTypeEnum.java @@ -34,9 +34,10 @@ public enum OrderImportTmpDataTypeEnum { BLOCK_GROOVE_POINTS_POINT(20), BLOCK_GROOVE_ISLET(21), BLOCK_GROOVE_ISLET_POINTS_POINT(22), - BLOCK_GROOVE_OFFSETLINE(23), - BLOCK_REMKAR(24), - PART_REMARK(25); + BLOCK_GROOVE_CORRELATIONS(23), + BLOCK_GROOVE_OFFSETLINE(24), + BLOCK_REMKAR(25), + PART_REMARK(26); private int type; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderImport/OrderImportTempDataDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderImport/OrderImportTempDataDO.java index 47e6d6e12..0ed53adfe 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderImport/OrderImportTempDataDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderImport/OrderImportTempDataDO.java @@ -54,6 +54,16 @@ public class OrderImportTempDataDO { */ private Integer type; + /** + * 设计端id + */ + private String outerId; + + /** + * 设计端归属id + */ + private String outerSubId; + /** * 物料编码 */ @@ -145,11 +155,21 @@ public class OrderImportTempDataDO { */ private String roomName; + /** + * 房间编号 + */ + private String roomCode; + /** * 柜体名称 */ private String bodyName; + /** + * 柜体编号 + */ + private String bodyCode; + /** * 加工组类型 */ @@ -160,6 +180,11 @@ public class OrderImportTempDataDO { */ private String groupName; + /** + * 加工组编号 + */ + private String groupCode; + /** * 创建人 */ 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 9d5cfbe2a..30db596c9 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 @@ -1,10 +1,35 @@ package com.cf.imes.module.executor.service.orderImport.handler.xml; +import com.cf.imes.framework.common.exception.ServiceException; +import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants; +import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator; +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.controller.admin.order.vo.order.OrderImportAsyncReqVO; +import com.cf.imes.module.executor.dal.dataobject.orderImport.OrderImportTaskDO; +import com.cf.imes.module.executor.dal.mysql.orderImport.OrderImportTaskMapper; +import com.cf.imes.module.executor.dal.mysql.orderImport.OrderImportTempDataMapper; +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.executor.service.order.OrderService; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.DefaultOrderImportXmlParserHandler; import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageBuilder; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; + +import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_FILE_ANALYZE_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORGAN_LOCK_ERROR; + /** * @author Gqr * @since 2025/1/9 9:21 @@ -12,6 +37,27 @@ import org.springframework.web.multipart.MultipartFile; @Service("defaultXmlOrderImportHandler") @Slf4j public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandler { + @Resource + private OrderImportTempDataMapper orderImportTempDataMapper; + + @Resource + private OrderService orderService; + + @Resource + private SnowFlakeGenerator snowFlakeGenerator; + + @Resource + private OrderImportTaskMapper orderImportTaskMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private RedisLockUtil redisLockUtil; + + @Resource + private ChenfengCacheProperties chenfengCacheProperties; + @Override public String getFactoryName() { return "default"; @@ -19,6 +65,61 @@ public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandl @Override public void prepareAndConvert(OrderImportAsyncReqVO importAsyncReqVO, MultipartFile file) { - // todo xml 准备、转换前置数据 + // 创建任务 + Long taskId = createImportTask(); + String importLockKey = String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, getUserOrganId()); + // 检查机构导入锁 + boolean lockResult = redisLockUtil.lock(importLockKey, String.valueOf(taskId), chenfengCacheProperties.getLockTimeout()); + if (!lockResult) { + throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR); + } + try { + DefaultOrderImportXmlParserHandler defaultOrderImportXmlParserHandler = new DefaultOrderImportXmlParserHandler(orderImportTempDataMapper, orderService, snowFlakeGenerator, importAsyncReqVO.getOrderId(), taskId); + defaultOrderImportXmlParserHandler.analyzeFile(file); + } catch (ServiceException sev) { + // 导入锁解锁 + redisLockUtil.unlock(importLockKey, taskId.toString()); + throw sev; + } catch (Exception e) { + log.error(ORDER_IMPORT_FILE_ANALYZE_ERROR.getMsg(), e); + // 导入锁解锁 + redisLockUtil.unlock(importLockKey, taskId.toString()); + throw new ServiceException(ORDER_IMPORT_FILE_ANALYZE_ERROR); + } + + Message message = MessageBuilder + .withBody(taskId.toString().getBytes()) + .setHeader("x-message-ttl", 60000) // 设置 TTL 为 60000 毫秒(60 秒) + .build(); + //如果处于事务中,待事务提交成功了再执行后续操作,防止事务未提交完成导致消费端查不到数据 + if (TransactionSynchronizationManager.isActualTransactionActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + // 数据库操作全部完成发送消息 + rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_EXCHANGE, null, message); + } + }); + } else { + // 数据库操作全部完成发送消息 + rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_EXCHANGE, null, message); + } + } + + /** + * 创建导入任务 + * + * @return taskId + */ + private Long createImportTask() { + // 创建导入任务 + OrderImportTaskDO orderImportTaskDO = OrderImportTaskDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .type(OrderImportTypeEnum.EXCEL.getType()) + .importStatus(OrderImportStatusEnum.IMPORT_NOT_YET.getStatus()) + .status(OrderImportTaskStatusEnum.CREATE_NOT_CONSUME.getStatus()) + .build(); + orderImportTaskMapper.insert(orderImportTaskDO); + return orderImportTaskDO.getId(); } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/excel/DefaultOrderImportExcelListener.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/excel/DefaultOrderImportExcelListener.java index e7186885a..b8ad48847 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/excel/DefaultOrderImportExcelListener.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/excel/DefaultOrderImportExcelListener.java @@ -97,6 +97,11 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener private int sort = 1; + /** + * 行号 + */ + private int rowIndex; + private static final String NUMBER_TYPE_ERR = "数量类型错误"; private static final String NOT_EMPTY = "不可为空"; private static final String ACCORD_ENUM = "请按照提示词语选择填入"; @@ -123,7 +128,7 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener // 获取行号 ReadRowHolder readRowHolder = context.readRowHolder(); - Integer rowIndex = readRowHolder.getRowIndex(); + rowIndex = readRowHolder.getRowIndex(); // 生产单信息在1-5行间 boolean isOrderInfo = (rowIndex >= 0 && rowIndex <= 4); @@ -600,14 +605,23 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener } + /** + * 获取行数的提示,第rowIndex行 + * + * @return + */ + private String getRowIndexNotification() { + return String.format("第%s行", rowIndex + 1); + } + // 判断非空,字典值判断 public void isNotEmptyAndDict(String value, String dictType, String errValue) { if (StringUtils.isEmpty(value)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NOT_EMPTY); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NOT_EMPTY); } else { DictDataRespDTO dictDataRespDTO = dictDataApi.parseDictData(dictType, value).getData(); if (dictDataRespDTO == null) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + ACCORD_ENUM); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + ACCORD_ENUM); } } } @@ -615,12 +629,12 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener // 非空判断,错误填入 private void isEmpty(String value, String errValue, int length) { if (StringUtils.isEmpty(value)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NOT_EMPTY); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NOT_EMPTY); } else { // 字符串长度检查 int size = value.length(); if (size > length) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_LENGTH_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_LENGTH_ERR); } } } @@ -629,7 +643,7 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener // 判断非零,错误返回;不为空时,判断是否符合枚举类 private void isNotEmptyAndBack(String value, Class> enumClass, String errValue, int length) { if (StringUtils.isEmpty(value)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NOT_EMPTY); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NOT_EMPTY); } else { isEmptyAndSize(value, length, errValue); try { @@ -646,10 +660,10 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener } } if (!isValid) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + ACCORD_ENUM); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + ACCORD_ENUM); } } catch (IllegalArgumentException e) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + ACCORD_ENUM); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + ACCORD_ENUM); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } @@ -670,13 +684,13 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener if (Boolean.TRUE.equals(ToolUtil.convertToType(value, targetType))) { if (Boolean.TRUE.equals(ToolUtil.checkNumber(value))) { if (!ToolUtil.checkPrecision(value, length, decimalLength)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_LENGTH_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_LENGTH_ERR); } } else { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + POSITIVE_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + POSITIVE_ERR); } } else { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_TYPE_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_TYPE_ERR); } } } @@ -695,13 +709,13 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener if (Boolean.TRUE.equals(ToolUtil.convertToType(value, targetType))) { if (Boolean.TRUE.equals(checkPositiveNumber(value))) { if (!ToolUtil.checkPrecision(value, length, decimalLength)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_LENGTH_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_LENGTH_ERR); } } else { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + "必须大于0"); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + "必须大于0"); } } else { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_TYPE_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_TYPE_ERR); } } } @@ -709,7 +723,7 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener // 判断非零,错误返回 private void isNotEmptyAndBack(String value, String errValue) { if (StringUtils.isEmpty(value)) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NOT_EMPTY); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NOT_EMPTY); } } @@ -718,7 +732,7 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener if (StringUtils.isNotEmpty(value)) { int size = value.length(); if (size > length) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_LENGTH_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_LENGTH_ERR); } } } @@ -727,10 +741,10 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener public void isEmptyAndPositiveNumber(String value, Class targetType, String errValue) { if (StringUtils.isNotEmpty(value)) { if (Boolean.FALSE.equals(ToolUtil.convertToType(value, targetType))) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + NUMBER_TYPE_ERR); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + NUMBER_TYPE_ERR); } else { if (Boolean.FALSE.equals(checkPositiveNumber(value))) { - throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, errValue + "数量必须大于0"); + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, getRowIndexNotification() + errValue + "数量必须大于0"); } } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/DefaultOrderImportXmlParserHandler.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/DefaultOrderImportXmlParserHandler.java new file mode 100644 index 000000000..d02e4405d --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/DefaultOrderImportXmlParserHandler.java @@ -0,0 +1,2049 @@ +package com.cf.imes.module.executor.util.fileConversion.admin.files.xml; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.map.MapUtil; +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.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; +import com.cf.imes.framework.common.util.json.JsonUtils; +import com.cf.imes.framework.dict.core.util.DictFrameworkUtils; +import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator; +import com.cf.imes.framework.organ.core.context.OrganContextHolder; +import com.cf.imes.framework.web.core.util.WebFrameworkUtils; +import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.dal.dataobject.orderImport.OrderImportTempDataDO; +import com.cf.imes.module.executor.dal.mysql.orderImport.OrderImportTempDataMapper; +import com.cf.imes.module.executor.enums.DataTypeEnum; +import com.cf.imes.module.executor.enums.DictTypeConstants; +import com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum; +import com.cf.imes.module.executor.enums.OrderStatusEnum; +import com.cf.imes.module.executor.enums.OrderTypeEnum; +import com.cf.imes.module.executor.service.order.OrderService; +import com.cf.imes.module.executor.util.fileConversion.admin.ToolUtil; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.AssemblyXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.BlockXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.CorrelationXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.CuttingOutlineXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.EdgingXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.GrooveXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.GrooveXmlVOS; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.GroupXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.HardwareXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.HoleXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.HoleXmlVOS; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.IsletXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.OffsetLineXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.OrderXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.OutlineXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.PlateXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.PointXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.PointXmlVOS; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.RawOutlineXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.RemarkXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.RoomBoxXmlVO; +import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.RoomXmlVO; +import jodd.util.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_BODYCODE_NOT_EXIST_VALID_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_DETAIL_VALID_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_GROUPCODE_NOT_EXIST_VALID_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_CUSTOMERNO_EXISTS; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_FIELD_DATE_FORMAT_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_FIELD_EMPTY; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_FIELD_LENGTH_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_FIELD_MOBILE_FORMAT_ERROR; +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ROOMCODE_NOT_EXIST_VALID_ERROR; +import static com.cf.imes.module.executor.enums.OrderImportConstants.NOT_ASSIGNED; +import static com.cf.imes.module.executor.enums.OrderImportConstants.NOT_ASSIGNED_CODE; + +/** + * 默认生产单xml解析处理器 + * + * @author Gqr + * @since 2025/2/18 16:31 + */ +@Slf4j +public class DefaultOrderImportXmlParserHandler { + + /** + * 存放生产单orders信息 + */ + private OrderDO orderDO; + /** + * 每500条操作入库一次 + */ + private static final int BATCH_COUNT = 500; + private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + + private static final String TYPE_ERR = "%s数据类型错误"; + private static final String POSITIVE_ERR = "%s数据需为正数"; + private static final String LONG_ERR = "%s数据长度不符合(共8位整数位5位,小数位3位)"; + private static final String IS_NULL = "%s不能为空"; + private static final String INVALID = "%s数据无效"; + + // todo 对编码去重,如果后期性能瓶颈需要改造到消费后用数据库 + private Set groupCodeSet = new HashSet<>(); + private Map> roomBodyCodeMap = new HashMap<>(); + + /** + * 补板用 + */ + private Long orderId; + + /** + * 是否补板 + */ + boolean addToExistsOrder; + + /** + * 导入任务id + */ + private Long taskId; + + private int sort = 1; + + // 全局对象,一般用于下级获取属性或者信息提示 + private RoomXmlVO roomXmlVO; + private RawOutlineXmlVO rawOutlineXmlVO; + private PointXmlVOS pointXmlVOS; + private OutlineXmlVO outlineXmlVO; + private StartElement se; + + // 全局编码标记,如进入plate时设置plateItemCode,结束时设为null + private String plateItemCode; + private String blockProductionCode; + private String partItemCode; + private String outerId; + + // 全局标签标记,如进入block时inBlock设为true,结束block时设为false + private boolean inBlock; + private boolean inOutline; + private boolean inCuttingOutline; + private boolean inRawOutline; + private boolean inGroove; + private boolean inPoints; + private boolean inIslet; + + private int pointNum; + + private OrderImportTempDataMapper orderImportTempDataMapper; + + private OrderService orderService; + + private SnowFlakeGenerator snowFlakeGenerator; + + private Map NOT_ASSIGNED_BODY_EXISTS_MAP = MapUtil.builder() + .put("false%true", false) + .put("true%true", false) + .put("true%false", false) + .build(); + + public DefaultOrderImportXmlParserHandler(OrderImportTempDataMapper orderImportTempDataMapper, OrderService orderService, SnowFlakeGenerator snowFlakeGenerator, Long orderId, Long taskId) { + this.orderImportTempDataMapper = orderImportTempDataMapper; + this.orderService = orderService; + this.snowFlakeGenerator = snowFlakeGenerator; + this.orderId = orderId; + this.taskId = taskId; + // 是否补板 + addToExistsOrder = ObjectUtil.isNotNull(orderId); + } + + /** + * 解析文件 + * + * @param file + * @throws Exception + */ + public void analyzeFile(MultipartFile file) throws Exception { + InputStream is = null; + try { + //初始化工厂类以创建出XMLEventReader对象 + XMLInputFactory factory = + XMLInputFactory.newFactory(); + is = file.getInputStream(); + //通过读取XML文件创建XMLEventReader + XMLEventReader reader = factory.createXMLEventReader(is); + + //判断是否还有下一个元素 + while (reader.hasNext()) { + //获取元素对象XMLEvent + XMLEvent en = reader.nextEvent(); + //判断是否是元素的开始 + if (en.isStartElement()) { + // 根据标签tag选择对应的解析方式 + se = en.asStartElement(); + String qName = se.getName().getLocalPart(); + // 单个标签上的属性 + Iterator attributes = se.getAttributes(); + switch (qName) { + case "Order": + analyzeOrderXml(attributes); + break; + case "Room": + analyzeRoomXml(attributes); + break; + case "Box": + analyzeBodyXml(attributes); + break; + case "Group": + analyzeGroupXml(attributes); + break; + case "Plate": + analyzePlateXml(attributes); + break; + case "Block": + analyzeBlockXml(attributes); + break; + case "Edging": + analyzeEdgingXml(attributes); + break; + case "Hardware": + analyzeHardwareXml(attributes); + break; + case "Assemblie": + analyzeAssemblieXml(attributes); + break; + case "Outline": + analyzeOutline(attributes); + break; + case "CuttingOutline": + analyzeCuttingOutline(attributes); + break; + case "RawOutline": + analyzeRawOutline(attributes); + break; + case "Holes": + analyzeHoles(attributes); + break; + case "Hole": + analyzeHole(attributes); + break; + case "Grooves": + analyzeGrooves(attributes); + break; + case "Groove": + analyzeGroove(attributes); + break; + case "Points": + analyzeGroovePoints(attributes); + break; + case "offsetLine": + analyzeOffsetLine(attributes); + break; + case "Islet": + analyzeIslet(attributes); + break; + case "Correlation": + analyzeCorrelation(attributes); + break; + case "Point": + analyzePoint(attributes); + break; + case "Remark": + analyzeRemark(attributes); + break; + default: + } + // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM + if (cachedDataList.size() >= BATCH_COUNT) { + saveData(); + // 存储完成清理 list + cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } + } else if (en.isEndElement()) { + // 根据标签tag选择对应的解析方式 + EndElement endElement = en.asEndElement(); + String qName = endElement.getName().getLocalPart(); + // 清空全局se + se = null; + // 单个标签上的属性 + switch (qName) { + case "Plate": + endPlate(); + break; + case "Block": + endBlockXml(); + break; + case "Edging": + endEdgingXml(); + break; + case "Hardware": + endHardware(); + break; + case "Assemblie": + endAssemblie(); + break; + case "Outline": + endOutline(); + break; + case "CuttingOutline": + endCuttingOutline(); + break; + case "RawOutline": + endRawOutline(); + break; + case "Groove": + endGroove(); + break; + case "Points": + endGroovePoints(); + break; + case "Islet": + endIslet(); + break; + default: + } + } + } + // 文件解析结束了保存一次,确保最后遗留的数据也存储到数据库 + saveData(); + // 保存生产单数据 + saveOrderTempData(); + log.info("所有数据解析完成!"); + } catch (Exception e) { + throw e; + } finally { + IOUtils.closeQuietly(is); + } + } + + /** + * 保存临时表 + */ + private void saveData() { + if (CollUtil.isNotEmpty(cachedDataList)) { + log.info("{}条数据,开始保存临时板材数据!", cachedDataList.size()); + orderImportTempDataMapper.insertBatchSomeColumn(cachedDataList); + log.info("xml导入临时板材数据保存成功!"); + } + } + + /** + * xml标签属性转java对象 + * + * @param clazz + * @param attributes + * @param + * @return 没有任何属性匹配上返回null + */ + private T getJavaBeanFromXmlAttr(Class clazz, Iterator attributes) throws Exception { + Field[] declaredFields = clazz.getDeclaredFields(); + T object = clazz.getDeclaredConstructor().newInstance(); + // 没有任何属性匹配上就返回null + boolean match = false; + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + for (int j = 0; j < declaredFields.length; j++) { + String fieldname = declaredFields[j].getName(); + if (attribute.getName().getLocalPart().equals(fieldname)) { + declaredFields[j].setAccessible(true); + declaredFields[j].set(object, attribute.getValue()); + if (!match) { + match = true; + } + break; + } + } + } + if (!match) { + return null; + } else { + return object; + } + } + + /** + * 解析xml中的生产单 + * + * @param attributes + * @throws Exception + */ + private void analyzeOrderXml(Iterator attributes) throws Exception { + // 从标签属性生成order对象 + OrderXmlVO orderXmlVO = getJavaBeanFromXmlAttr(OrderXmlVO.class, attributes); + if (ObjectUtil.isNull(orderXmlVO)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, "生产单内容为空"); + } + // 校验属性 + validOrderInfo(orderXmlVO); + } + + + /** + * 解析xml中的房间列表 + * + * @param attributes + */ + private void analyzeRoomXml(Iterator attributes) throws Exception { + // 从标签属性生成room对象 + RoomXmlVO roomXml = getJavaBeanFromXmlAttr(RoomXmlVO.class, attributes); + if (ObjectUtil.isNull(roomXml)) { + roomXml = new RoomXmlVO(); + } + roomXmlVO = roomXml; + // 校验房间属性 + checkRoom(roomXmlVO); + + // 每解析到一次room,设置一次全局roomcode给box列表用 + // room完接下来都认为是box,直到新的room出现 + String roomCode = StringUtils.isNotEmpty(roomXmlVO.getCode()) ? roomXmlVO.getCode() : NOT_ASSIGNED_CODE; + + Set bodyCodeSet = roomBodyCodeMap.get(roomCode); + if (CollUtil.isEmpty(bodyCodeSet)) { + roomBodyCodeMap.put(roomCode, new HashSet<>()); + } + } + + /** + * 校验房间数据 + * + * @param room + */ + private void checkRoom(RoomXmlVO room) { + isEmptyAndAdd(room::getCode, room::setCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(room::getName, room::setName, NOT_ASSIGNED); + + isEmptyAddAndPositiveNumberSize(room::getHeight, room::setHeight, "0", Double.class, "height", 8, 3); + isEmptyAddAndPositiveNumberSize(room::getLength, room::setLength, "0", Double.class, "length", 8, 3); + isEmptyAddAndPositiveNumberSize(room::getWidth, room::setWidth, "0", Double.class, "width", 8, 3); + isEmptyAddAndPositiveNumber(room::getMultipleNumber, room::setMultipleNumber, "1", Integer.class, "multipleNumber"); + isEmptyAddAndPositiveNumber(room::getMultipleNo, room::setMultipleNo, "1", Integer.class, "multipleNo"); + isEmptyAddAndNumber(room::getBasePointX, room::setBasePointX, "0", Double.class, "basePointX"); + isEmptyAddAndNumber(room::getBasePointY, room::setBasePointY, "0", Double.class, "basePointY"); + isEmptyAddAndNumber(room::getBasePointZ, room::setBasePointZ, "0", Double.class, "basePointZ"); + isEmptyAddAndNumber(room::getAxisXrotate, room::setAxisXrotate, "0", Double.class, "axisXrotate"); + isEmptyAddAndNumber(room::getAxisYrotate, room::setAxisYrotate, "0", Double.class, "axisYrotate"); + isEmptyAddAndNumber(room::getAxisZrotate, room::setAxisZrotate, "0", Double.class, "axisZrotate"); + } + + /** + * 解析xml中的柜体列表 + * + * @param attributes + */ + private void analyzeBodyXml(Iterator attributes) throws Exception { + // 从标签属性生成room对象 + RoomBoxXmlVO boxXmlVO = getJavaBeanFromXmlAttr(RoomBoxXmlVO.class, attributes); + if (ObjectUtil.isNull(boxXmlVO)) { + return; + } + // 校验柜体属性 + checkBox(boxXmlVO); + // 设置房间基准属性 + boxXmlVO.setRoomAxisXrotate(roomXmlVO.getAxisXrotate()); + boxXmlVO.setRoomAxisYrotate(roomXmlVO.getAxisYrotate()); + boxXmlVO.setRoomAxisZrotate(roomXmlVO.getAxisZrotate()); + boxXmlVO.setRoomBasePointX(roomXmlVO.getBasePointX()); + boxXmlVO.setRoomBasePointY(roomXmlVO.getBasePointY()); + boxXmlVO.setRoomBasePointZ(roomXmlVO.getBasePointZ()); + + String bodyCode = boxXmlVO.getCode(); + String roomCode = roomXmlVO.getCode(); + // 缓存roomCode+bodyCode + Set bodyCodeSet = roomBodyCodeMap.get(roomCode); + if (CollUtil.isNotEmpty(bodyCodeSet)) { + if (!bodyCodeSet.contains(bodyCode)) { + bodyCodeSet.add(bodyCode); + } + } else { + roomBodyCodeMap.put(roomCode, new HashSet<>() {{ + add(bodyCode); + }}); + } + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BODY.getType()) + .roomName(roomXmlVO.getName()) + .roomCode(roomCode) + .bodyName(boxXmlVO.getName()) + .bodyCode(bodyCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(boxXmlVO))) + .sort(sort++) + .build()); + } + + /** + * 校验柜体数据 + * + * @param box + */ + public void checkBox(RoomBoxXmlVO box) { + isEmptyAddAndPositiveNumberSize(box::getHeight, box::setHeight, "0", Double.class, "height", 8, 3); + isEmptyAddAndPositiveNumberSize(box::getLength, box::setLength, "0", Double.class, "length", 8, 3); + isEmptyAddAndPositiveNumberSize(box::getWidth, box::setWidth, "0", Double.class, "width", 8, 3); + isEmptyAddAndPositiveNumber(box::getMultipleNumber, box::setMultipleNumber, "1", Integer.class, "multipleNumber"); + isEmptyAddAndPositiveNumber(box::getMultipleNo, box::setMultipleNo, "1", Integer.class, "multipleNo"); + isEmptyAddAndNumber(box::getBasePointX, box::setBasePointX, "0", Double.class, "basePointX"); + isEmptyAddAndNumber(box::getBasePointY, box::setBasePointY, "0", Double.class, "basePointY"); + isEmptyAddAndNumber(box::getBasePointZ, box::setBasePointZ, "0", Double.class, "basePointZ"); + isEmptyAddAndNumber(box::getAxisXrotate, box::setAxisXrotate, "0", Double.class, "axisXrotate"); + isEmptyAddAndNumber(box::getAxisYrotate, box::setAxisYrotate, "0", Double.class, "axisYrotate"); + isEmptyAddAndNumber(box::getAxisZrotate, box::setAxisZrotate, "0", Double.class, "axisZrotate"); + isEmptyAndAdd(box::getCode, box::setCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(box::getName, box::setName, NOT_ASSIGNED); + } + + /** + * 解析xml中的加工组列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeGroupXml(Iterator attributes) throws Exception { + // 从标签属性生成group对象 + GroupXmlVO groupXmlVO = getJavaBeanFromXmlAttr(GroupXmlVO.class, attributes); + if (ObjectUtil.isNull(groupXmlVO)) { + groupXmlVO = new GroupXmlVO(); + } + // 校验加工组数据 + checkGroup(groupXmlVO); + + String groupXmlVOCode = groupXmlVO.getCode(); + if (!groupCodeSet.contains(groupXmlVOCode)) { + groupCodeSet.add(groupXmlVOCode); + } + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.GROUP.getType()) + .groupName(groupXmlVO.getName()) + .groupCode(groupXmlVOCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(groupXmlVO))) + .sort(sort++) + .build()); + + } + + /** + * 校验加工组 + * + * @param group + */ + private void checkGroup(GroupXmlVO group) { + isEmptyAndAdd(group::getCode, group::setCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(group::getName, group::setName, NOT_ASSIGNED); + isEmptyAddAndPositiveNumberSize(group::getLength, group::setLength, "0", Double.class, "length", 8, 3); + isEmptyAddAndPositiveNumberSize(group::getWidth, group::setWidth, "0", Double.class, "width", 8, 3); + isEmptyAddAndPositiveNumberSize(group::getHeight, group::setHeight, "0", Double.class, "height", 8, 3); + } + + /** + * 解析xml中的板材列表 + * + * @param attributes + * @throws Exception + */ + private void analyzePlateXml(Iterator attributes) throws Exception { + // 从标签属性生成plate对象 + PlateXmlVO plateXmlVO = getJavaBeanFromXmlAttr(PlateXmlVO.class, attributes); + if (ObjectUtil.isNull(plateXmlVO)) { + plateXmlVO = new PlateXmlVO(); + } + // 校验板材数据 + checkPlate(plateXmlVO); + + // 每解析到一次plate,设置一次全局plateItemCode给block列表用 + plateItemCode = String.valueOf(snowFlakeGenerator.nextId(null)); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.GOODS.getType()) + .innerGoodsId(plateItemCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(plateXmlVO))) + .sort(sort++) + .build()); + + } + + /** + * 校验板材 + * + * @param plate + */ + private void checkPlate(PlateXmlVO plate) { + isEmptyAndBack(plate::getName, "plate:name"); + isEmptyAndBack(plate::getMaterial, "plate:material"); + + // 纹理有效性判断 + isEmptyAddAndInvalid(plate::getGrained, plate::setGrained, "有", DictTypeConstants.PLATE_TEXTURE_TYPE, "grained"); + isEmptyAddAndInvalid(plate::getCoating, plate::setCoating, "双面", DictTypeConstants.COATING_TYPE, "coating"); + isEmptyAndPositiveNumber(plate::getLength, "length", plate::setLength, Double.class, 5, 3); + isEmptyAndPositiveNumber(plate::getWidth, "width", plate::setWidth, Double.class, 5, 3); + isEmptyAndPositiveNumber(plate::getThickness, "thickness", plate::setThickness, Double.class, 5, 3); + notEmptyPositiveNumberSize(plate::getOddmentLength, plate::setOddmentLength, "oddmentLength", Double.class, 5, 3); + notEmptyPositiveNumberSize(plate::getOddmentWidth, plate::setOddmentWidth, "oddmentWidth", Double.class, 5, 3); + notEmptyPositiveNumberSize(plate::getOddmentThickness, plate::setOddmentThickness, "oddmentThickness", Double.class, 5, 3); + isEmptyAddAndInvalid(plate::getOddment, plate::setOddment, "否", DictTypeConstants.ODDMENT_MARK, "oddment"); + isEmptyAddAndInvalid(plate::getUnitLength, plate::setUnitLength, "mm", DictTypeConstants.UNIT_LENGTH, "unitLength"); + notEmptyPositiveNumber(plate::getArea, "area", Double.class); + isEmptyAddAndInvalid(plate::getUnitArea, plate::setUnitArea, "m²", DictTypeConstants.UNIT_AREA, "unitArea"); + notEmptyPositiveNumber(plate::getCount, "count", Integer.class); + } + + /** + * plate标签结束 + */ + private void endPlate() { + // 设置全局参数 + plateItemCode = null; + } + + /** + * 解析xml中的加工组列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeBlockXml(Iterator attributes) throws Exception { + // 从标签属性生成block对象 + BlockXmlVO blockXmlVO = getJavaBeanFromXmlAttr(BlockXmlVO.class, attributes); + if (ObjectUtil.isNull(blockXmlVO)) { + blockXmlVO = new BlockXmlVO(); + } + // 校验板件 + checkBlock(blockXmlVO); + + // 全局参数 + inBlock = true; + String productionCode = blockXmlVO.getProductionCode(); + blockProductionCode = StringUtils.isNotEmpty(productionCode) ? productionCode : String.valueOf(snowFlakeGenerator.nextId(null)); + blockXmlVO.setProductionCode(blockProductionCode); + + // 如果有未命名的房间编号、柜体编号,直接在临时表创建这个柜体 + String roomCode = blockXmlVO.getRoomCode(); + String boxCode = blockXmlVO.getBoxCode(); + String groupCodes = blockXmlVO.getGroupCodes(); + // 校验检查房间、柜体、加工组编号 + checkRoomBoxGroup(se, roomCode, blockXmlVO.getRoomName(), boxCode, blockXmlVO.getBoxName(), groupCodes); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.PLATE.getType()) + .innerGoodsId(plateItemCode) + .roomCode(roomCode) + .bodyCode(boxCode) + .groupCode(groupCodes) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(blockXmlVO))) + .sort(sort++) + .build()); + + } + + /** + * 校验板件 + * + * @param blockXmlVO + */ + private void checkBlock(BlockXmlVO blockXmlVO) { + isEmptyAndAdd(blockXmlVO::getName, blockXmlVO::setName, NOT_ASSIGNED); + isEmptyAddAndInvalid(blockXmlVO::getType, blockXmlVO::setType, "背板", DictTypeConstants.PLATE_TYPE, "type"); + isEmptyAddAndInvalid(blockXmlVO::getOpenDirection, blockXmlVO::setOpenDirection, "非门板", DictTypeConstants.DOOR_OPENING_DIRECTIONS, "openDirection"); + isEmptyAddAndInvalid(blockXmlVO::getTexture, blockXmlVO::setTexture, "正纹", DictTypeConstants.GRAIN_TYPE, "texture"); + isEmptyAddAndInvalid(blockXmlVO::getLayoutFace, blockXmlVO::setLayoutFace, "随意面", DictTypeConstants.TYPOGRAPHY_TYPE, "layoutFace"); + isEmptyAddAndInvalid(blockXmlVO::getCoatingType, blockXmlVO::setCoatingType, "双面", DictTypeConstants.COATING_TYPE, "coatingType"); + isEmptyAndPositiveNumber(blockXmlVO::getLength, "length", blockXmlVO::setLength, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getWidth, "width", blockXmlVO::setWidth, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getThickness, "thickness", blockXmlVO::setThickness, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getCuttingLength, "cuttingLength", blockXmlVO::setCuttingLength, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getCuttingWidth, "cuttingWidth", blockXmlVO::setCuttingWidth, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getCuttingThickness, "cuttingThickness", blockXmlVO::setCuttingThickness, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getRawLength, "rawLength", blockXmlVO::setRawLength, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getRawWidth, "rawWidth", blockXmlVO::setRawWidth, Double.class, 5, 3); + isEmptyAndPositiveNumber(blockXmlVO::getRawThickness, "rawThickness", blockXmlVO::setRawThickness, Double.class, 5, 3); + isEmptyAddAndInvalid(blockXmlVO::getUnit, blockXmlVO::setUnit, "mm", DictTypeConstants.UNIT_LENGTH, "unit"); + isEmptyAddAndPositiveNumber(blockXmlVO::getMultipleNumber, blockXmlVO::setMultipleNumber, "1", Integer.class, "multipleNumber"); + isEmptyAddAndPositiveNumber(blockXmlVO::getMultipleNo, blockXmlVO::setMultipleNo, "1", Integer.class, "multipleNo"); + isEmptyAddAndInvalid(blockXmlVO::getUnregular, blockXmlVO::setUnregular, "否", DictTypeConstants.IS_NOT_MARK, "unregular"); + isEmptyAddAndInvalid(blockXmlVO::getDrilling, blockXmlVO::setDrilling, "否", DictTypeConstants.IS_NOT_MARK, "drilling"); + isEmptyAddAndInvalid(blockXmlVO::getSlotting, blockXmlVO::setSlotting, "否", DictTypeConstants.IS_NOT_MARK, "slotting"); + + isEmptyAndAdd(blockXmlVO::getRoomCode, blockXmlVO::setRoomCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(blockXmlVO::getRoomName, blockXmlVO::setRoomName, NOT_ASSIGNED); + isEmptyAndAdd(blockXmlVO::getBoxCode, blockXmlVO::setBoxCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(blockXmlVO::getBoxName, blockXmlVO::setBoxName, NOT_ASSIGNED); + + isEmptyAddAndNumber(blockXmlVO::getBasePointX, blockXmlVO::setBasePointX, "0", Double.class, "basePointX"); + isEmptyAddAndNumber(blockXmlVO::getBasePointY, blockXmlVO::setBasePointY, "0", Double.class, "basePointY"); + isEmptyAddAndNumber(blockXmlVO::getBasePointZ, blockXmlVO::setBasePointZ, "0", Double.class, "basePointZ"); + isEmptyAddAndNumber(blockXmlVO::getAxisXrotate, blockXmlVO::setAxisXrotate, "0", Double.class, "axisXrotate"); + isEmptyAddAndNumber(blockXmlVO::getAxisYrotate, blockXmlVO::setAxisYrotate, "0", Double.class, "axisYrotate"); + isEmptyAddAndNumber(blockXmlVO::getAxisZrotate, blockXmlVO::setAxisZrotate, "0", Double.class, "axisZrotate"); + } + + /** + * block标签结束 + */ + private void endBlockXml() { + // 全局inBlock结束 + inBlock = false; + } + + /** + * 解析xml中的封边条列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeEdgingXml(Iterator attributes) throws Exception { + // 从标签属性生成edging对象 + EdgingXmlVO edgingXmlVO = getJavaBeanFromXmlAttr(EdgingXmlVO.class, attributes); + if (ObjectUtil.isNull(edgingXmlVO)) { + edgingXmlVO = new EdgingXmlVO(); + } + // 校验封边条 + checkEdging(edgingXmlVO); + + // 如果有未命名的房间编号、柜体编号,直接在临时表创建这个柜体 + String roomCode = edgingXmlVO.getRoomCode(); + String boxCode = edgingXmlVO.getBoxCode(); + String groupCodes = edgingXmlVO.getGroupCode(); + // 校验检查房间、柜体、加工组编号 + checkRoomBoxGroup(se, roomCode, edgingXmlVO.getRoomName(), boxCode, edgingXmlVO.getBoxName(), groupCodes); + + // 设置全局参数 + String itemCode = edgingXmlVO.getItemCode(); + partItemCode = StringUtils.isNotEmpty(itemCode) ? itemCode : edgingXmlVO.getManufacturer() + edgingXmlVO.getBrand() + edgingXmlVO.getName() + edgingXmlVO.getMaterial() + + edgingXmlVO.getSpecs() + edgingXmlVO.getColor() + edgingXmlVO.getWidth() + edgingXmlVO.getThickness(); + edgingXmlVO.setItemCode(partItemCode); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.PART_EDGING.getType()) + .outerId(partItemCode) + .roomCode(roomCode) + .bodyCode(boxCode) + .groupCode(groupCodes) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(edgingXmlVO))) + .num(NumberUtil.parseDouble(edgingXmlVO.getCount())) + .sort(sort++) + .build()); + } + + /** + * Edging标签结束 + */ + private void endEdgingXml() { + // 设置全局参数 + partItemCode = null; + } + + /** + * 校验封边条配件 + * + * @param edgingXmlVO + */ + private void checkEdging(EdgingXmlVO edgingXmlVO) { + isEmptyAndAdd(edgingXmlVO::getRoomCode, edgingXmlVO::setRoomCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(edgingXmlVO::getRoomName, edgingXmlVO::setRoomName, NOT_ASSIGNED); + isEmptyAndAdd(edgingXmlVO::getBoxCode, edgingXmlVO::setBoxCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(edgingXmlVO::getBoxName, edgingXmlVO::setBoxName, NOT_ASSIGNED); + isEmptyAndBack(edgingXmlVO::getName, "name"); + isEmptyAndBack(edgingXmlVO::getMaterial, "material"); + isEmptyAndBack(edgingXmlVO::getColor, "color"); + isEmptyBackAndPositiveNumber(edgingXmlVO::getLength, "length", Double.class); + isEmptyBackAndPositiveNumber(edgingXmlVO::getWidth, "width", Double.class); + isEmptyBackAndPositiveNumber(edgingXmlVO::getThickness, "thickness", Double.class); + isEmptyAddAndInvalid(edgingXmlVO::getUnit, edgingXmlVO::setUnit, "mm", DictTypeConstants.UNIT_LENGTH, "unit"); + isEmptyBackAndPositiveNumber(edgingXmlVO::getCount, "count", Double.class); + isEmptyAddAndInvalid(edgingXmlVO::getUnitCount, edgingXmlVO::setUnitCount, "m", DictTypeConstants.UNIT_LENGTH, "unitCount"); + } + + /** + * 解析xml中的五金列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeHardwareXml(Iterator attributes) throws Exception { + // 从标签属性生成hardware对象 + HardwareXmlVO hardwareXmlVO = getJavaBeanFromXmlAttr(HardwareXmlVO.class, attributes); + if (ObjectUtil.isNull(hardwareXmlVO)) { + hardwareXmlVO = new HardwareXmlVO(); + } + // 校验五金 + checkHardware(hardwareXmlVO); + + // 如果有未命名的房间编号、柜体编号,直接在临时表创建这个柜体 + String roomCode = hardwareXmlVO.getRoomCode(); + String boxCode = hardwareXmlVO.getBoxCode(); + String groupCodes = hardwareXmlVO.getGroupCode(); + // 校验检查房间、柜体、加工组编号 + checkRoomBoxGroup(se, roomCode, hardwareXmlVO.getRoomName(), boxCode, hardwareXmlVO.getBoxName(), groupCodes); + + // 设置全局参数 + String itemCode = hardwareXmlVO.getItemCode(); + partItemCode = StringUtils.isNotEmpty(itemCode) ? itemCode : hardwareXmlVO.getManufacturer() + hardwareXmlVO.getBrand() + hardwareXmlVO.getName() + hardwareXmlVO.getMaterial() + + hardwareXmlVO.getSpecs() + hardwareXmlVO.getColor() + hardwareXmlVO.getType(); + hardwareXmlVO.setItemCode(partItemCode); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.PART_HARDWARE.getType()) + .outerId(partItemCode) + .roomCode(roomCode) + .bodyCode(boxCode) + .groupCode(groupCodes) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(hardwareXmlVO))) + .num(NumberUtil.parseDouble(hardwareXmlVO.getCount())) + .sort(sort++) + .build()); + } + + /** + * 校验五金 + * + * @param hardwareXmlVO + */ + private void checkHardware(HardwareXmlVO hardwareXmlVO) { + isEmptyAndAdd(hardwareXmlVO::getRoomCode, hardwareXmlVO::setRoomCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(hardwareXmlVO::getRoomName, hardwareXmlVO::setRoomName, NOT_ASSIGNED); + isEmptyAndAdd(hardwareXmlVO::getBoxCode, hardwareXmlVO::setBoxCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(hardwareXmlVO::getBoxName, hardwareXmlVO::setBoxName, NOT_ASSIGNED); + isEmptyAndBack(hardwareXmlVO::getName, "name"); + isEmptyAndBack(hardwareXmlVO::getMaterial, "material"); + isEmptyAndBack(hardwareXmlVO::getColor, "color"); + isEmptyBackAndPositiveNumber(hardwareXmlVO::getCount, "count", Double.class); + isEmptyAndBack(hardwareXmlVO::getUnitCount, "unitCount"); + isEmptyAndBack(hardwareXmlVO::getUnit, "unit"); + } + + /** + * Hardware标签结束 + */ + private void endHardware() { + // 设置全局参数 + partItemCode = null; + } + + /** + * 解析xml中的组件列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeAssemblieXml(Iterator attributes) throws Exception { + // 从标签属性生成assembly对象 + AssemblyXmlVO assemblyXmlVO = getJavaBeanFromXmlAttr(AssemblyXmlVO.class, attributes); + if (ObjectUtil.isNull(assemblyXmlVO)) { + assemblyXmlVO = new AssemblyXmlVO(); + } + // 校验组件 + checkAssemblie(assemblyXmlVO); + + // 如果有未命名的房间编号、柜体编号,直接在临时表创建这个柜体 + String roomCode = assemblyXmlVO.getRoomCode(); + String boxCode = assemblyXmlVO.getBoxCode(); + String groupCodes = assemblyXmlVO.getGroupCode(); + // 校验检查房间、柜体、加工组编号 + checkRoomBoxGroup(se, roomCode, assemblyXmlVO.getRoomName(), boxCode, assemblyXmlVO.getBoxName(), groupCodes); + + // 设置全局参数 + String itemCode = assemblyXmlVO.getItemCode(); + partItemCode = StringUtils.isNotEmpty(itemCode) ? itemCode : assemblyXmlVO.getManufacturer() + assemblyXmlVO.getBrand() + assemblyXmlVO.getName() + assemblyXmlVO.getMaterial() + + assemblyXmlVO.getSpecs() + assemblyXmlVO.getColor() + assemblyXmlVO.getType(); + assemblyXmlVO.setItemCode(partItemCode); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.PART_HARDWARE.getType()) + .outerId(partItemCode) + .roomCode(roomCode) + .bodyCode(boxCode) + .groupCode(groupCodes) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(assemblyXmlVO))) + .num(NumberUtil.parseDouble(assemblyXmlVO.getCount())) + .sort(sort++) + .build()); + + } + + /** + * 校验组件 + * + * @param assemblyXmlVO + */ + private void checkAssemblie(AssemblyXmlVO assemblyXmlVO) { + isEmptyAndBack(assemblyXmlVO::getName, "name"); + isEmptyAndBack(assemblyXmlVO::getMaterial, "name"); + isEmptyAndBack(assemblyXmlVO::getColor, "color"); + isEmptyBackAndPositiveNumber(assemblyXmlVO::getCount, "count", Double.class); + isEmptyAndBack(assemblyXmlVO::getUnitCount, "unitCount"); + isEmptyAndAdd(assemblyXmlVO::getRoomCode, assemblyXmlVO::setRoomCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(assemblyXmlVO::getRoomName, assemblyXmlVO::setRoomName, NOT_ASSIGNED); + isEmptyAndAdd(assemblyXmlVO::getBoxCode, assemblyXmlVO::setBoxCode, NOT_ASSIGNED_CODE); + isEmptyAndAdd(assemblyXmlVO::getBoxName, assemblyXmlVO::setBoxName, NOT_ASSIGNED); + } + + /** + * Assembly标签结束 + */ + private void endAssemblie() { + // 设置全局参数 + partItemCode = null; + } + + /** + * 解析blockxml的成品轮廓信息 + * + * @param attributes + * @throws Exception + */ + private void analyzeOutline(Iterator attributes) throws Exception { + // 设置全局参数 + inOutline = true; + if (inGroove) { + outlineXmlVO = getJavaBeanFromXmlAttr(OutlineXmlVO.class, attributes); + } + } + + /** + * Outline标签结束 + */ + private void endOutline() { + // 校验count和point数量 + if (inGroove) { + if (ObjectUtils.isNotNull(outlineXmlVO) && pointNum == 0) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, "原始造型(外)轮廓点阵列表不能为空"); + } + } + // 重置全局参数 + inOutline = false; + pointNum = 0; + } + + /** + * 解析blockxml的开料轮廓信息 + * + * @param attributes + * @throws Exception + */ + private void analyzeCuttingOutline(Iterator attributes) throws Exception { + // 设置全局参数 + inCuttingOutline = true; + // 从标签属性生成cuttingoutline对象 + CuttingOutlineXmlVO cuttingOutlineXmlVO = getJavaBeanFromXmlAttr(CuttingOutlineXmlVO.class, attributes); + // 校验 + isEmptyBackAndNumber(cuttingOutlineXmlVO::getReferenceOffsetX, Double.class, "referenceOffsetX"); + isEmptyBackAndNumber(cuttingOutlineXmlVO::getReferenceOffsetY, Double.class, "referenceOffsetY"); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_CUTTINGOUTLINE.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(cuttingOutlineXmlVO))) + .sort(sort++) + .build()); + + } + + /** + * CuttingOutline标签结束 + */ + private void endCuttingOutline() { + // 重置全局参数 + inCuttingOutline = false; + pointNum = 0; + } + + /** + * 解析blockxml的开料轮廓信息 + * + * @param attributes + * @throws Exception + */ + private void analyzeRawOutline(Iterator attributes) throws Exception { + // 设置全局参数 + inRawOutline = true; + // 从标签属性生成rawoutline对象 + rawOutlineXmlVO = getJavaBeanFromXmlAttr(RawOutlineXmlVO.class, attributes); + } + + /** + * RawOutline标签结束 + */ + private void endRawOutline() { + if (pointNum > 0 && ObjectUtil.isNotNull(rawOutlineXmlVO)) { + isEmptyBackAndNumber(rawOutlineXmlVO::getReferenceOffsetX, Double.class, "referenceOffsetX" + rawOutlineXmlVO.getReferenceOffsetX()); + isEmptyBackAndNumber(rawOutlineXmlVO::getReferenceOffsetY, Double.class, "referenceOffsetY" + rawOutlineXmlVO.getReferenceOffsetY()); + } + // 重置全局参数 + inRawOutline = false; + pointNum = 0; + } + + /** + * 解析blockxml的孔列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeHoles(Iterator attributes) throws Exception { + // 从标签属性生成hole对象 + HoleXmlVOS holeXmlVOS = getJavaBeanFromXmlAttr(HoleXmlVOS.class, attributes); + if (ObjectUtil.isNull(holeXmlVOS)) { + return; + } + // 校验holes + checkHoles(holeXmlVOS); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_HOLES.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(holeXmlVOS))) + .sort(sort++) + .build()); + } + + /** + * 校验孔列表 + * + * @param holeXmlVOS + */ + private void checkHoles(HoleXmlVOS holeXmlVOS) { + isEmptyAddAndPositiveNumber(holeXmlVOS::getCount, holeXmlVOS::setCount, "0", Integer.class, "count " + holeXmlVOS.getCount()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountFaceA, holeXmlVOS::setCountFaceA, "0", Integer.class, "countFaceA " + holeXmlVOS.getCountFaceA()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountFaceB, holeXmlVOS::setCountFaceB, "0", Integer.class, "countFaceB " + holeXmlVOS.getCountFaceB()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSide, holeXmlVOS::setCountSide, "0", Integer.class, "countSide " + holeXmlVOS.getCountSide()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideL, holeXmlVOS::setCountSideL, "0", Integer.class, "countSideL " + holeXmlVOS.getCountSideL()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideR, holeXmlVOS::setCountSideR, "0", Integer.class, "countSideR " + holeXmlVOS.getCountSideR()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideU, holeXmlVOS::setCountSideU, "0", Integer.class, "countSideU " + holeXmlVOS.getCountSideU()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountSideD, holeXmlVOS::setCountSideD, "0", Integer.class, "countSideD " + holeXmlVOS.getCountSideD()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountBevelled, holeXmlVOS::setCountBevelled, "0", Integer.class, "countBevelled " + holeXmlVOS.getCountBevelled()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountLocking, holeXmlVOS::setCountLocking, "0", Integer.class, "countLocking " + holeXmlVOS.getCountLocking()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountBuildIn, holeXmlVOS::setCountBuildIn, "0", Integer.class, "countBuildIn " + holeXmlVOS.getCountBuildIn()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountHinge, holeXmlVOS::setCountHinge, "0", Integer.class, "countHinge " + holeXmlVOS.getCountHinge()); + isEmptyAddAndPositiveNumber(holeXmlVOS::getCountThrough, holeXmlVOS::setCountThrough, "0", Integer.class, "countThrough " + holeXmlVOS.getCountThrough()); + } + + /** + * 解析孔明细 + * + * @param attributes + * @throws Exception + */ + private void analyzeHole(Iterator attributes) throws Exception { + // 从标签属性生成hole对象 + HoleXmlVO holeXmlVO = getJavaBeanFromXmlAttr(HoleXmlVO.class, attributes); + if (ObjectUtil.isNull(holeXmlVO)) { + return; + } + // 校验holes + checkHole(holeXmlVO); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_HOLE.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(holeXmlVO))) + .sort(sort++) + .build()); + } + + /** + * 校验孔明细 + * + * @param holeXmlVO + */ + private void checkHole(HoleXmlVO holeXmlVO) { + isEmptyBackAndInvalid(holeXmlVO::getDirection, DictTypeConstants.HOLE_DIRECTION, "direction "); + isEmptyBackAndPositiveNumber(holeXmlVO::getDiameter, "diameter", Double.class); + if (com.alibaba.nacos.common.utils.StringUtils.isNotEmpty(holeXmlVO.getType()) && holeXmlVO.getType().equals("沉头孔")) { + isEmptyBackAndPositiveNumber(holeXmlVO::getDiameterInner, "当小板孔类型为沉头孔时,小板孔沉头孔内径", Double.class); + isEmptyBackAndPositiveNumber(holeXmlVO::getDepthInner, "当小板孔类型为沉头孔时,沉头孔的深度", Double.class); + } + isEmptyBackAndPositiveNumber(holeXmlVO::getDepth, "depth", Double.class); + notEmptyPositiveNumber(holeXmlVO::getGroupNumber, "groupNumber", Integer.class); + isEmptyAddAndNumber(holeXmlVO::getGroupXoffset, holeXmlVO::setGroupXoffset, "0", Double.class, "groupXoffset"); + isEmptyAddAndNumber(holeXmlVO::getGroupYoffset, holeXmlVO::setGroupYoffset, "0", Double.class, "groupYoffset"); + isEmptyAddAndNumber(holeXmlVO::getGroupZoffset, holeXmlVO::setGroupZoffset, "0", Double.class, "groupZoffset"); + isEmptyBackAndNumber(holeXmlVO::getStartX, Double.class, "startX"); + isEmptyBackAndNumber(holeXmlVO::getStartY, Double.class, "startY"); + isEmptyBackAndNumber(holeXmlVO::getStartZ, Double.class, "startZ"); + isEmptyBackAndNumber(holeXmlVO::getEndX, Double.class, "endX"); + isEmptyBackAndNumber(holeXmlVO::getEndY, Double.class, "endY"); + isEmptyBackAndNumber(holeXmlVO::getEndZ, Double.class, "endZ"); + notEmptyPositiveNumber(holeXmlVO::getToolStartRotateX, "toolStartRotateX", Double.class); + notEmptyPositiveNumber(holeXmlVO::getToolStartRotateY, "toolStartRotateY", Double.class); + notEmptyPositiveNumber(holeXmlVO::getToolStartRotateZ, "toolStartRotateZ", Double.class); + notEmptyPositiveNumber(holeXmlVO::getToolEndRotateX, "toolEndRotateX", Double.class); + notEmptyPositiveNumber(holeXmlVO::getToolEndRotateY, "toolEndRotateY", Double.class); + notEmptyPositiveNumber(holeXmlVO::getToolEndRotateZ, "toolEndRotateZ", Double.class); + } + + /** + * 解析造型列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeGrooves(Iterator attributes) throws Exception { + // 从标签属性生成grooves对象 + GrooveXmlVOS grooveXmlVOS = getJavaBeanFromXmlAttr(GrooveXmlVOS.class, attributes); + if (ObjectUtil.isNotNull(grooveXmlVOS)) { + // 校验grooves + checkGooves(grooveXmlVOS); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVES.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(grooveXmlVOS))) + .sort(sort++) + .build()); + } + } + + /** + * 校验造型列表 + * + * @param grooveXmlVOS + */ + private void checkGooves(GrooveXmlVOS grooveXmlVOS) { + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount, grooveXmlVOS::setCount, "0", Double.class, "count"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountFaceA, grooveXmlVOS::setCountFaceA, "0", Double.class, "countFaceA"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountFaceB, grooveXmlVOS::setCountFaceB, "0", Double.class, "countFaceB"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSide, grooveXmlVOS::setCountSide, "0", Double.class, "countSide"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideL, grooveXmlVOS::setCountSideL, "0", Double.class, "countSideL"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideR, grooveXmlVOS::setCountSideR, "0", Double.class, "countSideR"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideU, grooveXmlVOS::setCountSideU, "0", Double.class, "countSideU"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountSideD, grooveXmlVOS::setCountSideD, "0", Double.class, "countSideD"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountBevelled, grooveXmlVOS::setCountBevelled, "0", Double.class, "countBevelled"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountRectangle, grooveXmlVOS::setCountRectangle, "0", Double.class, "countRectangle"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCountThrough, grooveXmlVOS::setCountThrough, "0", Double.class, "countThrough"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount2V, grooveXmlVOS::setCount2V, "0", Double.class, "count2V"); + isEmptyAddAndPositiveNumber(grooveXmlVOS::getCount3D, grooveXmlVOS::setCount3D, "0", Double.class, "count3D"); + } + + /** + * 解析造型 + * + * @param attributes + * @throws Exception + */ + private void analyzeGroove(Iterator attributes) throws Exception { + // 设置全局参数 + inGroove = true; + // 从标签属性生成grooves对象 + GrooveXmlVO grooveXmlVO = getJavaBeanFromXmlAttr(GrooveXmlVO.class, attributes); + if (ObjectUtil.isNotNull(grooveXmlVO)) { + // 校验grooves + checkGroove(grooveXmlVO); + // 设计端id + String grooveOuterId = grooveXmlVO.getId(); + outerId = grooveOuterId; + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE.getType()) + .outerId(grooveOuterId) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(grooveXmlVO))) + .sort(sort++) + .build()); + } + } + + /** + * Groove标签结束 + */ + private void endGroove() { + // 重置全局参数 + inGroove = false; + outerId = null; + } + + /** + * 校验造型明细 + * + * @param grooveXmlVO + */ + private void checkGroove(GrooveXmlVO grooveXmlVO) { + isEmptyAndBack(grooveXmlVO::getId, "id"); + + // 父孤岛id + isEmptyAndBack(grooveXmlVO::getType, "type"); + isEmptyBackAndInvalid(grooveXmlVO::getFace, DictTypeConstants.HOLE_FACE, "face"); + + if (grooveXmlVO.getType().trim().equals("矩形槽")) { + isEmptyAndBack(grooveXmlVO::getWidth, "当槽为矩形时,槽宽度"); + } + + isEmptyAddAndPositiveNumber(grooveXmlVO::getWidth, grooveXmlVO::setWidth, "0", Double.class, "width"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getLength, grooveXmlVO::setLength, "0", Double.class, "length"); + isEmptyBackAndPositiveNumber(grooveXmlVO::getDepth, "depth", Double.class); + isEmptyAddAndPositiveNumber(grooveXmlVO::getWidthExtend, grooveXmlVO::setWidthExtend, "0", Double.class, "widthExtend"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getLengthExtend, grooveXmlVO::setLengthExtend, "0", Double.class, "lengthExtend"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getDepthExtend, grooveXmlVO::setDepthExtend, "0", Double.class, "depthExtend"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getDirection, grooveXmlVO::setDirection, "0", Double.class, "direction"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getMode, grooveXmlVO::setMode, "0", Double.class, "mode"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getRound, grooveXmlVO::setRound, "0", Double.class, "round"); + + if (grooveXmlVO.getType().trim().equals("路径槽") || grooveXmlVO.getType().trim().equals("折返路径槽")) { + isEmptyAndBack(grooveXmlVO::getToolDiameter, "当槽为路径槽或是折返路径槽时,刀直径"); + + } + notEmptyPositiveNumber(grooveXmlVO::getToolDiameter, "toolDiameter", Double.class); + isEmptyAddAndPositiveNumber(grooveXmlVO::getRedundance, grooveXmlVO::setRedundance, "0", Double.class, "redundance"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getTangentAngle, grooveXmlVO::setTangentAngle, "0", Double.class, "tangentAngle"); + isEmptyAddAndPositiveNumber(grooveXmlVO::getIsletCount, grooveXmlVO::setIsletCount, "0", Integer.class, "isletCount"); + } + + /** + * 解析造型店镇道路列表 + * + * @param attributes + * @throws Exception + */ + private void analyzeGroovePoints(Iterator attributes) throws Exception { + // 设置全局参数 + inPoints = true; + // 从标签属性生成points对象 + pointXmlVOS = getJavaBeanFromXmlAttr(PointXmlVOS.class, attributes); + } + + /** + * Points标签结束 + */ + private void endGroovePoints() { + // 校验point数量 + if (ObjectUtil.isNotNull(pointXmlVOS) && pointNum == 0) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, inIslet ? "孤岛点阵列表不可为空" : "槽点坐标列表不可为空"); + } + // 重置全局参数 + inPoints = false; + pointNum = 0; + } + + /** + * 解析偏移刀路 + * + * @param attributes + * @throws Exception + */ + private void analyzeOffsetLine(Iterator attributes) throws Exception { + // 从标签属性生成grooves对象 + OffsetLineXmlVO offsetLineXmlVO = getJavaBeanFromXmlAttr(OffsetLineXmlVO.class, attributes); + if (ObjectUtil.isNotNull(offsetLineXmlVO)) { + // 校验grooves + checkOffsetLine(offsetLineXmlVO); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE_OFFSETLINE.getType()) + .outerGoodsId(blockProductionCode) + .outerSubId(outerId) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(offsetLineXmlVO))) + .sort(sort++) + .build()); + } + } + + /** + * 校验偏移刀路 + * + * @param offsetLineXmlVO + */ + private void checkOffsetLine(OffsetLineXmlVO offsetLineXmlVO) { + isEmptyBackAndNumber(offsetLineXmlVO::getOffset, Double.class, "offset"); + isEmptyBackAndPositiveNumber(offsetLineXmlVO::getDepth, "depth", Double.class); + isEmptyBackAndPositiveNumber(offsetLineXmlVO::getToolDiameter, "toolDiameter", Double.class); + isEmptyAddAndPositiveNumber(offsetLineXmlVO::getTangentAngle, offsetLineXmlVO::setTangentAngle, "0", Double.class, "tangentAngle"); + } + + /** + * 解析孤岛 + * + * @param attributes + * @throws Exception + */ + private void analyzeIslet(Iterator attributes) throws Exception { + // 设置全局参数 + inIslet = true; + // 从标签属性生成grooves对象 + IsletXmlVO isletXmlVO = getJavaBeanFromXmlAttr(IsletXmlVO.class, attributes); + if (ObjectUtil.isNotNull(isletXmlVO)) { + isEmptyAndBack(isletXmlVO::getId, "孤岛ID"); + outerId = isletXmlVO.getId(); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE_ISLET.getType()) + .outerGoodsId(blockProductionCode) + .outerId(outerId) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(isletXmlVO))) + .sort(sort++) + .build()); + } + } + + /** + * Islet标签结束 + */ + private void endIslet() { + // 重置全局参数 + inIslet = false; + pointNum = 0; + outerId = null; + } + + /** + * 解析关联配件 + * + * @param attributes + * @throws Exception + */ + private void analyzeCorrelation(Iterator attributes) throws Exception { + // 从标签属性生成correlation对象 + CorrelationXmlVO correlationXmlVO = getJavaBeanFromXmlAttr(CorrelationXmlVO.class, attributes); + if (ObjectUtil.isNotNull(correlationXmlVO)) { + if (StringUtils.isEmpty(correlationXmlVO.getItemCode())) { + isEmptyAndBack(correlationXmlVO::getName, "name"); + } + isEmptyBackAndPositiveNumber(correlationXmlVO::getCount, "count", Integer.class); + } + + } + + /** + * 解析点明细 + * + * @param attributes + * @throws Exception + */ + private void analyzePoint(Iterator attributes) throws Exception { + // 从标签属性生成point对象 + PointXmlVO pointXmlVO = getJavaBeanFromXmlAttr(PointXmlVO.class, attributes); + if (ObjectUtil.isNull(pointXmlVO)) { + return; + } + + if (inOutline) { + if (inGroove) { + checkPoint(pointXmlVO, "原始造型(外)轮廓"); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE_OUTLINE_POINT.getType()) + .outerGoodsId(blockProductionCode) + .outerSubId(outerId) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } else { + checkOutlinePoint(pointXmlVO); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_OUTLINE_POINT.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } + } + if (inCuttingOutline) { + checkPointRemoveZ(pointXmlVO, "开料成型轮廓信息"); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_CUTTINGOUTLINE_POINT.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } + if (inRawOutline) { + checkPointRemoveZ(pointXmlVO, "坯料轮廓信息"); + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_RAWOUTLINE_POINT.getType()) + .outerGoodsId(blockProductionCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } + if (inPoints) { + if (inIslet) { + checkPointRemoveZ(pointXmlVO, "孤岛"); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE_ISLET_POINTS_POINT.getType()) + .outerGoodsId(blockProductionCode) + .outerSubId(outerId) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } else { + checkPoint(pointXmlVO, "刀路点阵"); + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BLOCK_GROOVE_POINTS_POINT.getType()) + .outerGoodsId(blockProductionCode) + .outerSubId(outerId) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(pointXmlVO))) + .sort(sort++) + .build()); + } + } + // 列表数量累加 + pointNum++; + } + + /** + * 校验点明细 + * + * @param pointXmlVO + * @param name + */ + private void checkPoint(PointXmlVO pointXmlVO, String name) { + checkPointRemoveZ(pointXmlVO, name); + isEmptyBackAndNumber(pointXmlVO::getPointZ, Double.class, name + "pointZ"); + } + + /** + * 解析备注 + * + * @param attributes + * @throws Exception + */ + private void analyzeRemark(Iterator attributes) throws Exception { + // 从标签属性生成correlation对象 + RemarkXmlVO remarkXmlVO = getJavaBeanFromXmlAttr(RemarkXmlVO.class, attributes); + + // 添加到临时表 + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(inBlock ? OrderImportTmpDataTypeEnum.BLOCK_REMKAR.getType() : OrderImportTmpDataTypeEnum.PART_REMARK.getType()) + .outerSubId(inBlock ? blockProductionCode : partItemCode) + .createTime(LocalDateTime.now()) + .detail(JsonUtils.zipString(JSON.toJSONString(remarkXmlVO))) + .sort(sort++) + .build()); + } + + /** + * 校验成品轮廓 + * + * @param pointXmlVO + */ + private void checkOutlinePoint(PointXmlVO pointXmlVO) { + isEmptyBackAndNumber(pointXmlVO::getPointX, Double.class, "pointX"); + isEmptyBackAndNumber(pointXmlVO::getPointY, Double.class, "pointY"); + isEmptyBackAndNumber(pointXmlVO::getCurvature, Double.class, "curvature"); + isEmptyBackAndNumber(pointXmlVO::getRadius, Double.class, "radius"); + + checkEdging(pointXmlVO); + + isEmptyAddAndPositiveNumber(pointXmlVO::getPreMilling, pointXmlVO::setPreMilling, "0", Double.class, "预铣/精修量"); + isEmptyAddAndNumber(pointXmlVO::getScale, pointXmlVO::setScale, "0", Double.class, "延展/收缩量"); + isEmptyAddAndPositiveNumber(pointXmlVO::getCount, pointXmlVO::setCount, "0", Double.class, "单边封边尺寸"); + isEmptyAddAndPositiveNumber(pointXmlVO::getCountUnit, pointXmlVO::setCountUnit, "m", String.class, "封边条长度单位"); + } + + private void checkPointRemoveZ(PointXmlVO pointXmlVO, String name) { + isEmptyBackAndNumber(pointXmlVO::getPointX, Double.class, "pointX"); + isEmptyBackAndNumber(pointXmlVO::getPointY, Double.class, "pointY"); + isEmptyBackAndNumber(pointXmlVO::getCurvature, Double.class, "curvature"); + isEmptyBackAndNumber(pointXmlVO::getRadius, Double.class, "radius"); + } + + /** + * 校验板件中的封边条 + * + * @param pointXmlVO + */ + public void checkEdging(PointXmlVO pointXmlVO) { + if (!(StringUtils.isEmpty(pointXmlVO.getItemCode()) && StringUtils.isEmpty(pointXmlVO.getEdgingName()) && + StringUtils.isEmpty(pointXmlVO.getEdgingColor()) && StringUtils.isEmpty(pointXmlVO.getEdgingMaterial()) && + (StringUtils.isEmpty(pointXmlVO.getEdgingThickness()) || pointXmlVO.getEdgingThickness().trim().equals("0")))) { + if (StringUtils.isEmpty(pointXmlVO.getEdgingName())) { + pointXmlVO.setEdgingName("封边条"); + } + if (StringUtils.isEmpty(pointXmlVO.getItemCode())) { + if (StringUtils.isEmpty(pointXmlVO.getEdgingColor()) || StringUtils.isEmpty(pointXmlVO.getEdgingMaterial())) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, "当封边条没有物料编码时,封边条颜色、材质不可为空"); + } + } + isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingThickness, pointXmlVO::setEdgingThickness, "0", Double.class, "edgingThickness"); + isEmptyAddAndPositiveNumber(pointXmlVO::getEdgingExtend, pointXmlVO::setEdgingExtend, "0", Double.class, "edgingExtend"); + } + } + + /** + * 校验生产单信息 + * + * @param orderXmlVO + */ + public void validOrderInfo(OrderXmlVO orderXmlVO) { + // 自定义单号校验 + validCustomOrderNo("orderCode", orderXmlVO.getOrderCode()); + // 校验非空 + validOrderInfoEmpty("orderCode", orderXmlVO.getOrderCode()); + validOrderInfoEmpty("customer", orderXmlVO.getCustomer()); + validOrderInfoEmpty("dealer", orderXmlVO.getDealer()); + validOrderInfoEmpty("customerAddress", orderXmlVO.getCustomerAddress()); + validOrderInfoEmpty("customerPhone", orderXmlVO.getCustomerPhone()); + validOrderInfoEmpty("deliveryDate", orderXmlVO.getDeliveryDate()); + + // 长度校验 + validOrderInfoLength("orderCode", orderXmlVO.getOrderCode(), 32); + validOrderInfoLength("customer", orderXmlVO.getCustomer(), 255); + validOrderInfoLength("dealer", orderXmlVO.getDealer(), 255); + validOrderInfoLength("customerAddress", orderXmlVO.getCustomerAddress(), 255); + validOrderInfoLength("seller", orderXmlVO.getSeller(), 64); + validOrderInfoLength("memo", orderXmlVO.getMemo(), 255); + + // 校验手机号 + validatePhoneNumbers(orderXmlVO); + + LocalDate orderDate; + LocalDate deliverDate; + // 校验订单日期、出货日期 + String xmlOrderData = orderXmlVO.getOrderDate(); + if (ObjectUtil.isNull(xmlOrderData)) { + orderDate = LocalDate.now(); + } else { + orderDate = validOrderInfoDate("orderDate", orderXmlVO.getOrderDate()); + } + + String xmlDeliveryDate = orderXmlVO.getDeliveryDate(); + if (ObjectUtil.isNull(xmlDeliveryDate)) { + deliverDate = orderDate.plus(30, ChronoUnit.DAYS); + } else { + deliverDate = validOrderInfoDate("deliveryDate", xmlDeliveryDate); + // 出货时间早于导入时间,自动延长30天 + if (orderDate != null && deliverDate.isBefore(orderDate)) { + deliverDate = orderDate.plus(30, ChronoUnit.DAYS); + } + } + orderDO = OrderDO.builder() + .dataType(DataTypeEnum.FILE_IMPORT.getStatus()) + .customer(orderXmlVO.getCustomer()) + .customOrderNo(orderXmlVO.getOrderCode()) + .dealer(orderXmlVO.getDealer()) + .dealerPhoneNumber(orderXmlVO.getDealerPhone()) + .address(orderXmlVO.getCustomerAddress()) + .phoneNumber(orderXmlVO.getCustomerPhone()) + .salesman(orderXmlVO.getSeller()) + .splitter(orderXmlVO.getAnalyst()) + .remark(orderXmlVO.getMemo()) + .orderDate(orderDate.atStartOfDay()) + .deliveryDate(deliverDate.atStartOfDay()) + .orderType(OrderTypeEnum.MAIN_ORDER.getStatus()) + .organId(OrganContextHolder.getOrganId()) + .build(); + String loginUserName = WebFrameworkUtils.getLoginUserName(); + LocalDateTime now = LocalDateTime.now(); + orderDO.setCreator(loginUserName); + orderDO.setUpdater(loginUserName); + orderDO.setCreateTime(now); + orderDO.setUpdateTime(now); + } + + /** + * 生产单数据保存临时表 + */ + private void saveOrderTempData() { + OrderImportTempDataDO orderInfoTempDataDO = OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.ORDER.getType()) + .createTime(LocalDateTime.now()) + .sort(0) + .build(); + // 非补板即新增生成单,记录基础信息 + if (!addToExistsOrder) { + orderDO.setId(orderId); + orderDO.setStatus(NumberUtil.compare(sort, 1) > 0 ? OrderStatusEnum.NEW_ORDER.getStatus() : OrderStatusEnum.EMPTY.getStatus()); + orderInfoTempDataDO.setDetail(JsonUtils.zipString(JSON.toJSONString(orderDO))); + } + orderImportTempDataMapper.insert(orderInfoTempDataDO); + log.info("xml导入临时生产单数据保存成功!"); + } + + /** + * 校验/缓存检查房间、柜体、加工组编码 + * + * @param se + * @param roomCode + * @param boxCode + * @param groupCodes + */ + private void checkRoomBoxGroup(StartElement se, String roomCode, String roomName, String boxCode, String boxName, String groupCodes) { + boolean roomEmpty = StringUtil.equals(roomCode, NOT_ASSIGNED_CODE); + boolean bodyEmpty = StringUtil.equals(boxCode, NOT_ASSIGNED_CODE); + String existKey = roomEmpty + "%" + bodyEmpty; + if ((roomEmpty || bodyEmpty) && NOT_ASSIGNED_BODY_EXISTS_MAP.containsKey(existKey) && !NOT_ASSIGNED_BODY_EXISTS_MAP.get(existKey)) { + cachedDataList.add(OrderImportTempDataDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .taskId(taskId) + .type(OrderImportTmpDataTypeEnum.BODY.getType()) + .roomCode(roomCode) + .roomName(roomName) + .bodyCode(boxCode) + .bodyName(boxName) + .createTime(LocalDateTime.now()) + .sort(sort++) + .build()); + // 添加到标识缓存map + NOT_ASSIGNED_BODY_EXISTS_MAP.put(existKey, true); + } + + // 校验板件的房间、柜体、加工组编号 + Set bodyCodeSet = roomBodyCodeMap.get(roomCode); + if (CollUtil.isNotEmpty(bodyCodeSet)) { + if (!bodyCodeSet.contains(boxCode) && !StringUtils.equals(NOT_ASSIGNED_CODE, boxCode)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_BODYCODE_NOT_EXIST_VALID_ERROR, se, boxCode); + } + } else if (!StringUtils.equals(NOT_ASSIGNED_CODE, roomCode)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ROOMCODE_NOT_EXIST_VALID_ERROR, se, roomCode); + } + + + if (StringUtils.isNotEmpty(groupCodes) && !groupCodeSet.contains(groupCodes)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_GROUPCODE_NOT_EXIST_VALID_ERROR, se, groupCodes); + } + } + + /** + * 校验手机号 + * + * @param orderXmlVO + */ + private void validatePhoneNumbers(OrderXmlVO orderXmlVO) { + validOrderInfoPhone("customerPhone", orderXmlVO.getCustomerPhone()); + validOrderInfoPhone("dealerPhone", orderXmlVO.getDealerPhone()); + validOrderInfoPhone("sellerPhone", orderXmlVO.getSellerPhone()); + validOrderInfoPhone("designerPhone", orderXmlVO.getDesignerPhone()); + validOrderInfoPhone("analystPhone", orderXmlVO.getAnalystPhone()); + } + + /** + * 自定义单号校验 + * + * @param key + * @param val + */ + private void validCustomOrderNo(String key, String val) { + if (StringUtils.isNotEmpty(val) && !orderService.customOrderNoIsExists(val)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_CUSTOMERNO_EXISTS, key, val); + } + } + + /** + * 校验空 + * + * @param key + * @param val + */ + private void validOrderInfoEmpty(String key, String val) { + if (StringUtils.isEmpty(val)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_FIELD_EMPTY, key); + } + } + + /** + * 生产单属性长度校验 + * + * @param key + * @param val + * @param length + */ + private void validOrderInfoLength(String key, String val, int length) { + if (StringUtils.isNotEmpty(val) && length < val.length()) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_FIELD_LENGTH_ERROR, key, length); + } + } + + /** + * 校验手机号格式 + * + * @param key + * @param val + */ + private void validOrderInfoPhone(String key, String val) { + if (StringUtils.isNotEmpty(val) && Boolean.FALSE.equals(ToolUtil.validatePhoneNumber(val))) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_FIELD_MOBILE_FORMAT_ERROR, key); + } + } + + /** + * 校验时间格式 + * + * @param key + * @param val + */ + private LocalDate validOrderInfoDate(String key, String val) { + try { + return LocalDateTimeUtil.parseDate(val, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } catch (Exception e) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_FIELD_DATE_FORMAT_ERROR, key); + } + } + + /** + * 非空判断+数据类型+数据正数 + * + * @param getter: + * @param setter: + * @param name: 字段错误名称 + * @param targetType: 数字类型 + */ + private void notEmptyPositiveNumber(Supplier getter, String name, Class targetType) { + String value = getter.get(); + if (!StringUtils.isEmpty(value)) { // 非空 + positiveNumber(value, name, targetType); + } + } + + /** + * 数量类型+数量正数 + * + * @param value: + * @param name: 字段错误名称 + * @param targetType: 需要转换的数字类型 + */ + private void positiveNumber(String value, String name, Class targetType) { + if (ToolUtil.convertToType(value, targetType)) { + if (!ToolUtil.checkNumber(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + POSITIVE_ERR, name)); + } + } else { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + POSITIVE_ERR, name)); + } + + } + + /** + * 非空判断,空赋初始值 + * + * @param getter: + * @param setter: + * @param defaultValue: 赋值空值 + */ + + private void isEmptyAndAdd(Supplier getter, Consumer setter, String defaultValue) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + setter.accept(defaultValue); + } + } + + /** + * 空值赋值+数量类型+数量正数+数据长度 + * + * @param getter: + * @param setter: + * @param defaultValue: 赋值数据 + * @param targetType: 数据类型 + * @param name: 字段错误名称 + */ + private void isEmptyAddAndPositiveNumberSize(Supplier getter, Consumer setter, String defaultValue, Class targetType, String name, Integer length, Integer decimalLength) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + setter.accept(defaultValue); + } else { + positiveNumberSize(value, setter, targetType, name, length, decimalLength); + } + } + + /** + * 数量类型+数量正数+数据长度 + * + * @param value: 待校验数据 + * @param targetType: 数据类型 + * @param name: 字段错误名称 + */ + private void positiveNumberSize(String value, Consumer setter, Class targetType, String name, Integer length, Integer decimalLength) { + if (ToolUtil.convertToType(value, targetType)) { + if (ToolUtil.checkNumber(value)) { + if (!ToolUtil.checkPrecision(value, length, decimalLength)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + LONG_ERR, name)); + } + } else { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + POSITIVE_ERR, name)); + } + } else { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + TYPE_ERR, name)); + } + } + + /** + * 空值赋值 +数量类型+数量正数 + * + * @param getter: + * @param setter: + * @param defaultValue: 赋值数据 + * @param targetType: 数据类型 + * @param name: 字段错误名称 + */ + private void isEmptyAddAndPositiveNumber(Supplier getter, Consumer setter, String defaultValue, Class targetType, String name) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + setter.accept(defaultValue); + } else { + positiveNumber(value, name, targetType); + } + } + + /** + * 空值赋值+数量类型 + * + * @param getter: + * @param setter: + * @param defaultValue: 赋值数据 + * @param targetType: 数据类型 + * @param name: 字段错误名称 + */ + private void isEmptyAddAndNumber(Supplier getter, Consumer setter, String defaultValue, Class targetType, String name) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + setter.accept(defaultValue); + } else { + if (!ToolUtil.convertToType(value.trim(), targetType)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + TYPE_ERR, name)); + } + } + } + + /** + * 非空判断,错误返回 + * + * @param getter: + * @param name: 字段错误名称 + */ + private void isEmptyAndBack(Supplier getter, String name) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + IS_NULL, name)); + } + } + + /** + * 空值返回+非空有效性判断 + * + * @param getter: + * @param setter: + * @param defaultValue: 赋值数据 + * @param dictTypeConstants: 字典标签 + * @param name: 字段错误名称 + */ + private void isEmptyAddAndInvalid(Supplier getter, Consumer setter, String defaultValue, String dictTypeConstants, String name) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + setter.accept(defaultValue); + } else { + String dictData = DictFrameworkUtils.parseDictDataValue(dictTypeConstants, value.trim()); + if (StringUtils.isEmpty(dictData)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + INVALID, name)); + } + } + } + + /** + * 非空错返 +数量类型+数量正数+数据长度 + * + * @param getter: + * @param name: 字段错误名称 + * @param setter: + * @param targetType: 需要转换的数字类型 + */ + private void isEmptyAndPositiveNumber(Supplier getter, String name, Consumer setter, Class targetType, Integer length, Integer decimalLength) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + IS_NULL, name)); + } else { + positiveNumberSize(value, setter, targetType, name, length, decimalLength); + } + } + + /** + * 非空判断 +数据类型+数据正数+数据长度 + * + * @param getter: + * @param setter: + * @param name: 字段错误名称 + * @param targetType: 数字类型 + */ + private void notEmptyPositiveNumberSize(Supplier getter, Consumer setter, String name, Class targetType, Integer length, Integer decimalLength) { + String value = getter.get(); + if (StringUtils.isNotEmpty(value)) { // 非空 + positiveNumberSize(value, setter, targetType, name, length, decimalLength); + } + } + + /** + * 非空错返+数量类型+数量正数 + * + * @param getter: + * @param name: 字段错误名称 + * @param targetType: 需要转换的数字类型 + */ + private void isEmptyBackAndPositiveNumber(Supplier getter, String name, Class targetType) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + IS_NULL, name)); + } else { + positiveNumber(value, name, targetType); + } + } + + /** + * 数量类型+数量正数 + 返回值 + * + * @param value: + * @param name: 字段错误名称 + * @param targetType: 需要转换的数字类型 + */ + private void positiveNumberAndBack(String value, String name, Class targetType) { + if (ToolUtil.convertToType(value, targetType)) { + if (!ToolUtil.checkNumber(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + POSITIVE_ERR, name)); + } + } else { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + TYPE_ERR, name)); + } + } + + /** + * 空值错返+数量类型 + * + * @param getter: + * @param targetType: 数据类型 + * @param name: 字段错误名称 + */ + private void isEmptyBackAndNumber(Supplier getter, Class targetType, String name) { + String value = getter.get(); + if (StringUtils.isEmpty(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + IS_NULL, name)); + } else { + if (!ToolUtil.convertToType(value.trim(), targetType)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + TYPE_ERR, name)); + } + } + } + + /** + * 空值赋值+非空有效性判断 + * + * @param getter: + * @param dictTypeConstants: 字典标签 + * @param name: 字段错误名称 + */ + private void isEmptyBackAndInvalid(Supplier getter, String dictTypeConstants, String name) { + String value = getter.get(); + if (com.alibaba.nacos.common.utils.StringUtils.isEmpty(value)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + IS_NULL, name)); + } else { + String dictData = DictFrameworkUtils.parseDictDataValue(dictTypeConstants, value.trim()); + if (StringUtils.isEmpty(dictData)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_DETAIL_VALID_ERROR, String.format(se.toString() + INVALID, name)); + } + } + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/VO/RoomBoxXmlVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/VO/RoomBoxXmlVO.java new file mode 100644 index 000000000..0fbdef396 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/util/fileConversion/admin/files/xml/VO/RoomBoxXmlVO.java @@ -0,0 +1,72 @@ +package com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class RoomBoxXmlVO implements Serializable { + + // 房间名称 + private String name; + + // 房间编号 + private String code; + + // 房间高度 + private String height; + + // 房间宽度 + private String width; + + // 房间深度 + private String length; + + // 成倍拆单数量 + private String multipleNumber; + + // 成倍拆单序号 + private String multipleNo; + + + // 基点X坐标 + private String basePointX; + + // 基点Y坐标 + private String basePointY; + + // 基点Z坐标 + private String basePointZ; + + // 绕X轴旋转角度 + private String axisXrotate; + + // 绕Y轴旋转角度 + private String axisYrotate; + + // 绕Z轴旋转角度 + private String axisZrotate; + + // 房间基点X坐标 + private String roomBasePointX; + + // 房间基点Y坐标 + private String roomBasePointY; + + // 房间基点Z坐标 + private String roomBasePointZ; + + // 房间绕X轴旋转角度 + private String roomAxisXrotate; + + // 房间绕Y轴旋转角度 + private String roomAxisYrotate; + + // 房间绕Z轴旋转角度 + private String roomAxisZrotate; + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/pom.xml b/cf-module-prod-plan/cf-module-prod-plan-biz/pom.xml index 30e8c4e17..eb9e52472 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/pom.xml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/pom.xml @@ -30,6 +30,10 @@ cf-module-prod-plan-api ${revision} + + com.cf.imes + cf-spring-boot-starter-biz-dict + @@ -249,6 +253,10 @@ com.cf.imes cf-spring-boot-starter-biz-id + + com.cf.imes + cf-spring-boot-starter-biz-dict + @@ -269,12 +277,12 @@ copy-dependencies - - - - - - + + + target/lib + + com.cf.imes + diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/vo/OrderImportTempDataReqVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/vo/OrderImportTempDataReqVO.java index 4130dfa5e..66b812c3a 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/vo/OrderImportTempDataReqVO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/vo/OrderImportTempDataReqVO.java @@ -47,11 +47,21 @@ public class OrderImportTempDataReqVO { */ private String roomName; + /** + * 房间编号 + */ + private String roomCode; + /** * 柜体名称 */ private String bodyName; + /** + * 柜体编号 + */ + private String bodyCode; + /** * 加工组类型 */ @@ -61,4 +71,9 @@ public class OrderImportTempDataReqVO { * 模块名称 */ private String groupName; + + /** + * 外部id + */ + private String outerId; } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/AssemblyXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/AssemblyXmlVO.java new file mode 100644 index 000000000..98b47313f --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/AssemblyXmlVO.java @@ -0,0 +1,92 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 组件/部件信息 +public class AssemblyXmlVO implements Serializable { + + // 五金物料编码 + private String itemCode; + + // 类型——抽屉Drawer、酒格WineGrid、框架/拼框门FrameDoor、线条(顶线、脚线、挡水条等)Line、桌面/台面TableTop、水槽Sink…… + private String type; + + // 厂家 + private String manufacturer; + + // 品牌 + private String brand; + + // 名称 + private String name; + + // 材质 + private String material; + + // 颜色 + private String color; + + // 规格/类型 + private String specs; + + // 长度 + private String length; + + // 宽度 + private String width; + + // 高 + private String height; + + // 数量 + private String count; + + // 长度单位 + private String unit; + + // 数量单位 + private String unitCount; + + // 仓库 + private String warehouse; + + // 货架 + private String shelf; + + // 房间名称 + private String roomName; + + // 房间号 + private String roomCode; + + // 柜体名称 + private String boxName; + + // 柜体号 + private String boxCode; + + // 加工组号 + private String groupCode; + + // 加工组名称 + private String groupName; + + // 模块名称 + private String moduleName; + + // 模块号 + private String moduleCode; + + // 子组件/部件物料编码 + private String subCodes; + + // 备注 +// private RemarkXmlVOS remarkXmlVOS; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/BlockXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/BlockXmlVO.java new file mode 100644 index 000000000..d90ac51c2 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/BlockXmlVO.java @@ -0,0 +1,138 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 板件信息 +public class BlockXmlVO implements Serializable { + + @Serial + private static final long serialVersionUID = -2203972183257792706L; + + // 设计编号 + private String designCode; + + // 生产编号 + private String productionCode; + + // 名称 + private String name; + + // 类型——类型——背板类、层板类、立板类 -- order_plate_type + private String type; + + // 是否见光板/面板 ——是/否 + private String visible; + + // 开向——左开、右开、上开、下开、非门板 -- doorOpeningDirections + private String openDirection; + + // 设计纹路——正纹、反纹、可翻转 -- grainType + private String texture; + + // 设计饰面——无、单面、双面 + private String coatingType; + + // 成品长 + private String length; + + // 成品宽 + private String width; + + // 成品厚 + private String thickness; + + // 坯料长 + private String rawLength; + + // 坯料宽 + private String rawWidth; + + // 坯料厚 + private String rawThickness; + + // 开料长 + private String cuttingLength; + + // 开料宽 + private String cuttingWidth; + + // 开料厚 + private String cuttingThickness; + + // 成倍拆单数量 + private String multipleNumber; + + // 成倍拆单序号 + private String multipleNo; + + // 异形——是/否 + private String unregular; + + // 挖槽——是/否 + private String slotting; + + // 排版面——设计正面、设计反面、随意面 -- typographyType + private String layoutFace; + + // 正面饰面颜色、无 + private String coatingObverse; + + // 反面饰面颜色、无 + private String coatingReverse; + + // 长度单位 + private String unit; + + // 是否钻孔 + private String drilling; + + // 房间名称 + private String roomName; + + // 房间号 + private String roomCode; + + // 房间名称 + private String boxName; + + // 柜体号 + private String boxCode; + + // 加工组号 + private String groupCodes; + + // 柜体名称 + private String groupName; + + // 模块名称 + private String moduleName; + + // 模块号 + private String moduleCode; + + // 基点X坐标 + private String basePointX; + + // 基点Y坐标 + private String basePointY; + + // 基点Z坐标 + private String basePointZ; + + // 绕X轴旋转角度 + private String axisXrotate; + + // 绕Y轴旋转角度 + private String axisYrotate; + + // 绕Z轴旋转角度 + private String axisZrotate; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CorrelationXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CorrelationXmlVO.java new file mode 100644 index 000000000..8b34b11e4 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CorrelationXmlVO.java @@ -0,0 +1,55 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CorrelationXmlVO implements Serializable { + + // 关联五金/关联组件物料编码 + private String itemCode; + + // 类型 + private String type; + + // 厂家 + private String manufacturer; + + // 品牌 + private String brand; + + // 名称 + private String name; + + // 材质 + private String material; + + // 颜色 + private String color; + + // 规格/类型 + private String specs; + + // 长 + private String length; + + // 宽 + private String width; + + // 高 + private String height; + + // 长度单位 + private String unit; + + // 数量 + private String count; + + // 数量单位 + private String unitCount; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CuttingOutlineXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CuttingOutlineXmlVO.java new file mode 100644 index 000000000..ccaea09a1 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/CuttingOutlineXmlVO.java @@ -0,0 +1,20 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 开料成型(还需进行精修/铣削/打磨的板材,成品尺寸-封边+预留边)轮廓信息 +public class CuttingOutlineXmlVO implements Serializable { + + // 相对于成品轮廓,基准点的X坐标偏移量 + private String referenceOffsetX; + + // 相对于成品轮廓,基准点的Y坐标偏移量 + private String referenceOffsetY; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/EdgingXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/EdgingXmlVO.java new file mode 100644 index 000000000..1f98ada11 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/EdgingXmlVO.java @@ -0,0 +1,92 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +// 封边条信息 +public class EdgingXmlVO implements Serializable { + + @Serial + private static final long serialVersionUID = -8053518845837052834L; + + // 封边条物料编码 + private String itemCode; + + // 厂家 + private String manufacturer; + + // 品牌 + private String brand; + + // 名称 + private String name; + + // 材质 + private String material; + + // 颜色 + private String color; + + // 规格 + private String specs; + + // 长 + private String length; + + // 宽 + private String width; + + // 厚 + private String thickness; + + // 长度单位——默认m米 + private String unit; + + // 仓库 + private String warehouse; + + // 货架 + private String shelf; + + // 数量 + private String count; + + // 数量单位(默认m米) + private String unitCount; + + // 房间名称 + private String roomName; + + // 房间号 + private String roomCode; + + // 柜体名称 + private String boxName; + + // 柜体号 + private String boxCode; + + // 加工组名称 + private String groupName; + + // 加工组号 + private String groupCode; + + // 模块名称 + private String moduleName; + + // 模块号 + private String moduleCode; + +// // 备注 +// private RemarkXmlVOS remarkXmlVOS; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/ExtraVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/ExtraVO.java new file mode 100644 index 000000000..da7dec82c --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/ExtraVO.java @@ -0,0 +1,44 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 板补充备注 格式 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ExtraVO { + + @Schema(description ="板类型" ) + private String boardType; + + @Schema(description ="挖穿的孔数" ) + private String throughHoleCount; + + @Schema(description ="挖穿的孔数" ) + private String throughModelCount; + + @Schema(description ="是否有二维刀路" ) + private String has2DModel; + + @Schema(description ="是否有三维刀路" ) + private String has3DModel; + + @Schema(description ="排版面" ) + private String composingFace; + + @Schema(description ="板边备注" ) + private List edgeRemarks; + + @Schema(description ="封边备注" ) + private List rectSealDetail; + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVO.java new file mode 100644 index 000000000..2e33a1804 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVO.java @@ -0,0 +1,73 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 凹槽信息 +public class GrooveXmlVO implements Serializable { + + // 凹槽ID + private String id; + + // 内部孤岛ID集合 + private String subIDs; + + // 类型——矩形槽Rectangle、路径槽Path、内铣槽internalMilling、折返路径槽turnbackPath + private String type; + + // 加工面——正面、反面、左侧面、右侧面、上侧面、下侧面、斜面 + private String face; + + // 宽度 + private String width; + + // 长度 + private String length; + + // 深度 + private String depth; + + // 加宽 + private String widthExtend; + + // 加长 + private String lengthExtend; + + // 加深 + private String depthExtend; + + // 造型/凹槽(边缘)的刀路方向——内圈顺时针(最)外圈逆时针、内圈顺时针(最)外圈顺时针、内圈逆时针(最)外圈顺时针、内圈逆时针(最)外圈逆时针 + private String direction; + + // 加工模式/方式——由内向外、由外向内 + private String mode; + + // 圆角半径 + private String round; + + // 刀名称 + private String toolName; + + // 刀号 + private String toolNo; + + // 刀直径 + private String toolDiameter; + + // 刀路冗余量——偏移重叠量 + private String redundance; + + // 角度——二维刀路V型刀提角/清角用 + private String tangentAngle; + + // 内层(不含内嵌凹槽内的孤岛)孤岛数量 + private String isletCount; + + private String result; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVOS.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVOS.java new file mode 100644 index 000000000..23dafc946 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GrooveXmlVOS.java @@ -0,0 +1,53 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 凹槽列表 +public class GrooveXmlVOS implements Serializable { + + // 凹槽数量 + private String count; + + // 正面垂凹槽数量/凹槽数量 + private String countFaceA; + + // 反面凹槽数量/凹槽数量 + private String countFaceB; + + // 侧凹槽数量/凹槽数量 + private String countSide; + + // 左侧槽数量/凹槽数量 + private String countSideL; + + // 右侧槽数量/凹槽数量 + private String countSideR; + + // 上侧槽数量/凹槽数量 + private String countSideU; + + // 下侧槽数量/凹槽数量 + private String countSideD; + + // 斜面凹槽数量 + private String countBevelled; + + // 矩形凹槽数量 + private String countRectangle; + + // 挖穿造型/槽数量 + private String countThrough; + + // 二维造型刀路数量 + private String count2V; + + // 三维造型刀路(浮雕)数量 + private String count3D; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GroupXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GroupXmlVO.java new file mode 100644 index 000000000..cafea5de7 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/GroupXmlVO.java @@ -0,0 +1,33 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class GroupXmlVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1168768925661067043L; + + // 加工组名称 + private String name; + + // 加工组编号 + private String code; + + // 加工组高度 + private String height; + + // 加工组宽度 + private String width; + + // 加工组长度 + private String length; + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HardwareXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HardwareXmlVO.java new file mode 100644 index 000000000..d35ecff79 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HardwareXmlVO.java @@ -0,0 +1,92 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 五金信息 +public class HardwareXmlVO implements Serializable { + + // 五金物料编码 + private String itemCode; + + // 类型——拉手Handle、铰链Hinge、导轨Track、衣杆/裤杆Pole、杆托/杆座PoleBase、拉直器Straightener、灯带LightBelt、螺丝(及螺母)Screw(Nut)…… + private String type; + + // 厂家 + private String manufacturer; + + // 品牌 + private String brand; + + // 名称 + private String name; + + // 材质 + private String material; + + // 颜色 + private String color; + + // 规格/类型 + private String specs; + + // 长度 + private String length; + + // 宽度 + private String width; + + // 厚 + private String thickness; + + // 数量 + private String count; + + // 长度单位 + private String unit; + + // 数量单位 + private String unitCount; + + // 仓库 + private String warehouse; + + // 货架 + private String shelf; + + // 房间名称 + private String roomName; + + // 房间号 + private String roomCode; + + // 柜体名称 + private String boxName; + + // 柜体号 + private String boxCode; + + // 加工组号 + private String groupCode; + + // 加工组名称 + private String groupName; + + // 模块名称 + private String moduleName; + + // 模块号 + private String moduleCode; + + // 子五金物料编码 + private String subCodes; + +// // 备注 +// private RemarkXmlVOS remarkXmlVOS; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVO.java new file mode 100644 index 000000000..85962bc95 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVO.java @@ -0,0 +1,91 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class HoleXmlVO implements Serializable { + + // 孔类型 + private String type; + + // 拆单名/商品名 + private String name; + + // 加工面——正面、反面、左侧面、右侧面、上侧面、下侧面、斜面 + private String face; + + // 方向——向后Z-、向前Z+、向右X+、向左X-、向下Y-、向上Y+、斜O 孔加工面 + private String direction; + + // 直径/沉头孔外直径 + private String diameter; + + // 沉头孔内直径 + private String diameterInner; + + // 深度/沉头孔浅孔深度 + private String depth; + + // 沉头孔深孔深度 + private String depthInner; + + // 孔组数量 + private String groupNumber; + + // 孔组X坐标偏移 + private String groupXoffset; + + // 孔组Y坐标偏移 + private String groupYoffset; + + // 孔组Z坐标偏移 + private String groupZoffset; + + // 刀名称 + private String toolName; + + // 刀号 + private String toolNo; + + // 起点坐标X + private String startX; + + // 起点坐标Y + private String startY; + + // 起点坐标Z + private String startZ; + + // 刀具起点X轴旋转角度 + private String toolStartRotateX; + + // 刀具起点Y轴旋转角度 + private String toolStartRotateY; + + // 刀具起点Z轴旋转角度 + private String toolStartRotateZ; + + // 终点坐标X + private String endX; + + // 终点坐标Y + private String endY; + + // 终点坐标Z + private String endZ; + + // 刀具终点X轴旋转角度 + private String toolEndRotateX; + + // 刀具终点Y轴旋转角度 + private String toolEndRotateY; + + // 刀具终点Z轴旋转角度 + private String toolEndRotateZ; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVOS.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVOS.java new file mode 100644 index 000000000..47a9bf84d --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/HoleXmlVOS.java @@ -0,0 +1,53 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 孔列表 +public class HoleXmlVOS implements Serializable { + + // 孔数量 + private String count; + + // 正面垂直孔数量 + private String countFaceA; + + // 反面垂直孔数量 + private String countFaceB; + + // 水平侧孔数量 + private String countSide; + + // 左侧孔数量 + private String countSideL; + + // 右侧孔数量 + private String countSideR; + + // 上侧孔数量 + private String countSideU; + + // 下侧孔数量 + private String countSideD; + + // 斜面孔数量 + private String countBevelled; + + // 偏心轮/锁定孔数 + private String countLocking; + + // 预埋件孔数量 + private String countBuildIn; + + // 铰链孔数量 + private String countHinge; + + // 挖穿孔数量(通孔/对成孔) + private String countThrough; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/IsletXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/IsletXmlVO.java new file mode 100644 index 000000000..88105be8c --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/IsletXmlVO.java @@ -0,0 +1,23 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 孤岛信息 +public class IsletXmlVO implements Serializable { + + // 孤岛ID + private String id; + + // 内部槽ID集合 + private String subIDs; + + // 内层(不含内嵌孤岛内的凹槽)凹槽数量 + private String grooveCount; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/OffsetLineXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/OffsetLineXmlVO.java new file mode 100644 index 000000000..3857d89f0 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/OffsetLineXmlVO.java @@ -0,0 +1,32 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 偏移刀路信息 +public class OffsetLineXmlVO implements Serializable { + + // 偏移值——正值外偏/右偏、负值内偏/左偏 + private String offset; + + // 深度 + private String depth; + + // 刀名称 + private String toolName; + + // 刀号 + private String toolNo; + + // 刀直径 + private String toolDiameter; + + // 角度——二维刀路V型刀提角/清角用 + private String tangentAngle; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PlateXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PlateXmlVO.java new file mode 100644 index 000000000..cd908edf8 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PlateXmlVO.java @@ -0,0 +1,89 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 板材信息 +public class PlateXmlVO implements Serializable { + + // 物料编码 + private String itemCode; + + // 厂家 + private String manufacturer; + + // 品牌 + private String brand; + + // 名称 + private String name; + + // 材质 + private String material; + + // 饰面类型——无、单面、双面 + private String coating; + + // 有无纹理 有 无 + private String grained; + + // 正面饰面颜色、无(空) + private String coatingObverse; + + // 反面饰面颜色、无(空) + private String coatingReverse; + + // 规格 + private String specs; + + // 长 + private String length; + + // 宽 + private String width; + + // 厚 + private String thickness; + + // 是否余料 + private String oddment; + + // 余料长 + private String oddmentLength; + + // 余料宽 + private String oddmentWidth; + + // 余料厚 + private String oddmentThickness; + + // 长度单位——默认mm毫米 + private String unitLength; + + // 面积 + private String area; + + // 面积单位——默认m²平方米 + private String unitArea; + + // 仓库 + private String warehouse; + + // 货架 + private String shelf; + + // 余料编号 + private String oddmentNo; + + // 备注信息 + private String memo; + + // 数量 + private String count; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PointXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PointXmlVO.java new file mode 100644 index 000000000..a9f525594 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/PointXmlVO.java @@ -0,0 +1,71 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +// 孤岛点信息 +public class PointXmlVO implements Serializable { + + // 点X坐标 + private String pointX; + + // 点Y坐标 + private String pointY; + + // 点Z坐标 (在outline中不用) + private String pointZ; + + // 圆弧凹凸度——直线段为0 + private String curvature; + + // 边圆弧半径——直线段为0 + private String radius; + + // 加工工艺 + private String process; + + // 封边条物料编码 + private String itemCode; + + // 封边条物料名称 + private String edgingName; + + // 封边条颜色 + private String edgingColor; + + // 封边条材质 + private String edgingMaterial; + + // 封边条厚度 + private String edgingThickness; + + // 封边条宽度 + private String edgingWidth; + + // 封边条长度 + private String edgingLength; + + // 封边条余量 + private String edgingExtend; + + // 预铣/精修量 + private String preMilling; + + // 延展/收缩量,预留边 + private String scale; + + // 边备注信息 + private String remark; + + // 单边封边尺寸 + private String count; + + // 封边尺寸单位 + private String countUnit; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RectSealVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RectSealVO.java new file mode 100644 index 000000000..14ee9aad9 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RectSealVO.java @@ -0,0 +1,30 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 板备注 格式 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class RectSealVO { + + @Schema(description ="点id" ) + private String pointID; + + @Schema(description ="预留边" ) + private String reservedEdge; + + @Schema(description ="封边颜色" ) + private String sealColor; + + @Schema(description ="封边尺寸" ) + private String sealSize; + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RemarkXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RemarkXmlVO.java new file mode 100644 index 000000000..c750b12f3 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RemarkXmlVO.java @@ -0,0 +1,19 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class RemarkXmlVO implements Serializable { + + // 备注名称 + private String name; + + // 备注信息 + private String info; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RoomBoxXmlVO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RoomBoxXmlVO.java new file mode 100644 index 000000000..96dc2cc86 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/orderImport/xml/vo/RoomBoxXmlVO.java @@ -0,0 +1,76 @@ +package com.cf.imes.module.plan.controller.orderImport.xml.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class RoomBoxXmlVO implements Serializable { + + @Serial + private static final long serialVersionUID = -1320628670435686511L; + + // 房间名称 + private String name; + + // 房间编号 + private String code; + + // 房间高度 + private String height; + + // 房间宽度 + private String width; + + // 房间深度 + private String length; + + // 成倍拆单数量 + private String multipleNumber; + + // 成倍拆单序号 + private String multipleNo; + + + // 基点X坐标 + private String basePointX; + + // 基点Y坐标 + private String basePointY; + + // 基点Z坐标 + private String basePointZ; + + // 绕X轴旋转角度 + private String axisXrotate; + + // 绕Y轴旋转角度 + private String axisYrotate; + + // 绕Z轴旋转角度 + private String axisZrotate; + + // 房间基点X坐标 + private String roomBasePointX; + + // 房间基点Y坐标 + private String roomBasePointY; + + // 房间基点Z坐标 + private String roomBasePointZ; + + // 房间绕X轴旋转角度 + private String roomAxisXrotate; + + // 房间绕Y轴旋转角度 + private String roomAxisYrotate; + + // 房间绕Z轴旋转角度 + private String roomAxisZrotate; + +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataDO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataDO.java index 54aefd5ed..a584980fd 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataDO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.module.plan.dal.elasticsearch.BasePosition; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -54,6 +55,16 @@ public class OrderImportTempDataDO { */ private Integer type; + /** + * 设计端id + */ + private String outerId; + + /** + * 设计端归属id + */ + private String outerSubId; + /** * 物料编码 */ @@ -145,11 +156,33 @@ public class OrderImportTempDataDO { */ private String roomName; + /** + * 房间编号 + */ + private String roomCode; + + /** + * imes房间id + */ + @TableField(exist = false) + private Long innerRoomId; + /** * 柜体名称 */ private String bodyName; + /** + * 柜体编号 + */ + private String bodyCode; + + /** + * imes柜体id + */ + @TableField(exist = false) + private Long innerBodyId; + /** * 加工组类型 */ @@ -160,11 +193,28 @@ public class OrderImportTempDataDO { */ private String groupName; + /** + * 加工组编号 + */ + private String groupCode; + + /** + * imes加工组id + */ + @TableField(exist = false) + private Long innerGroupId; + /** * 数量 */ private Double num; + @TableField(exist = false) + private int plateNum; + + @TableField(exist = false) + private int unregularNum; + /** * 创建人 */ @@ -185,4 +235,16 @@ public class OrderImportTempDataDO { * 排序号 */ private int sort; + + /** + * 房间基准信息 + */ + @TableField(exist = false) + private BasePosition roomPosition; + + /** + * 柜体基准信息 + */ + @TableField(exist = false) + private BasePosition bodyPosition; } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartItemCodeGroupDO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartItemCodeGroupDO.java new file mode 100644 index 000000000..ba9433b47 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartItemCodeGroupDO.java @@ -0,0 +1,38 @@ +package com.cf.imes.module.plan.dal.dataobject.orderImport; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author Gqr + * @since 2025/2/27 12:02 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderImportTempDataPartItemCodeGroupDO implements Serializable { + + @Serial + private static final long serialVersionUID = 7562741999326100586L; + + /** + * 配件编码 + */ + private String itemCode; + + /** + * 配件类型 + */ + private int type; + + /** + * 排序号 + */ + private int sortn; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartRoomBodyGroupGroupDO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartRoomBodyGroupGroupDO.java new file mode 100644 index 000000000..6067d74b6 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderImport/OrderImportTempDataPartRoomBodyGroupGroupDO.java @@ -0,0 +1,42 @@ +package com.cf.imes.module.plan.dal.dataobject.orderImport; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author Gqr + * @since 2025/2/27 14:10 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderImportTempDataPartRoomBodyGroupGroupDO implements Serializable { + @Serial + private static final long serialVersionUID = 4444878625562385937L; + + /** + * 房间编号 + */ + private String roomCode; + + /** + * 柜体编号 + */ + private String bodyCode; + + /** + * 加工组编号 + */ + private String groupCode; + + /** + * 配件数量 + */ + private double partsNum; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/mysql/orderImport/OrderImportTempDataMapper.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/mysql/orderImport/OrderImportTempDataMapper.java index 1acb01472..08064da11 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/mysql/orderImport/OrderImportTempDataMapper.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/mysql/orderImport/OrderImportTempDataMapper.java @@ -5,6 +5,8 @@ import com.cf.imes.module.plan.controller.orderImport.vo.OrderImportTempDataReqV import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataDO; import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataGoodsGroupDO; import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataGoodsIdGroupDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataPartItemCodeGroupDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataPartRoomBodyGroupGroupDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -153,4 +155,20 @@ public interface OrderImportTempDataMapper extends BaseMapperX selectPartList(@Param("reqVO") OrderImportTempDataReqVO reqVO); + + /** + * 查询配件itemcode分组 + * + * @param reqVO + * @return + */ + List selectPartItemCodeGroup(@Param("reqVO") OrderImportTempDataReqVO reqVO); + + /** + * 查询配件itemcode下的房间+柜体+加工组分组 + * + * @param reqVO + * @return + */ + List selectPartRoomBodyGroupGroup(@Param("reqVO") OrderImportTempDataReqVO reqVO); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultExcelOrderImportConsumer.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultExcelOrderImportConsumer.java index 8737a8c7c..cc2e1fdce 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultExcelOrderImportConsumer.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultExcelOrderImportConsumer.java @@ -118,6 +118,7 @@ public class DefaultExcelOrderImportConsumer { @DS("imes_prod") @Transactional(rollbackFor = Exception.class) public void orderImport(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception { + log.info("====================【生产单默认excel导入收到消息:{}】====================", message); Long organId = null; Long taskId = Long.parseLong(message); try { @@ -133,11 +134,13 @@ public class DefaultExcelOrderImportConsumer { // 创建生产单 Long orderId = createOrder(taskId); // 创建工厂 + log.info("====================【生产单默认excel导入处理临时数据开始】===================="); DefaultExcelOrderImportFactory defaultExcelOrderImportFactory = new DefaultExcelOrderImportFactory(taskId, orderId, organId, orderImportTaskDO.getCreator(), snowFlakeGenerator, idWorker, orderImportTaskMapper, orderImportTempDataMapper, dictDataApi, goodsMapper, rawGoodsMapper, orderPartsMapper, orderBodyMapper, orderGroupMapper, plateMapper, orderItemMapper, plateGoodMapper, orderInputProcessor, partsMapper); // 解析临时表数据 defaultExcelOrderImportFactory.analyzeTempData(); + log.info("====================【生产单默认excel导入处理临时数据结束】===================="); } catch (Exception e) { // 确认消息进入死信队列 channel.basicNack(deliveryTag, false, false); diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultXmlOrderImportConsumer.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultXmlOrderImportConsumer.java new file mode 100644 index 000000000..319601c47 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/consumer/DefaultXmlOrderImportConsumer.java @@ -0,0 +1,260 @@ +package com.cf.imes.module.plan.service.orderImport.consumer; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.cf.imes.framework.common.enums.OrderPackageStatusEnum; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; +import com.cf.imes.framework.common.util.json.JsonUtils; +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.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.OrderImportTmpDataTypeEnum; +import com.cf.imes.module.executor.enums.OrderStatusEnum; +import com.cf.imes.module.plan.dal.dataobject.order.OrderDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataDO; +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.orderImport.OrderImportTempDataMapper; +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.orderParts.PartsMapper; +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.order.OrderInputProcessor; +import com.cf.imes.module.plan.service.orderImport.factory.DefaultXmlOrderImportFactory; +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.messaging.handler.annotation.Header; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Optional; + +import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_NOT_EXISTS; +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; + +/** + * 默认excel导入生产单消费者 + * + * @author Gqr + * @since 2025/2/19 16:22 + */ +@Component +@Slf4j +public class DefaultXmlOrderImportConsumer { + @Resource + private OrderImportTaskMapper orderImportTaskMapper; + + @Resource + private OrderImportTempDataMapper orderImportTempDataMapper; + + @Resource + private OrderMapper orderMapper; + + @Resource + private RedisLockUtil redisLockUtil; + + @Resource + private SnowFlakeGenerator snowFlakeGenerator; + + @Resource + private SnowflakeIdWorker3rd idWorker; + + @Resource + private GoodsMapper goodsMapper; + + @Resource + private RawGoodsMapper rawGoodsMapper; + + @Resource + private OrderPartsMapper orderPartsMapper; + + @Resource + private OrderBodyMapper orderBodyMapper; + + @Resource + private OrderGroupMapper orderGroupMapper; + + @Resource + private PlateMapper plateMapper; + + @Resource + private OrderItemMapper orderItemMapper; + + @Resource + private PlateGoodMapper plateGoodMapper; + + @Resource + private OrderInputProcessor orderInputProcessor; + + @Resource + private PartsMapper partsMapper; + + @RabbitListener(queues = RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_QUEUE) + @DS("imes_prod") + @Transactional(rollbackFor = Exception.class) + public void orderImport(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception { + log.info("====================【生产单默认xml导入收到消息:{}】====================", message); + Long organId = null; + Long taskId = Long.parseLong(message); + try { + organId = OrganContextHolder.getOrganId(); + if (ObjectUtil.isNull(organId)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORGANID_NOT_EXISTS); + } + // 确认任务,更新状态为消费成功,没有找到任务中断后续消费 + OrderImportTaskDO orderImportTaskDO = confirmOrderImport(taskId); + if (ObjectUtil.isNull(orderImportTaskDO)) { + return; + } + // 创建生产单 + Long orderId = createOrder(taskId); + log.info("====================【生产单默认xml导入处理临时数据开始】===================="); + // 创建工厂 + DefaultXmlOrderImportFactory defaultExcelOrderImportFactory = new DefaultXmlOrderImportFactory(taskId, orderId, organId, orderImportTaskDO.getCreator(), + snowFlakeGenerator, idWorker, orderImportTaskMapper, orderImportTempDataMapper, goodsMapper, rawGoodsMapper, orderPartsMapper, + orderBodyMapper, orderGroupMapper, plateMapper, orderItemMapper, plateGoodMapper, orderInputProcessor, partsMapper); + // 解析临时表数据 + defaultExcelOrderImportFactory.analyzeTempData(); + log.info("====================【生产单默认xml导入处理临时数据结束】===================="); + } catch (Exception e) { + // 确认消息进入死信队列 + channel.basicNack(deliveryTag, false, false); + String importFailNotify = ORDER_IMPORT_FAIL.getMsg(); + // 更新状态为消费失败、导入失败 + orderImportTaskMapper.update(new LambdaUpdateWrapper().eq(OrderImportTaskDO::getId, taskId) + .set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_FAIL.getStatus()) + .set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus()) + .set(OrderImportTaskDO::getResult, importFailNotify)); + log.error(importFailNotify, e); + throw e; + } finally { + // 手动确认消息接收 + channel.basicAck(deliveryTag, false); + // 导入锁解锁 + redisLockUtil.unlock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message); + } + } + + /** + * 确认导入任务,更新任务状态 + * + * @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; + } + + /** + * 创建生产单 + * + * @param taskId + * @return + */ + private Long createOrder(Long taskId) { + // 查询临时表中的order + LambdaQueryWrapper orderTempData = new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.ORDER.getType()) + .eq(OrderImportTempDataDO::getSort, 0); + OrderImportTempDataDO orderImportTempDataDO = orderImportTempDataMapper.selectOne(orderTempData); + // 不是新单不用创建 + if (ObjectUtil.isNotNull(orderImportTempDataDO) && ObjectUtil.isNotNull(orderImportTempDataDO.getOrderId())) { + Long existOrderId = orderImportTempDataDO.getOrderId(); + // 校验生产单id + OrderDO orderDO = orderMapper.selectById(existOrderId); + Optional.ofNullable(orderDO).orElseThrow(() -> ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_NOT_EXISTS, existOrderId)); + // 更新补板生产单属性 + updateOrder(orderDO); + return existOrderId; + } + // 取临时order数据,detail转orderDO,插入新增orderDO + String orderTempDetail = JsonUtils.unzipString(orderImportTempDataDO.getDetail()); + OrderDO newOrder = JSON.parseObject(orderTempDetail, OrderDO.class); + Long orderId = (Long) snowFlakeGenerator.nextId(null); + newOrder.setId(orderId); + orderMapper.insert(newOrder); + // 生产单id更新到导入任务表 + orderImportTaskMapper.update(new LambdaUpdateWrapper() + .eq(OrderImportTaskDO::getId, taskId) + .set(OrderImportTaskDO::getOrderId, orderId)); + return orderId; + } + + /** + * 更新补板生产单的属性 + * + * @param orderDO + */ + public void updateOrder(OrderDO orderDO) { + // 发货日期校验 + LocalDate orderDate = LocalDate.from(orderDO.getOrderDate()); + LocalDate deliveryDate = LocalDate.from(orderDO.getDeliveryDate()); + if (deliveryDate.isBefore(orderDate)) { + // 将 deliveryDate 设置为 orderDate 后的第 30 天 + deliveryDate = orderDate.plusMonths(1); + } + orderDO.setDeliveryDate(deliveryDate.atStartOfDay()); + if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.EMPTY.getStatus())) { + orderDO.setStatus(OrderStatusEnum.NEW_ORDER.getStatus()); + } + if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.FINISH_PRODUCTION.getStatus())) { + orderDO.setStatus(OrderStatusEnum.IN_PRODUCTION.getStatus()); + } + if (Objects.equals(orderDO.getPackaged(), OrderPackageStatusEnum.PACKAGED.getStatus())) { + orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus()); + } + orderMapper.updateById(orderDO); + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultExcelOrderImportFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultExcelOrderImportFactory.java index 2f449a4d9..46f8d226b 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultExcelOrderImportFactory.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultExcelOrderImportFactory.java @@ -67,7 +67,6 @@ import java.util.List; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS; import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PARTS_REMARK_MODEL; import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL; -import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL_COMPRESS; /** * 默认excel导入生产单工厂服务 @@ -78,9 +77,9 @@ import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PL @Slf4j public class DefaultExcelOrderImportFactory { /** - * 分组中做分页的阈值,如:总数1000以上就边分组边分页,否则一次性查出来 + * 分组中做分页的阈值,如:总数100以上就边分组边分页,否则一次性查出来 */ - private static final int BATCH_THRESHOLD_NUMBER = 1000; + private static final int BATCH_THRESHOLD_NUMBER = 100; private Long organId; @@ -183,12 +182,21 @@ public class DefaultExcelOrderImportFactory { */ public void analyzeTempData() { try { + log.info("====================【生产单默认xml导入处理商品开始】===================="); // 解析商品数据 analyzeGoods(); + log.info("====================【生产单默认xml导入处理商品结束】===================="); + + log.info("====================【生产单默认xml导入处理配件商品开始】===================="); // 解析配件数据 analyzePartsGoods(); + log.info("====================【生产单默认xml导入处理配件商品结束】===================="); + + log.info("====================【生产单默认xml导入处理小板/配件开始】===================="); // 解析小板/配件项 analyzeRooms(); + log.info("====================【生产单默认xml导入处理小板/配件结束】===================="); + // 删除临时数据 deleteTempData(); // 完成所有流程后更新任务为导入成功 @@ -196,7 +204,6 @@ public class DefaultExcelOrderImportFactory { } catch (Exception e) { // 数据库数据回滚,此时删除 ES 里的数据 orderInputProcessor.deleteByOrderId(orderId, ORDER_PLATE_MODEL); - orderInputProcessor.deleteByOrderId(orderId, ORDER_PLATE_MODEL_COMPRESS); orderInputProcessor.deleteByOrderId(orderId, ORDER_PARTS_REMARK_MODEL); throw e; } finally { @@ -457,7 +464,7 @@ public class DefaultExcelOrderImportFactory { orderInputProcessor.batchSaveOrderPartsModel(orderPartsRemarks); if (!isLast) { // 存储完成清理 list - orderPartsRemarks = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + orderPartsRemarks.clear(); } } } @@ -845,7 +852,7 @@ public class DefaultExcelOrderImportFactory { baseBatchMapper.insertBatchSomeColumn(list); if (!isLast) { // 存储完成清理 list - list = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + list.clear(); } } } 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 new file mode 100644 index 000000000..a027e020f --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/DefaultXmlOrderImportFactory.java @@ -0,0 +1,2005 @@ +package com.cf.imes.module.plan.service.orderImport.factory; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +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.JSONObject; +import com.alibaba.nacos.common.utils.StringUtils; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; +import com.cf.imes.framework.common.util.json.JsonUtils; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.dict.core.util.DictFrameworkUtils; +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.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.organ.core.context.OrganContextHolder; +import com.cf.imes.module.executor.enums.DictTypeConstants; +import com.cf.imes.module.executor.enums.OrderImportStatusEnum; +import com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum; +import com.cf.imes.module.executor.enums.OrderItemTypeEnum; +import com.cf.imes.module.plan.controller.orderImport.vo.OrderImportTempDataReqVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.AssemblyXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.BlockXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.CorrelationXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.CuttingOutlineXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.EdgingXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.ExtraVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.GrooveXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.GrooveXmlVOS; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.GroupXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.HardwareXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.HoleXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.HoleXmlVOS; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.OffsetLineXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.PlateXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.PointXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.RectSealVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.RemarkXmlVO; +import com.cf.imes.module.plan.controller.orderImport.xml.vo.RoomBoxXmlVO; +import com.cf.imes.module.plan.dal.dataobject.goods.GoodsDO; +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.orderImport.OrderImportTempDataDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataPartItemCodeGroupDO; +import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataPartRoomBodyGroupGroupDO; +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.orderParts.PartsDO; +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.BasePosition; +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.OrderPartsRemark; +import com.cf.imes.module.plan.dal.elasticsearch.PartsInfo; +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.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.orderImport.OrderImportTempDataMapper; +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.orderParts.PartsMapper; +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.order.OrderInputProcessor; +import org.apache.ibatis.session.ResultContext; +import org.apache.ibatis.session.ResultHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.cf.imes.module.executor.enums.OrderImportConstants.NOT_ASSIGNED; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS; +import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PARTS_REMARK_MODEL; +import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL; + +/** + * 默认xml导入生产单工厂服务 + * + * @author Gqr + * @since 2025/2/19 16:26 + */ +public class DefaultXmlOrderImportFactory { + /** + * 分组中做分页的阈值,如:总数100以上就边分组边分页,否则一次性查出来 + */ + private static final int BATCH_THRESHOLD_NUMBER = 100; + private static final Logger log = LoggerFactory.getLogger(DefaultXmlOrderImportFactory.class); + + private Long organId; + + private Long orderId; + + private Long taskId; + + private List rawGoodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List goodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderPartsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderBodyDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderGroupDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List plateDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderItemDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List plateGoodDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderModelDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List orderPartsRemarks = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + private List partsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + + private static final String EMPTY_STRING = new String(); + private static final BigDecimal BIG_ZERO = new BigDecimal(0); + + private static final int GOODS_TYPE = OrderImportTmpDataTypeEnum.GOODS.getType(); + private static final int BODY_TYPE = OrderImportTmpDataTypeEnum.BODY.getType(); + private static final int GROUP_TYPE = OrderImportTmpDataTypeEnum.GROUP.getType(); + private static final int PLATE_TYPE = OrderImportTmpDataTypeEnum.PLATE.getType(); + private static final int PART_EDGING_TYPE = OrderImportTmpDataTypeEnum.PART_EDGING.getType(); + private static final int PART_HARDWARE_TYPE = OrderImportTmpDataTypeEnum.PART_HARDWARE.getType(); + private static final int PART_ASSEMBLY_TYPE = OrderImportTmpDataTypeEnum.PART_ASSEMBLY.getType(); + + private SnowFlakeGenerator snowFlakeGenerator; + + private SnowflakeIdWorker3rd idWorker; + + private OrderImportTaskMapper orderImportTaskMapper; + + private OrderImportTempDataMapper orderImportTempDataMapper; + + private GoodsMapper goodsMapper; + + private RawGoodsMapper rawGoodsMapper; + + private OrderPartsMapper orderPartsMapper; + + private OrderBodyMapper orderBodyMapper; + + private OrderGroupMapper orderGroupMapper; + + private PlateMapper plateMapper; + + private OrderItemMapper orderItemMapper; + + private PlateGoodMapper plateGoodMapper; + + private OrderInputProcessor orderInputProcessor; + + private PartsMapper partsMapper; + + private String operatorName; + + public DefaultXmlOrderImportFactory(Long taskId, + Long orderId, + Long organId, + String operatorName, + SnowFlakeGenerator snowFlakeGenerator, + SnowflakeIdWorker3rd idWorker, + OrderImportTaskMapper orderImportTaskMapper, + OrderImportTempDataMapper orderImportTempDataMapper, + GoodsMapper goodsMapper, + RawGoodsMapper rawGoodsMapper, + OrderPartsMapper orderPartsMapper, + OrderBodyMapper orderBodyMapper, + OrderGroupMapper orderGroupMapper, + PlateMapper plateMapper, + OrderItemMapper orderItemMapper, + PlateGoodMapper plateGoodMapper, + OrderInputProcessor orderInputProcessor, + PartsMapper partsMapper) { + this.taskId = taskId; + this.orderId = orderId; + this.organId = organId; + this.operatorName = operatorName; + this.snowFlakeGenerator = snowFlakeGenerator; + this.idWorker = idWorker; + this.orderImportTaskMapper = orderImportTaskMapper; + this.orderImportTempDataMapper = orderImportTempDataMapper; + this.goodsMapper = goodsMapper; + this.rawGoodsMapper = rawGoodsMapper; + this.orderPartsMapper = orderPartsMapper; + this.orderBodyMapper = orderBodyMapper; + this.orderGroupMapper = orderGroupMapper; + this.plateMapper = plateMapper; + this.orderItemMapper = orderItemMapper; + this.plateGoodMapper = plateGoodMapper; + this.orderInputProcessor = orderInputProcessor; + this.partsMapper = partsMapper; + } + + private Map> roomBodyMap = new HashMap<>(); // 房间code: (柜体code:柜体数据) + + private Map groupMap = new HashMap<>(); // 加工组code:加工组数据 + + private Map orderPartsDOMap = new HashMap<>(); // 配件code:orderpartsdo + + /** + * 解析临时表数据 + */ + public void analyzeTempData() { + try { + log.info("====================【生产单默认xml导入处理柜体开始】===================="); + // 解析柜体数据 + analyzeBodyNoPaging(); + log.info("====================【生产单默认xml导入处理柜体结束】===================="); + + log.info("====================【生产单默认xml导入处理加工组开始】===================="); + // 解析加工组 + analyzeGroupNoPaging(); + log.info("====================【生产单默认xml导入处理加工组结束】===================="); + + log.info("====================【生产单默认xml导入处理商品开始】===================="); + // 解析商品数据 + analyzeGoodsDetailNoPaging(); + log.info("====================【生产单默认xml导入处理商品结束】===================="); + + log.info("====================【生产单默认xml导入处理板件开始】===================="); + // 解析板件 + analyzePlate(); + log.info("====================【生产单默认xml导入处理板件结束】===================="); + + log.info("====================【生产单默认xml导入处理配件开始】===================="); + // 解析配件 + analyzeParts(); + log.info("====================【生产单默认xml导入处理配件结束】===================="); + + log.info("====================【生产单默认xml导入处理回显开始】===================="); + // 把缓存数据回显到业务表 + writeBackToOrders(); + log.info("====================【生产单默认xml导入处理回显结束】===================="); + + // 删除临时数据 + deleteTempData(); + // 完成所有流程后更新任务为导入成功 + updateTaskSuccess(); + } catch (Exception e) { + // 数据库数据回滚,此时删除 ES 里的数据 + orderInputProcessor.deleteByOrderId(orderId, ORDER_PLATE_MODEL); + orderInputProcessor.deleteByOrderId(orderId, ORDER_PARTS_REMARK_MODEL); + throw e; + } finally { + clearAll(); + } + } + + private void analyzeBodyNoPaging() { + // 查询柜体列表 + List bodyTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, BODY_TYPE) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO bodyDO : bodyTempDataList) { + String roomCode = bodyDO.getRoomCode(); + String bodyCode = bodyDO.getBodyCode(); + + Map bodyTempMap = roomBodyMap.get(roomCode); + if (MapUtil.isNotEmpty(bodyTempMap)) { + OrderImportTempDataDO bodyTempData = bodyTempMap.get(bodyCode); + if (ObjectUtil.isNotNull(bodyTempData)) { + // 有房间有柜体,不再缓存 + return; + } + // 有房间没柜体,取房间id,后续操作增加房间下柜体 + Map.Entry anyBody = bodyTempMap.entrySet().iterator().next(); + bodyDO.setInnerRoomId(anyBody.getValue().getInnerRoomId()); + } + + // 创建order_body + OrderBodyDO orderBodyDO = createOrderBodyDO(bodyDO); + orderBodyDOS.add(orderBodyDO); + // 批量插入orderGroup + orderInfoBatchInsertWithinThreshold(orderBodyMapper, orderBodyDOS, false); + // imes房间id、柜体id回显到临时数据 + bodyDO.setInnerBodyId(orderBodyDO.getId()); + bodyDO.setInnerRoomId(orderBodyDO.getRoomId()); + if (MapUtil.isNotEmpty(bodyTempMap)) { + bodyTempMap.put(bodyCode, bodyDO); + } else { + // 缓存柜体 + roomBodyMap.put(roomCode, MapUtil.builder().put(bodyCode, bodyDO).build()); + } + } + //最后批量插入一次,避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入 + orderInfoBatchInsertWithinThreshold(orderBodyMapper, orderBodyDOS, true); + } + + /** + * 不分页解析商品id分组列表 + */ + private void analyzeGoodsDetailNoPaging() { + // 查询商品列表 + List goodsTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, GOODS_TYPE) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO goodsTempData : goodsTempDataList) { + String detail = goodsTempData.getDetail(); + if (StringUtils.isNotBlank(detail)) { + PlateXmlVO plateXmlVO = JsonUtils.parseObject(JsonUtils.unzipString(detail), PlateXmlVO.class); + if (StringUtils.equals(plateXmlVO.getGrained().trim(), "无")) { + plateXmlVO.setGrained("false"); + } else if (StringUtils.equals(plateXmlVO.getGrained().trim(), "有")) { + plateXmlVO.setGrained("true"); + } + + Long rawGoodsId = (Long) snowFlakeGenerator.nextId(null); + Long goodsId = NumberUtil.parseLong(goodsTempData.getInnerGoodsId()); + RawGoodsDO rawGoodsDO = RawGoodsDO.builder() + .id(rawGoodsId) + .organId(organId) + .orderId(orderId) + .rawGoodsId(plateXmlVO.getItemCode()) + .goodsName(plateXmlVO.getName()) + .material(plateXmlVO.getMaterial()) + .color(plateXmlVO.getCoatingObverse()) + .colorBlack(plateXmlVO.getCoatingReverse()) + .texture(Boolean.valueOf(plateXmlVO.getGrained())) + .thickness(Double.parseDouble(plateXmlVO.getThickness())) + .brand(plateXmlVO.getBrand()) + .spec(plateXmlVO.getSpecs()) + .price(0.00) + .deleted(false) + .build(); + rawGoodsDO.setCreator(operatorName); + rawGoodsDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + rawGoodsDO.setCreateTime(now); + rawGoodsDO.setUpdateTime(now); + + GoodsDO goodsDO = GoodsDO.builder() + .id(goodsId) + .organId(organId) + .orderId(orderId) + .rawGoodsId(String.valueOf(rawGoodsId)) + .goodsId(plateXmlVO.getItemCode()) + .goodsName(plateXmlVO.getName()) + .material(plateXmlVO.getMaterial()) + .color(plateXmlVO.getCoatingObverse()) + .colorBlack(plateXmlVO.getCoatingReverse()) + .texture(Boolean.valueOf(plateXmlVO.getGrained())) + .width(BigDecimal.valueOf(Double.parseDouble(plateXmlVO.getWidth()))) + .height(BigDecimal.valueOf(Double.parseDouble(plateXmlVO.getLength()))) + .thickness(BigDecimal.valueOf(Double.parseDouble(plateXmlVO.getThickness()))) + .brand(plateXmlVO.getBrand()) + .spec(plateXmlVO.getSpecs()) + .remark(plateXmlVO.getMemo()) + .planId(0L) + .price(0.00) + .deleted(false) + .build(); + goodsDO.setCreator(operatorName); + goodsDO.setUpdater(operatorName); + goodsDO.setCreateTime(now); + goodsDO.setUpdateTime(now); + + // 解析大板 + analyzePlateGoods(goodsDO); + goodsDOS.add(goodsDO); + rawGoodsDOS.add(rawGoodsDO); + // 批量插入rawgoods、goods + orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, false); + orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, false); + } + } + // 最后批量插入rawgoods、goods、plategoods一次,避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入 + orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, true); + orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, true); + orderInfoBatchInsertWithinThreshold(plateGoodMapper, plateGoodDOS, true); + } + + /** + * 不分页解析加工组 + */ + private void analyzeGroupNoPaging() { + // 查询加工组列表 + List groupTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, GROUP_TYPE) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO groupDO : groupTempDataList) { + // 创建order_group + OrderGroupDO orderGroupDO = createOrderGroupDO(groupDO); + orderGroupDOS.add(orderGroupDO); + // 批量插入orderGroup + orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, false); + // imes柜体id回显到临时数据 + groupDO.setInnerGroupId(orderGroupDO.getId()); + // 缓存加工组 + groupMap.put(groupDO.getGroupCode(), groupDO); + } + //最后批量插入一次,避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入 + orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, true); + } + + private void analyzePlate() { + Page page = new Page<>(1, BATCH_THRESHOLD_NUMBER); + orderImportTempDataMapper.selectList(page, new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, PLATE_TYPE) + .eq(OrderImportTempDataDO::getOrganId, organId), new ResultHandler<>() { + int count = 0; + + @Override + public void handleResult(ResultContext resultContext) { + OrderImportTempDataDO plateTempData = resultContext.getResultObject(); + + // 解析板件明细数据 + String detail = JsonUtils.unzipString(plateTempData.getDetail()); + BlockXmlVO blockXmlVO = JSON.parseObject(detail, BlockXmlVO.class); + + long plateNo = idWorker.nextId(); + long obtainingTime = idWorker.obtainingTime(); + Long plateId = (Long) snowFlakeGenerator.nextId(null); + + // 成品面积 + Double length = changeUnit(blockXmlVO.getLength(), blockXmlVO.getUnit(), DictTypeConstants.UNIT_LENGTH); + Double width = changeUnit(blockXmlVO.getWidth(), blockXmlVO.getUnit(), DictTypeConstants.UNIT_LENGTH); + BigDecimal area = BigDecimal.valueOf((length / 1000) * (width / 1000)); + + // 获取开门类型 + int doorType = Integer.parseInt(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.DOOR_OPENING_DIRECTIONS, blockXmlVO.getOpenDirection())); + + // 获取房间柜体缓存 + String roomCode = plateTempData.getRoomCode(); + String bodyCode = plateTempData.getBodyCode(); + + // 房间、柜体基点坐标 + BasePosition roomBasePoint = null; + BasePosition bodyBasePoint = null; + + Map roomTempDataMap = roomBodyMap.get(roomCode); + OrderImportTempDataDO roomBodyTempDataDO = null; + // 板材数量和异形数量回显到柜体 + if (MapUtil.isNotEmpty(roomTempDataMap)) { + roomBodyTempDataDO = roomTempDataMap.get(bodyCode); + if (ObjectUtil.isNotNull(roomBodyTempDataDO)) { + if (convertToBoolean(blockXmlVO.getUnregular())) { + roomBodyTempDataDO.setUnregularNum(roomBodyTempDataDO.getUnregularNum() + 1); + roomBasePoint = roomBodyTempDataDO.getRoomPosition(); + bodyBasePoint = roomBodyTempDataDO.getBodyPosition(); + } else { + roomBodyTempDataDO.setPlateNum(roomBodyTempDataDO.getPlateNum() + 1); + } + } + } + + // 获取加工组缓存 + String groupCode = plateTempData.getGroupCode(); + OrderImportTempDataDO groupTempDataDO = groupMap.get(groupCode); + // 柜体id回显到加工组 + if (ObjectUtil.isNotNull(groupTempDataDO) && ObjectUtil.isNull(groupTempDataDO.getInnerBodyId()) && ObjectUtil.isNotNull(roomBodyTempDataDO)) { + groupTempDataDO.setInnerBodyId(roomBodyTempDataDO.getInnerBodyId()); + } + + long goodsId = Long.parseLong(plateTempData.getInnerGoodsId()); + // 板类型 + int plateType = Integer.parseInt(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.PLATE_TYPE, blockXmlVO.getType())); + PlateDO plateDO = PlateDO.builder() + .id(plateId) + .orderId(orderId) + .name(blockXmlVO.getName()) + .plateNo((obtainingTime) + Long.toString(plateNo).substring(2)) + .type(plateType) + .goodsId(goodsId) + .width(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getWidth()))) + .height(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getLength()))) + .thickness(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getThickness()))) + .splitHeight(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getLength()))) + .splitThickness(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getThickness()))) + .splitWidth(BigDecimal.valueOf(Double.parseDouble(blockXmlVO.getWidth()))) + .area(area) + .texture(Integer.valueOf(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.GRAIN_TYPE, blockXmlVO.getTexture()))) + .holeFace(Integer.valueOf(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.TYPOGRAPHY_TYPE, blockXmlVO.getLayoutFace()))) + .isDoor(doorType != 0) + .openDoorType(doorType) + .isSculpt(false) + .isSpecialShaped(convertToBoolean(blockXmlVO.getUnregular())) + .customPlateNoBuilder(new StringBuilder()) + .organId(organId) + .holeArrange(0) + .holeFace(0) + .unregularPointCount(0) + .frontHoleCount(0) + .backHoleCount(0) + .sideHoleCount(0) + .frontModelCount(0) + .backModelCount(0) + .isDoor(false) + .offsetX(BIG_ZERO) + .offsetY(BIG_ZERO) + .isArcAcross(false) + .moduleTypeId(0L) + .isRowHole(false) + .isOptimized(false) + .isCutted(0) + .isCancel(false) + .filterType(EMPTY_STRING) + .sealLeft(BigDecimal.ZERO) + .sealRight(BigDecimal.ZERO) + .sealUp(BigDecimal.ZERO) + .sealDown(BigDecimal.ZERO) + .remark(EMPTY_STRING) + .deleted(false) + .build(); + plateDO.setCreator(operatorName); + plateDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + plateDO.setCreateTime(now); + plateDO.setUpdateTime(now); + + OrderItemDO orderItemDO = OrderItemDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PLATE_ITEM.getStatus()) + .plateId(plateId) + .groupId(ObjectUtil.isNotNull(groupTempDataDO) ? groupTempDataDO.getInnerGroupId() : 0L) + .roomId(roomBodyTempDataDO.getInnerRoomId()) + .bodyId(roomBodyTempDataDO.getInnerBodyId()) + .num(1.0) + .organId(organId) + .packageId(0L) + .partsId(0L) + .build(); + // 批量插入order_item + orderItemDOS.add(orderItemDO); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false); + + // 基点坐标 + BasePosition plateBasePosition = BasePosition.builder() + .basePoint(String.valueOf(plateId)) + .basePointX(Double.valueOf(blockXmlVO.getBasePointX())) + .basePointY(Double.valueOf(blockXmlVO.getBasePointY())) + .basePointZ(Double.valueOf(blockXmlVO.getBasePointZ())) + .axisXrotate(Double.valueOf(blockXmlVO.getAxisXrotate())) + .axisYrotate(Double.valueOf(blockXmlVO.getAxisYrotate())) + .axisZrotate(Double.valueOf(blockXmlVO.getAxisZrotate())) + .build(); + + // 板件es数据 + OrderModelDO orderModelDO = OrderModelDO.builder() + .orderId(orderId) + .plateId(plateId) + .has2DModel(false) + .has3DModel(false) + .texture(plateDO.getTexture()) + .typographicFace(plateDO.getHoleFace()) + .openDoorType(plateDO.getOpenDoorType()) + .boardType(blockXmlVO.getType()) + .roomBasePosition(roomBasePoint) + .bodyBasePosition(bodyBasePoint) + .plateBasePosition(plateBasePosition) + .splitLength(BigDecimal.valueOf(Long.parseLong(blockXmlVO.getCuttingLength()))) + .splitWidth(BigDecimal.valueOf(Long.parseLong(blockXmlVO.getCuttingWidth()))) + .pointDetail(new ArrayList<>()) + .rawPointDetail(new ArrayList<>()) + .basePointDetail(new ArrayList<>()) + .holeCount(new HashMap<>()) + .holeDetail(new ArrayList<>()) + .contourCount(new HashMap<>()) + .contourDetail(new ArrayList<>()) + .sideHoleDetail(new ArrayList<>()) + .sideRemark(new HashMap<>()) + .plateExtraRemark(new JSONObject()) + .build(); + + String blockProductionCode = blockXmlVO.getProductionCode(); + // 处理es封边值 + addSealEdge(blockProductionCode, plateDO, orderItemDO, orderModelDO); + // 偏移量 不含封边 + addCuttingOutlinePointDetail(blockProductionCode, plateDO, orderModelDO); + addRawOutlinePointDetail(blockProductionCode, orderModelDO); + // 孔数据 + addHole(blockProductionCode, plateDO, orderModelDO); + // 造型数据 (槽), 孤岛信息 + addContourDetail(blockProductionCode, plateDO, orderModelDO); + // 小板关联配件 + addParts(blockProductionCode, orderModelDO); + // 小板备注信息 + addRemark(blockProductionCode, plateDO, orderModelDO); + // 查询大板id用于小板轮廓goodsId + GoodsDO goodsDO = goodsMapper.selectById(goodsId); + if (ObjectUtil.isNull(goodsDO)) { + throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS, orderId, goodsId); + } + orderModelDO.setGoodsId(goodsDO.getGoodsId()); + orderModelDO.setPlateGoodsId(goodsId); + orderModelDO.setOrganId(organId); + orderModelDO.setCreator(operatorName); + orderModelDO.setUpdater(operatorName); + orderModelDOS.add(orderModelDO); + + // 批量插入order_plate + plateDOS.add(plateDO); + orderInfoBatchInsertWithinThreshold(plateMapper, plateDOS, false); + // 批量插入造型数据 + orderModelsBatchInsertWithinThreshold(false); + } + } + ); + //最后批量插入一次,避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入 + orderInfoBatchInsertWithinThreshold(plateMapper, plateDOS, true); + // 批量插入造型数据 + orderModelsBatchInsertWithinThreshold(true); + } + + /** + * 处理es封边值 + * + * @param blockProductionCode + * @param plateDO + * @param orderModelDO + */ + private void addSealEdge(String blockProductionCode, PlateDO plateDO, OrderItemDO orderItemDO, OrderModelDO orderModelDO) { + List outlinePointTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_OUTLINE_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + BigDecimal sealLeft = BigDecimal.valueOf(0); + BigDecimal sealRight = BigDecimal.valueOf(0); + BigDecimal sealUp = BigDecimal.valueOf(0); + BigDecimal sealDown = BigDecimal.valueOf(0); + + ExtraVO extraVO = ExtraVO.builder() + .edgeRemarks(new ArrayList<>()) + .rectSealDetail(new ArrayList<>()) + .build(); + int indexId = 0; + for (OrderImportTempDataDO pointTempData : outlinePointTempDataList) { + String detail = pointTempData.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + double x = Double.parseDouble(pointXmlVO.getPointX()); + double y = Double.parseDouble(pointXmlVO.getPointY()); + BigDecimal size = new BigDecimal(pointXmlVO.getEdgingThickness()); + + String itemCode = pointXmlVO.getItemCode(); + if (StringUtils.isNotEmpty(itemCode)) { + // 配件编码匹配,不存在需要新增 + addSealEdgePart(orderItemDO, pointXmlVO); + } + + if (!plateDO.getIsSpecialShaped()) { + if (x == 0 && y == 0) { + sealDown = size; + } + if (x != 0 && y == 0) { + sealRight = size; + } + if (x != 0 && y != 0) { + sealUp = size; + } + if (x == 0 && y != 0) { + sealLeft = size; + } + } + + orderModelDO.getRawPointDetail().add(PointDetail.builder() + .pointX(x) + .pointY(y) + .curve(Double.parseDouble(pointXmlVO.getCurvature())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .sealSize(size) + .build()); + extraVO.getEdgeRemarks().add(pointXmlVO.getRemark()); + extraVO.getRectSealDetail().add(RectSealVO.builder() + .pointID(String.valueOf(indexId)) + .reservedEdge(pointXmlVO.getScale()) + .sealColor(pointXmlVO.getEdgingColor()) + .sealSize(pointXmlVO.getEdgingThickness()) + .build()); + indexId++; + } + } + String jsonString = JSON.toJSONString(extraVO); + JSONObject jsonObject = JSON.parseObject(jsonString); + orderModelDO.setPlateExtraRemark(jsonObject); + plateDO.setSealUp(sealUp).setSealDown(sealDown).setSealLeft(sealLeft).setSealRight(sealRight); + } + + /** + * 新增封边条配件 + * + * @param pointXmlVO + */ + private void addSealEdgePart(OrderItemDO orderItemDO, PointXmlVO pointXmlVO) { + String itemCode = pointXmlVO.getItemCode(); + OrderPartsDO orderPartsDOinMap = orderPartsDOMap.get(itemCode); + if (ObjectUtil.isNull(orderPartsDOinMap)) { + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .name(pointXmlVO.getEdgingName()) + .goodsId(itemCode) + .type("封边条") + .orderId(orderId) + .material(pointXmlVO.getEdgingMaterial()) + .unit(pointXmlVO.getCountUnit()) + .isComposite(false) + .subparts(EMPTY_STRING) + .remark(EMPTY_STRING) + .model(EMPTY_STRING) + .subparts(EMPTY_STRING) + .price(0.0) + .deleted(false) + .organId(organId) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + + // 批量插入orderParts + orderPartsDOS.add(orderPartsDO); + // 缓存配件 + orderPartsDOMap.put(itemCode, orderPartsDO); + orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, false); + + // 封边总长度单位换算 + Double count = changeUnit(pointXmlVO.getCount(), pointXmlVO.getCountUnit(), DictTypeConstants.UNIT_LENGTH); + OrderItemDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .type(OrderItemTypeEnum.PARTS_ITEM.getStatus()) + .partsId(orderPartsDO.getId()) + .groupId(orderItemDO.getGroupId()) + .roomId(orderItemDO.getRoomId()) + .bodyId(orderItemDO.getBodyId()) + .num(count) + .organId(organId) + .build(); + // 批量插入order_item + orderItemDOS.add(orderItemDO); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false); + } + } + + /** + * 处理es开料点明细 + * + * @param blockProductionCode + * @param plateDO + * @param orderModelDO + */ + private void addCuttingOutlinePointDetail(String blockProductionCode, PlateDO plateDO, OrderModelDO orderModelDO) { + // 查询CuttingOutline + List cuttingOutlineXmlVOS = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_CUTTINGOUTLINE.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (CollUtil.isNotEmpty(cuttingOutlineXmlVOS)) { + String cuttingOutlineTempDataDetail = cuttingOutlineXmlVOS.get(0).getDetail(); + if (StringUtils.isNotEmpty(cuttingOutlineTempDataDetail)) { + CuttingOutlineXmlVO cuttingOutlineXmlVO = JSON.parseObject(JsonUtils.unzipString(cuttingOutlineTempDataDetail), CuttingOutlineXmlVO.class); + plateDO.setOffsetX(BigDecimal.valueOf(Double.parseDouble(cuttingOutlineXmlVO.getReferenceOffsetX()))). + setOffsetY(BigDecimal.valueOf(Double.parseDouble(cuttingOutlineXmlVO.getReferenceOffsetY()))); + orderModelDO.setOffsetX(plateDO.getOffsetX()).setOffsetY(plateDO.getOffsetY()); + // 查询CuttingOutline.Point + List cuttingOutlineXmlPointVOS = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_CUTTINGOUTLINE_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO cuttingOutlineXmlPointVO : cuttingOutlineXmlPointVOS) { + String detail = cuttingOutlineXmlPointVO.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + orderModelDO.getPointDetail().add(PointDetail.builder() + .pointX(Double.parseDouble(pointXmlVO.getPointX())) + .pointY(Double.parseDouble(pointXmlVO.getPointY())) + .curve(Double.parseDouble(pointXmlVO.getCurvature())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .process(pointXmlVO.getProcess()) + .build()); + } + } + } + } + } + + /** + * 处理es胚料点明细 + * + * @param blockProductionCode + * @param orderModelDO + */ + private void addRawOutlinePointDetail(String blockProductionCode, OrderModelDO orderModelDO) { + // 查询RawOutline.Point + List cuttingOutlineXmlPointVOS = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_RAWOUTLINE_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO cuttingOutlineXmlPointVO : cuttingOutlineXmlPointVOS) { + String detail = cuttingOutlineXmlPointVO.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + orderModelDO.getBasePointDetail().add(PointDetail.builder() + .pointX(Double.parseDouble(pointXmlVO.getPointX())) + .pointY(Double.parseDouble(pointXmlVO.getPointY())) + .curve(Double.parseDouble(pointXmlVO.getCurvature())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .process(pointXmlVO.getProcess()) + .build()); + } + } + } + + /** + * 处理es孔数据 + * + * @param blockProductionCode + * @param plateDO + * @param orderModelDO + */ + private void addHole(String blockProductionCode, PlateDO plateDO, OrderModelDO orderModelDO) { + // 查holes对象 + List holeXmlVOSTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_HOLES.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (CollUtil.isNotEmpty(holeXmlVOSTempDataList)) { + String holeXmlVOSTempDataDetail = holeXmlVOSTempDataList.get(0).getDetail(); + if (StringUtils.isNotEmpty(holeXmlVOSTempDataDetail)) { + HoleXmlVOS holeXmlVOS = JSON.parseObject(JsonUtils.unzipString(holeXmlVOSTempDataDetail), HoleXmlVOS.class); + Map holeCountMap = new HashMap<>(); + holeCountMap.put("count", Integer.valueOf(holeXmlVOS.getCount())); + holeCountMap.put("countFaceA", Integer.valueOf(holeXmlVOS.getCountFaceA())); + holeCountMap.put("countFaceB", Integer.valueOf(holeXmlVOS.getCountFaceB())); + holeCountMap.put("countSide", Integer.valueOf(holeXmlVOS.getCountSide())); + holeCountMap.put("countSideL", Integer.valueOf(holeXmlVOS.getCountSideL())); + holeCountMap.put("countSideD", Integer.valueOf(holeXmlVOS.getCountSideD())); + holeCountMap.put("countSideR", Integer.valueOf(holeXmlVOS.getCountSideR())); + holeCountMap.put("countSideU", Integer.valueOf(holeXmlVOS.getCountSideU())); + holeCountMap.put("countBevelled", Integer.valueOf(holeXmlVOS.getCountBevelled())); + holeCountMap.put("countLocking", Integer.valueOf(holeXmlVOS.getCountLocking())); + holeCountMap.put("countBuildIn", Integer.valueOf(holeXmlVOS.getCountBuildIn())); + holeCountMap.put("countHinge", Integer.valueOf(holeXmlVOS.getCountHinge())); + holeCountMap.put("countThrough", Integer.valueOf(holeXmlVOS.getCountThrough())); + + orderModelDO.getHoleCount().putAll(holeCountMap); + plateDO.setFrontHoleCount(Integer.valueOf(holeXmlVOS.getCountFaceA())); + plateDO.setBackHoleCount(Integer.valueOf(holeXmlVOS.getCountFaceB())); + plateDO.setSideHoleCount(Integer.valueOf(holeXmlVOS.getCountSide())); + + if (holeXmlVOS.getCountThrough() != null && Integer.parseInt(holeXmlVOS.getCountThrough()) > 0) { + plateDO.setFilterType(plateDO.getFilterType() + ",2"); + } + // 查hole列表 + List holeXmlVOTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_HOLE.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO holeXmlVOTempData : holeXmlVOTempDataList) { + String detail = holeXmlVOTempData.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + HoleXmlVO holeXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), HoleXmlVO.class); + HoleDetail holeDetail = createHoleDetail(holeXmlVO); + orderModelDO.getHoleDetail().add(holeDetail); + } + } + } + } + } + + /** + * 创建孔明细对象 + * + * @param holeXmlVO + * @return + */ + private HoleDetail createHoleDetail(HoleXmlVO holeXmlVO) { + String faceType = DictFrameworkUtils.parseDictDataValue(DictTypeConstants.HOLE_FACE, holeXmlVO.getFace()); + Integer faceTypeValue = StringUtils.isNotEmpty(faceType) ? Integer.parseInt(faceType) : 2; + Integer direction = Integer.valueOf(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.HOLE_DIRECTION, holeXmlVO.getDirection())); + Double radius = holeXmlVO.getDiameter() != null ? Double.parseDouble(holeXmlVO.getDiameter()) / 2 : 0; + Double depth = holeXmlVO.getDepth() != null ? Double.parseDouble(holeXmlVO.getDepth()) : 0; + + return HoleDetail.builder() + .holeName(holeXmlVO.getName()) + .faceType(faceTypeValue) + .direction(direction) + .holeTypeStr(holeXmlVO.getType()) + .radius(radius) + .depth(depth) + .startX(holeXmlVO.getStartX() != null ? Double.parseDouble(holeXmlVO.getStartX()) : 0) + .startY(holeXmlVO.getStartY() != null ? Double.parseDouble(holeXmlVO.getStartY()) : 0) + .startZ(holeXmlVO.getStartZ() != null ? Double.parseDouble(holeXmlVO.getStartZ()) : 0) + .endX(holeXmlVO.getEndX() != null ? Double.parseDouble(holeXmlVO.getEndX()) : 0) + .endY(holeXmlVO.getEndY() != null ? Double.parseDouble(holeXmlVO.getEndY()) : 0) + .endZ(holeXmlVO.getEndZ() != null ? Double.parseDouble(holeXmlVO.getEndZ()) : 0) + .build(); + } + + /** + * 处理es造型、孤岛数据 + * + * @param blockProductionCode + * @param plateDO + * @param orderModelDO + */ + private void addContourDetail(String blockProductionCode, PlateDO plateDO, OrderModelDO orderModelDO) { + // 查grooves + List groovesXmlVOTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVES.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (CollUtil.isNotEmpty(groovesXmlVOTempDataList)) { + String groovesXMLVOSTempDataDetail = groovesXmlVOTempDataList.get(0).getDetail(); + if (StringUtils.isNotEmpty(groovesXMLVOSTempDataDetail)) { + GrooveXmlVOS grooveXmlVOS = JSON.parseObject(JsonUtils.unzipString(groovesXMLVOSTempDataDetail), GrooveXmlVOS.class); + + Map contourCount = new HashMap<>(); + contourCount.put("count", Integer.valueOf(grooveXmlVOS.getCount())); + contourCount.put("countFaceA", Integer.valueOf(grooveXmlVOS.getCountFaceA())); + contourCount.put("countFaceB", Integer.valueOf(grooveXmlVOS.getCountFaceB())); + contourCount.put("countSide", Integer.valueOf(grooveXmlVOS.getCountSide())); + contourCount.put("countSideL", Integer.valueOf(grooveXmlVOS.getCountSideL())); + contourCount.put("countSideD", Integer.valueOf(grooveXmlVOS.getCountSideD())); + contourCount.put("countSideR", Integer.valueOf(grooveXmlVOS.getCountSideR())); + contourCount.put("countSideU", Integer.valueOf(grooveXmlVOS.getCountSideU())); + contourCount.put("countBevelled", Integer.valueOf(grooveXmlVOS.getCountBevelled())); + contourCount.put("countRectangle", Integer.valueOf(grooveXmlVOS.getCountRectangle())); + contourCount.put("count2V", Integer.valueOf(grooveXmlVOS.getCount2V())); + contourCount.put("count3D", Integer.valueOf(grooveXmlVOS.getCount3D())); + contourCount.put("countThrough", Integer.valueOf(grooveXmlVOS.getCountThrough())); + + orderModelDO.getContourCount().putAll(contourCount); + orderModelDO.setHas2DModel(contourCount.getOrDefault("count2V", 0) > 0); + orderModelDO.setHas3DModel(contourCount.getOrDefault("count3D", 0) > 0); + plateDO.setFrontModelCount(Integer.valueOf(grooveXmlVOS.getCountFaceA())); + plateDO.setBackModelCount(Integer.valueOf(grooveXmlVOS.getCountFaceB())); + if (grooveXmlVOS.getCountThrough() != null && Integer.parseInt(grooveXmlVOS.getCountThrough()) > 0) { + plateDO.setFilterType(plateDO.getFilterType() + ",1"); + } + + addGrooveDetailsToPlateDetail(blockProductionCode, orderModelDO); + } + } + } + + /** + * 处理es关联配件 + * + * @param blockProductionCode + * @param orderModelDO + */ + private void addParts(String blockProductionCode, OrderModelDO orderModelDO) { + List partsInfos = new ArrayList<>(); + List correlationTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_CORRELATIONS.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO correlationTempData : correlationTempDataList) { + String correlationTempDataDetail = correlationTempData.getDetail(); + if (StringUtils.isNotEmpty(correlationTempDataDetail)) { + CorrelationXmlVO correlationXmlVO = JSON.parseObject(JsonUtils.unzipString(correlationTempDataDetail), CorrelationXmlVO.class); + String partCode = StringUtils.isNotEmpty(correlationXmlVO.getItemCode()) ? correlationXmlVO.getItemCode() : correlationXmlVO.getName() + correlationXmlVO.getColor() + correlationXmlVO.getMaterial() + correlationXmlVO.getSpecs() + + correlationXmlVO.getMaterial() + correlationXmlVO.getBrand() + correlationXmlVO.getType(); + + // 获取配件信息 + OrderPartsDO orderPartsDO = orderPartsDOMap.get(partCode); + // 板件上面添加配件信息 + if (ObjectUtil.isNotNull(orderPartsDO)) { + partsInfos.add(PartsInfo.builder() + .id(orderPartsDO.getId()) + .name(orderPartsDO.getName()) + .partNum(Double.valueOf(correlationXmlVO.getCount())) + .unit(orderPartsDO.getUnit()) + .build()); + } + } + } + orderModelDO.setPartsInfos(partsInfos); + } + + /** + * 处理es小板备注信息 + * + * @param blockProductionCode + * @param plateDO + * @param orderModelDO + */ + private void addRemark(String blockProductionCode, PlateDO plateDO, OrderModelDO orderModelDO) { + // 查grooves + List blockRemarkTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_REMKAR.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO blockRemarkTempData : blockRemarkTempDataList) { + String blockRemarkTempDataDetail = blockRemarkTempData.getDetail(); + if (StringUtils.isNotEmpty(blockRemarkTempDataDetail)) { + RemarkXmlVO remarkXmlVO = JSON.parseObject(JsonUtils.unzipString(blockRemarkTempDataDetail), RemarkXmlVO.class); + orderModelDO.getSideRemark().put(remarkXmlVO.getName(), remarkXmlVO.getInfo()); + } + } + plateDO.setRemark(JSON.toJSONString(orderModelDO.getSideRemark())); + } + + /** + * 添加造型数据明细 + * + * @param blockProductionCode + * @param orderModelDO + */ + private void addGrooveDetailsToPlateDetail(String blockProductionCode, OrderModelDO orderModelDO) { + // 查询GrooveXml + List grooveXmlVOList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE.getType()) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO grooveXmlVOTempData : grooveXmlVOList) { + String detail = grooveXmlVOTempData.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + GrooveXmlVO grooveXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), GrooveXmlVO.class); + ModelDetail modelDetail = createModelDetail(blockProductionCode, grooveXmlVO); + orderModelDO.getContourDetail().add(modelDetail); + } + } + } + + + /** + * 创建造型明细对象 + * + * @param grooveXmlVO + * @return + */ + private ModelDetail createModelDetail(String blockProductionCode, GrooveXmlVO grooveXmlVO) { + // 槽内孤岛id转换 + String[] subIDs = null; + if (grooveXmlVO.getSubIDs() != null) { + subIDs = Arrays.stream(grooveXmlVO.getSubIDs().split(",")).map(String::valueOf).toArray(String[]::new); + } + String grooveId = grooveXmlVO.getId(); + return ModelDetail.builder() + .id(Integer.valueOf(grooveXmlVO.getId())) + .subIDs(subIDs) + .type(grooveXmlVO.getType()) + .grooveFace(grooveXmlVO.getFace()) + .width(Double.parseDouble(grooveXmlVO.getWidth())) + .length(Double.parseDouble(grooveXmlVO.getLength())) + .depth(Double.parseDouble(grooveXmlVO.getDepth())) + .knifeName(grooveXmlVO.getToolName()) + .toolNo(grooveXmlVO.getToolNo()) + .knifeRadius(Double.parseDouble(grooveXmlVO.getToolDiameter()) / 2) + .round(Double.parseDouble(grooveXmlVO.getRound())) + .redundance(Double.parseDouble(grooveXmlVO.getRedundance())) + .tangentAngle(Double.parseDouble(grooveXmlVO.getTangentAngle())) + .originModeling(getOriginModelingData(blockProductionCode, grooveXmlVO, subIDs)) + .pointList(addPointDetail(blockProductionCode, grooveId)) + .offSetList(addOffSetDetail(blockProductionCode, grooveId)) + .mode(grooveXmlVO.getMode()) + .build(); + } + + // 造像轮廓数据 + + /** + * 造型轮廓数据 + * + * @param grooveXmlVO + * @param subIDs + * @return + */ + private IOriginModelingData getOriginModelingData(String blockProductionCode, GrooveXmlVO grooveXmlVO, String[] subIDs) { + // 孤岛信息 + List> holes = null; + if (ArrayUtil.isNotEmpty(subIDs)) { + holes = new ArrayList<>(); + + // 遍历subIDs + for (String subID : subIDs) { + // 获取孤岛信息 + // id查询Islet + List IsletVOTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_ISLET.getType()) + .eq(OrderImportTempDataDO::getOuterId, subID) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (CollUtil.isNotEmpty(IsletVOTempDataList)) { + List hole = getHole(blockProductionCode, subID); + holes.add(hole); + } + } + + } + return IOriginModelingData.builder() + .knifeRadius(Double.parseDouble(grooveXmlVO.getToolDiameter()) / 2) + .direction(grooveXmlVO.getDirection()) + .outline(addOutlineDetail(blockProductionCode, grooveXmlVO.getId())) + .holes(holes) + .addLen(Double.valueOf(grooveXmlVO.getLengthExtend())) + .addDepth(Double.valueOf(grooveXmlVO.getDepthExtend())) + .addWidth(Double.valueOf(grooveXmlVO.getWidthExtend())) + .build(); + } + + /** + * 原始造型(外)轮廓信息 + * + * @param blockProductionCode + * @param subId + * @return + */ + private List addOutlineDetail(String blockProductionCode, String subId) { + List iContourDataList = new ArrayList<>(); + List grooveOutLinePointXmlVOList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_OUTLINE_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, subId) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO tempDataDO : grooveOutLinePointXmlVOList) { + String detail = tempDataDO.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + iContourDataList.add(IContourData.builder() + .pts(new Point(Double.parseDouble(pointXmlVO.getPointX()), Double.parseDouble(pointXmlVO.getPointY()), Double.parseDouble(pointXmlVO.getPointZ()))) + .buls(Double.parseDouble(pointXmlVO.getCurvature())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .build()); + } + } + return iContourDataList; + } + + /** + * 孤岛点信息 + * + * @param blockProductionCode + * @param subID + * @return + */ + private List getHole(String blockProductionCode, String subID) { + List iContourDataList = new ArrayList<>(); + List IsletPointVOTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_ISLET_POINTS_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, subID) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO tempDataDO : IsletPointVOTempDataList) { + String detail = tempDataDO.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + iContourDataList.add(IContourData.builder() + .pts(new Point(Double.parseDouble(pointXmlVO.getPointX()), Double.parseDouble(pointXmlVO.getPointY()), Double.parseDouble(pointXmlVO.getPointZ()))) + .buls(Double.parseDouble(pointXmlVO.getCurvature())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .build()); + } + } + return iContourDataList; + } + + private List addPointDetail(String blockProductionCode, String subId) { + List pointLists = new ArrayList<>(); + // 查询GrooveXml + List grooveXmlPointVOList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_POINTS_POINT.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, subId) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO grooveXmlPointVOTempData : grooveXmlPointVOList) { + String detail = grooveXmlPointVOTempData.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + PointXmlVO pointXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), PointXmlVO.class); + pointLists.add(PointList.builder() + .pointX(Double.parseDouble(pointXmlVO.getPointX())) + .pointY(Double.parseDouble(pointXmlVO.getPointY())) + .pointZ(Double.parseDouble(pointXmlVO.getPointZ())) + .radius(Double.parseDouble(pointXmlVO.getRadius())) + .holeRadius(Double.parseDouble(pointXmlVO.getRadius())) + .build()); + } + } + return pointLists; + } + + // 偏移量列表 + private List addOffSetDetail(String blockProductionCode, String subId) { + List offSetList = new ArrayList<>(); + // 查询GrooveXml + List offsetLineXmlTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.BLOCK_GROOVE_OFFSETLINE.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, subId) + .eq(OrderImportTempDataDO::getOuterGoodsId, blockProductionCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + for (OrderImportTempDataDO offsetLineXmlTempData : offsetLineXmlTempDataList) { + String detail = offsetLineXmlTempData.getDetail(); + if (StringUtils.isNotEmpty(detail)) { + OffsetLineXmlVO offsetLineXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), OffsetLineXmlVO.class); + offSetList.add(OffSetList.builder() + .value(Double.parseDouble(offsetLineXmlVO.getOffset())) + .depth(Double.parseDouble(offsetLineXmlVO.getDepth())) + .angle(Double.parseDouble(offsetLineXmlVO.getTangentAngle())) + .name(offsetLineXmlVO.getToolName()) + .radius(Double.parseDouble(offsetLineXmlVO.getToolDiameter()) / 2) + .build()); + } + } + return offSetList; + } + + /** + * 解析配件列表 + */ + private void analyzeParts() { + // 查询配件itemCode分组 + OrderImportTempDataReqVO partItemCodeGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).build(); + List partItemCodeGroupList = orderImportTempDataMapper.selectPartItemCodeGroup(partItemCodeGroupReqVO); + for (OrderImportTempDataPartItemCodeGroupDO itemCodeGroupDO : partItemCodeGroupList) { + int type = itemCodeGroupDO.getType(); + if (PART_EDGING_TYPE == type) { + createEdging(itemCodeGroupDO); + } + if (PART_HARDWARE_TYPE == type) { + createHardware(itemCodeGroupDO); + } + if (PART_ASSEMBLY_TYPE == type) { + createAssembly(itemCodeGroupDO); + } + } + // 最后批量插入一次,避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入 + orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, true); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, true); + // 批量插入配件备注 + orderPartsRemarksBatchInsertWithinThreshold(true); + } + + /** + * 创建封边条配件 + * + * @param itemCodeGroupDO + */ + private void createEdging(OrderImportTempDataPartItemCodeGroupDO itemCodeGroupDO) { + String itemCode = itemCodeGroupDO.getItemCode(); + // 查询itemcode所属edging + OrderImportTempDataDO edgingTempData = orderImportTempDataMapper.selectOne(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_EDGING.getType()) + .eq(OrderImportTempDataDO::getOuterId, itemCode) + .eq(OrderImportTempDataDO::getSort, itemCodeGroupDO.getSortn()) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (ObjectUtil.isNull(edgingTempData)) { + return; + } + Long partId = (Long) snowFlakeGenerator.nextId(null); + EdgingXmlVO edgingXmlVO = JSON.parseObject(JsonUtils.unzipString(edgingTempData.getDetail()), EdgingXmlVO.class); + + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id(partId) + .orderId(orderId) + .goodsId(edgingXmlVO.getItemCode()) + .name(edgingXmlVO.getName()) + .color(edgingXmlVO.getColor()) + .material(edgingXmlVO.getMaterial()) + .category("封边条") + .type("封边条") + .width(Double.valueOf(edgingXmlVO.getWidth())) + .length(Double.valueOf(edgingXmlVO.getLength())) + .thickness(Double.valueOf(edgingXmlVO.getThickness())) + .brand(edgingXmlVO.getBrand()) + .factory(edgingXmlVO.getManufacturer()) + .spec(edgingXmlVO.getSpecs()) + .unit(edgingXmlVO.getUnit()) + .isComposite(false) + .subparts(EMPTY_STRING) + .remark(EMPTY_STRING) + .model(EMPTY_STRING) + .subparts(EMPTY_STRING) + .price(0.0) + .deleted(false) + .organId(organId) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + + // 查询itemCode下的房间、柜体、加工组分组和数量 + OrderImportTempDataReqVO partItemCodeGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(OrderImportTmpDataTypeEnum.PART_EDGING.getType()).outerId(itemCode).build(); + List partRoomBodyGroupGroupDOS = orderImportTempDataMapper.selectPartRoomBodyGroupGroup(partItemCodeGroupReqVO); + for (OrderImportTempDataPartRoomBodyGroupGroupDO partRoomBodyGroupGroupDO : partRoomBodyGroupGroupDOS) { + // 获取房间柜体缓存 + String roomCode = edgingXmlVO.getRoomCode(); + String bodyCode = edgingXmlVO.getBoxCode(); + + Map roomTempDataMap = roomBodyMap.get(roomCode); + OrderImportTempDataDO roomBodyTempDataDO = null; + if (MapUtil.isNotEmpty(roomTempDataMap)) { + roomBodyTempDataDO = roomTempDataMap.get(bodyCode); + } + + // 获取加工组缓存 + String groupCode = partRoomBodyGroupGroupDO.getGroupCode(); + OrderImportTempDataDO groupTempDataDO = groupMap.get(groupCode); + // 柜体id回显到加工组 + if (ObjectUtil.isNotNull(groupTempDataDO) && ObjectUtil.isNull(groupTempDataDO.getInnerBodyId()) && ObjectUtil.isNotNull(roomBodyTempDataDO)) { + groupTempDataDO.setInnerBodyId(roomBodyTempDataDO.getInnerBodyId()); + } + + OrderItemDO orderItemDO = OrderItemDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .organId(organId) + .orderId(orderId) + .type(OrderItemTypeEnum.PARTS_ITEM.getStatus()) + .partsId(partId) + .groupId(ObjectUtil.isNotNull(groupTempDataDO) ? groupTempDataDO.getInnerGroupId() : 0L) + .roomId(roomBodyTempDataDO.getInnerRoomId()) + .bodyId(roomBodyTempDataDO.getInnerBodyId()) + .num(NumberUtil.toDouble(partRoomBodyGroupGroupDO.getPartsNum())) + .packageId(0L) + .plateId(0L) + .build(); + // 批量插入order_item + orderItemDOS.add(orderItemDO); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false); + } + + // 查询配件备注 + List partRemarkTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_REMARK.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, edgingXmlVO.getItemCode()) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + List partRemarkXmlVOList = new ArrayList<>(); + for (OrderImportTempDataDO partRemarkXmlTempData : partRemarkTempDataList) { + String partRemarkDetail = partRemarkXmlTempData.getDetail(); + if (StringUtils.isNotEmpty(partRemarkDetail)) { + partRemarkXmlVOList.add(JSON.parseObject(JsonUtils.unzipString(partRemarkDetail), RemarkXmlVO.class)); + } + } + // 记录备注到order_parts + String partRemark = getRemark(partRemarkXmlVOList); + orderPartsDO.setRemark(partRemark); + + // 解析配件商品 + analyzePartsGoods(orderPartsDO); + // 批量插入orderParts + orderPartsDOS.add(orderPartsDO); + // 缓存配件 + orderPartsDOMap.put(itemCode, orderPartsDO); + orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, false); + // 批量插入配件备注 + orderPartsRemarks.add(OrderPartsRemark.builder() + .partsId(partId) + .orderId(orderId) + .remark(partRemarkXmlVOList.toString()) + .build()); + orderPartsRemarksBatchInsertWithinThreshold(false); + } + + /** + * 创建五金配件 + * + * @param itemCodeGroupDO + */ + private void createHardware(OrderImportTempDataPartItemCodeGroupDO itemCodeGroupDO) { + String itemCode = itemCodeGroupDO.getItemCode(); + // 查询itemcode所属edging + OrderImportTempDataDO hardwareTempData = orderImportTempDataMapper.selectOne(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_HARDWARE.getType()) + .eq(OrderImportTempDataDO::getOuterId, itemCode) + .eq(OrderImportTempDataDO::getSort, itemCodeGroupDO.getSortn()) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (ObjectUtil.isNull(hardwareTempData)) { + return; + } + + Long partId = (Long) snowFlakeGenerator.nextId(null); + HardwareXmlVO hardwareXmlVO = JSON.parseObject(JsonUtils.unzipString(hardwareTempData.getDetail()), HardwareXmlVO.class); + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id(partId) + .orderId(orderId) + .goodsId(hardwareXmlVO.getItemCode()) + .name(hardwareXmlVO.getName()) + .color(hardwareXmlVO.getColor()) + .material(hardwareXmlVO.getMaterial()) + .category("五金") + .type(hardwareXmlVO.getType()) + .width(Double.valueOf(hardwareXmlVO.getWidth())) + .length(Double.valueOf(hardwareXmlVO.getLength())) + .thickness(Double.valueOf(hardwareXmlVO.getThickness())) + .brand(hardwareXmlVO.getBrand()) + .factory(hardwareXmlVO.getManufacturer()) + .spec(hardwareXmlVO.getSpecs()) + .unit(hardwareXmlVO.getUnit()) + .isComposite(false) + .subparts(hardwareXmlVO.getSubCodes()) + .remark(EMPTY_STRING) + .model(EMPTY_STRING) + .subparts(EMPTY_STRING) + .price(0.0) + .deleted(false) + .organId(organId) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + + // 查询itemCode下的房间、柜体、加工组分组和数量 + OrderImportTempDataReqVO partItemCodeGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(OrderImportTmpDataTypeEnum.PART_HARDWARE.getType()).outerId(itemCode).build(); + List partRoomBodyGroupGroupDOS = orderImportTempDataMapper.selectPartRoomBodyGroupGroup(partItemCodeGroupReqVO); + for (OrderImportTempDataPartRoomBodyGroupGroupDO partRoomBodyGroupGroupDO : partRoomBodyGroupGroupDOS) { + // 获取房间柜体缓存 + String roomCode = hardwareXmlVO.getRoomCode(); + String bodyCode = hardwareXmlVO.getBoxCode(); + + Map roomTempDataMap = roomBodyMap.get(roomCode); + OrderImportTempDataDO roomBodyTempDataDO = null; + if (MapUtil.isNotEmpty(roomTempDataMap)) { + roomBodyTempDataDO = roomTempDataMap.get(bodyCode); + } + + // 获取加工组缓存 + String groupCode = partRoomBodyGroupGroupDO.getGroupCode(); + OrderImportTempDataDO groupTempDataDO = groupMap.get(groupCode); + // 柜体id回显到加工组 + if (ObjectUtil.isNotNull(groupTempDataDO) && ObjectUtil.isNull(groupTempDataDO.getInnerBodyId()) && ObjectUtil.isNotNull(roomBodyTempDataDO)) { + groupTempDataDO.setInnerBodyId(roomBodyTempDataDO.getInnerBodyId()); + } + + OrderItemDO orderItemDO = OrderItemDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .organId(organId) + .orderId(orderId) + .type(OrderItemTypeEnum.PARTS_ITEM.getStatus()) + .partsId(partId) + .groupId(ObjectUtil.isNotNull(groupTempDataDO) ? groupTempDataDO.getInnerGroupId() : 0L) + .roomId(roomBodyTempDataDO.getInnerRoomId()) + .bodyId(roomBodyTempDataDO.getInnerBodyId()) + .num(NumberUtil.toDouble(partRoomBodyGroupGroupDO.getPartsNum())) + .packageId(0L) + .plateId(0L) + .build(); + // 批量插入order_item + orderItemDOS.add(orderItemDO); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false); + } + + // 查询配件备注 + List partRemarkTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_REMARK.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, itemCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + List partRemarkXmlVOList = new ArrayList<>(); + for (OrderImportTempDataDO partRemarkXmlTempData : partRemarkTempDataList) { + String partRemarkDetail = partRemarkXmlTempData.getDetail(); + if (StringUtils.isNotEmpty(partRemarkDetail)) { + partRemarkXmlVOList.add(JSON.parseObject(JsonUtils.unzipString(partRemarkDetail), RemarkXmlVO.class)); + } + } + // 记录备注到order_parts + String partRemark = getRemark(partRemarkXmlVOList); + orderPartsDO.setRemark(partRemark); + + // 解析配件商品 + analyzePartsGoods(orderPartsDO); + // 批量插入orderParts + orderPartsDOS.add(orderPartsDO); + // 缓存配件 + orderPartsDOMap.put(itemCode, orderPartsDO); + orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, false); + // 批量插入配件备注 + orderPartsRemarks.add(OrderPartsRemark.builder() + .partsId(partId) + .orderId(orderId) + .remark(partRemarkXmlVOList.toString()) + .build()); + orderPartsRemarksBatchInsertWithinThreshold(false); + } + + /** + * 创建组件配件 + * + * @param itemCodeGroupDO + */ + private void createAssembly(OrderImportTempDataPartItemCodeGroupDO itemCodeGroupDO) { + String itemCode = itemCodeGroupDO.getItemCode(); + // 查询itemcode所属edging + OrderImportTempDataDO assemblyTempData = orderImportTempDataMapper.selectOne(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_HARDWARE.getType()) + .eq(OrderImportTempDataDO::getOuterId, itemCode) + .eq(OrderImportTempDataDO::getSort, itemCodeGroupDO.getSortn()) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + if (ObjectUtil.isNull(assemblyTempData)) { + return; + } + Long partId = (Long) snowFlakeGenerator.nextId(null); + AssemblyXmlVO assemblyXmlVO = JSON.parseObject(JsonUtils.unzipString(assemblyTempData.getDetail()), AssemblyXmlVO.class); + OrderPartsDO orderPartsDO = OrderPartsDO.builder() + .id(partId) + .orderId(orderId) + .goodsId(assemblyXmlVO.getItemCode()) + .name(assemblyXmlVO.getName()) + .color(assemblyXmlVO.getColor()) + .material(assemblyXmlVO.getMaterial()) + .category("组件") + .type(assemblyXmlVO.getType()) + .width(Double.valueOf(assemblyXmlVO.getWidth())) + .length(Double.valueOf(assemblyXmlVO.getLength())) + .thickness(Double.valueOf(assemblyXmlVO.getHeight())) + .brand(assemblyXmlVO.getBrand()) + .factory(assemblyXmlVO.getManufacturer()) + .spec(assemblyXmlVO.getSpecs()) + .unit(assemblyXmlVO.getUnit()) + .isComposite(true) + .subparts(assemblyXmlVO.getSubCodes()) + .remark(EMPTY_STRING) + .model(EMPTY_STRING) + .subparts(EMPTY_STRING) + .price(0.0) + .deleted(false) + .organId(organId) + .build(); + orderPartsDO.setCreator(operatorName); + orderPartsDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderPartsDO.setCreateTime(now); + orderPartsDO.setUpdateTime(now); + + // 查询itemCode下的房间、柜体、加工组分组和数量 + OrderImportTempDataReqVO partItemCodeGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(OrderImportTmpDataTypeEnum.PART_ASSEMBLY.getType()).outerId(itemCode).build(); + List partRoomBodyGroupGroupDOS = orderImportTempDataMapper.selectPartRoomBodyGroupGroup(partItemCodeGroupReqVO); + for (OrderImportTempDataPartRoomBodyGroupGroupDO partRoomBodyGroupGroupDO : partRoomBodyGroupGroupDOS) { + // 获取房间柜体缓存 + String roomCode = assemblyXmlVO.getRoomCode(); + String bodyCode = assemblyXmlVO.getBoxCode(); + + Map roomTempDataMap = roomBodyMap.get(roomCode); + OrderImportTempDataDO roomBodyTempDataDO = null; + if (MapUtil.isNotEmpty(roomTempDataMap)) { + roomBodyTempDataDO = roomTempDataMap.get(bodyCode); + } + + // 获取加工组缓存 + String groupCode = partRoomBodyGroupGroupDO.getGroupCode(); + OrderImportTempDataDO groupTempDataDO = groupMap.get(groupCode); + // 柜体id回显到加工组 + if (ObjectUtil.isNotNull(groupTempDataDO) && ObjectUtil.isNull(groupTempDataDO.getInnerBodyId()) && ObjectUtil.isNotNull(roomBodyTempDataDO)) { + groupTempDataDO.setInnerBodyId(roomBodyTempDataDO.getInnerBodyId()); + } + + OrderItemDO orderItemDO = OrderItemDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .organId(organId) + .orderId(orderId) + .type(OrderItemTypeEnum.PARTS_ITEM.getStatus()) + .partsId(partId) + .groupId(ObjectUtil.isNotNull(groupTempDataDO) ? groupTempDataDO.getInnerGroupId() : 0L) + .roomId(roomBodyTempDataDO.getInnerRoomId()) + .bodyId(roomBodyTempDataDO.getInnerBodyId()) + .num(NumberUtil.toDouble(partRoomBodyGroupGroupDO.getPartsNum())) + .packageId(0L) + .plateId(0L) + .build(); + // 批量插入order_item + orderItemDOS.add(orderItemDO); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false); + } + + // 查询配件备注 + List partRemarkTempDataList = orderImportTempDataMapper.selectList(new LambdaQueryWrapper() + .eq(OrderImportTempDataDO::getTaskId, taskId) + .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.PART_REMARK.getType()) + .eq(OrderImportTempDataDO::getOuterSubId, itemCode) + .eq(OrderImportTempDataDO::getOrganId, organId) + ); + List partRemarkXmlVOList = new ArrayList<>(); + for (OrderImportTempDataDO partRemarkXmlTempData : partRemarkTempDataList) { + String partRemarkDetail = partRemarkXmlTempData.getDetail(); + if (StringUtils.isNotEmpty(partRemarkDetail)) { + partRemarkXmlVOList.add(JSON.parseObject(JsonUtils.unzipString(partRemarkDetail), RemarkXmlVO.class)); + } + } + // 记录备注到order_parts + String partRemark = getRemark(partRemarkXmlVOList); + orderPartsDO.setRemark(partRemark); + + // 解析配件商品 + analyzePartsGoods(orderPartsDO); + // 批量插入orderParts + orderPartsDOS.add(orderPartsDO); + // 缓存配件 + orderPartsDOMap.put(itemCode, orderPartsDO); + orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, false); + // 批量插入配件备注 + orderPartsRemarks.add(OrderPartsRemark.builder() + .partsId(partId) + .orderId(orderId) + .remark(partRemarkXmlVOList.toString()) + .build()); + orderPartsRemarksBatchInsertWithinThreshold(false); + } + + private void writeBackToOrders() { + // 回显柜体id到加工组 + for (Map.Entry groupEntry : groupMap.entrySet()) { + OrderImportTempDataDO groupTempData = groupEntry.getValue(); + Long innerBodyId = groupTempData.getInnerBodyId(); + if (ObjectUtils.isNotNull(innerBodyId)) { + orderGroupMapper.update(new LambdaUpdateWrapper() + .eq(OrderGroupDO::getId, groupTempData.getInnerGroupId()) + .eq(OrderGroupDO::getOrganId, organId) + .set(OrderGroupDO::getBodyId, innerBodyId) + .set(OrderGroupDO::getGroupTypeId, innerBodyId) + ); + } + } + // 回显板件数、异形数到柜体 + for (Map.Entry> bodyEntry : roomBodyMap.entrySet()) { + Map bodyTempDataMap = bodyEntry.getValue(); + for (Map.Entry bodyTempDataEntry : bodyTempDataMap.entrySet()) { + OrderImportTempDataDO bodyTempData = bodyTempDataEntry.getValue(); + int plateNum = bodyTempData.getPlateNum(); + int unregularNum = bodyTempData.getUnregularNum(); + if (plateNum > 0 || unregularNum > 0) { + orderBodyMapper.update(new LambdaUpdateWrapper() + .eq(OrderBodyDO::getId, bodyTempData.getInnerBodyId()) + .eq(OrderBodyDO::getOrganId, organId) + .set(OrderBodyDO::getPlateNum, plateNum + unregularNum) + .set(OrderBodyDO::getUnregularNum, unregularNum) + ); + } + } + } + } + + /** + * 创建生产单柜体orderBody + * + * @param groupDO + * @return + */ + private OrderBodyDO createOrderBodyDO(OrderImportTempDataDO groupDO) { + Long innerRoomId = groupDO.getInnerRoomId(); + Long bodyId = (Long) snowFlakeGenerator.nextId(null); + Long roomId = (Long) snowFlakeGenerator.nextId(null); + String detail = groupDO.getDetail(); + RoomBoxXmlVO roomBoxXmlVO = new RoomBoxXmlVO(); + if (StringUtils.isNotEmpty(detail)) { + roomBoxXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), RoomBoxXmlVO.class); + groupDO.setRoomPosition(BasePosition.builder() + .basePoint(String.valueOf(roomId)) + .basePointX(Double.valueOf(roomBoxXmlVO.getRoomBasePointX())) + .basePointY(Double.valueOf(roomBoxXmlVO.getRoomBasePointY())) + .basePointZ(Double.valueOf(roomBoxXmlVO.getRoomBasePointZ())) + .axisXrotate(Double.valueOf(roomBoxXmlVO.getRoomAxisXrotate())) + .axisYrotate(Double.valueOf(roomBoxXmlVO.getRoomAxisYrotate())) + .axisZrotate(Double.valueOf(roomBoxXmlVO.getRoomAxisZrotate())) + .build()); + + groupDO.setBodyPosition(BasePosition.builder() + .basePoint(String.valueOf(bodyId)) + .basePointX(Double.valueOf(roomBoxXmlVO.getBasePointX())) + .basePointY(Double.valueOf(roomBoxXmlVO.getBasePointY())) + .basePointZ(Double.valueOf(roomBoxXmlVO.getBasePointZ())) + .axisXrotate(Double.valueOf(roomBoxXmlVO.getAxisXrotate())) + .axisYrotate(Double.valueOf(roomBoxXmlVO.getAxisYrotate())) + .axisZrotate(Double.valueOf(roomBoxXmlVO.getAxisZrotate())) + .build()); + } + OrderBodyDO orderBodyDO = OrderBodyDO.builder() + .id(bodyId) + .orderId(orderId) + .roomId(ObjectUtil.isNotNull(innerRoomId) ? innerRoomId : roomId) + .roomName(groupDO.getRoomName()) + .name(groupDO.getBodyName()) + .width(NumberUtil.parseDouble(roomBoxXmlVO.getWidth())) + .height(NumberUtil.parseDouble(roomBoxXmlVO.getHeight())) + .depth(NumberUtil.parseDouble(roomBoxXmlVO.getLength())) + .multiNum(0) + .unregularNum(0) + .filename("无") + .remark("无") + .organId(organId) + .plateNum(0) + .deleted(false) + .build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); + return orderBodyDO; + } + + /** + * 创建生产单加工组orderGroup + * + * @param groupDO + * @return + */ + private OrderGroupDO createOrderGroupDO(OrderImportTempDataDO groupDO) { + String detail = groupDO.getDetail(); + GroupXmlVO groupXmlVO = new GroupXmlVO(); + if (StringUtils.isNotEmpty(detail)) { + groupXmlVO = JSON.parseObject(JsonUtils.unzipString(detail), GroupXmlVO.class); + } + OrderGroupDO orderGroupDO = OrderGroupDO.builder() + .id((Long) snowFlakeGenerator.nextId(null)) + .orderId(orderId) + .organId(organId) + .bodyId(0L) + .groupTypeId(0L) + .groupTypeName(NOT_ASSIGNED) + .name(groupDO.getGroupName()) + .width(NumberUtil.parseDouble(groupXmlVO.getWidth())) + .height(NumberUtil.parseDouble(groupXmlVO.getHeight())) + .depth(NumberUtil.parseDouble(groupXmlVO.getLength())) + .multiNum(0) + .plateNum(0) + .unregularNum(0) + .filename("无") + .remark("无") + .deleted(false) + .build(); + orderGroupDO.setCreator(operatorName); + orderGroupDO.setUpdater(operatorName); + LocalDateTime now = LocalDateTime.now(); + orderGroupDO.setCreateTime(now); + orderGroupDO.setUpdateTime(now); + return orderGroupDO; + } + + /** + * 每达到阈值就批量插入一次 + * + * @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(); + } + } + } + + /** + * 每达到阈值就批量插入一次生产单造型数据和压缩数据 + * + * @param isLast 是否最后一次插入,不是就需要清理list + */ + private void orderModelsBatchInsertWithinThreshold(boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(orderModelDOS) && (orderModelDOS.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + // 保存生产单造型数据 + orderInputProcessor.batchSaveModel(orderModelDOS); + if (!isLast) { + // 存储完成清理 list + orderModelDOS.clear(); + } + } + } + + /** + * 每达到阈值就批量插入一次生产单造型数据和压缩数据 + * + * @param isLast 是否最后一次插入,不是就需要清理list + */ + private void orderPartsRemarksBatchInsertWithinThreshold(boolean isLast) { + // 达到批量的阈值就做一次插入 + if (CollUtil.isNotEmpty(orderPartsRemarks) && (orderPartsRemarks.size() >= BATCH_THRESHOLD_NUMBER || isLast)) { + orderInputProcessor.batchSaveOrderPartsModel(orderPartsRemarks); + if (!isLast) { + // 存储完成清理 list + orderPartsRemarks = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER); + } + } + } + + /** + * 长度面积数值按单位转换 + * + * @param lengthStr + * @param unit + * @param type + * @return + */ + public Double changeUnit(String lengthStr, String unit, String type) { + String dictData = DictFrameworkUtils.parseDictDataValue(type, unit); + Double length = Double.parseDouble(lengthStr); + return length * Double.parseDouble(dictData); + } + + /** + * 是否转换布尔值 + * + * @param str + * @return + */ + public Boolean convertToBoolean(String str) { + Boolean isTrue; + switch (str) { + case "是": + isTrue = true; + break; + default: + isTrue = false; + break; + } + return isTrue; + } + + /** + * 备注信息提取,判断长度是否超过255,超过255则截取255,并保存在备注中 + * + * @param finalRemarkXmlVOS + * @return + */ + private String getRemark(List finalRemarkXmlVOS) { + StringBuilder sb = new StringBuilder(); + for (RemarkXmlVO remarkXmlVO : finalRemarkXmlVOS) { + String info = remarkXmlVO.getInfo(); + if (info.length() > 255) { + info = info.substring(0, 255); + } + sb.append(info); + } + return sb.toString(); + } + + /** + * 解析大板 + * 大板库没有新增,有就赋值goodsId + * + * @param goodsDO + */ + private void analyzePlateGoods(GoodsDO goodsDO) { + PlateGoodDO plateGoodDO = null; + List existPlateGoodDOS = new ArrayList<>(); + if (StringUtils.isNotEmpty(goodsDO.getGoodsId())) { + // goodsId查询是否存在大板 + plateGoodDO = getPlateGood(goodsDO.getGoodsId()); + } else { + // 没有goodsId,大板属性匹配大板 + existPlateGoodDOS = plateGoodMapper.selectList(new LambdaQueryWrapperX() + .eq(PlateGoodDO::getGoodsName, goodsDO.getGoodsName()) + .eq(PlateGoodDO::getMaterial, goodsDO.getMaterial()) + .eq(PlateGoodDO::getColor, goodsDO.getColor()) + .eqIfPresent(PlateGoodDO::getTexture, goodsDO.getTexture()) + .eqIfPresent(PlateGoodDO::getWidth, goodsDO.getWidth()) + .eqIfPresent(PlateGoodDO::getHeight, goodsDO.getHeight()) + .eq(PlateGoodDO::getThickness, goodsDO.getThickness()) + .eqIfPresent(PlateGoodDO::getSpec, goodsDO.getSpec()) + .eq(PlateGoodDO::getDeleted, 0) + .eq(PlateGoodDO::getOrganId, organId)); + } + + if (CollUtil.isNotEmpty(existPlateGoodDOS)) { + // 存在大板 + goodsDO.setGoodsId(existPlateGoodDOS.get(0).getGoodsId()); + } else if (plateGoodDO != null) { + // 存在大板 + goodsDO.setGoodsId(plateGoodDO.getGoodsId()); + } else { + // 不存在大板,新增 + long plateNo = idWorker.nextId(); + long obtainingTime = idWorker.obtainingTime(); + + // 大板id设置到orderGoodsDO + String goodsId = StringUtils.isEmpty(goodsDO.getGoodsId()) ? (obtainingTime) + Long.toString(plateNo).substring(2) : goodsDO.getGoodsId(); + goodsDO.setGoodsId(goodsId); + + plateGoodDO = BeanUtils.toBean(goodsDO, PlateGoodDO.class) + .setId((Long) snowFlakeGenerator.nextId(null)) + .setGoodsId(goodsId); + + // 批量插入plategood + plateGoodDOS.add(plateGoodDO); + orderInfoBatchInsertWithinThreshold(plateGoodMapper, plateGoodDOS, false); + } + } + + /** + * 查询大板信息 + * + * @param goodsId + * @return + */ + private PlateGoodDO getPlateGood(String goodsId) { + List plateGoodDOs = plateGoodMapper.selectGoodOne(goodsId, organId); + if (!plateGoodDOs.isEmpty()) { + return plateGoodDOs.get(0); + } + return null; + } + + /** + * 解析配件 + * 配件库没有新增,有就赋值goodsId + * + * @param partsDO + * @return + */ + private void analyzePartsGoods(OrderPartsDO partsDO) { + if (partsDO.getGoodsId() != null && !partsDO.getGoodsId().isEmpty()) { // 有goodsId + PartsDO parts = partsMapper.selectByGoodID(partsDO.getGoodsId(), OrganContextHolder.getOrganId()); + if (ObjectUtil.isNull(parts)) { // 不存在记录,存入数据库 + // 批量插入parts + partsDOS.add(BeanUtils.toBean(partsDO, PartsDO.class).setOrganId(organId)); + orderInfoBatchInsertWithinThreshold(partsMapper, partsDOS, false); + } + } + } + + /** + * 清空所有列表 + */ + private void clearAll() { + rawGoodsDOS.clear(); + goodsDOS.clear(); + orderPartsDOS.clear(); + orderBodyDOS.clear(); + orderGroupDOS.clear(); + plateDOS.clear(); + orderItemDOS.clear(); + plateGoodDOS.clear(); + orderModelDOS.clear(); + orderPartsRemarks.clear(); + partsDOS.clear(); + } + + /** + * 移除taskId下所有临时数据 + */ + private void deleteTempData() { + orderImportTempDataMapper.delete(new LambdaQueryWrapper().eq(OrderImportTempDataDO::getTaskId, taskId)); + } + + /** + * 更新为导入成功 + */ + private void updateTaskSuccess() { + 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/resources/mapper/orderImport/OrderImportTempDataMapper.xml b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/mapper/orderImport/OrderImportTempDataMapper.xml index 64d3ce32b..67594d1f5 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/mapper/orderImport/OrderImportTempDataMapper.xml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/mapper/orderImport/OrderImportTempDataMapper.xml @@ -249,4 +249,19 @@ from order_import_temp_data where task_id = #{reqVO.taskId} and type = '${@com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum@PART.type}' and inner_goods_id = #{reqVO.goodsId} + + + + \ No newline at end of file