From eba504d0bf5657aee84da5fc36edc71a3d3ac4bc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 13 May 2026 00:57:29 +0800 Subject: [PATCH] feat(wms):补充 inventory 相关的单测 --- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryMapper.java | 29 +++++++++++++++++++++++++++++ yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- yudao-module-wms/src/test/resources/sql/clean.sql | 3 +++ yudao-module-wms/src/test/resources/sql/create_tables.sql | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 182 insertions(+), 2 deletions(-) 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 bb34abf..39b10e3 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 @@ -8,8 +8,11 @@ import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPag import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO; import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO; import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.math.BigDecimal; + /** * WMS 库存 Mapper * @@ -63,6 +66,32 @@ public interface WmsInventoryMapper extends BaseMapperX { return selectCount(WmsInventoryDO::getSkuId, skuId); } + default WmsInventoryDO selectBySkuIdAndWarehouseIdAndAreaId(Long skuId, Long warehouseId, Long areaId) { + return selectOne(WmsInventoryDO::getSkuId, skuId, + WmsInventoryDO::getWarehouseId, warehouseId, + WmsInventoryDO::getAreaId, areaId); + } + + default WmsInventoryDO selectBySkuIdAndWarehouseIdAndAreaIdForUpdate(Long skuId, Long warehouseId, Long areaId) { + return selectOneForUpdate(WmsInventoryDO::getSkuId, skuId, + WmsInventoryDO::getWarehouseId, warehouseId, + WmsInventoryDO::getAreaId, areaId); + } + + /** + * 增量更新库存数量 + * + * @param id 库存编号 + * @param quantity 变更数量 + * @return 更新行数 + */ + @SuppressWarnings("UnusedReturnValue") + default int updateQuantity(Long id, BigDecimal quantity) { + return update(null, new LambdaUpdateWrapper() + .eq(WmsInventoryDO::getId, id) + .setSql("quantity = quantity + (" + quantity + ")")); + } + private static void appendDimensionOrder(MPJLambdaWrapperX query, String type) { if (StrUtil.equals(WmsInventoryPageReqVO.TYPE_WAREHOUSE, type)) { query.orderByAsc(WmsInventoryDO::getWarehouseId) 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 7df3bac..5a94c09 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 @@ -3,21 +3,29 @@ package cn.iocoder.yudao.module.wms.service.inventory; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO; +import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO; import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO; import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO; import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; +import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryHistoryMapper; import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryMapper; import cn.iocoder.yudao.module.wms.dal.mysql.md.item.WmsItemMapper; import cn.iocoder.yudao.module.wms.dal.mysql.md.item.WmsItemSkuMapper; +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties; +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import java.math.BigDecimal; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; -@Import(WmsInventoryServiceImpl.class) +@Import({WmsInventoryServiceImpl.class, WmsInventoryDetailServiceImpl.class, WmsInventoryHistoryServiceImpl.class, + WmsProperties.class}) public class WmsInventoryServiceImplTest extends BaseDbUnitTest { @Resource @@ -26,9 +34,67 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { @Resource private WmsInventoryMapper inventoryMapper; @Resource + private WmsInventoryHistoryMapper inventoryHistoryMapper; + @Resource private WmsItemMapper itemMapper; @Resource private WmsItemSkuMapper skuMapper; + @Resource + private WmsProperties wmsProperties; + + @Test + public void testChangeInventory_createInventory() { + // mock 数据 + wmsProperties.setBatchEnable(false); + WmsItemDO item = createItem("ITEM-001", "红富士苹果"); + WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装"); + WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, 1001L, "5.00"); + + // 调用 + inventoryService.changeInventory(reqDTO); + + // 断言:库存余额 + WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseIdAndAreaId(sku.getId(), 100L, 1001L); + assertNotNull(inventory); + assertEquals(0, new BigDecimal("5.00").compareTo(inventory.getQuantity())); + // 断言:库存流水 + List histories = inventoryHistoryMapper.selectList(); + assertEquals(1, histories.size()); + WmsInventoryHistoryDO history = histories.get(0); + assertEquals(sku.getId(), history.getSkuId()); + assertEquals(100L, history.getWarehouseId()); + assertEquals(1001L, history.getAreaId()); + assertEquals(0, BigDecimal.ZERO.compareTo(history.getBeforeQuantity())); + assertEquals(0, new BigDecimal("5.00").compareTo(history.getAfterQuantity())); + assertEquals(reqDTO.getOrderId(), history.getOrderId()); + assertEquals(reqDTO.getOrderNo(), history.getOrderNo()); + assertEquals(reqDTO.getOrderType(), history.getOrderType()); + } + + @Test + public void testChangeInventory_updateInventory() { + // mock 数据 + wmsProperties.setBatchEnable(false); + WmsItemDO item = createItem("ITEM-001", "红富士苹果"); + WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装"); + inventoryMapper.insert(createInventory(sku.getId(), 100L, 1001L, "2.00")); + WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, 1001L, "3.00"); + + // 调用 + inventoryService.changeInventory(reqDTO); + + // 断言:库存余额 + WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseIdAndAreaId(sku.getId(), 100L, 1001L); + assertNotNull(inventory); + assertEquals(0, new BigDecimal("5.00").compareTo(inventory.getQuantity())); + // 断言:库存流水 + List histories = inventoryHistoryMapper.selectList(); + assertEquals(1, histories.size()); + WmsInventoryHistoryDO history = histories.get(0); + assertEquals(0, new BigDecimal("2.00").compareTo(history.getBeforeQuantity())); + assertEquals(0, new BigDecimal("5.00").compareTo(history.getAfterQuantity())); + assertEquals(0, new BigDecimal("3.00").compareTo(history.getQuantity())); + } @Test public void testGetInventoryPage_groupByWarehouse() { @@ -125,4 +191,18 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { .build(); } + private static WmsInventoryChangeReqDTO createChangeReq(Long skuId, Long warehouseId, Long areaId, String quantity) { + return new WmsInventoryChangeReqDTO() + .setOrderId(1L) + .setOrderNo("RK202605120001") + .setOrderType(WmsInventoryOrderTypeEnum.RECEIPT.getType()) + .setItems(List.of(new WmsInventoryChangeReqDTO.Item() + .setSkuId(skuId) + .setWarehouseId(warehouseId) + .setAreaId(areaId) + .setQuantity(new BigDecimal(quantity)) + .setAmount(new BigDecimal("100.00")) + .setRemark("测试入库"))); + } + } diff --git a/yudao-module-wms/src/test/resources/sql/clean.sql b/yudao-module-wms/src/test/resources/sql/clean.sql index 03fc147..eea18af 100644 --- a/yudao-module-wms/src/test/resources/sql/clean.sql +++ b/yudao-module-wms/src/test/resources/sql/clean.sql @@ -1,3 +1,6 @@ +DELETE FROM "wms_receipt_order_detail"; +DELETE FROM "wms_receipt_order"; +DELETE FROM "wms_inventory_history"; DELETE FROM "wms_inventory_detail"; DELETE FROM "wms_inventory"; DELETE FROM "wms_item_sku"; diff --git a/yudao-module-wms/src/test/resources/sql/create_tables.sql b/yudao-module-wms/src/test/resources/sql/create_tables.sql index 172dee9..6c8e2ca 100644 --- a/yudao-module-wms/src/test/resources/sql/create_tables.sql +++ b/yudao-module-wms/src/test/resources/sql/create_tables.sql @@ -50,7 +50,8 @@ CREATE TABLE IF NOT EXISTS "wms_inventory" ( "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, "tenant_id" bigint NOT NULL DEFAULT '0', - PRIMARY KEY ("id") + PRIMARY KEY ("id"), + CONSTRAINT "uk_wms_inventory_sku_warehouse_area" UNIQUE ("sku_id", "warehouse_id", "area_id", "tenant_id", "deleted") ) COMMENT 'WMS 库存表'; CREATE TABLE IF NOT EXISTS "wms_inventory_detail" ( @@ -76,3 +77,70 @@ CREATE TABLE IF NOT EXISTS "wms_inventory_detail" ( "tenant_id" bigint NOT NULL DEFAULT '0', PRIMARY KEY ("id") ) COMMENT 'WMS 库存明细表'; + +CREATE TABLE IF NOT EXISTS "wms_inventory_history" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "warehouse_id" bigint NOT NULL, + "area_id" bigint NOT NULL DEFAULT '0', + "sku_id" bigint NOT NULL, + "quantity" decimal(24, 6) NOT NULL DEFAULT '0', + "before_quantity" decimal(24, 6) DEFAULT NULL, + "after_quantity" decimal(24, 6) DEFAULT NULL, + "batch_no" varchar(64) DEFAULT NULL, + "production_date" timestamp DEFAULT NULL, + "expiration_date" timestamp DEFAULT NULL, + "amount" decimal(24, 6) DEFAULT NULL, + "remark" varchar(255) DEFAULT NULL, + "order_id" bigint DEFAULT NULL, + "order_no" varchar(64) DEFAULT NULL, + "order_type" tinyint DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', + PRIMARY KEY ("id") +) COMMENT 'WMS 库存流水表'; + +CREATE TABLE IF NOT EXISTS "wms_receipt_order" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar(64) NOT NULL, + "type" tinyint NOT NULL, + "status" tinyint NOT NULL DEFAULT '0', + "biz_order_no" varchar(64) DEFAULT NULL, + "merchant_id" bigint DEFAULT NULL, + "remark" varchar(255) DEFAULT NULL, + "warehouse_id" bigint NOT NULL, + "area_id" bigint NOT NULL DEFAULT '0', + "total_quantity" decimal(20, 2) NOT NULL DEFAULT '0', + "total_amount" decimal(10, 2) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', + PRIMARY KEY ("id") +) COMMENT 'WMS 入库单表'; + +CREATE TABLE IF NOT EXISTS "wms_receipt_order_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "remark" varchar(255) DEFAULT NULL, + "order_id" bigint NOT NULL, + "sku_id" bigint NOT NULL, + "warehouse_id" bigint NOT NULL, + "area_id" bigint NOT NULL DEFAULT '0', + "batch_no" varchar(64) DEFAULT NULL, + "production_date" timestamp DEFAULT NULL, + "expiration_date" timestamp DEFAULT NULL, + "quantity" decimal(20, 2) NOT NULL DEFAULT '0', + "amount" decimal(10, 2) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', + PRIMARY KEY ("id") +) COMMENT 'WMS 入库单明细表'; -- libgit2 0.21.4