上架数量显示异常

This commit is contained in:
秦鸿展
2026-04-15 10:06:46 +08:00
parent f63917ed03
commit fdb70db6f6
2 changed files with 81 additions and 26 deletions
@@ -407,6 +407,8 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
// 如果获取失败,记录日志但继续处理
}
}
// 仅按「本入库单」与 material_inventory.in_order_number 比对批次是否冲突;避免其它单据已落库的批次拦截本单首笔收货
String currentInOrderNumber = resolveCurrentInOrderNumberForBatchReceipt(stockReceiptOrderDO);
//批量新增或修改物料信息
List<ReceiptMaterialDetail> receiptMaterialDetailList = new ArrayList<>();
@@ -416,7 +418,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
for (ReceiptMaterialDetailDO receiptMaterialDetailDO : receiptMaterialDetailDOList){
extractBatchAttributesToReceiptDetail(receiptMaterialDetailDO);
// 自动生成批次号并校验唯一性(包括子项)
generateAndValidateBatchNumber(receiptMaterialDetailDO, shipperId);
generateAndValidateBatchNumber(receiptMaterialDetailDO, shipperId, currentInOrderNumber);
// 当 materialMoreDetailList 为空时(如 PDA 未传),从 receiptMaterialDetailDO 的 batch_number、material_status_code 等字段构建,确保更多属性能保存并回显
if (CollectionUtils.isEmpty(receiptMaterialDetailDO.getMaterialMoreDetailList())) {
receiptMaterialDetailDO.setMaterialMoreDetailList(buildMaterialMoreDetailFromReceiptFields(receiptMaterialDetailDO));
@@ -1204,27 +1206,51 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
);
}
/**
* 解析本笔收货对应的入库单号:DO 未带时从收货单主表补全,供批次校验限定「本单」范围。
*/
private String resolveCurrentInOrderNumberForBatchReceipt(StockReceiptOrderDO stockReceiptOrderDO) {
if (stockReceiptOrderDO == null) {
return null;
}
String in = stockReceiptOrderDO.getInOrderNumber();
if (StringUtils.isNotBlank(in)) {
return in.trim();
}
Long receiptOrderId = stockReceiptOrderDO.getReceiptOrderId();
if (receiptOrderId == null) {
return null;
}
StockReceiptOrder head = stockReceiptOrderMapper.selectById(receiptOrderId);
if (head != null && StringUtils.isNotBlank(head.getInOrderNumber())) {
return head.getInOrderNumber().trim();
}
return null;
}
/**
* @description 自动生成批次号并校验唯一性
* @author Auto
* @date 2026/1/28
* @param receiptMaterialDetailDO 收货明细
* @param shipperId 货主ID
* @param currentInOrderNumber 当前入库单号,与 material_inventory.in_order_number 一致时才视为本单内批次冲突
* @return void
*/
private void generateAndValidateBatchNumber(ReceiptMaterialDetailDO receiptMaterialDetailDO, Long shipperId) {
private void generateAndValidateBatchNumber(ReceiptMaterialDetailDO receiptMaterialDetailDO, Long shipperId,
String currentInOrderNumber) {
if (receiptMaterialDetailDO == null) {
return;
}
// 处理当前明细
processBatchNumberForDetail(receiptMaterialDetailDO, shipperId);
processBatchNumberForDetail(receiptMaterialDetailDO, shipperId, currentInOrderNumber);
// 递归处理子项
List<ReceiptMaterialDetailDO> children = receiptMaterialDetailDO.getChildren();
if (!CollectionUtils.isEmpty(children)) {
for (ReceiptMaterialDetailDO child : children) {
generateAndValidateBatchNumber(child, shipperId);
generateAndValidateBatchNumber(child, shipperId, currentInOrderNumber);
}
}
}
@@ -1235,9 +1261,11 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
* @date 2026/1/28
* @param receiptMaterialDetailDO 收货明细
* @param shipperId 货主ID
* @param currentInOrderNumber 当前入库单号
* @return void
*/
private void processBatchNumberForDetail(ReceiptMaterialDetailDO receiptMaterialDetailDO, Long shipperId) {
private void processBatchNumberForDetail(ReceiptMaterialDetailDO receiptMaterialDetailDO, Long shipperId,
String currentInOrderNumber) {
if (receiptMaterialDetailDO == null) {
return;
}
@@ -1252,21 +1280,25 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
receiptMaterialDetailDO.setBatchNumber(batchNumber);
}
// 校验批次号唯一性:货主+商品+库存属性值相同时,批次号不能重复
// 校验批次号:仅本入库单范围内,货主+商品+库存属性+批次在库存中是否已存在(不同入库单允许相同批次号)
if (shipperId != null && materialBaseInfoId != null && batchNumber != null && !batchNumber.trim().isEmpty()) {
// 使用 LambdaQueryWrapper 查询库存表中是否存在相同的货主+商品+库存属性值+批次号的记录
if (StringUtils.isBlank(currentInOrderNumber)) {
log.warn("batchReceiptUpdate:未解析到入库单号,跳过库存批次重复校验,receiptOrderNumber={}",
receiptMaterialDetailDO != null ? receiptMaterialDetailDO.getReceiptOrderNumber() : null);
return;
}
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MaterialInventory> wrapper =
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MaterialInventory>()
.eq(MaterialInventory::getShipperId, shipperId)
.eq(MaterialInventory::getMaterialBaseInfoId, materialBaseInfoId)
.eq(MaterialInventory::getBatchNumber, batchNumber)
.eq(MaterialInventory::getDelFlag, 1);
.eq(MaterialInventory::getDelFlag, 1)
.eq(MaterialInventory::getInOrderNumber, currentInOrderNumber);
// 如果库存属性值不为空,需要精确匹配;如果为空,查询库存属性值为空或null的记录
if (materialStatusCode != null && !materialStatusCode.trim().isEmpty()) {
wrapper.eq(MaterialInventory::getMaterialStatusCode, materialStatusCode);
} else {
// 如果库存属性值为空,查询库存属性值为null或空字符串的记录
wrapper.and(w -> w.isNull(MaterialInventory::getMaterialStatusCode)
.or()
.eq(MaterialInventory::getMaterialStatusCode, ""));
@@ -1274,12 +1306,13 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
List<MaterialInventory> existingInventoryList = materialInventoryMapper.selectList(wrapper);
// 如果存在相同的货主+商品+库存属性值+批次号的记录,抛出异常
if (!CollectionUtils.isEmpty(existingInventoryList)) {
String statusCodeDesc = (materialStatusCode != null && !materialStatusCode.trim().isEmpty())
? ",库存属性值:" + materialStatusCode
: ",库存属性值:空";
throw new ServiceException("批次号【" + batchNumber + "已存在,货主ID【" + shipperId + "】+商品ID【" + materialBaseInfoId + "" + statusCodeDesc + "相同的记录不允许使用重复的批次号");
throw new ServiceException("批次号【" + batchNumber + "在本入库单「" + currentInOrderNumber
+ "」下已存在库存,货主ID【" + shipperId + "】+商品ID【" + materialBaseInfoId + "" + statusCodeDesc
+ ",不允许重复使用");
}
}
}