excel、xml异步导入调整:同步板材库匹配逻辑

This commit is contained in:
gaoqr
2025-04-17 16:39:56 +08:00
parent 71f939168a
commit b3bb0fff73
10 changed files with 271 additions and 254 deletions
@@ -97,6 +97,7 @@ public class ErrorCodeConstants {
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, "导入校验异常:板件{}下柜体编码{}不存在于柜体编码列表中");
public static final ErrorCode ORDER_IMPORT_PLATEGOODS_NOT_EXIST_VALID_ERROR = new ErrorCode(1_002_031_016, "导入校验异常:第{}行的板材不存在,请确保板材管理中存在对应商品编号或商品(名称+材质+颜色+厚度+品牌)组合的板材后导入");
// ========== manage板材/配件 1_004_001_000 ==========
public static final ErrorCode PARTS_NOT_EXISTS = new ErrorCode(1_004_001_000, "配件不存在");
@@ -11,6 +11,7 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderImportAs
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.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTypeEnum;
@@ -67,6 +68,9 @@ public class DefaultExcelOrderImportHandler implements AbstractExcelOrderImportH
@Resource
private ChenfengCacheProperties chenfengCacheProperties;
@Resource
private PlateGoodMapper plateGoodMapper;
@Override
public String getFactoryName() {
return "default";
@@ -84,7 +88,7 @@ public class DefaultExcelOrderImportHandler implements AbstractExcelOrderImportH
throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR);
}
DefaultOrderImportExcelListener excelListener =
new DefaultOrderImportExcelListener(orderImportTempDataMapper, orderService, dictDataApi, snowFlakeGenerator, importAsyncReqVO.getOrderId(), taskId);
new DefaultOrderImportExcelListener(orderImportTempDataMapper, orderService, dictDataApi, snowFlakeGenerator, plateGoodMapper, importAsyncReqVO.getOrderId(), taskId);
try (InputStream inputStream = file.getInputStream()) {
// 读取excel
@@ -10,6 +10,7 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderImportAs
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.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTypeEnum;
@@ -58,6 +59,9 @@ public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandl
@Resource
private ChenfengCacheProperties chenfengCacheProperties;
@Resource
private PlateGoodMapper plateGoodMapper;
@Override
public String getFactoryName() {
return "default";
@@ -74,7 +78,7 @@ public class DefaultXmlOrderImportHandler implements AbstractXmlOrderImportHandl
throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR);
}
try {
DefaultOrderImportXmlParserHandler defaultOrderImportXmlParserHandler = new DefaultOrderImportXmlParserHandler(orderImportTempDataMapper, orderService, snowFlakeGenerator, importAsyncReqVO.getOrderId(), taskId);
DefaultOrderImportXmlParserHandler defaultOrderImportXmlParserHandler = new DefaultOrderImportXmlParserHandler(orderImportTempDataMapper, orderService, snowFlakeGenerator, plateGoodMapper, importAsyncReqVO.getOrderId(), taskId);
defaultOrderImportXmlParserHandler.analyzeFile(file);
} catch (ServiceException sev) {
// 导入锁解锁
@@ -1,5 +1,6 @@
package com.cf.imes.module.executor.util.fileConversion.admin.files.excel;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
@@ -16,7 +17,9 @@ 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.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.executor.dal.mysql.orderImport.OrderImportTempDataMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.enums.CategoryEnum;
import com.cf.imes.module.executor.enums.DataTypeEnum;
import com.cf.imes.module.executor.enums.DictTypeConstants;
@@ -27,12 +30,15 @@ import com.cf.imes.module.executor.enums.OrderStatusEnum;
import com.cf.imes.module.executor.enums.QuarrelEnum;
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.PlateXmlVO;
import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.xml.stream.Location;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -47,6 +53,7 @@ import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_
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_PLATEGOODS_NOT_EXIST_VALID_ERROR;
/**
* 默认生产单excel导入监听器
@@ -80,6 +87,8 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener
private SnowFlakeGenerator snowFlakeGenerator;
private PlateGoodMapper plateGoodMapper;
/**
* 补板用
*/
@@ -111,11 +120,12 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener
private static final String EMPTY_STRING = new String();
public DefaultOrderImportExcelListener(OrderImportTempDataMapper orderImportTempDataMapper, OrderService orderService, DictDataApi dictDataApi, SnowFlakeGenerator snowFlakeGenerator, Long orderId, Long taskId) {
public DefaultOrderImportExcelListener(OrderImportTempDataMapper orderImportTempDataMapper, OrderService orderService, DictDataApi dictDataApi, SnowFlakeGenerator snowFlakeGenerator, PlateGoodMapper plateGoodMapper, Long orderId, Long taskId) {
this.orderImportTempDataMapper = orderImportTempDataMapper;
this.orderService = orderService;
this.dictDataApi = dictDataApi;
this.snowFlakeGenerator = snowFlakeGenerator;
this.plateGoodMapper = plateGoodMapper;
this.orderId = orderId;
this.taskId = taskId;
// 是否补板
@@ -603,6 +613,34 @@ public final class DefaultOrderImportExcelListener extends AnalysisEventListener
isNotEmptyAndDict(vo.getTexture(), DictTypeConstants.GRAIN_TYPE, "纹路");
isNotEmptyAndDict(vo.getOpenDoorType(), DictTypeConstants.DOOR_OPENING_DIRECTIONS, "开门方向");
// 查询板材库是否有对应
queryPlateExists(vo);
}
/**
* 查询板材库是否有对应物料编码
* 不存在再使用material、coatingObverse、thickness、brand、name查询是否存在匹配,还是不存在提示板材库先添加
*
* @param plate
*/
private void queryPlateExists(OrderPlateImportExcelVO plate) {
PlateGoodDO plateGoodDO = null;
List<PlateGoodDO> plateGoodDOs;
if (StringUtils.isNotEmpty(plate.getGoodsId())) {
plateGoodDOs = plateGoodMapper.selectGoodOne(plate.getGoodsId(), OrganContextHolder.getOrganId());
} else {
plateGoodDOs = plateGoodMapper.selectGood(plate.getMaterial(), plate.getColor(),
BigDecimal.valueOf(Long.parseLong(plate.getThickness())),
plate.getBrand(), plate.getName(), OrganContextHolder.getOrganId());
}
if (CollUtil.isNotEmpty(plateGoodDOs)) {
plateGoodDO = plateGoodDOs.get(0);
}
if (ObjectUtil.isNull(plateGoodDO)) {
throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATEGOODS_NOT_EXIST_VALID_ERROR, rowIndex + 1);
}
}
/**
@@ -16,7 +16,9 @@ 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.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.executor.dal.mysql.orderImport.OrderImportTempDataMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.enums.DataTypeEnum;
import com.cf.imes.module.executor.enums.DictTypeConstants;
import com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum;
@@ -56,6 +58,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.xml.stream.Location;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.events.Attribute;
@@ -64,6 +67,7 @@ import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -75,6 +79,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -86,6 +91,7 @@ import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_
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_PLATEGOODS_NOT_EXIST_VALID_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;
@@ -119,6 +125,7 @@ public class DefaultOrderImportXmlParserHandler {
private Set<String> groupCodeSet = new HashSet<>();
private Map<String, RoomXmlVO> roomMap = new HashMap<>();
private Map<String, RoomBoxXmlVO> roomBodyMap = new HashMap<>();
private Map<String, Long> existGoodsIdMap = new HashMap<>(); // 物料编码:已创建的innerGoodsId
/**
* 补板用
@@ -174,6 +181,8 @@ public class DefaultOrderImportXmlParserHandler {
private SnowFlakeGenerator snowFlakeGenerator;
private PlateGoodMapper plateGoodMapper;
// 基础常量
private static final String FIELD_AXISXROTATE = "axisXrotate";
private static final String FIELD_AXISYROTATE = "axisYrotate";
@@ -193,10 +202,11 @@ public class DefaultOrderImportXmlParserHandler {
private static final String FIELD_THICKNESS = "thickness";
private static final String FIELD_ORDERCODE = "orderCode";
public DefaultOrderImportXmlParserHandler(OrderImportTempDataMapper orderImportTempDataMapper, OrderService orderService, SnowFlakeGenerator snowFlakeGenerator, Long orderId, Long taskId) {
public DefaultOrderImportXmlParserHandler(OrderImportTempDataMapper orderImportTempDataMapper, OrderService orderService, SnowFlakeGenerator snowFlakeGenerator, PlateGoodMapper plateGoodMapper, Long orderId, Long taskId) {
this.orderImportTempDataMapper = orderImportTempDataMapper;
this.orderService = orderService;
this.snowFlakeGenerator = snowFlakeGenerator;
this.plateGoodMapper = plateGoodMapper;
this.orderId = orderId;
this.taskId = taskId;
// 是否补板
@@ -244,7 +254,7 @@ public class DefaultOrderImportXmlParserHandler {
analyzeGroupXml(attributes);
break;
case "Plate":
analyzePlateXml(attributes);
analyzePlateXml(attributes, en.getLocation());
break;
case "Block":
analyzeBlockXml(attributes);
@@ -602,29 +612,40 @@ public class DefaultOrderImportXmlParserHandler {
* @param attributes
* @throws Exception
*/
private void analyzePlateXml(Iterator<Attribute> attributes) throws Exception {
private void analyzePlateXml(Iterator<Attribute> attributes, Location location) throws Exception {
// 从标签属性生成plate对象
PlateXmlVO plateXmlVO = getJavaBeanFromXmlAttr(PlateXmlVO.class, attributes);
if (ObjectUtil.isNull(plateXmlVO)) {
plateXmlVO = new PlateXmlVO();
}
// 校验板材数据
checkPlate(plateXmlVO);
checkPlate(plateXmlVO, location);
// 每解析到一次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());
// 相同的itemCode不重复创建临时Goods数据
String currentItemCode = plateXmlVO.getItemCode();
Long existInnerGoodsId = existGoodsIdMap.get(currentItemCode);
if(ObjectUtil.isNull(existInnerGoodsId)) {
Long innerGoodsId = (Long) snowFlakeGenerator.nextId(null);
plateItemCode = String.valueOf(innerGoodsId);
existGoodsIdMap.put(currentItemCode, innerGoodsId);
// 添加到临时表
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());
} else {
plateItemCode = String.valueOf(existInnerGoodsId);
}
}
@@ -633,7 +654,7 @@ public class DefaultOrderImportXmlParserHandler {
*
* @param plate
*/
private void checkPlate(PlateXmlVO plate) {
private void checkPlate(PlateXmlVO plate, Location location) {
isEmptyAndBack(plate::getName, "plate:name");
isEmptyAndBack(plate::getMaterial, "plate:material");
@@ -651,6 +672,37 @@ public class DefaultOrderImportXmlParserHandler {
notEmptyPositiveNumber(plate::getArea, "area", Double.class);
isEmptyAddAndInvalid(plate::getUnitArea, plate::setUnitArea, "", DictTypeConstants.UNIT_AREA, "unitArea");
notEmptyPositiveNumber(plate::getCount, FIELD_COUNT, Integer.class);
// 查询板材库是否有对应
queryPlateExists(plate,location);
}
/**
* 查询板材库是否有对应物料编码
* 不存在再使用material、coatingObverse、thickness、brand、name查询是否存在匹配,还是不存在提示板材库先添加
*
* @param plate
*/
private void queryPlateExists(PlateXmlVO plate, Location location) {
PlateGoodDO plateGoodDO = null;
List<PlateGoodDO> plateGoodDOs;
if (StringUtils.isNotEmpty(plate.getItemCode())) {
plateGoodDOs = plateGoodMapper.selectGoodOne(plate.getItemCode(), OrganContextHolder.getOrganId());
} else {
plateGoodDOs = plateGoodMapper.selectGood(plate.getMaterial(), plate.getCoatingObverse(),
BigDecimal.valueOf(Long.parseLong(plate.getThickness())),
plate.getBrand(), plate.getName(), OrganContextHolder.getOrganId());
}
if (CollUtil.isNotEmpty(plateGoodDOs)) {
plateGoodDO = plateGoodDOs.get(0);
}
if (ObjectUtil.isNotNull(plateGoodDO)) {
plate.setItemCode(plateGoodDO.getGoodsId());
} else {
throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATEGOODS_NOT_EXIST_VALID_ERROR, location.getLineNumber());
}
}
/**
@@ -1642,7 +1694,6 @@ public class DefaultOrderImportXmlParserHandler {
if (ObjectUtil.isNull(roomBoxXmlVO)) {
// 检查roomCode
if (!bodyEmpty) {
throw ServiceExceptionUtil.exception(ORDER_IMPORT_BODYCODE_NOT_EXIST_VALID_ERROR, se, boxCode);