From 32813c08739b86d51c6ee8437caf0d74f8140f4e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 15 May 2026 08:25:17 +0800 Subject: [PATCH] feat(wms):优化入库、出库等订单的完成、取消逻辑,避免并发问题 --- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/check/WmsCheckOrderMapper.java | 7 +++++++ yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/movement/WmsMovementOrderMapper.java | 7 +++++++ yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/receipt/WmsReceiptOrderMapper.java | 7 +++++++ yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java | 7 +++++++ yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java | 12 ++++++++---- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java | 12 ++++++++---- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java | 12 ++++++++---- yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java | 12 ++++++++---- yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java | 24 ++++++++++++++++++++++++ yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java | 35 +++++++++++++++++++++++++++++++++++ yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java | 34 ++++++++++++++++++++++++++++++++++ yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImplTest.java | 34 ++++++++++++++++++++++++++++++++++ yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java | 34 ++++++++++++++++++++++++++++++++++ 13 files changed, 221 insertions(+), 16 deletions(-) diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/check/WmsCheckOrderMapper.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/check/WmsCheckOrderMapper.java index 723269c..9871e76 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/check/WmsCheckOrderMapper.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/check/WmsCheckOrderMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderPageReqVO; import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -42,4 +43,10 @@ public interface WmsCheckOrderMapper extends BaseMapperX { return selectCount(WmsCheckOrderDO::getWarehouseId, warehouseId); } + default int updateByIdAndStatus(Long id, Integer status, WmsCheckOrderDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(WmsCheckOrderDO::getId, id) + .eq(WmsCheckOrderDO::getStatus, status)); + } + } diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/movement/WmsMovementOrderMapper.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/movement/WmsMovementOrderMapper.java index 305dd66..3375902 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/movement/WmsMovementOrderMapper.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/movement/WmsMovementOrderMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderPageReqVO; import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -43,4 +44,10 @@ public interface WmsMovementOrderMapper extends BaseMapperX .or().eq(WmsMovementOrderDO::getTargetWarehouseId, warehouseId))); } + default int updateByIdAndStatus(Long id, Integer status, WmsMovementOrderDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(WmsMovementOrderDO::getId, id) + .eq(WmsMovementOrderDO::getStatus, status)); + } + } diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/receipt/WmsReceiptOrderMapper.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/receipt/WmsReceiptOrderMapper.java index 85cf105..550e6e2 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/receipt/WmsReceiptOrderMapper.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/receipt/WmsReceiptOrderMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderPageReqVO; import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -47,4 +48,10 @@ public interface WmsReceiptOrderMapper extends BaseMapperX { return selectCount(WmsReceiptOrderDO::getWarehouseId, warehouseId); } + default int updateByIdAndStatus(Long id, Integer status, WmsReceiptOrderDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(WmsReceiptOrderDO::getId, id) + .eq(WmsReceiptOrderDO::getStatus, status)); + } + } diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java index 34a6e40..f14df68 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO; import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -47,4 +48,10 @@ public interface WmsShipmentOrderMapper extends BaseMapperX return selectCount(WmsShipmentOrderDO::getWarehouseId, warehouseId); } + default int updateByIdAndStatus(Long id, Integer status, WmsShipmentOrderDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(WmsShipmentOrderDO::getId, id) + .eq(WmsShipmentOrderDO::getStatus, status)); + } + } diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java index b4a05aa..7c2c5f2 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java @@ -102,8 +102,10 @@ public class WmsCheckOrderServiceImpl implements WmsCheckOrderService { List details = checkOrderDetailService.validateCheckOrderDetailListExists(id); // 2. 完成盘库单 - checkOrderMapper.updateById(new WmsCheckOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.FINISHED.getStatus())); + if (checkOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsCheckOrderDO().setStatus(WmsOrderStatusEnum.FINISHED.getStatus())) == 0) { + throw exception(CHECK_ORDER_STATUS_NOT_PREPARE); + } // 3. 盘点库存 changeInventory(order, details); @@ -116,8 +118,10 @@ public class WmsCheckOrderServiceImpl implements WmsCheckOrderService { validateCheckOrderPrepare(id); // 2. 作废盘库单 - checkOrderMapper.updateById(new WmsCheckOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.CANCELED.getStatus())); + if (checkOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsCheckOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus())) == 0) { + throw exception(CHECK_ORDER_STATUS_NOT_PREPARE); + } } @Override diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java index a02de22..942ce4e 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java @@ -102,8 +102,10 @@ public class WmsMovementOrderServiceImpl implements WmsMovementOrderService { List details = movementOrderDetailService.validateMovementOrderDetailListExists(id); // 2. 完成移库单 - movementOrderMapper.updateById(new WmsMovementOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.FINISHED.getStatus())); + if (movementOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsMovementOrderDO().setStatus(WmsOrderStatusEnum.FINISHED.getStatus())) == 0) { + throw exception(MOVEMENT_ORDER_STATUS_NOT_PREPARE); + } // 3. 移动库存 changeInventory(order, details); @@ -116,8 +118,10 @@ public class WmsMovementOrderServiceImpl implements WmsMovementOrderService { validateMovementOrderPrepare(id); // 2. 作废移库单 - movementOrderMapper.updateById(new WmsMovementOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.CANCELED.getStatus())); + if (movementOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsMovementOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus())) == 0) { + throw exception(MOVEMENT_ORDER_STATUS_NOT_PREPARE); + } } @Override diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java index bcb1df0..5a40ab0 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java @@ -105,8 +105,10 @@ public class WmsReceiptOrderServiceImpl implements WmsReceiptOrderService { List details = receiptOrderDetailService.validateReceiptOrderDetailListExists(id); // 2. 完成入库单 - receiptOrderMapper.updateById(new WmsReceiptOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.FINISHED.getStatus())); + if (receiptOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsReceiptOrderDO().setStatus(WmsOrderStatusEnum.FINISHED.getStatus())) == 0) { + throw exception(RECEIPT_ORDER_STATUS_NOT_PREPARE); + } // 3. 写入库存 createInventory(order, details); @@ -119,8 +121,10 @@ public class WmsReceiptOrderServiceImpl implements WmsReceiptOrderService { validateReceiptOrderPrepare(id); // 2. 作废入库单 - receiptOrderMapper.updateById(new WmsReceiptOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.CANCELED.getStatus())); + if (receiptOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsReceiptOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus())) == 0) { + throw exception(RECEIPT_ORDER_STATUS_NOT_PREPARE); + } } @Override diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java index ba016e9..a657997 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java @@ -105,8 +105,10 @@ public class WmsShipmentOrderServiceImpl implements WmsShipmentOrderService { List details = shipmentOrderDetailService.validateShipmentOrderDetailListExists(id); // 2. 完成出库单 - shipmentOrderMapper.updateById(new WmsShipmentOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.FINISHED.getStatus())); + if (shipmentOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsShipmentOrderDO().setStatus(WmsOrderStatusEnum.FINISHED.getStatus())) == 0) { + throw exception(SHIPMENT_ORDER_STATUS_NOT_PREPARE); + } // 3. 扣减库存 changeInventory(order, details); @@ -119,8 +121,10 @@ public class WmsShipmentOrderServiceImpl implements WmsShipmentOrderService { validateShipmentOrderPrepare(id); // 2. 作废出库单 - shipmentOrderMapper.updateById(new WmsShipmentOrderDO().setId(id) - .setStatus(WmsOrderStatusEnum.CANCELED.getStatus())); + if (shipmentOrderMapper.updateByIdAndStatus(id, WmsOrderStatusEnum.PREPARE.getStatus(), + new WmsShipmentOrderDO().setStatus(WmsOrderStatusEnum.CANCELED.getStatus())) == 0) { + throw exception(SHIPMENT_ORDER_STATUS_NOT_PREPARE); + } } @Override diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java index a0ab5f7..f2a9fb3 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java @@ -320,6 +320,30 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { } @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 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", "红富士苹果"); diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java index 8a4a6ad..a49d505 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java @@ -27,6 +27,7 @@ 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_REQUIRED; 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; @@ -162,6 +163,23 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { } @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).changeInventory(any()); + } + + @Test public void testCancelCheckOrder_success() { // mock 数据 WmsCheckOrderDO order = createCheckOrder(100L); @@ -178,6 +196,23 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { } @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()); diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java index 33aefed..fd6392e 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java @@ -26,6 +26,7 @@ import java.util.Arrays; 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; @@ -136,6 +137,22 @@ public class WmsMovementOrderServiceImplTest extends BaseDbUnitTest { } @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); @@ -162,6 +179,23 @@ public class WmsMovementOrderServiceImplTest extends BaseDbUnitTest { } @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()); diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImplTest.java index 2f28877..d6e48b9 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImplTest.java @@ -27,6 +27,7 @@ import java.util.Arrays; 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; @@ -134,6 +135,22 @@ public class WmsReceiptOrderServiceImplTest extends BaseDbUnitTest { } @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); @@ -150,6 +167,23 @@ public class WmsReceiptOrderServiceImplTest extends BaseDbUnitTest { } @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()); diff --git a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java index 76d3179..01baa85 100644 --- a/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java +++ b/yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java @@ -28,6 +28,7 @@ import java.util.Arrays; 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; @@ -134,6 +135,22 @@ public class WmsShipmentOrderServiceImplTest extends BaseDbUnitTest { } @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); @@ -150,6 +167,23 @@ public class WmsShipmentOrderServiceImplTest extends BaseDbUnitTest { } @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()); -- libgit2 0.21.4