fix(material): 解决入场钢卷号查询中的字符串排序问题

- 为WmsMaterialCoilBo的materialType字段添加@NotBlank验证注解
- 重构getMaxEnterCoilNoByPrefix方法,将字符串排序改为数值排序
- 添加边界校验和前缀长度验证(必须为4位)
- 优化查询逻辑,先查询所有匹配记录再手动筛选数值最大值
- 增加详细的日志记录和异常处理机制
- 提升代码性能,使用固定容量HashMap和字段选择优化
This commit is contained in:
2026-01-12 16:29:46 +08:00
parent 7e630a9abe
commit d8d3136a71
2 changed files with 71 additions and 27 deletions

View File

@@ -133,6 +133,7 @@ public class WmsMaterialCoilBo extends BaseEntity {
private Long actualWarehouseId; private Long actualWarehouseId;
//材料类型 //材料类型
@NotBlank(message = "物料类型不能为空")
private String materialType; private String materialType;

View File

@@ -2259,10 +2259,10 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
@Override @Override
public Map<String, Object> checkCoilNoDuplicate(String enterCoilNo, String currentCoilNo) { public Map<String, Object> checkCoilNoDuplicate(String enterCoilNo, String currentCoilNo) {
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
boolean enterCoilNoDuplicate = false; boolean enterCoilNoDuplicate = false;
boolean currentCoilNoDuplicate = false; boolean currentCoilNoDuplicate = false;
// 检查入场钢卷号是否重复 // 检查入场钢卷号是否重复
if (StringUtils.isNotBlank(enterCoilNo)) { if (StringUtils.isNotBlank(enterCoilNo)) {
LambdaQueryWrapper<WmsMaterialCoil> enterWrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<WmsMaterialCoil> enterWrapper = Wrappers.lambdaQuery();
@@ -2271,7 +2271,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
long enterCount = baseMapper.selectCount(enterWrapper); long enterCount = baseMapper.selectCount(enterWrapper);
enterCoilNoDuplicate = enterCount > 0; enterCoilNoDuplicate = enterCount > 0;
} }
// 检查当前钢卷号是否重复 // 检查当前钢卷号是否重复
if (StringUtils.isNotBlank(currentCoilNo)) { if (StringUtils.isNotBlank(currentCoilNo)) {
LambdaQueryWrapper<WmsMaterialCoil> currentWrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<WmsMaterialCoil> currentWrapper = Wrappers.lambdaQuery();
@@ -2280,7 +2280,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
long currentCount = baseMapper.selectCount(currentWrapper); long currentCount = baseMapper.selectCount(currentWrapper);
currentCoilNoDuplicate = currentCount > 0; currentCoilNoDuplicate = currentCount > 0;
} }
// 判断重复类型 // 判断重复类型
String duplicateType; String duplicateType;
if (enterCoilNoDuplicate && currentCoilNoDuplicate) { if (enterCoilNoDuplicate && currentCoilNoDuplicate) {
@@ -2292,45 +2292,88 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
} else { } else {
duplicateType = "none"; duplicateType = "none";
} }
result.put("duplicateType", duplicateType); result.put("duplicateType", duplicateType);
result.put("enterCoilNoDuplicate", enterCoilNoDuplicate); result.put("enterCoilNoDuplicate", enterCoilNoDuplicate);
result.put("currentCoilNoDuplicate", currentCoilNoDuplicate); result.put("currentCoilNoDuplicate", currentCoilNoDuplicate);
return result; return result;
} }
/** /**
* 根据入场钢卷号前缀查询最大的入场钢卷号 * 根据入场钢卷号前缀查询最大的入场钢卷号
* 前端传入入场钢卷号的前四位,查询所有符合的入场钢卷号,返回最大值 * 前端传入入场钢卷号的前四位,查询所有符合的入场钢卷号,返回数值上的最大值
*
* @param enterCoilNoPrefix 入场钢卷号前缀建议为4位
* @return 包含最大钢卷号和前缀的Mapkey分别为maxEnterCoilNo、prefix
*/ */
@Override @Override
public Map<String, Object> getMaxEnterCoilNoByPrefix(String enterCoilNoPrefix) { public Map<String, Object> getMaxEnterCoilNoByPrefix(String enterCoilNoPrefix) {
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>(2); // 初始化固定容量,提升性能
result.put("prefix", enterCoilNoPrefix); // 先赋值前缀,避免重复代码
// 1. 边界校验:前缀为空/空白字符串直接返回null
if (StringUtils.isBlank(enterCoilNoPrefix)) { if (StringUtils.isBlank(enterCoilNoPrefix)) {
log.warn("查询最大入场钢卷号失败:前缀为空");
result.put("maxEnterCoilNo", null); result.put("maxEnterCoilNo", null);
result.put("prefix", enterCoilNoPrefix);
return result; return result;
} }
// 查询所有以该前缀开头的入场钢卷号 // 2. 前缀长度校验可选根据业务要求比如强制4位
LambdaQueryWrapper<WmsMaterialCoil> wrapper = Wrappers.lambdaQuery(); if (enterCoilNoPrefix.length() != 4) {
wrapper.likeRight(WmsMaterialCoil::getEnterCoilNo, enterCoilNoPrefix) log.warn("查询最大入场钢卷号失败前缀长度不符合要求需4位当前前缀{}", enterCoilNoPrefix);
.eq(WmsMaterialCoil::getDelFlag, 0) result.put("maxEnterCoilNo", null);
.orderByDesc(WmsMaterialCoil::getEnterCoilNo) return result;
.last("LIMIT 1");
WmsMaterialCoil maxCoil = baseMapper.selectOne(wrapper);
String maxEnterCoilNo = null;
if (maxCoil != null && StringUtils.isNotBlank(maxCoil.getEnterCoilNo())) {
maxEnterCoilNo = maxCoil.getEnterCoilNo();
} }
result.put("maxEnterCoilNo", maxEnterCoilNo); try {
result.put("prefix", enterCoilNoPrefix); // 3. 构建查询条件:匹配前缀 + 未删除
LambdaQueryWrapper<WmsMaterialCoil> wrapper = Wrappers.lambdaQuery();
wrapper.likeRight(WmsMaterialCoil::getEnterCoilNo, enterCoilNoPrefix)
.eq(WmsMaterialCoil::getDelFlag, 0)
.select(WmsMaterialCoil::getEnterCoilNo); // 仅查询需要的字段,提升性能
// 4. 查询所有匹配的钢卷记录
List<WmsMaterialCoil> coilList = baseMapper.selectList(wrapper);
log.info("根据前缀{}查询到匹配的钢卷记录数:{}", enterCoilNoPrefix, coilList.size());
// 5. 手动筛选数值最大的钢卷号(解决字符串排序问题)
String maxEnterCoilNo = null;
long maxNum = -1;
for (WmsMaterialCoil coil : coilList) {
String coilNo = coil.getEnterCoilNo();
// 跳过空值、非纯数字的钢卷号
if (StringUtils.isBlank(coilNo) || !coilNo.matches("^\\d+$")) {
log.debug("跳过无效钢卷号:{}(空值或非纯数字)", coilNo);
continue;
}
// 处理大数溢出风险如果钢卷号超过Long范围可改用BigDecimal
long currentNum;
try {
currentNum = Long.parseLong(coilNo);
} catch (NumberFormatException e) {
log.warn("钢卷号{}转换为数字失败:{}", coilNo, e.getMessage());
continue;
}
// 更新最大值
if (currentNum > maxNum) {
maxNum = currentNum;
maxEnterCoilNo = coilNo;
}
}
// 6. 结果赋值 + 日志记录
result.put("maxEnterCoilNo", maxEnterCoilNo);
log.info("前缀{}对应的最大入场钢卷号:{}", enterCoilNoPrefix, maxEnterCoilNo == null ? "无匹配记录" : maxEnterCoilNo);
} catch (Exception e) {
// 7. 全局异常捕获,避免接口报错
log.error("查询最大入场钢卷号失败,前缀:{}", enterCoilNoPrefix, e);
result.put("maxEnterCoilNo", null);
}
return result; return result;
} }