feat(wms): 支持库存操作按批次号

- 新增按批次号进行库存增减的功能
- 修改入库、出库、移库等操作,支持指定批次号
- 优化库存查询逻辑,优先按批次号匹配
- 修复测试接口路径配置
This commit is contained in:
2025-09-12 14:26:51 +08:00
parent 3842bb9a84
commit fdec7e1d47
2 changed files with 64 additions and 24 deletions

View File

@@ -163,7 +163,7 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
throw new RuntimeException("未能获取到单位");
}
// 入库操作
changeStock(bo.getWarehouseId(), bo.getItemType(), bo.getItemId(), bo.getQuantity(), true, unit);
changeStock(bo.getWarehouseId(), bo.getItemType(), bo.getItemId(), bo.getBatchNo(), bo.getQuantity(), true, unit);
return true;
}
@Override
@@ -184,7 +184,7 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
throw new RuntimeException("未能获取到单位");
}
// 出库操作
changeStock(bo.getWarehouseId(), bo.getItemType(), bo.getItemId(), bo.getQuantity(), false, unit);
changeStock(bo.getWarehouseId(), bo.getItemType(), bo.getItemId(), bo.getBatchNo(), bo.getQuantity(), false, unit);
return true;
}
@@ -272,7 +272,7 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
// 执行入库操作(退库就是入库)
changeStock(returnDetail.getWarehouseId(), returnDetail.getItemType(),
returnDetail.getItemId(), returnDetail.getQuantity(), true, unit);
returnDetail.getItemId(), returnDetail.getBatchNo(), returnDetail.getQuantity(), true, unit);
}
// 更新单据状态为已审核2
returnStockIo.setStatus(2);
@@ -297,23 +297,24 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
if (details == null || details.isEmpty()) {
throw new RuntimeException("单据明细不能为空");
}
//如果details.batchNo不相等则需要去stock表新建一条批次号不同的记录
for (WmsStockIoDetail detail : details) {
String ioType = stockIo.getIoType();
if ("in".equals(ioType)) {
// 入库:目标库位库存增加
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), true, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit());
} else if ("out".equals(ioType)) {
// 出库:目标库位库存减少
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), false, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit());
} else if ("transfer".equals(ioType)) {
// 移库fromWarehouseId减少warehouseId增加
if (detail.getFromWarehouseId() == null) {
throw new RuntimeException("移库明细缺少源库位ID");
}
// 先减少源库位
changeStock(detail.getFromWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), false, detail.getUnit());
changeStock(detail.getFromWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit());
// 再增加目标库位
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), true, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit());
} else {
throw new RuntimeException("未知的出入库类型");
}
@@ -343,19 +344,18 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
String ioType = stockIo.getIoType();
if ("in".equals(ioType)) {
// 入库撤销:目标库位库存减少
// changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), false, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit());
} else if ("out".equals(ioType)) {
// 出库撤销:目标库位库存增加
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), true, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit());
} else if ("transfer".equals(ioType)) {
if (detail.getFromWarehouseId() == null) {
throw new ServiceException("移库明细缺少源库位ID");
}
// 源库位库存增加
changeStock(detail.getFromWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), true, detail.getUnit());
changeStock(detail.getFromWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), true, detail.getUnit());
// 目标库位库存减少
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getQuantity(), false, detail.getUnit());
changeStock(detail.getWarehouseId(), detail.getItemType(), detail.getItemId(), detail.getBatchNo(), detail.getQuantity(), false, detail.getUnit());
} else {
throw new ServiceException("未知的出入库类型");
}
@@ -427,12 +427,32 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
* 库存增减isAdd=true为增加false为减少减少时校验库存是否足够
*/
private void changeStock(Long warehouseId, String itemType, Long itemId, BigDecimal quantity, boolean isAdd, String unit) {
WmsStock stock = stockMapper.selectOne(Wrappers.<WmsStock>lambdaQuery()
.eq(WmsStock::getWarehouseId, warehouseId)
.eq(WmsStock::getItemType, itemType)
.eq(WmsStock::getItemId, itemId)
// .eq(WmsStock::getBatchNo, batchNo)
.last("limit 1"));
changeStock(warehouseId, itemType, itemId, null, quantity, isAdd, unit);
}
/**
* 库存增减支持批次号isAdd=true为增加false为减少减少时校验库存是否足够
*/
private void changeStock(Long warehouseId, String itemType, Long itemId, String batchNo, BigDecimal quantity, boolean isAdd, String unit) {
WmsStock stock = null;
if (StringUtils.isNotBlank(batchNo)) {
// 如果指定了批次号,按批次号查找
stock = stockMapper.selectOne(Wrappers.<WmsStock>lambdaQuery()
.eq(WmsStock::getWarehouseId, warehouseId)
.eq(WmsStock::getItemType, itemType)
.eq(WmsStock::getItemId, itemId)
.eq(WmsStock::getBatchNo, batchNo)
.last("limit 1"));
} else {
// 如果没有指定批次号,查找任意一个批次
stock = stockMapper.selectOne(Wrappers.<WmsStock>lambdaQuery()
.eq(WmsStock::getWarehouseId, warehouseId)
.eq(WmsStock::getItemType, itemType)
.eq(WmsStock::getItemId, itemId)
.last("limit 1"));
}
if (stock == null) {
if (!isAdd) {
throw new RuntimeException("库存不足,无法出库/移库");
@@ -442,18 +462,37 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
stock.setWarehouseId(warehouseId);
stock.setItemType(itemType);
stock.setItemId(itemId);
stock.setBatchNo("B-100");
stock.setBatchNo(StringUtils.isNotBlank(batchNo) ? batchNo : "B-100");
stock.setQuantity(quantity);
stock.setUnit(unit);
stockMapper.insert(stock);
} else {
BigDecimal newQty = isAdd ? stock.getQuantity().add(quantity) : stock.getQuantity().subtract(quantity);
if (newQty.compareTo(BigDecimal.ZERO) < 0) {
throw new RuntimeException("库存不足,无法出库/移库");
// 如果指定了批次号且与现有库存批次号不同,需要新建记录
if (StringUtils.isNotBlank(batchNo) && !batchNo.equals(stock.getBatchNo())) {
if (!isAdd) {
throw new RuntimeException("指定批次号库存不足,无法出库/移库");
}
// 新建不同批次号的库存记录
WmsStock newStock = new WmsStock();
newStock.setWarehouseId(warehouseId);
newStock.setItemType(itemType);
newStock.setItemId(itemId);
newStock.setBatchNo(batchNo);
newStock.setQuantity(quantity);
newStock.setUnit(unit);
stockMapper.insert(newStock);
stock = newStock; // 更新stock引用用于日志记录
} else {
// 更新现有库存
BigDecimal newQty = isAdd ? stock.getQuantity().add(quantity) : stock.getQuantity().subtract(quantity);
if (newQty.compareTo(BigDecimal.ZERO) < 0) {
throw new RuntimeException("库存不足,无法出库/移库");
}
stock.setQuantity(newQty);
stockMapper.updateById(stock);
}
stock.setQuantity(newQty);
stockMapper.updateById(stock);
}
// 记录库存变更日志
WmsStockLog log = new WmsStockLog();
log.setWarehouseId(warehouseId);