From acda3c95de8dcddb447759e99edd670b9bda543f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 14 Jun 2026 14:32:54 +0800 Subject: [PATCH] fix(wms): 优化库存批量锁定顺序 --- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java | 5 ++++- yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java index 1e1a17a..4951440 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; import org.apache.ibatis.annotations.Mapper; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -99,8 +100,10 @@ public interface WmsInventoryMapper extends BaseMapperX { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } + List sortedIds = new ArrayList<>(ids); + Collections.sort(sortedIds); return selectList(new LambdaQueryWrapperX() - .in(WmsInventoryDO::getId, ids) + .in(WmsInventoryDO::getId, sortedIds) .orderByAsc(WmsInventoryDO::getId) .last("FOR UPDATE")); } diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java index 22b4ca1..3585c6e 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java @@ -241,6 +241,46 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { } @Test + public void testChangeInventory_multipleExistingInventoryKeys() { + // mock 数据 + WmsItemDO item = createItem("ITEM-001", "红富士苹果"); + WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装"); + inventoryMapper.insert(createInventory(sku.getId(), 200L, "7.00")); + inventoryMapper.insert(createInventory(sku.getId(), 100L, "5.00")); + WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "2.00"); + List items = new ArrayList<>(reqDTO.getItems()); + items.add(new WmsInventoryChangeReqDTO.Item() + .setSkuId(sku.getId()) + .setWarehouseId(200L) + .setQuantity(new BigDecimal("3.00")) + .setPrice(new BigDecimal("100.00")) + .setTotalPrice(new BigDecimal("300.00")) + .setRemark("测试入库 2")); + reqDTO.setItems(items); + + // 调用 + inventoryService.changeInventory(reqDTO); + + // 断言:多条已存在库存余额分别更新 + WmsInventoryDO inventory1 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L); + assertNotNull(inventory1); + assertEquals(0, new BigDecimal("7.00").compareTo(inventory1.getQuantity())); + WmsInventoryDO inventory2 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 200L); + assertNotNull(inventory2); + assertEquals(0, new BigDecimal("10.00").compareTo(inventory2.getQuantity())); + // 断言:库存流水保持入参明细顺序 + List histories = inventoryHistoryMapper.selectList(); + histories.sort(Comparator.comparing(WmsInventoryHistoryDO::getId)); + assertEquals(2, histories.size()); + assertEquals(100L, histories.get(0).getWarehouseId()); + assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getBeforeQuantity())); + assertEquals(0, new BigDecimal("7.00").compareTo(histories.get(0).getAfterQuantity())); + assertEquals(200L, histories.get(1).getWarehouseId()); + assertEquals(0, new BigDecimal("7.00").compareTo(histories.get(1).getBeforeQuantity())); + assertEquals(0, new BigDecimal("10.00").compareTo(histories.get(1).getAfterQuantity())); + } + + @Test public void testChangeInventory_concurrentCreateSameInventoryOnlyOneBalance() throws Exception { // mock 数据 WmsItemDO item = createItem("ITEM-001", "红富士苹果"); -- libgit2 0.21.4