1、新增生产单xml导入异步处理;2、excel导入提示优化;

This commit is contained in:
gaoqr
2025-02-28 16:27:34 +08:00
parent 98653b0445
commit 38054f58f9
41 changed files with 6007 additions and 43 deletions
@@ -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, "导入校验异常:板件{}下柜体编码{}不存在于柜体编码列表中");
}
@@ -16,4 +16,9 @@ public class OrderImportConstants {
* 房间、柜体缺省name
*/
public static final String NOT_ASSIGNED = "未命名";
/**
* 房间柜体缺省code
*/
public static final String NOT_ASSIGNED_CODE = "未命编号";
}
@@ -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;
@@ -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;
/**
* 创建人
*/
@@ -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();
}
}
@@ -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<? extends Enum<?>> 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");
}
}
}
@@ -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;
}