forked from wangziqi/ruoyi-vue-pro
🎉 Initial commit
This commit is contained in:
@@ -0,0 +1,672 @@
|
||||
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.order.WmsOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryCheckReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_INVENTORY_CHANGED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.INVENTORY_QUANTITY_NOT_ENOUGH;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Import({WmsInventoryServiceImpl.class, WmsInventoryHistoryServiceImpl.class})
|
||||
public class WmsInventoryServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsInventoryServiceImpl inventoryService;
|
||||
|
||||
@Resource
|
||||
private WmsInventoryMapper inventoryMapper;
|
||||
@Resource
|
||||
private WmsInventoryHistoryMapper inventoryHistoryMapper;
|
||||
@Resource
|
||||
private WmsItemMapper itemMapper;
|
||||
@Resource
|
||||
private WmsItemSkuMapper skuMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
@MockitoBean
|
||||
private WmsItemService itemService;
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_createInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "5.00");
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:库存余额
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(inventory.getQuantity()));
|
||||
// 断言:库存流水
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
assertEquals(1, histories.size());
|
||||
WmsInventoryHistoryDO history = histories.get(0);
|
||||
assertEquals(sku.getId(), history.getSkuId());
|
||||
assertEquals(100L, history.getWarehouseId());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(history.getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(history.getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("500.00").compareTo(history.getTotalPrice()));
|
||||
assertEquals(reqDTO.getOrderId(), history.getOrderId());
|
||||
assertEquals(reqDTO.getOrderNo(), history.getOrderNo());
|
||||
assertEquals(reqDTO.getOrderType(), history.getOrderType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_updateInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "3.00");
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:库存余额
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(inventory.getQuantity()));
|
||||
// 断言:库存流水
|
||||
List<WmsInventoryHistoryDO> 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()));
|
||||
assertEquals(0, new BigDecimal("300.00").compareTo(history.getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_sameInventoryKeyKeepItemGranularity() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "5.00");
|
||||
List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems());
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(100L)
|
||||
.setQuantity(new BigDecimal("7.00"))
|
||||
.setPrice(new BigDecimal("140.00"))
|
||||
.setTotalPrice(new BigDecimal("980.00"))
|
||||
.setRemark("测试入库 2"));
|
||||
reqDTO.setItems(items);
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:库存余额只保留一条,数量逐条累加
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("12.00").compareTo(inventory.getQuantity()));
|
||||
// 断言:库存流水保持用户明细颗粒度
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
histories.sort(Comparator.comparing(WmsInventoryHistoryDO::getId));
|
||||
assertEquals(2, histories.size());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(histories.get(0).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("500.00").compareTo(histories.get(0).getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(1).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("12.00").compareTo(histories.get(1).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(histories.get(1).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("980.00").compareTo(histories.get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_sameExistingInventoryKeyKeepItemGranularity() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "3.00");
|
||||
List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems());
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(100L)
|
||||
.setQuantity(new BigDecimal("4.00"))
|
||||
.setPrice(new BigDecimal("80.00"))
|
||||
.setTotalPrice(new BigDecimal("320.00"))
|
||||
.setRemark("测试入库 2"));
|
||||
reqDTO.setItems(items);
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:库存余额只保留一条,数量逐条累加
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("9.00").compareTo(inventory.getQuantity()));
|
||||
// 断言:库存流水保持用户明细颗粒度
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
histories.sort(Comparator.comparing(WmsInventoryHistoryDO::getId));
|
||||
assertEquals(2, histories.size());
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(histories.get(0).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(histories.get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("300.00").compareTo(histories.get(0).getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(1).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("9.00").compareTo(histories.get(1).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("4.00").compareTo(histories.get(1).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("320.00").compareTo(histories.get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_multipleInventoryKeysKeepItemGranularity() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "5.00");
|
||||
List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems());
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(200L)
|
||||
.setQuantity(new BigDecimal("3.00"))
|
||||
.setPrice(new BigDecimal("60.00"))
|
||||
.setTotalPrice(new BigDecimal("180.00"))
|
||||
.setRemark("测试入库 2"));
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(100L)
|
||||
.setQuantity(new BigDecimal("-2.00"))
|
||||
.setPrice(new BigDecimal("40.00"))
|
||||
.setTotalPrice(new BigDecimal("-80.00"))
|
||||
.setRemark("测试出库"));
|
||||
reqDTO.setItems(items);
|
||||
|
||||
// 调用
|
||||
inventoryService.changeInventory(reqDTO);
|
||||
|
||||
// 断言:不同库存余额分别更新
|
||||
WmsInventoryDO inventory1 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory1);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(inventory1.getQuantity()));
|
||||
WmsInventoryDO inventory2 = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 200L);
|
||||
assertNotNull(inventory2);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(inventory2.getQuantity()));
|
||||
// 断言:批量加锁后仍按明细颗粒度记录 before/after
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
histories.sort(Comparator.comparing(WmsInventoryHistoryDO::getId));
|
||||
assertEquals(3, histories.size());
|
||||
assertEquals(100L, histories.get(0).getWarehouseId());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(histories.get(0).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("500.00").compareTo(histories.get(0).getTotalPrice()));
|
||||
assertEquals(200L, histories.get(1).getWarehouseId());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(histories.get(1).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(histories.get(1).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("180.00").compareTo(histories.get(1).getTotalPrice()));
|
||||
assertEquals(100L, histories.get(2).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(2).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(histories.get(2).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("-80.00").compareTo(histories.get(2).getTotalPrice()));
|
||||
}
|
||||
|
||||
@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<WmsInventoryChangeReqDTO.Item> 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<WmsInventoryHistoryDO> 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", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
int threadCount = 4;
|
||||
CountDownLatch readyLatch = new CountDownLatch(threadCount);
|
||||
CountDownLatch startLatch = new CountDownLatch(1);
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
|
||||
List<Future<?>> futures = new ArrayList<>(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
futures.add(executorService.submit(() -> {
|
||||
readyLatch.countDown();
|
||||
try {
|
||||
startLatch.await();
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
inventoryService.changeInventory(createChangeReq(sku.getId(), 100L, "1.00"));
|
||||
}));
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用
|
||||
assertTrue(readyLatch.await(5, TimeUnit.SECONDS));
|
||||
startLatch.countDown();
|
||||
for (Future<?> future : futures) {
|
||||
future.get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
} finally {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
// 断言:并发补行后仍只有一条库存余额,数量累计正确
|
||||
List<WmsInventoryDO> inventories = inventoryMapper.selectListByKeys(Collections.singletonList(
|
||||
new WmsInventoryDO().setSkuId(sku.getId()).setWarehouseId(100L)));
|
||||
assertEquals(1, inventories.size());
|
||||
assertEquals(0, new BigDecimal("4.00").compareTo(inventories.get(0).getQuantity()));
|
||||
assertEquals(threadCount, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_quantityNotEnough() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "-3.00");
|
||||
mockItemSkuAndItem(item, sku);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH,
|
||||
item.getName(), sku.getName(), 100L, new BigDecimal("2.00"), new BigDecimal("-3.00"));
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(inventory.getQuantity()));
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_quantityNotEnoughWithoutInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "-3.00");
|
||||
mockItemSkuAndItem(item, sku);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH,
|
||||
item.getName(), sku.getName(), 100L, new BigDecimal("0.00"), new BigDecimal("-3.00"));
|
||||
assertEquals(0L, inventoryMapper.selectCount());
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeInventory_quantityNotEnoughRollbackCreatedInventories() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "5.00");
|
||||
List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems());
|
||||
items.add(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(sku.getId())
|
||||
.setWarehouseId(200L)
|
||||
.setQuantity(new BigDecimal("-1.00"))
|
||||
.setPrice(new BigDecimal("20.00"))
|
||||
.setTotalPrice(new BigDecimal("-20.00"))
|
||||
.setRemark("测试出库"));
|
||||
reqDTO.setItems(items);
|
||||
mockItemSkuAndItem(item, sku);
|
||||
|
||||
// 调用,并断言:第二条明细库存不足,事务回滚前面补齐的库存行
|
||||
assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH,
|
||||
item.getName(), sku.getName(), 200L, new BigDecimal("0.00"), new BigDecimal("-1.00"));
|
||||
assertNull(inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L));
|
||||
assertNull(inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 200L));
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckInventory_updateExistingInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryDO inventory = createInventory(sku.getId(), 100L, "10.00");
|
||||
inventoryMapper.insert(inventory);
|
||||
WmsInventoryCheckReqDTO reqDTO = createCheckReq(inventory.getId(), sku.getId(), 100L,
|
||||
"10.00", "7.00");
|
||||
|
||||
// 调用
|
||||
inventoryService.checkInventory(reqDTO);
|
||||
|
||||
// 断言:库存余额直接调整为实盘数量
|
||||
WmsInventoryDO dbInventory = inventoryMapper.selectById(inventory.getId());
|
||||
assertNotNull(dbInventory);
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(dbInventory.getQuantity()));
|
||||
// 断言:库存流水记录盘库差异
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
assertEquals(1, histories.size());
|
||||
WmsInventoryHistoryDO history = histories.get(0);
|
||||
assertEquals(sku.getId(), history.getSkuId());
|
||||
assertEquals(100L, history.getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("10.00").compareTo(history.getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(history.getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("-3.00").compareTo(history.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("-300.00").compareTo(history.getTotalPrice()));
|
||||
assertEquals(reqDTO.getOrderId(), history.getOrderId());
|
||||
assertEquals(reqDTO.getOrderNo(), history.getOrderNo());
|
||||
assertEquals(reqDTO.getOrderType(), history.getOrderType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckInventory_existingInventoryChanged() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryDO inventory = createInventory(sku.getId(), 100L, "12.00");
|
||||
inventoryMapper.insert(inventory);
|
||||
WmsInventoryCheckReqDTO reqDTO = createCheckReq(inventory.getId(), sku.getId(), 100L,
|
||||
"10.00", "7.00");
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> inventoryService.checkInventory(reqDTO), CHECK_ORDER_INVENTORY_CHANGED);
|
||||
WmsInventoryDO dbInventory = inventoryMapper.selectById(inventory.getId());
|
||||
assertNotNull(dbInventory);
|
||||
assertEquals(0, new BigDecimal("12.00").compareTo(dbInventory.getQuantity()));
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckInventory_createNewInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryCheckReqDTO reqDTO = createCheckReq(null, sku.getId(), 100L,
|
||||
"0.00", "5.00");
|
||||
|
||||
// 调用
|
||||
inventoryService.checkInventory(reqDTO);
|
||||
|
||||
// 断言:新增库存直接落为实盘数量
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(inventory.getQuantity()));
|
||||
// 断言:库存流水记录从 0 到实盘数量
|
||||
List<WmsInventoryHistoryDO> histories = inventoryHistoryMapper.selectList();
|
||||
assertEquals(1, histories.size());
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(histories.get(0).getBeforeQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getAfterQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(histories.get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("500.00").compareTo(histories.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckInventory_createNewZeroInventory() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsInventoryCheckReqDTO reqDTO = createCheckReq(null, sku.getId(), 100L,
|
||||
"0.00", "0.00");
|
||||
|
||||
// 调用
|
||||
inventoryService.checkInventory(reqDTO);
|
||||
|
||||
// 断言:新增零库存商品也会生成库存余额行
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, BigDecimal.ZERO.compareTo(inventory.getQuantity()));
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckInventory_newInventoryAlreadyExists() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "3.00"));
|
||||
WmsInventoryCheckReqDTO reqDTO = createCheckReq(null, sku.getId(), 100L,
|
||||
"0.00", "5.00");
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> inventoryService.checkInventory(reqDTO), CHECK_ORDER_INVENTORY_CHANGED);
|
||||
WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L);
|
||||
assertNotNull(inventory);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(inventory.getQuantity()));
|
||||
assertEquals(0L, inventoryHistoryMapper.selectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventoryPage_filterByWarehouse() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 200L, "5.00"));
|
||||
// 准备参数
|
||||
WmsInventoryPageReqVO reqVO = new WmsInventoryPageReqVO();
|
||||
reqVO.setType(WmsInventoryPageReqVO.TYPE_WAREHOUSE);
|
||||
reqVO.setWarehouseId(100L);
|
||||
|
||||
// 调用
|
||||
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
WmsInventoryDO inventory = pageResult.getList().get(0);
|
||||
assertEquals(100L, inventory.getWarehouseId());
|
||||
assertEquals(sku.getId(), inventory.getSkuId());
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(inventory.getQuantity()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventoryPage_groupByWarehouse_minQuantity() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 200L, "7.00"));
|
||||
// 准备参数
|
||||
WmsInventoryPageReqVO reqVO = new WmsInventoryPageReqVO();
|
||||
reqVO.setType(WmsInventoryPageReqVO.TYPE_WAREHOUSE);
|
||||
reqVO.setMinQuantity(new BigDecimal("6.00"));
|
||||
|
||||
// 调用
|
||||
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertEquals(200L, pageResult.getList().get(0).getWarehouseId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventoryPage_onlyPositiveQuantity() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "0.00"));
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 200L, "0.01"));
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 300L, "1.00"));
|
||||
// 准备参数
|
||||
WmsInventoryPageReqVO reqVO = new WmsInventoryPageReqVO();
|
||||
reqVO.setType(WmsInventoryPageReqVO.TYPE_WAREHOUSE);
|
||||
reqVO.setOnlyPositiveQuantity(true);
|
||||
|
||||
// 调用
|
||||
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(2, pageResult.getTotal());
|
||||
assertEquals(2, pageResult.getList().size());
|
||||
assertEquals(200L, pageResult.getList().get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("0.01").compareTo(pageResult.getList().get(0).getQuantity()));
|
||||
assertEquals(300L, pageResult.getList().get(1).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("1.00").compareTo(pageResult.getList().get(1).getQuantity()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventoryPage_sku() {
|
||||
// mock 数据
|
||||
WmsItemDO item = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsItemSkuDO sku2 = createSku(item.getId(), "SKU-002", "5kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku.getId(), 100L, "2.00"));
|
||||
inventoryMapper.insert(createInventory(sku2.getId(), 100L, "3.00"));
|
||||
// 准备参数
|
||||
WmsInventoryPageReqVO reqVO = new WmsInventoryPageReqVO();
|
||||
reqVO.setType(WmsInventoryPageReqVO.TYPE_ITEM);
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setSkuId(sku.getId());
|
||||
|
||||
// 调用
|
||||
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertEquals(sku.getId(), pageResult.getList().get(0).getSkuId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventoryPage_orderByItemDimension() {
|
||||
// mock 数据
|
||||
WmsItemDO item1 = createItem("ITEM-001", "红富士苹果");
|
||||
WmsItemSkuDO sku1 = createSku(item1.getId(), "SKU-001", "10kg 箱装");
|
||||
WmsItemDO item2 = createItem("ITEM-002", "香蕉");
|
||||
WmsItemSkuDO sku2 = createSku(item2.getId(), "SKU-002", "5kg 箱装");
|
||||
inventoryMapper.insert(createInventory(sku2.getId(), 100L, "3.00"));
|
||||
inventoryMapper.insert(createInventory(sku1.getId(), 200L, "2.00"));
|
||||
inventoryMapper.insert(createInventory(sku1.getId(), 100L, "1.00"));
|
||||
// 准备参数
|
||||
WmsInventoryPageReqVO reqVO = new WmsInventoryPageReqVO();
|
||||
reqVO.setType(WmsInventoryPageReqVO.TYPE_ITEM);
|
||||
|
||||
// 调用
|
||||
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(3, pageResult.getTotal());
|
||||
assertEquals(sku1.getId(), pageResult.getList().get(0).getSkuId());
|
||||
assertEquals(100L, pageResult.getList().get(0).getWarehouseId());
|
||||
assertEquals(sku1.getId(), pageResult.getList().get(1).getSkuId());
|
||||
assertEquals(200L, pageResult.getList().get(1).getWarehouseId());
|
||||
assertEquals(sku2.getId(), pageResult.getList().get(2).getSkuId());
|
||||
assertEquals(100L, pageResult.getList().get(2).getWarehouseId());
|
||||
}
|
||||
|
||||
private WmsItemDO createItem(String code, String name) {
|
||||
WmsItemDO item = WmsItemDO.builder()
|
||||
.code(code)
|
||||
.name(name)
|
||||
.unit("箱")
|
||||
.categoryId(1L)
|
||||
.build();
|
||||
itemMapper.insert(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
private WmsItemSkuDO createSku(Long itemId, String code, String name) {
|
||||
WmsItemSkuDO sku = WmsItemSkuDO.builder()
|
||||
.itemId(itemId)
|
||||
.code(code)
|
||||
.name(name)
|
||||
.barCode("69010001")
|
||||
.build();
|
||||
skuMapper.insert(sku);
|
||||
return sku;
|
||||
}
|
||||
|
||||
private void mockItemSkuAndItem(WmsItemDO item, WmsItemSkuDO sku) {
|
||||
when(itemSkuService.validateItemSkuExists(sku.getId())).thenReturn(sku);
|
||||
when(itemService.validateItemExists(item.getId())).thenReturn(item);
|
||||
}
|
||||
|
||||
private static WmsInventoryDO createInventory(Long skuId, Long warehouseId, String quantity) {
|
||||
return WmsInventoryDO.builder()
|
||||
.skuId(skuId)
|
||||
.warehouseId(warehouseId)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsInventoryChangeReqDTO createChangeReq(Long skuId, Long warehouseId, String quantity) {
|
||||
return new WmsInventoryChangeReqDTO()
|
||||
.setOrderId(1L)
|
||||
.setOrderNo("RK202605120001")
|
||||
.setOrderType(WmsOrderTypeEnum.RECEIPT.getType())
|
||||
.setItems(Collections.singletonList(new WmsInventoryChangeReqDTO.Item()
|
||||
.setSkuId(skuId)
|
||||
.setWarehouseId(warehouseId)
|
||||
.setQuantity(new BigDecimal(quantity))
|
||||
.setPrice(new BigDecimal("100.00"))
|
||||
.setTotalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")))
|
||||
.setRemark("测试入库")));
|
||||
}
|
||||
|
||||
private static WmsInventoryCheckReqDTO createCheckReq(Long inventoryId, Long skuId, Long warehouseId,
|
||||
String quantity, String checkQuantity) {
|
||||
return new WmsInventoryCheckReqDTO()
|
||||
.setOrderId(2L)
|
||||
.setOrderNo("PK202605120001")
|
||||
.setOrderType(WmsOrderTypeEnum.CHECK.getType())
|
||||
.setItems(Collections.singletonList(new WmsInventoryCheckReqDTO.Item()
|
||||
.setInventoryId(inventoryId)
|
||||
.setSkuId(skuId)
|
||||
.setWarehouseId(warehouseId)
|
||||
.setQuantity(new BigDecimal(quantity))
|
||||
.setCheckQuantity(new BigDecimal(checkQuantity))
|
||||
.setPrice(new BigDecimal("100.00"))
|
||||
.setRemark("测试盘库")));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package cn.iocoder.yudao.module.wms.service.md.item;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemBrandDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.md.item.WmsItemBrandMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_NAME_DUPLICATE;
|
||||
|
||||
@Import(WmsItemBrandServiceImpl.class)
|
||||
public class WmsItemBrandServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsItemBrandServiceImpl brandService;
|
||||
|
||||
@Resource
|
||||
private WmsItemBrandMapper brandMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemService itemService;
|
||||
|
||||
@Test
|
||||
public void testCreateItemBrand_nameDuplicate() {
|
||||
// mock 数据
|
||||
brandMapper.insert(createBrand("B001", "华为"));
|
||||
WmsItemBrandSaveReqVO reqVO = createBrandSaveReqVO(null, "B002", "华为");
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> brandService.createItemBrand(reqVO), ITEM_BRAND_NAME_DUPLICATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateItemBrand_nameDuplicate() {
|
||||
// mock 数据
|
||||
brandMapper.insert(createBrand("B001", "华为"));
|
||||
WmsItemBrandDO brand = createBrand("B002", "小米");
|
||||
brandMapper.insert(brand);
|
||||
WmsItemBrandSaveReqVO reqVO = createBrandSaveReqVO(brand.getId(), "B002", "华为");
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> brandService.updateItemBrand(reqVO), ITEM_BRAND_NAME_DUPLICATE);
|
||||
}
|
||||
|
||||
private static WmsItemBrandDO createBrand(String code, String name) {
|
||||
return WmsItemBrandDO.builder()
|
||||
.code(code)
|
||||
.name(name)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsItemBrandSaveReqVO createBrandSaveReqVO(Long id, String code, String name) {
|
||||
WmsItemBrandSaveReqVO reqVO = new WmsItemBrandSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setCode(code);
|
||||
reqVO.setName(name);
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package cn.iocoder.yudao.module.wms.service.md.warehouse;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo.WmsWarehouseSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.md.warehouse.WmsWarehouseMapper;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
|
||||
import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderService;
|
||||
import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderService;
|
||||
import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderService;
|
||||
import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.WAREHOUSE_CODE_DUPLICATE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.WAREHOUSE_HAS_INVENTORY;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Import(WmsWarehouseServiceImpl.class)
|
||||
public class WmsWarehouseServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsWarehouseServiceImpl warehouseService;
|
||||
|
||||
@Resource
|
||||
private WmsWarehouseMapper warehouseMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsInventoryService inventoryService;
|
||||
@MockitoBean
|
||||
private WmsReceiptOrderService receiptOrderService;
|
||||
@MockitoBean
|
||||
private WmsShipmentOrderService shipmentOrderService;
|
||||
@MockitoBean
|
||||
private WmsMovementOrderService movementOrderService;
|
||||
@MockitoBean
|
||||
private WmsCheckOrderService checkOrderService;
|
||||
|
||||
@Test
|
||||
public void testCreateWarehouse_codeDuplicate() {
|
||||
// mock 数据
|
||||
WmsWarehouseDO warehouse = createWarehouse("WH001", "成品仓");
|
||||
warehouseMapper.insert(warehouse);
|
||||
|
||||
// 调用,并断言
|
||||
WmsWarehouseSaveReqVO reqVO = createWarehouseSaveReqVO();
|
||||
assertServiceException(() -> warehouseService.createWarehouse(reqVO), WAREHOUSE_CODE_DUPLICATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWarehouse_codeDuplicate() {
|
||||
// mock 数据
|
||||
WmsWarehouseDO warehouse = createWarehouse("WH001", "成品仓");
|
||||
warehouseMapper.insert(warehouse);
|
||||
WmsWarehouseDO updateWarehouse = createWarehouse("WH002", "原料仓");
|
||||
warehouseMapper.insert(updateWarehouse);
|
||||
|
||||
// 调用,并断言
|
||||
WmsWarehouseSaveReqVO reqVO = createWarehouseSaveReqVO();
|
||||
reqVO.setId(updateWarehouse.getId());
|
||||
assertServiceException(() -> warehouseService.updateWarehouse(reqVO), WAREHOUSE_CODE_DUPLICATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteWarehouse_hasInventory() {
|
||||
// mock 数据
|
||||
WmsWarehouseDO warehouse = createWarehouse();
|
||||
warehouseMapper.insert(warehouse);
|
||||
when(inventoryService.getInventoryCountByWarehouseId(warehouse.getId())).thenReturn(1L);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> warehouseService.deleteWarehouse(warehouse.getId()), WAREHOUSE_HAS_INVENTORY);
|
||||
assertNotNull(warehouseMapper.selectById(warehouse.getId()));
|
||||
}
|
||||
|
||||
private static WmsWarehouseDO createWarehouse() {
|
||||
return createWarehouse("WH001", "成品仓");
|
||||
}
|
||||
|
||||
private static WmsWarehouseDO createWarehouse(String code, String name) {
|
||||
return WmsWarehouseDO.builder()
|
||||
.code(code)
|
||||
.name(name)
|
||||
.sort(1)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsWarehouseSaveReqVO createWarehouseSaveReqVO() {
|
||||
WmsWarehouseSaveReqVO reqVO = new WmsWarehouseSaveReqVO();
|
||||
reqVO.setCode("WH001");
|
||||
reqVO.setName("半成品仓");
|
||||
reqVO.setSort(1);
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.check;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@Import(WmsCheckOrderDetailServiceImpl.class)
|
||||
public class WmsCheckOrderDetailServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsCheckOrderDetailServiceImpl checkOrderDetailService;
|
||||
|
||||
@Resource
|
||||
private WmsCheckOrderDetailMapper checkOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
|
||||
@Test
|
||||
public void testCreateCheckOrderDetailList_success() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(
|
||||
createCheckOrderDetailReqVO(null, 1001L, "10.00", "9.00"),
|
||||
createCheckOrderDetailReqVO(null, 1002L, "20.00", "21.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderDetailService.createCheckOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(orderId, details.get(0).getOrderId());
|
||||
assertEquals(orderId, details.get(1).getOrderId());
|
||||
assertEquals(100L, details.get(0).getWarehouseId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCheckOrderDetailList_ignoreId() {
|
||||
// mock 数据
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(
|
||||
createCheckOrderDetailReqVO(999L, 1001L, "10.00", "9.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderDetailService.createCheckOrderDetailList(10L, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(10L);
|
||||
assertEquals(1, details.size());
|
||||
assertNotNull(details.get(0).getId());
|
||||
assertEquals(1001L, details.get(0).getSkuId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCheckOrderDetailList_diff() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsCheckOrderDetailDO detail01 = createCheckOrderDetail(orderId, 1001L, "10.00", "9.00");
|
||||
WmsCheckOrderDetailDO detail02 = createCheckOrderDetail(orderId, 1002L, "20.00", "21.00");
|
||||
checkOrderDetailMapper.insert(detail01);
|
||||
checkOrderDetailMapper.insert(detail02);
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(
|
||||
createCheckOrderDetailReqVO(detail01.getId(), 2001L, "11.00", "8.00"),
|
||||
createCheckOrderDetailReqVO(null, 2002L, "22.00", "25.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderDetailService.updateCheckOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言:修改
|
||||
WmsCheckOrderDetailDO dbUpdateDetail = checkOrderDetailMapper.selectById(detail01.getId());
|
||||
assertNotNull(dbUpdateDetail);
|
||||
assertEquals(orderId, dbUpdateDetail.getOrderId());
|
||||
assertEquals(2001L, dbUpdateDetail.getSkuId());
|
||||
assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("8.00").compareTo(dbUpdateDetail.getCheckQuantity()));
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(dbUpdateDetail.getPrice()));
|
||||
assertEquals(100L, dbUpdateDetail.getWarehouseId());
|
||||
// 断言:新增
|
||||
List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
WmsCheckOrderDetailDO dbCreateDetail = details.stream()
|
||||
.filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId()))
|
||||
.findFirst().orElse(null);
|
||||
assertNotNull(dbCreateDetail);
|
||||
assertEquals(orderId, dbCreateDetail.getOrderId());
|
||||
assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("25.00").compareTo(dbCreateDetail.getCheckQuantity()));
|
||||
// 断言:删除
|
||||
assertNull(checkOrderDetailMapper.selectById(detail02.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCheckOrderDetailList_detailNotExists() {
|
||||
// mock 数据
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(
|
||||
createCheckOrderDetailReqVO(999L, 1001L, "10.00", "9.00"));
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> checkOrderDetailService.updateCheckOrderDetailList(10L, reqVO),
|
||||
CHECK_ORDER_DETAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
private static WmsCheckOrderSaveReqVO createCheckOrderReqVO(WmsCheckOrderDetailSaveReqVO... details) {
|
||||
WmsCheckOrderSaveReqVO reqVO = new WmsCheckOrderSaveReqVO();
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDetailSaveReqVO createCheckOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String checkQuantity) {
|
||||
WmsCheckOrderDetailSaveReqVO reqVO = new WmsCheckOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setInventoryId(300L);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setCheckQuantity(new BigDecimal(checkQuantity));
|
||||
reqVO.setPrice(new BigDecimal("100.00"));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDetailDO createCheckOrderDetail(Long orderId, Long skuId,
|
||||
String quantity, String checkQuantity) {
|
||||
return WmsCheckOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(100L)
|
||||
.inventoryId(300L)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.checkQuantity(new BigDecimal(checkQuantity))
|
||||
.price(new BigDecimal("100.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.check;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderMapper;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryCheckReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_INVENTORY_CHANGED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_DELETABLE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_PREPARE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@Import({WmsCheckOrderServiceImpl.class, WmsCheckOrderDetailServiceImpl.class})
|
||||
public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsCheckOrderServiceImpl checkOrderService;
|
||||
|
||||
@Resource
|
||||
private WmsCheckOrderMapper checkOrderMapper;
|
||||
@Resource
|
||||
private WmsCheckOrderDetailMapper checkOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsWarehouseService warehouseService;
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
@MockitoBean
|
||||
private WmsInventoryService inventoryService;
|
||||
|
||||
@Test
|
||||
public void testCreateCheckOrder_calculateTotals() {
|
||||
// mock 数据
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(100L,
|
||||
createCheckOrderDetailReqVO(null, 200L, "10.00", "7.00", "5.00"),
|
||||
createCheckOrderDetailReqVO(null, 201L, "20.00", "25.00", "2.00"));
|
||||
|
||||
// 调用
|
||||
Long orderId = checkOrderService.createCheckOrder(reqVO);
|
||||
|
||||
// 断言:盘库单汇总由后端计算
|
||||
WmsCheckOrderDO order = checkOrderMapper.selectById(orderId);
|
||||
assertNotNull(order);
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(order.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("90.00").compareTo(order.getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("85.00").compareTo(order.getActualPrice()));
|
||||
// 断言:盘库明细保存单价
|
||||
List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(details.get(0).getPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCheckOrder_calculateTotals() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
WmsCheckOrderDetailDO oldDetail = createCheckOrderDetail(order.getId(), 200L, 100L, "10.00", "7.00");
|
||||
checkOrderDetailMapper.insert(oldDetail);
|
||||
WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO(100L,
|
||||
createCheckOrderDetailReqVO(oldDetail.getId(), 200L, "8.00", "10.00", "6.00"),
|
||||
createCheckOrderDetailReqVO(null, 201L, "2.00", "1.00", "4.00"));
|
||||
reqVO.setId(order.getId());
|
||||
reqVO.setNo(order.getNo());
|
||||
|
||||
// 调用
|
||||
checkOrderService.updateCheckOrder(reqVO);
|
||||
|
||||
// 断言:盘库单汇总由后端重新计算
|
||||
WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("1.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("56.00").compareTo(dbOrder.getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("64.00").compareTo(dbOrder.getActualPrice()));
|
||||
List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(order.getId());
|
||||
assertEquals(2, details.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_success() {
|
||||
// mock 数据
|
||||
Long warehouseId = 100L;
|
||||
Long skuId = 200L;
|
||||
WmsCheckOrderDO order = createCheckOrder(warehouseId);
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), skuId, warehouseId,
|
||||
"10.00", "7.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderService.completeCheckOrder(order.getId());
|
||||
|
||||
// 断言:盘库单
|
||||
WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
|
||||
// 断言:库存盘点
|
||||
ArgumentCaptor<WmsInventoryCheckReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryCheckReqDTO.class);
|
||||
verify(inventoryService).checkInventory(captor.capture());
|
||||
WmsInventoryCheckReqDTO inventoryReqDTO = captor.getValue();
|
||||
assertEquals(order.getId(), inventoryReqDTO.getOrderId());
|
||||
assertEquals(order.getNo(), inventoryReqDTO.getOrderNo());
|
||||
assertEquals(WmsOrderTypeEnum.CHECK.getType(), inventoryReqDTO.getOrderType());
|
||||
assertEquals(1, inventoryReqDTO.getItems().size());
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
|
||||
assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
|
||||
assertEquals(300L, inventoryReqDTO.getItems().get(0).getInventoryId());
|
||||
assertEquals(0, new BigDecimal("10.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("7.00").compareTo(inventoryReqDTO.getItems().get(0).getCheckQuantity()));
|
||||
assertEquals(0, new BigDecimal("30.00").compareTo(inventoryReqDTO.getItems().get(0).getPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_zeroDifference() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), 200L, 100L,
|
||||
"10.00", "10.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderService.completeCheckOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
|
||||
verify(inventoryService).checkInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_newInventoryCurrentMissing() {
|
||||
// mock 数据
|
||||
Long warehouseId = 100L;
|
||||
Long skuId = 200L;
|
||||
WmsCheckOrderDO order = createCheckOrder(warehouseId);
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createNewInventoryCheckOrderDetail(order.getId(), skuId, warehouseId,
|
||||
"0.00", "5.00"));
|
||||
// 调用
|
||||
checkOrderService.completeCheckOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
ArgumentCaptor<WmsInventoryCheckReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryCheckReqDTO.class);
|
||||
verify(inventoryService).checkInventory(captor.capture());
|
||||
WmsInventoryCheckReqDTO inventoryReqDTO = captor.getValue();
|
||||
assertEquals(1, inventoryReqDTO.getItems().size());
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
|
||||
assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
|
||||
assertNull(inventoryReqDTO.getItems().get(0).getInventoryId());
|
||||
assertEquals(0, new BigDecimal("0.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("5.00").compareTo(inventoryReqDTO.getItems().get(0).getCheckQuantity()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_checkInventoryChanged() {
|
||||
// mock 数据
|
||||
Long warehouseId = 100L;
|
||||
Long skuId = 200L;
|
||||
WmsCheckOrderDO order = createCheckOrder(warehouseId);
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createNewInventoryCheckOrderDetail(order.getId(), skuId, warehouseId,
|
||||
"0.00", "5.00"));
|
||||
doThrow(exception(CHECK_ORDER_INVENTORY_CHANGED)).when(inventoryService).checkInventory(any());
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
|
||||
CHECK_ORDER_INVENTORY_CHANGED);
|
||||
assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
|
||||
checkOrderMapper.selectById(order.getId()).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_detailRequired() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
|
||||
CHECK_ORDER_DETAIL_REQUIRED);
|
||||
verify(inventoryService, never()).checkInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteCheckOrder_duplicateComplete() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), 200L, 100L,
|
||||
"10.00", "7.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderService.completeCheckOrder(order.getId());
|
||||
|
||||
// 调用,并断言:二次完成不能再次写库存
|
||||
assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
|
||||
CHECK_ORDER_STATUS_NOT_PREPARE);
|
||||
verify(inventoryService).checkInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelCheckOrder_success() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
checkOrderService.cancelCheckOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus());
|
||||
verify(inventoryService, never()).checkInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByIdAndStatus_statusNotMatch() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L);
|
||||
checkOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
int updateCount = checkOrderMapper.updateByIdAndStatus(order.getId(),
|
||||
WmsOrderStatusEnum.FINISHED.getStatus(),
|
||||
new WmsCheckOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus()));
|
||||
|
||||
// 断言
|
||||
assertEquals(0, updateCount);
|
||||
assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
|
||||
checkOrderMapper.selectById(order.getId()).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteCheckOrder_canceled() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus());
|
||||
checkOrderMapper.insert(order);
|
||||
checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), 200L, 100L,
|
||||
"10.00", "8.00"));
|
||||
|
||||
// 调用
|
||||
checkOrderService.deleteCheckOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
assertNull(checkOrderMapper.selectById(order.getId()));
|
||||
assertEquals(0, checkOrderDetailMapper.selectListByOrderId(order.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteCheckOrder_finished() {
|
||||
// mock 数据
|
||||
WmsCheckOrderDO order = createCheckOrder(100L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus());
|
||||
checkOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> checkOrderService.deleteCheckOrder(order.getId()),
|
||||
CHECK_ORDER_STATUS_NOT_DELETABLE);
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDO createCheckOrder(Long warehouseId) {
|
||||
return new WmsCheckOrderDO()
|
||||
.setNo("PK202605120001")
|
||||
.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0))
|
||||
.setStatus(WmsOrderStatusEnum.PREPARE.getStatus())
|
||||
.setWarehouseId(warehouseId)
|
||||
.setTotalQuantity(new BigDecimal("-3.00"))
|
||||
.setTotalPrice(new BigDecimal("300.00"))
|
||||
.setActualPrice(new BigDecimal("210.00"));
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDetailDO createCheckOrderDetail(Long orderId, Long skuId, Long warehouseId,
|
||||
String quantity, String checkQuantity) {
|
||||
return WmsCheckOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(warehouseId)
|
||||
.inventoryId(300L)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.checkQuantity(new BigDecimal(checkQuantity))
|
||||
.price(new BigDecimal("30.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDetailDO createNewInventoryCheckOrderDetail(Long orderId, Long skuId, Long warehouseId,
|
||||
String quantity, String checkQuantity) {
|
||||
return WmsCheckOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(warehouseId)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.checkQuantity(new BigDecimal(checkQuantity))
|
||||
.price(new BigDecimal("30.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsCheckOrderSaveReqVO createCheckOrderReqVO(Long warehouseId, WmsCheckOrderDetailSaveReqVO... details) {
|
||||
WmsCheckOrderSaveReqVO reqVO = new WmsCheckOrderSaveReqVO();
|
||||
reqVO.setNo("PK202605120002");
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(warehouseId);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsCheckOrderDetailSaveReqVO createCheckOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String checkQuantity,
|
||||
String price) {
|
||||
WmsCheckOrderDetailSaveReqVO reqVO = new WmsCheckOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setInventoryId(300L);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setCheckQuantity(new BigDecimal(checkQuantity));
|
||||
reqVO.setPrice(new BigDecimal(price));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.movement;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_DETAIL_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@Import(WmsMovementOrderDetailServiceImpl.class)
|
||||
public class WmsMovementOrderDetailServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsMovementOrderDetailServiceImpl movementOrderDetailService;
|
||||
|
||||
@Resource
|
||||
private WmsMovementOrderDetailMapper movementOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
|
||||
@Test
|
||||
public void testCreateMovementOrderDetailList_success() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(
|
||||
createMovementOrderDetailReqVO(null, 1001L, "1.00"),
|
||||
createMovementOrderDetailReqVO(null, 1002L, "2.00"));
|
||||
|
||||
// 调用
|
||||
movementOrderDetailService.createMovementOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(orderId, details.get(0).getOrderId());
|
||||
assertEquals(orderId, details.get(1).getOrderId());
|
||||
assertEquals(100L, details.get(0).getSourceWarehouseId());
|
||||
assertEquals(200L, details.get(0).getTargetWarehouseId());
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(details.get(0).getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("200.00").compareTo(details.get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMovementOrderDetailList_ignoreId() {
|
||||
// mock 数据
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(
|
||||
createMovementOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用
|
||||
movementOrderDetailService.createMovementOrderDetailList(10L, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(10L);
|
||||
assertEquals(1, details.size());
|
||||
assertNotNull(details.get(0).getId());
|
||||
assertEquals(1001L, details.get(0).getSkuId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMovementOrderDetailList_diff() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsMovementOrderDetailDO detail01 = createMovementOrderDetail(orderId, 1001L, "1.00");
|
||||
WmsMovementOrderDetailDO detail02 = createMovementOrderDetail(orderId, 1002L, "2.00");
|
||||
movementOrderDetailMapper.insert(detail01);
|
||||
movementOrderDetailMapper.insert(detail02);
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(
|
||||
createMovementOrderDetailReqVO(detail01.getId(), 2001L, "11.00"),
|
||||
createMovementOrderDetailReqVO(null, 2002L, "22.00"));
|
||||
|
||||
// 调用
|
||||
movementOrderDetailService.updateMovementOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言:修改
|
||||
WmsMovementOrderDetailDO dbUpdateDetail = movementOrderDetailMapper.selectById(detail01.getId());
|
||||
assertNotNull(dbUpdateDetail);
|
||||
assertEquals(orderId, dbUpdateDetail.getOrderId());
|
||||
assertEquals(2001L, dbUpdateDetail.getSkuId());
|
||||
assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("1100.00").compareTo(dbUpdateDetail.getTotalPrice()));
|
||||
assertEquals(100L, dbUpdateDetail.getSourceWarehouseId());
|
||||
assertEquals(200L, dbUpdateDetail.getTargetWarehouseId());
|
||||
// 断言:新增
|
||||
List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
WmsMovementOrderDetailDO dbCreateDetail = details.stream()
|
||||
.filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId()))
|
||||
.findFirst().orElse(null);
|
||||
assertNotNull(dbCreateDetail);
|
||||
assertEquals(orderId, dbCreateDetail.getOrderId());
|
||||
assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("2200.00").compareTo(dbCreateDetail.getTotalPrice()));
|
||||
// 断言:删除
|
||||
assertNull(movementOrderDetailMapper.selectById(detail02.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMovementOrderDetailList_detailNotExists() {
|
||||
// mock 数据
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(
|
||||
createMovementOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> movementOrderDetailService.updateMovementOrderDetailList(10L, reqVO),
|
||||
MOVEMENT_ORDER_DETAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
private static WmsMovementOrderSaveReqVO createMovementOrderReqVO(WmsMovementOrderDetailSaveReqVO... details) {
|
||||
WmsMovementOrderSaveReqVO reqVO = new WmsMovementOrderSaveReqVO();
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setSourceWarehouseId(100L);
|
||||
reqVO.setTargetWarehouseId(200L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDetailSaveReqVO createMovementOrderDetailReqVO(Long id, Long skuId, String quantity) {
|
||||
WmsMovementOrderDetailSaveReqVO reqVO = new WmsMovementOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal("100.00"));
|
||||
reqVO.setTotalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDetailDO createMovementOrderDetail(Long orderId, Long skuId, String quantity) {
|
||||
return WmsMovementOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.sourceWarehouseId(100L)
|
||||
.targetWarehouseId(200L)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.price(new BigDecimal("100.00"))
|
||||
.totalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.movement;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderMapper;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_DETAIL_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_STATUS_NOT_DELETABLE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_STATUS_NOT_PREPARE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_WAREHOUSE_SAME;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@Import({WmsMovementOrderServiceImpl.class, WmsMovementOrderDetailServiceImpl.class})
|
||||
public class WmsMovementOrderServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsMovementOrderServiceImpl movementOrderService;
|
||||
|
||||
@Resource
|
||||
private WmsMovementOrderMapper movementOrderMapper;
|
||||
@Resource
|
||||
private WmsMovementOrderDetailMapper movementOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsWarehouseService warehouseService;
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
@MockitoBean
|
||||
private WmsInventoryService inventoryService;
|
||||
|
||||
@Test
|
||||
public void testCreateMovementOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(null, 100L, 200L,
|
||||
createMovementOrderDetailReqVO(null, 3001L, "1.50", "10.00", "16.00"),
|
||||
createMovementOrderDetailReqVO(null, 3002L, "2.50", "20.00", "51.00"));
|
||||
|
||||
// 调用
|
||||
Long orderId = movementOrderService.createMovementOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(orderId);
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("4.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("67.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(0, new BigDecimal("16.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMovementOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L);
|
||||
movementOrderMapper.insert(order);
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(order.getId(), 100L, 200L,
|
||||
createMovementOrderDetailReqVO(null, 3001L, "3.00", "30.00", "88.00"));
|
||||
|
||||
// 调用
|
||||
movementOrderService.updateMovementOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(order.getId());
|
||||
assertEquals(1, details.size());
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteMovementOrder_success() {
|
||||
// mock 数据
|
||||
Long sourceWarehouseId = 100L;
|
||||
Long targetWarehouseId = 200L;
|
||||
Long skuId = 300L;
|
||||
WmsMovementOrderDO order = createMovementOrder(sourceWarehouseId, targetWarehouseId);
|
||||
movementOrderMapper.insert(order);
|
||||
movementOrderDetailMapper.insert(createMovementOrderDetail(order.getId(), skuId,
|
||||
sourceWarehouseId, targetWarehouseId));
|
||||
|
||||
// 调用
|
||||
movementOrderService.completeMovementOrder(order.getId());
|
||||
|
||||
// 断言:移库单
|
||||
WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
|
||||
// 断言:库存变更
|
||||
ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class);
|
||||
verify(inventoryService).changeInventory(captor.capture());
|
||||
WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue();
|
||||
assertEquals(order.getId(), inventoryReqDTO.getOrderId());
|
||||
assertEquals(order.getNo(), inventoryReqDTO.getOrderNo());
|
||||
assertEquals(WmsOrderTypeEnum.MOVEMENT.getType(), inventoryReqDTO.getOrderType());
|
||||
assertEquals(2, inventoryReqDTO.getItems().size());
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
|
||||
assertEquals(sourceWarehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("-2.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("-40.00").compareTo(inventoryReqDTO.getItems().get(0).getTotalPrice()));
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(1).getSkuId());
|
||||
assertEquals(targetWarehouseId, inventoryReqDTO.getItems().get(1).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(inventoryReqDTO.getItems().get(1).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("40.00").compareTo(inventoryReqDTO.getItems().get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteMovementOrder_detailRequired() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L);
|
||||
movementOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> movementOrderService.completeMovementOrder(order.getId()),
|
||||
MOVEMENT_ORDER_DETAIL_REQUIRED);
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteMovementOrder_duplicateComplete() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L);
|
||||
movementOrderMapper.insert(order);
|
||||
movementOrderDetailMapper.insert(createMovementOrderDetail(order.getId(), 300L, 100L, 200L));
|
||||
|
||||
// 调用
|
||||
movementOrderService.completeMovementOrder(order.getId());
|
||||
|
||||
// 调用,并断言:二次完成不能再次写库存
|
||||
assertServiceException(() -> movementOrderService.completeMovementOrder(order.getId()),
|
||||
MOVEMENT_ORDER_STATUS_NOT_PREPARE);
|
||||
verify(inventoryService).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMovementOrder_sameWarehouse() {
|
||||
// 准备参数
|
||||
WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(100L, 100L);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> movementOrderService.createMovementOrder(reqVO), MOVEMENT_ORDER_WAREHOUSE_SAME);
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelMovementOrder_success() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L);
|
||||
movementOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
movementOrderService.cancelMovementOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus());
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByIdAndStatus_statusNotMatch() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L);
|
||||
movementOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
int updateCount = movementOrderMapper.updateByIdAndStatus(order.getId(),
|
||||
WmsOrderStatusEnum.FINISHED.getStatus(),
|
||||
new WmsMovementOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus()));
|
||||
|
||||
// 断言
|
||||
assertEquals(0, updateCount);
|
||||
assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
|
||||
movementOrderMapper.selectById(order.getId()).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteMovementOrder_canceled() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus());
|
||||
movementOrderMapper.insert(order);
|
||||
movementOrderDetailMapper.insert(createMovementOrderDetail(order.getId(), 300L, 100L, 200L));
|
||||
|
||||
// 调用
|
||||
movementOrderService.deleteMovementOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
assertNull(movementOrderMapper.selectById(order.getId()));
|
||||
assertEquals(0, movementOrderDetailMapper.selectListByOrderId(order.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteMovementOrder_finished() {
|
||||
// mock 数据
|
||||
WmsMovementOrderDO order = createMovementOrder(100L, 200L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus());
|
||||
movementOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> movementOrderService.deleteMovementOrder(order.getId()),
|
||||
MOVEMENT_ORDER_STATUS_NOT_DELETABLE);
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDO createMovementOrder(Long sourceWarehouseId, Long targetWarehouseId) {
|
||||
return new WmsMovementOrderDO()
|
||||
.setNo("YK202605120001")
|
||||
.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0))
|
||||
.setStatus(WmsOrderStatusEnum.PREPARE.getStatus())
|
||||
.setSourceWarehouseId(sourceWarehouseId)
|
||||
.setTargetWarehouseId(targetWarehouseId)
|
||||
.setTotalQuantity(new BigDecimal("2.00"))
|
||||
.setTotalPrice(new BigDecimal("20.00"));
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDetailDO createMovementOrderDetail(Long orderId, Long skuId,
|
||||
Long sourceWarehouseId, Long targetWarehouseId) {
|
||||
return WmsMovementOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.sourceWarehouseId(sourceWarehouseId)
|
||||
.targetWarehouseId(targetWarehouseId)
|
||||
.quantity(new BigDecimal("2.00"))
|
||||
.price(new BigDecimal("20.00"))
|
||||
.totalPrice(new BigDecimal("40.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static WmsMovementOrderSaveReqVO createMovementOrderReqVO(Long sourceWarehouseId, Long targetWarehouseId) {
|
||||
return createMovementOrderReqVO(null, sourceWarehouseId, targetWarehouseId);
|
||||
}
|
||||
|
||||
private static WmsMovementOrderSaveReqVO createMovementOrderReqVO(Long id, Long sourceWarehouseId,
|
||||
Long targetWarehouseId,
|
||||
WmsMovementOrderDetailSaveReqVO... details) {
|
||||
WmsMovementOrderSaveReqVO reqVO = new WmsMovementOrderSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setNo("YK202605120001");
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setSourceWarehouseId(sourceWarehouseId);
|
||||
reqVO.setTargetWarehouseId(targetWarehouseId);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDetailSaveReqVO createMovementOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price) {
|
||||
return createMovementOrderDetailReqVO(id, skuId, quantity, price, null);
|
||||
}
|
||||
|
||||
private static WmsMovementOrderDetailSaveReqVO createMovementOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price,
|
||||
String totalPrice) {
|
||||
WmsMovementOrderDetailSaveReqVO reqVO = new WmsMovementOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal(price));
|
||||
if (totalPrice != null) {
|
||||
reqVO.setTotalPrice(new BigDecimal(totalPrice));
|
||||
}
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.receipt;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.receipt.WmsReceiptOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RECEIPT_ORDER_DETAIL_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@Import(WmsReceiptOrderDetailServiceImpl.class)
|
||||
public class WmsReceiptOrderDetailServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsReceiptOrderDetailServiceImpl receiptOrderDetailService;
|
||||
|
||||
@Resource
|
||||
private WmsReceiptOrderDetailMapper receiptOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
|
||||
@Test
|
||||
public void testCreateReceiptOrderDetailList_success() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderReqVO(
|
||||
createReceiptOrderDetailReqVO(null, 1001L, "1.00"),
|
||||
createReceiptOrderDetailReqVO(null, 1002L, "2.00"));
|
||||
|
||||
// 调用
|
||||
receiptOrderDetailService.createReceiptOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsReceiptOrderDetailDO> details = receiptOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(orderId, details.get(0).getOrderId());
|
||||
assertEquals(orderId, details.get(1).getOrderId());
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(details.get(0).getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("200.00").compareTo(details.get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateReceiptOrderDetailList_ignoreId() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderReqVO(
|
||||
createReceiptOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用
|
||||
receiptOrderDetailService.createReceiptOrderDetailList(10L, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsReceiptOrderDetailDO> details = receiptOrderDetailMapper.selectListByOrderId(10L);
|
||||
assertEquals(1, details.size());
|
||||
assertNotNull(details.get(0).getId());
|
||||
assertEquals(1001L, details.get(0).getSkuId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateReceiptOrderDetailList_diff() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsReceiptOrderDetailDO detail01 = createReceiptOrderDetail(orderId, 1001L, "1.00");
|
||||
WmsReceiptOrderDetailDO detail02 = createReceiptOrderDetail(orderId, 1002L, "2.00");
|
||||
receiptOrderDetailMapper.insert(detail01);
|
||||
receiptOrderDetailMapper.insert(detail02);
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderReqVO(
|
||||
createReceiptOrderDetailReqVO(detail01.getId(), 2001L, "11.00"),
|
||||
createReceiptOrderDetailReqVO(null, 2002L, "22.00"));
|
||||
|
||||
// 调用
|
||||
receiptOrderDetailService.updateReceiptOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言:修改
|
||||
WmsReceiptOrderDetailDO dbUpdateDetail = receiptOrderDetailMapper.selectById(detail01.getId());
|
||||
assertNotNull(dbUpdateDetail);
|
||||
assertEquals(orderId, dbUpdateDetail.getOrderId());
|
||||
assertEquals(2001L, dbUpdateDetail.getSkuId());
|
||||
assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("1100.00").compareTo(dbUpdateDetail.getTotalPrice()));
|
||||
// 断言:新增
|
||||
List<WmsReceiptOrderDetailDO> details = receiptOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
WmsReceiptOrderDetailDO dbCreateDetail = details.stream()
|
||||
.filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId()))
|
||||
.findFirst().orElse(null);
|
||||
assertNotNull(dbCreateDetail);
|
||||
assertEquals(orderId, dbCreateDetail.getOrderId());
|
||||
assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("2200.00").compareTo(dbCreateDetail.getTotalPrice()));
|
||||
// 断言:删除
|
||||
assertNull(receiptOrderDetailMapper.selectById(detail02.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateReceiptOrderDetailList_detailNotExists() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderReqVO(
|
||||
createReceiptOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> receiptOrderDetailService.updateReceiptOrderDetailList(10L, reqVO),
|
||||
RECEIPT_ORDER_DETAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderSaveReqVO createReceiptOrderReqVO(WmsReceiptOrderDetailSaveReqVO... details) {
|
||||
WmsReceiptOrderSaveReqVO reqVO = new WmsReceiptOrderSaveReqVO();
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDetailSaveReqVO createReceiptOrderDetailReqVO(Long id, Long skuId, String quantity) {
|
||||
WmsReceiptOrderDetailSaveReqVO reqVO = new WmsReceiptOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal("100.00"));
|
||||
reqVO.setTotalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDetailDO createReceiptOrderDetail(Long orderId, Long skuId, String quantity) {
|
||||
return WmsReceiptOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(100L)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.price(new BigDecimal("100.00"))
|
||||
.totalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.receipt;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.receipt.WmsReceiptOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.receipt.WmsReceiptOrderMapper;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsReceiptOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RECEIPT_ORDER_DETAIL_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RECEIPT_ORDER_STATUS_NOT_PREPARE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RECEIPT_ORDER_STATUS_NOT_DELETABLE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@Import({WmsReceiptOrderServiceImpl.class, WmsReceiptOrderDetailServiceImpl.class})
|
||||
public class WmsReceiptOrderServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsReceiptOrderServiceImpl receiptOrderService;
|
||||
|
||||
@Resource
|
||||
private WmsReceiptOrderMapper receiptOrderMapper;
|
||||
@Resource
|
||||
private WmsReceiptOrderDetailMapper receiptOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsWarehouseService warehouseService;
|
||||
@MockitoBean
|
||||
private WmsMerchantService merchantService;
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
@MockitoBean
|
||||
private WmsInventoryService inventoryService;
|
||||
|
||||
@Test
|
||||
public void testCreateReceiptOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderSaveReqVO(null,
|
||||
createReceiptOrderDetailReqVO(null, 2001L, "1.50", "10.00", "16.00"),
|
||||
createReceiptOrderDetailReqVO(null, 2002L, "2.50", "20.00", "51.00"));
|
||||
|
||||
// 调用
|
||||
Long orderId = receiptOrderService.createReceiptOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsReceiptOrderDO dbOrder = receiptOrderMapper.selectById(orderId);
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("4.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("67.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsReceiptOrderDetailDO> details = receiptOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(0, new BigDecimal("16.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateReceiptOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L);
|
||||
receiptOrderMapper.insert(order);
|
||||
WmsReceiptOrderSaveReqVO reqVO = createReceiptOrderSaveReqVO(order.getId(),
|
||||
createReceiptOrderDetailReqVO(null, 2001L, "3.00", "30.00", "88.00"));
|
||||
|
||||
// 调用
|
||||
receiptOrderService.updateReceiptOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsReceiptOrderDO dbOrder = receiptOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsReceiptOrderDetailDO> details = receiptOrderDetailMapper.selectListByOrderId(order.getId());
|
||||
assertEquals(1, details.size());
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteReceiptOrder_success() {
|
||||
// mock 数据
|
||||
Long warehouseId = 100L;
|
||||
Long skuId = 200L;
|
||||
WmsReceiptOrderDO order = createReceiptOrder(warehouseId);
|
||||
receiptOrderMapper.insert(order);
|
||||
receiptOrderDetailMapper.insert(createReceiptOrderDetail(order.getId(), skuId, warehouseId));
|
||||
|
||||
// 调用
|
||||
receiptOrderService.completeReceiptOrder(order.getId());
|
||||
|
||||
// 断言:入库单
|
||||
WmsReceiptOrderDO dbOrder = receiptOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
|
||||
// 断言:库存变更
|
||||
ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class);
|
||||
verify(inventoryService).changeInventory(captor.capture());
|
||||
WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue();
|
||||
assertEquals(order.getId(), inventoryReqDTO.getOrderId());
|
||||
assertEquals(order.getNo(), inventoryReqDTO.getOrderNo());
|
||||
assertEquals(WmsOrderTypeEnum.RECEIPT.getType(), inventoryReqDTO.getOrderType());
|
||||
assertEquals(1, inventoryReqDTO.getItems().size());
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
|
||||
assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("2.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("40.00").compareTo(inventoryReqDTO.getItems().get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteReceiptOrder_detailRequired() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L);
|
||||
receiptOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> receiptOrderService.completeReceiptOrder(order.getId()),
|
||||
RECEIPT_ORDER_DETAIL_REQUIRED);
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteReceiptOrder_duplicateComplete() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L);
|
||||
receiptOrderMapper.insert(order);
|
||||
receiptOrderDetailMapper.insert(createReceiptOrderDetail(order.getId(), 200L, 100L));
|
||||
|
||||
// 调用
|
||||
receiptOrderService.completeReceiptOrder(order.getId());
|
||||
|
||||
// 调用,并断言:二次完成不能再次写库存
|
||||
assertServiceException(() -> receiptOrderService.completeReceiptOrder(order.getId()),
|
||||
RECEIPT_ORDER_STATUS_NOT_PREPARE);
|
||||
verify(inventoryService).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelReceiptOrder_success() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L);
|
||||
receiptOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
receiptOrderService.cancelReceiptOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
WmsReceiptOrderDO dbOrder = receiptOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus());
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByIdAndStatus_statusNotMatch() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L);
|
||||
receiptOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
int updateCount = receiptOrderMapper.updateByIdAndStatus(order.getId(),
|
||||
WmsOrderStatusEnum.FINISHED.getStatus(),
|
||||
new WmsReceiptOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus()));
|
||||
|
||||
// 断言
|
||||
assertEquals(0, updateCount);
|
||||
assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
|
||||
receiptOrderMapper.selectById(order.getId()).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteReceiptOrder_canceled() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus());
|
||||
receiptOrderMapper.insert(order);
|
||||
receiptOrderDetailMapper.insert(createReceiptOrderDetail(order.getId(), 200L, 100L));
|
||||
|
||||
// 调用
|
||||
receiptOrderService.deleteReceiptOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
assertNull(receiptOrderMapper.selectById(order.getId()));
|
||||
assertEquals(0, receiptOrderDetailMapper.selectListByOrderId(order.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteReceiptOrder_finished() {
|
||||
// mock 数据
|
||||
WmsReceiptOrderDO order = createReceiptOrder(100L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus());
|
||||
receiptOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> receiptOrderService.deleteReceiptOrder(order.getId()),
|
||||
RECEIPT_ORDER_STATUS_NOT_DELETABLE);
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDO createReceiptOrder(Long warehouseId) {
|
||||
return new WmsReceiptOrderDO()
|
||||
.setNo("RK202605120001")
|
||||
.setType(WmsReceiptOrderTypeEnum.PURCHASE.getType())
|
||||
.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0))
|
||||
.setStatus(WmsOrderStatusEnum.PREPARE.getStatus())
|
||||
.setWarehouseId(warehouseId)
|
||||
.setTotalQuantity(new BigDecimal("2.00"))
|
||||
.setTotalPrice(new BigDecimal("20.00"));
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderSaveReqVO createReceiptOrderSaveReqVO(Long id,
|
||||
WmsReceiptOrderDetailSaveReqVO... details) {
|
||||
WmsReceiptOrderSaveReqVO reqVO = new WmsReceiptOrderSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setNo("RK202605120001");
|
||||
reqVO.setType(WmsReceiptOrderTypeEnum.PURCHASE.getType());
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDetailSaveReqVO createReceiptOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price) {
|
||||
return createReceiptOrderDetailReqVO(id, skuId, quantity, price, null);
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDetailSaveReqVO createReceiptOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price,
|
||||
String totalPrice) {
|
||||
WmsReceiptOrderDetailSaveReqVO reqVO = new WmsReceiptOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal(price));
|
||||
if (totalPrice != null) {
|
||||
reqVO.setTotalPrice(new BigDecimal(totalPrice));
|
||||
}
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsReceiptOrderDetailDO createReceiptOrderDetail(Long orderId, Long skuId, Long warehouseId) {
|
||||
return WmsReceiptOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(warehouseId)
|
||||
.quantity(new BigDecimal("2.00"))
|
||||
.price(new BigDecimal("20.00"))
|
||||
.totalPrice(new BigDecimal("40.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.shipment;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_DETAIL_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@Import(WmsShipmentOrderDetailServiceImpl.class)
|
||||
public class WmsShipmentOrderDetailServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsShipmentOrderDetailServiceImpl shipmentOrderDetailService;
|
||||
|
||||
@Resource
|
||||
private WmsShipmentOrderDetailMapper shipmentOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
|
||||
@Test
|
||||
public void testCreateShipmentOrderDetailList_success() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO(
|
||||
createShipmentOrderDetailReqVO(null, 1001L, "1.00"),
|
||||
createShipmentOrderDetailReqVO(null, 1002L, "2.00"));
|
||||
|
||||
// 调用
|
||||
shipmentOrderDetailService.createShipmentOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(orderId, details.get(0).getOrderId());
|
||||
assertEquals(orderId, details.get(1).getOrderId());
|
||||
assertEquals(100L, details.get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(details.get(0).getTotalPrice()));
|
||||
assertEquals(0, new BigDecimal("200.00").compareTo(details.get(1).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateShipmentOrderDetailList_ignoreId() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO(
|
||||
createShipmentOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用
|
||||
shipmentOrderDetailService.createShipmentOrderDetailList(10L, reqVO);
|
||||
|
||||
// 断言
|
||||
List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(10L);
|
||||
assertEquals(1, details.size());
|
||||
assertNotNull(details.get(0).getId());
|
||||
assertEquals(1001L, details.get(0).getSkuId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateShipmentOrderDetailList_diff() {
|
||||
// mock 数据
|
||||
Long orderId = 10L;
|
||||
WmsShipmentOrderDetailDO detail01 = createShipmentOrderDetail(orderId, 1001L, "1.00");
|
||||
WmsShipmentOrderDetailDO detail02 = createShipmentOrderDetail(orderId, 1002L, "2.00");
|
||||
shipmentOrderDetailMapper.insert(detail01);
|
||||
shipmentOrderDetailMapper.insert(detail02);
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO(
|
||||
createShipmentOrderDetailReqVO(detail01.getId(), 2001L, "11.00"),
|
||||
createShipmentOrderDetailReqVO(null, 2002L, "22.00"));
|
||||
|
||||
// 调用
|
||||
shipmentOrderDetailService.updateShipmentOrderDetailList(orderId, reqVO);
|
||||
|
||||
// 断言:修改
|
||||
WmsShipmentOrderDetailDO dbUpdateDetail = shipmentOrderDetailMapper.selectById(detail01.getId());
|
||||
assertNotNull(dbUpdateDetail);
|
||||
assertEquals(orderId, dbUpdateDetail.getOrderId());
|
||||
assertEquals(2001L, dbUpdateDetail.getSkuId());
|
||||
assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("1100.00").compareTo(dbUpdateDetail.getTotalPrice()));
|
||||
// 断言:新增
|
||||
List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
WmsShipmentOrderDetailDO dbCreateDetail = details.stream()
|
||||
.filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId()))
|
||||
.findFirst().orElse(null);
|
||||
assertNotNull(dbCreateDetail);
|
||||
assertEquals(orderId, dbCreateDetail.getOrderId());
|
||||
assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity()));
|
||||
assertEquals(0, new BigDecimal("2200.00").compareTo(dbCreateDetail.getTotalPrice()));
|
||||
// 断言:删除
|
||||
assertNull(shipmentOrderDetailMapper.selectById(detail02.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateShipmentOrderDetailList_detailNotExists() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO(
|
||||
createShipmentOrderDetailReqVO(999L, 1001L, "1.00"));
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> shipmentOrderDetailService.updateShipmentOrderDetailList(10L, reqVO),
|
||||
SHIPMENT_ORDER_DETAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderSaveReqVO createShipmentOrderReqVO(WmsShipmentOrderDetailSaveReqVO... details) {
|
||||
WmsShipmentOrderSaveReqVO reqVO = new WmsShipmentOrderSaveReqVO();
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDetailSaveReqVO createShipmentOrderDetailReqVO(Long id, Long skuId, String quantity) {
|
||||
WmsShipmentOrderDetailSaveReqVO reqVO = new WmsShipmentOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal("100.00"));
|
||||
reqVO.setTotalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDetailDO createShipmentOrderDetail(Long orderId, Long skuId, String quantity) {
|
||||
return WmsShipmentOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(100L)
|
||||
.quantity(new BigDecimal(quantity))
|
||||
.price(new BigDecimal("100.00"))
|
||||
.totalPrice(new BigDecimal(quantity).multiply(new BigDecimal("100.00")))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package cn.iocoder.yudao.module.wms.service.order.shipment;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderDetailMapper;
|
||||
import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderMapper;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
|
||||
import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
|
||||
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService;
|
||||
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_DETAIL_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_STATUS_NOT_DELETABLE;
|
||||
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_STATUS_NOT_PREPARE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@Import({WmsShipmentOrderServiceImpl.class, WmsShipmentOrderDetailServiceImpl.class})
|
||||
public class WmsShipmentOrderServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private WmsShipmentOrderServiceImpl shipmentOrderService;
|
||||
|
||||
@Resource
|
||||
private WmsShipmentOrderMapper shipmentOrderMapper;
|
||||
@Resource
|
||||
private WmsShipmentOrderDetailMapper shipmentOrderDetailMapper;
|
||||
|
||||
@MockitoBean
|
||||
private WmsWarehouseService warehouseService;
|
||||
@MockitoBean
|
||||
private WmsMerchantService merchantService;
|
||||
@MockitoBean
|
||||
private WmsItemSkuService itemSkuService;
|
||||
@MockitoBean
|
||||
private WmsInventoryService inventoryService;
|
||||
|
||||
@Test
|
||||
public void testCreateShipmentOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderSaveReqVO(null,
|
||||
createShipmentOrderDetailReqVO(null, 2001L, "1.50", "10.00", "16.00"),
|
||||
createShipmentOrderDetailReqVO(null, 2002L, "2.50", "20.00", "51.00"));
|
||||
|
||||
// 调用
|
||||
Long orderId = shipmentOrderService.createShipmentOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(orderId);
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("4.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("67.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId);
|
||||
assertEquals(2, details.size());
|
||||
assertEquals(0, new BigDecimal("16.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateShipmentOrder_calculateTotal() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L);
|
||||
shipmentOrderMapper.insert(order);
|
||||
WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderSaveReqVO(order.getId(),
|
||||
createShipmentOrderDetailReqVO(null, 2001L, "3.00", "30.00", "88.00"));
|
||||
|
||||
// 调用
|
||||
shipmentOrderService.updateShipmentOrder(reqVO);
|
||||
|
||||
// 断言
|
||||
WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(0, new BigDecimal("3.00").compareTo(dbOrder.getTotalQuantity()));
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(dbOrder.getTotalPrice()));
|
||||
List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(order.getId());
|
||||
assertEquals(1, details.size());
|
||||
assertEquals(0, new BigDecimal("88.00").compareTo(details.get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteShipmentOrder_success() {
|
||||
// mock 数据
|
||||
Long warehouseId = 100L;
|
||||
Long skuId = 200L;
|
||||
WmsShipmentOrderDO order = createShipmentOrder(warehouseId);
|
||||
shipmentOrderMapper.insert(order);
|
||||
shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), skuId, warehouseId));
|
||||
|
||||
// 调用
|
||||
shipmentOrderService.completeShipmentOrder(order.getId());
|
||||
|
||||
// 断言:出库单
|
||||
WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
|
||||
// 断言:库存变更
|
||||
ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class);
|
||||
verify(inventoryService).changeInventory(captor.capture());
|
||||
WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue();
|
||||
assertEquals(order.getId(), inventoryReqDTO.getOrderId());
|
||||
assertEquals(order.getNo(), inventoryReqDTO.getOrderNo());
|
||||
assertEquals(WmsOrderTypeEnum.SHIPMENT.getType(), inventoryReqDTO.getOrderType());
|
||||
assertEquals(1, inventoryReqDTO.getItems().size());
|
||||
assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
|
||||
assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
|
||||
assertEquals(0, new BigDecimal("-2.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
|
||||
assertEquals(0, new BigDecimal("-40.00").compareTo(inventoryReqDTO.getItems().get(0).getTotalPrice()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteShipmentOrder_detailRequired() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L);
|
||||
shipmentOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> shipmentOrderService.completeShipmentOrder(order.getId()),
|
||||
SHIPMENT_ORDER_DETAIL_REQUIRED);
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteShipmentOrder_duplicateComplete() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L);
|
||||
shipmentOrderMapper.insert(order);
|
||||
shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), 200L, 100L));
|
||||
|
||||
// 调用
|
||||
shipmentOrderService.completeShipmentOrder(order.getId());
|
||||
|
||||
// 调用,并断言:二次完成不能再次写库存
|
||||
assertServiceException(() -> shipmentOrderService.completeShipmentOrder(order.getId()),
|
||||
SHIPMENT_ORDER_STATUS_NOT_PREPARE);
|
||||
verify(inventoryService).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelShipmentOrder_success() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L);
|
||||
shipmentOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
shipmentOrderService.cancelShipmentOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(order.getId());
|
||||
assertNotNull(dbOrder);
|
||||
assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus());
|
||||
verify(inventoryService, never()).changeInventory(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByIdAndStatus_statusNotMatch() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L);
|
||||
shipmentOrderMapper.insert(order);
|
||||
|
||||
// 调用
|
||||
int updateCount = shipmentOrderMapper.updateByIdAndStatus(order.getId(),
|
||||
WmsOrderStatusEnum.FINISHED.getStatus(),
|
||||
new WmsShipmentOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus()));
|
||||
|
||||
// 断言
|
||||
assertEquals(0, updateCount);
|
||||
assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
|
||||
shipmentOrderMapper.selectById(order.getId()).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteShipmentOrder_canceled() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus());
|
||||
shipmentOrderMapper.insert(order);
|
||||
shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), 200L, 100L));
|
||||
|
||||
// 调用
|
||||
shipmentOrderService.deleteShipmentOrder(order.getId());
|
||||
|
||||
// 断言
|
||||
assertNull(shipmentOrderMapper.selectById(order.getId()));
|
||||
assertEquals(0, shipmentOrderDetailMapper.selectListByOrderId(order.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteShipmentOrder_finished() {
|
||||
// mock 数据
|
||||
WmsShipmentOrderDO order = createShipmentOrder(100L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus());
|
||||
shipmentOrderMapper.insert(order);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> shipmentOrderService.deleteShipmentOrder(order.getId()),
|
||||
SHIPMENT_ORDER_STATUS_NOT_DELETABLE);
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDO createShipmentOrder(Long warehouseId) {
|
||||
return new WmsShipmentOrderDO()
|
||||
.setNo("CK202605120001")
|
||||
.setType(WmsShipmentOrderTypeEnum.SALE.getType())
|
||||
.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0))
|
||||
.setStatus(WmsOrderStatusEnum.PREPARE.getStatus())
|
||||
.setWarehouseId(warehouseId)
|
||||
.setTotalQuantity(new BigDecimal("2.00"))
|
||||
.setTotalPrice(new BigDecimal("20.00"));
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderSaveReqVO createShipmentOrderSaveReqVO(Long id,
|
||||
WmsShipmentOrderDetailSaveReqVO... details) {
|
||||
WmsShipmentOrderSaveReqVO reqVO = new WmsShipmentOrderSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setNo("CK202605120001");
|
||||
reqVO.setType(WmsShipmentOrderTypeEnum.SALE.getType());
|
||||
reqVO.setOrderTime(LocalDateTime.of(2026, 5, 12, 0, 0));
|
||||
reqVO.setWarehouseId(100L);
|
||||
reqVO.setDetails(Arrays.asList(details));
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDetailSaveReqVO createShipmentOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price) {
|
||||
return createShipmentOrderDetailReqVO(id, skuId, quantity, price, null);
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDetailSaveReqVO createShipmentOrderDetailReqVO(Long id, Long skuId,
|
||||
String quantity, String price,
|
||||
String totalPrice) {
|
||||
WmsShipmentOrderDetailSaveReqVO reqVO = new WmsShipmentOrderDetailSaveReqVO();
|
||||
reqVO.setId(id);
|
||||
reqVO.setSkuId(skuId);
|
||||
reqVO.setQuantity(new BigDecimal(quantity));
|
||||
reqVO.setPrice(new BigDecimal(price));
|
||||
if (totalPrice != null) {
|
||||
reqVO.setTotalPrice(new BigDecimal(totalPrice));
|
||||
}
|
||||
return reqVO;
|
||||
}
|
||||
|
||||
private static WmsShipmentOrderDetailDO createShipmentOrderDetail(Long orderId, Long skuId, Long warehouseId) {
|
||||
return WmsShipmentOrderDetailDO.builder()
|
||||
.orderId(orderId)
|
||||
.skuId(skuId)
|
||||
.warehouseId(warehouseId)
|
||||
.quantity(new BigDecimal("2.00"))
|
||||
.price(new BigDecimal("20.00"))
|
||||
.totalPrice(new BigDecimal("40.00"))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
spring:
|
||||
main:
|
||||
lazy-initialization: true # 开启懒加载,加快速度
|
||||
banner-mode: off # 单元测试,禁用 Banner
|
||||
|
||||
--- #################### 数据库相关配置 ####################
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
|
||||
driver-class-name: org.h2.Driver
|
||||
username: sa
|
||||
password:
|
||||
druid:
|
||||
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
|
||||
initial-size: 1 # 单元测试,配置为 1,提升启动速度
|
||||
sql:
|
||||
init:
|
||||
schema-locations: classpath:/sql/create_tables.sql
|
||||
|
||||
data:
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 16379 # 端口(单元测试,使用 16379 端口)
|
||||
database: 0 # 数据库索引
|
||||
|
||||
mybatis:
|
||||
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
|
||||
|
||||
--- #################### 芋道相关配置 ####################
|
||||
|
||||
yudao:
|
||||
info:
|
||||
base-package: cn.iocoder.yudao.module
|
||||
16
yudao-module-wms/src/test/resources/sql/clean.sql
Normal file
16
yudao-module-wms/src/test/resources/sql/clean.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
DELETE FROM "wms_check_order_detail";
|
||||
DELETE FROM "wms_check_order";
|
||||
DELETE FROM "wms_movement_order_detail";
|
||||
DELETE FROM "wms_movement_order";
|
||||
DELETE FROM "wms_shipment_order_detail";
|
||||
DELETE FROM "wms_shipment_order";
|
||||
DELETE FROM "wms_receipt_order_detail";
|
||||
DELETE FROM "wms_receipt_order";
|
||||
DELETE FROM "wms_inventory_history";
|
||||
DELETE FROM "wms_inventory";
|
||||
DELETE FROM "wms_item_sku";
|
||||
DELETE FROM "wms_item";
|
||||
DELETE FROM "wms_item_category";
|
||||
DELETE FROM "wms_item_brand";
|
||||
DELETE FROM "wms_warehouse";
|
||||
DELETE FROM "wms_merchant";
|
||||
320
yudao-module-wms/src/test/resources/sql/create_tables.sql
Normal file
320
yudao-module-wms/src/test/resources/sql/create_tables.sql
Normal file
@@ -0,0 +1,320 @@
|
||||
CREATE TABLE IF NOT EXISTS "wms_warehouse" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"code" varchar(20) NOT NULL,
|
||||
"name" varchar(50) NOT NULL,
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
"sort" int DEFAULT '0',
|
||||
"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_merchant" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"code" varchar(20) NOT NULL,
|
||||
"name" varchar(60) NOT NULL,
|
||||
"type" tinyint NOT NULL,
|
||||
"level" varchar(10) DEFAULT NULL,
|
||||
"bank_name" varchar(255) DEFAULT NULL,
|
||||
"bank_account" varchar(40) DEFAULT NULL,
|
||||
"address" varchar(200) DEFAULT NULL,
|
||||
"mobile" varchar(13) DEFAULT NULL,
|
||||
"telephone" varchar(13) DEFAULT NULL,
|
||||
"contact" varchar(30) DEFAULT NULL,
|
||||
"email" varchar(50) DEFAULT NULL,
|
||||
"remark" varchar(255) 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_item_brand" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"code" varchar(20) NOT NULL,
|
||||
"name" varchar(30) NOT 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_item_category" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"parent_id" bigint NOT NULL DEFAULT '0',
|
||||
"code" varchar(20) NOT NULL,
|
||||
"name" varchar(30) NOT NULL,
|
||||
"sort" int DEFAULT '0',
|
||||
"status" tinyint NOT NULL DEFAULT '1',
|
||||
"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_item" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"code" varchar(20) DEFAULT NULL,
|
||||
"name" varchar(60) NOT NULL,
|
||||
"category_id" bigint NOT NULL,
|
||||
"unit" varchar(20) DEFAULT NULL,
|
||||
"brand_id" bigint DEFAULT NULL,
|
||||
"remark" varchar(255) 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_item_sku" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"item_id" bigint NOT NULL,
|
||||
"bar_code" varchar(64) DEFAULT NULL,
|
||||
"code" varchar(64) DEFAULT NULL,
|
||||
"length" decimal(10, 1) DEFAULT NULL,
|
||||
"width" decimal(10, 1) DEFAULT NULL,
|
||||
"height" decimal(10, 1) DEFAULT NULL,
|
||||
"gross_weight" decimal(10, 3) DEFAULT NULL,
|
||||
"net_weight" decimal(10, 3) DEFAULT NULL,
|
||||
"cost_price" decimal(16, 2) DEFAULT NULL,
|
||||
"selling_price" decimal(16, 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 商品 SKU 表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "wms_inventory" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"sku_id" bigint NOT NULL,
|
||||
"warehouse_id" bigint NOT NULL,
|
||||
"area_id" bigint NOT NULL DEFAULT '0',
|
||||
"quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"remark" varchar(255) 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"),
|
||||
CONSTRAINT "uk_sku_id_warehouse_id" UNIQUE ("sku_id", "warehouse_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(20, 2) NOT NULL DEFAULT '0',
|
||||
"before_quantity" decimal(20, 2) DEFAULT NULL,
|
||||
"after_quantity" decimal(20, 2) DEFAULT NULL,
|
||||
"batch_no" varchar(64) DEFAULT NULL,
|
||||
"production_date" timestamp DEFAULT NULL,
|
||||
"expiration_date" timestamp DEFAULT NULL,
|
||||
"price" decimal(16, 2) DEFAULT NULL,
|
||||
"total_price" decimal(16, 2) DEFAULT NULL,
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
"order_id" bigint DEFAULT NULL,
|
||||
"order_no" varchar(64) DEFAULT NULL,
|
||||
"order_type" int 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" int NOT NULL,
|
||||
"order_time" timestamp NOT NULL,
|
||||
"status" int 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_price" decimal(16, 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,
|
||||
"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',
|
||||
"price" decimal(16, 2) DEFAULT NULL,
|
||||
"total_price" decimal(16, 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_shipment_order" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"no" varchar(64) NOT NULL,
|
||||
"type" int NOT NULL,
|
||||
"order_time" timestamp NOT NULL,
|
||||
"status" int 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_price" decimal(16, 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_shipment_order_detail" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"order_id" bigint NOT NULL,
|
||||
"sku_id" bigint NOT NULL,
|
||||
"warehouse_id" bigint NOT NULL,
|
||||
"area_id" bigint NOT NULL DEFAULT '0',
|
||||
"inventory_detail_id" bigint DEFAULT NULL,
|
||||
"batch_no" varchar(64) DEFAULT NULL,
|
||||
"production_date" timestamp DEFAULT NULL,
|
||||
"expiration_date" timestamp DEFAULT NULL,
|
||||
"quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"price" decimal(16, 2) DEFAULT NULL,
|
||||
"total_price" decimal(16, 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_movement_order" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"no" varchar(64) NOT NULL,
|
||||
"order_time" timestamp NOT NULL,
|
||||
"status" int NOT NULL DEFAULT '0',
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
"source_warehouse_id" bigint NOT NULL,
|
||||
"target_warehouse_id" bigint NOT NULL,
|
||||
"total_quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"total_price" decimal(16, 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_movement_order_detail" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"order_id" bigint NOT NULL,
|
||||
"sku_id" bigint NOT NULL,
|
||||
"source_warehouse_id" bigint NOT NULL,
|
||||
"target_warehouse_id" bigint NOT NULL,
|
||||
"inventory_detail_id" bigint DEFAULT NULL,
|
||||
"batch_no" varchar(64) DEFAULT NULL,
|
||||
"production_date" timestamp DEFAULT NULL,
|
||||
"expiration_date" timestamp DEFAULT NULL,
|
||||
"quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"price" decimal(16, 2) DEFAULT NULL,
|
||||
"total_price" decimal(16, 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_check_order" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"no" varchar(64) NOT NULL,
|
||||
"order_time" timestamp NOT NULL,
|
||||
"status" int NOT NULL DEFAULT '0',
|
||||
"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_price" decimal(16, 2) DEFAULT NULL,
|
||||
"actual_price" decimal(16, 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_check_order_detail" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"order_id" bigint NOT NULL,
|
||||
"sku_id" bigint NOT NULL,
|
||||
"warehouse_id" bigint NOT NULL,
|
||||
"area_id" bigint NOT NULL DEFAULT '0',
|
||||
"inventory_id" bigint DEFAULT NULL,
|
||||
"inventory_detail_id" bigint DEFAULT NULL,
|
||||
"batch_no" varchar(64) DEFAULT NULL,
|
||||
"production_date" timestamp DEFAULT NULL,
|
||||
"expiration_date" timestamp DEFAULT NULL,
|
||||
"receipt_time" timestamp DEFAULT NULL,
|
||||
"quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"check_quantity" decimal(20, 2) NOT NULL DEFAULT '0',
|
||||
"price" decimal(16, 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 盘库单明细表';
|
||||
Reference in New Issue
Block a user