Commit 86d760fdb1593fdd591aa5447cc75058f0681e03
1 parent
fe38e4fd
feat(wms):减法,去掉批次号等字段
Showing
29 changed files
with
939 additions
and
231 deletions
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/inventory/vo/history/WmsInventoryHistoryRespVO.java
| ... | ... | @@ -40,12 +40,6 @@ public class WmsInventoryHistoryRespVO { |
| 40 | 40 | private BigDecimal beforeQuantity; |
| 41 | 41 | @Schema(description = "变化后库存数量", example = "100.00") |
| 42 | 42 | private BigDecimal afterQuantity; |
| 43 | - @Schema(description = "批号", example = "BATCH001") | |
| 44 | - private String batchNo; | |
| 45 | - @Schema(description = "生产日期") | |
| 46 | - private LocalDateTime productionDate; | |
| 47 | - @Schema(description = "过期日期") | |
| 48 | - private LocalDateTime expirationDate; | |
| 49 | 43 | @Schema(description = "金额", example = "1000.00") |
| 50 | 44 | private BigDecimal amount; |
| 51 | 45 | @Schema(description = "备注", example = "备注") | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/detail/WmsCheckOrderDetailRespVO.java
| ... | ... | @@ -46,15 +46,6 @@ public class WmsCheckOrderDetailRespVO { |
| 46 | 46 | @Schema(description = "库存编号", example = "1024") |
| 47 | 47 | private Long inventoryId; |
| 48 | 48 | |
| 49 | - @Schema(description = "批号", example = "B202605110001") | |
| 50 | - private String batchNo; | |
| 51 | - | |
| 52 | - @Schema(description = "生产日期") | |
| 53 | - private LocalDateTime productionDate; | |
| 54 | - | |
| 55 | - @Schema(description = "过期日期") | |
| 56 | - private LocalDateTime expirationDate; | |
| 57 | - | |
| 58 | 49 | @Schema(description = "入库时间") |
| 59 | 50 | private LocalDateTime receiptTime; |
| 60 | 51 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/detail/WmsCheckOrderDetailSaveReqVO.java
| ... | ... | @@ -23,16 +23,6 @@ public class WmsCheckOrderDetailSaveReqVO { |
| 23 | 23 | @Schema(description = "库存编号", example = "1024") |
| 24 | 24 | private Long inventoryId; |
| 25 | 25 | |
| 26 | - @Schema(description = "批号", example = "B202605110001") | |
| 27 | - @Size(max = 64, message = "批号长度不能超过 64 个字符") | |
| 28 | - private String batchNo; | |
| 29 | - | |
| 30 | - @Schema(description = "生产日期") | |
| 31 | - private LocalDateTime productionDate; | |
| 32 | - | |
| 33 | - @Schema(description = "过期日期") | |
| 34 | - private LocalDateTime expirationDate; | |
| 35 | - | |
| 36 | 26 | @Schema(description = "入库时间") |
| 37 | 27 | private LocalDateTime receiptTime; |
| 38 | 28 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/detail/WmsMovementOrderDetailRespVO.java
| ... | ... | @@ -49,15 +49,6 @@ public class WmsMovementOrderDetailRespVO { |
| 49 | 49 | @Schema(description = "目标仓库名称", example = "上海仓") |
| 50 | 50 | private String targetWarehouseName; |
| 51 | 51 | |
| 52 | - @Schema(description = "批号", example = "B202605110001") | |
| 53 | - private String batchNo; | |
| 54 | - | |
| 55 | - @Schema(description = "生产日期") | |
| 56 | - private LocalDateTime productionDate; | |
| 57 | - | |
| 58 | - @Schema(description = "过期日期") | |
| 59 | - private LocalDateTime expirationDate; | |
| 60 | - | |
| 61 | 52 | @Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 62 | 53 | private BigDecimal quantity; |
| 63 | 54 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/detail/WmsMovementOrderDetailSaveReqVO.java
| ... | ... | @@ -7,7 +7,6 @@ import jakarta.validation.constraints.Size; |
| 7 | 7 | import lombok.Data; |
| 8 | 8 | |
| 9 | 9 | import java.math.BigDecimal; |
| 10 | -import java.time.LocalDateTime; | |
| 11 | 10 | |
| 12 | 11 | @Schema(description = "管理后台 - WMS 移库单明细保存 Request VO") |
| 13 | 12 | @Data |
| ... | ... | @@ -20,16 +19,6 @@ public class WmsMovementOrderDetailSaveReqVO { |
| 20 | 19 | @NotNull(message = "SKU 不能为空") |
| 21 | 20 | private Long skuId; |
| 22 | 21 | |
| 23 | - @Schema(description = "批号", example = "B202605110001") | |
| 24 | - @Size(max = 64, message = "批号长度不能超过 64 个字符") | |
| 25 | - private String batchNo; | |
| 26 | - | |
| 27 | - @Schema(description = "生产日期") | |
| 28 | - private LocalDateTime productionDate; | |
| 29 | - | |
| 30 | - @Schema(description = "过期日期") | |
| 31 | - private LocalDateTime expirationDate; | |
| 32 | - | |
| 33 | 22 | @Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 34 | 23 | @NotNull(message = "移库数量不能为空") |
| 35 | 24 | @DecimalMin(value = "0", inclusive = false, message = "移库数量必须大于 0") | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/detail/WmsReceiptOrderDetailRespVO.java
| ... | ... | @@ -43,15 +43,6 @@ public class WmsReceiptOrderDetailRespVO { |
| 43 | 43 | @Schema(description = "仓库名称", example = "北京仓") |
| 44 | 44 | private String warehouseName; |
| 45 | 45 | |
| 46 | - @Schema(description = "批号", example = "B202605110001") | |
| 47 | - private String batchNo; | |
| 48 | - | |
| 49 | - @Schema(description = "生产日期") | |
| 50 | - private LocalDateTime productionDate; | |
| 51 | - | |
| 52 | - @Schema(description = "过期日期") | |
| 53 | - private LocalDateTime expirationDate; | |
| 54 | - | |
| 55 | 46 | @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 56 | 47 | private BigDecimal quantity; |
| 57 | 48 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/detail/WmsReceiptOrderDetailSaveReqVO.java
| ... | ... | @@ -7,7 +7,6 @@ import jakarta.validation.constraints.Size; |
| 7 | 7 | import lombok.Data; |
| 8 | 8 | |
| 9 | 9 | import java.math.BigDecimal; |
| 10 | -import java.time.LocalDateTime; | |
| 11 | 10 | |
| 12 | 11 | @Schema(description = "管理后台 - WMS 入库单明细保存 Request VO") |
| 13 | 12 | @Data |
| ... | ... | @@ -20,16 +19,6 @@ public class WmsReceiptOrderDetailSaveReqVO { |
| 20 | 19 | @NotNull(message = "SKU 不能为空") |
| 21 | 20 | private Long skuId; |
| 22 | 21 | |
| 23 | - @Schema(description = "批号", example = "B202605110001") | |
| 24 | - @Size(max = 64, message = "批号长度不能超过 64 个字符") | |
| 25 | - private String batchNo; | |
| 26 | - | |
| 27 | - @Schema(description = "生产日期") | |
| 28 | - private LocalDateTime productionDate; | |
| 29 | - | |
| 30 | - @Schema(description = "过期日期") | |
| 31 | - private LocalDateTime expirationDate; | |
| 32 | - | |
| 33 | 22 | @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 34 | 23 | @NotNull(message = "入库数量不能为空") |
| 35 | 24 | @DecimalMin(value = "0", inclusive = false, message = "入库数量必须大于 0") | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/detail/WmsShipmentOrderDetailRespVO.java
| ... | ... | @@ -43,15 +43,6 @@ public class WmsShipmentOrderDetailRespVO { |
| 43 | 43 | @Schema(description = "仓库名称", example = "北京仓") |
| 44 | 44 | private String warehouseName; |
| 45 | 45 | |
| 46 | - @Schema(description = "批号", example = "B202605110001") | |
| 47 | - private String batchNo; | |
| 48 | - | |
| 49 | - @Schema(description = "生产日期") | |
| 50 | - private LocalDateTime productionDate; | |
| 51 | - | |
| 52 | - @Schema(description = "过期日期") | |
| 53 | - private LocalDateTime expirationDate; | |
| 54 | - | |
| 55 | 46 | @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 56 | 47 | private BigDecimal quantity; |
| 57 | 48 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/detail/WmsShipmentOrderDetailSaveReqVO.java
| ... | ... | @@ -7,7 +7,6 @@ import jakarta.validation.constraints.Size; |
| 7 | 7 | import lombok.Data; |
| 8 | 8 | |
| 9 | 9 | import java.math.BigDecimal; |
| 10 | -import java.time.LocalDateTime; | |
| 11 | 10 | |
| 12 | 11 | @Schema(description = "管理后台 - WMS 出库单明细保存 Request VO") |
| 13 | 12 | @Data |
| ... | ... | @@ -20,16 +19,6 @@ public class WmsShipmentOrderDetailSaveReqVO { |
| 20 | 19 | @NotNull(message = "SKU 不能为空") |
| 21 | 20 | private Long skuId; |
| 22 | 21 | |
| 23 | - @Schema(description = "批号", example = "B202605110001") | |
| 24 | - @Size(max = 64, message = "批号长度不能超过 64 个字符") | |
| 25 | - private String batchNo; | |
| 26 | - | |
| 27 | - @Schema(description = "生产日期") | |
| 28 | - private LocalDateTime productionDate; | |
| 29 | - | |
| 30 | - @Schema(description = "过期日期") | |
| 31 | - private LocalDateTime expirationDate; | |
| 32 | - | |
| 33 | 22 | @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| 34 | 23 | @NotNull(message = "出库数量不能为空") |
| 35 | 24 | @DecimalMin(value = "0", inclusive = false, message = "出库数量必须大于 0") | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/inventory/WmsInventoryHistoryDO.java
| ... | ... | @@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.annotation.TableName; |
| 10 | 10 | import lombok.*; |
| 11 | 11 | |
| 12 | 12 | import java.math.BigDecimal; |
| 13 | -import java.time.LocalDateTime; | |
| 14 | 13 | |
| 15 | 14 | /** |
| 16 | 15 | * WMS 库存流水 DO |
| ... | ... | @@ -60,21 +59,6 @@ public class WmsInventoryHistoryDO extends BaseDO { |
| 60 | 59 | */ |
| 61 | 60 | private BigDecimal afterQuantity; |
| 62 | 61 | |
| 63 | - // ========= 批次效期相关字段 ========= | |
| 64 | - | |
| 65 | - /** | |
| 66 | - * 批号 | |
| 67 | - */ | |
| 68 | - private String batchNo; | |
| 69 | - /** | |
| 70 | - * 生产日期 | |
| 71 | - */ | |
| 72 | - private LocalDateTime productionDate; | |
| 73 | - /** | |
| 74 | - * 过期日期 | |
| 75 | - */ | |
| 76 | - private LocalDateTime expirationDate; | |
| 77 | - | |
| 78 | 62 | // ========= 金额备注相关字段 ========= |
| 79 | 63 | |
| 80 | 64 | /** | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/check/WmsCheckOrderDetailDO.java
| ... | ... | @@ -67,20 +67,6 @@ public class WmsCheckOrderDetailDO extends BaseDO { |
| 67 | 67 | */ |
| 68 | 68 | private Long inventoryId; |
| 69 | 69 | |
| 70 | - // ========= 批次效期字段 ========= | |
| 71 | - | |
| 72 | - /** | |
| 73 | - * 批号 | |
| 74 | - */ | |
| 75 | - private String batchNo; | |
| 76 | - /** | |
| 77 | - * 生产日期 | |
| 78 | - */ | |
| 79 | - private LocalDateTime productionDate; | |
| 80 | - /** | |
| 81 | - * 过期日期 | |
| 82 | - */ | |
| 83 | - private LocalDateTime expirationDate; | |
| 84 | 70 | /** |
| 85 | 71 | * 入库时间 |
| 86 | 72 | */ | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/movement/WmsMovementOrderDetailDO.java
| ... | ... | @@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.annotation.TableName; |
| 9 | 9 | import lombok.*; |
| 10 | 10 | |
| 11 | 11 | import java.math.BigDecimal; |
| 12 | -import java.time.LocalDateTime; | |
| 13 | 12 | |
| 14 | 13 | /** |
| 15 | 14 | * WMS 移库单明细 DO |
| ... | ... | @@ -69,21 +68,6 @@ public class WmsMovementOrderDetailDO extends BaseDO { |
| 69 | 68 | */ |
| 70 | 69 | private Long targetWarehouseId; |
| 71 | 70 | |
| 72 | - // ========= 批次效期字段 ========= | |
| 73 | - | |
| 74 | - /** | |
| 75 | - * 批号 | |
| 76 | - */ | |
| 77 | - private String batchNo; | |
| 78 | - /** | |
| 79 | - * 生产日期 | |
| 80 | - */ | |
| 81 | - private LocalDateTime productionDate; | |
| 82 | - /** | |
| 83 | - * 过期日期 | |
| 84 | - */ | |
| 85 | - private LocalDateTime expirationDate; | |
| 86 | - | |
| 87 | 71 | // ========= 汇总金额字段 ========= |
| 88 | 72 | |
| 89 | 73 | /** | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/receipt/WmsReceiptOrderDetailDO.java
| ... | ... | @@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.annotation.TableName; |
| 9 | 9 | import lombok.*; |
| 10 | 10 | |
| 11 | 11 | import java.math.BigDecimal; |
| 12 | -import java.time.LocalDateTime; | |
| 13 | 12 | |
| 14 | 13 | /** |
| 15 | 14 | * WMS 入库单明细 DO |
| ... | ... | @@ -60,21 +59,6 @@ public class WmsReceiptOrderDetailDO extends BaseDO { |
| 60 | 59 | */ |
| 61 | 60 | private Long warehouseId; |
| 62 | 61 | |
| 63 | - // ========= 批次效期字段 ========= | |
| 64 | - | |
| 65 | - /** | |
| 66 | - * 批号 | |
| 67 | - */ | |
| 68 | - private String batchNo; | |
| 69 | - /** | |
| 70 | - * 生产日期 | |
| 71 | - */ | |
| 72 | - private LocalDateTime productionDate; | |
| 73 | - /** | |
| 74 | - * 过期日期 | |
| 75 | - */ | |
| 76 | - private LocalDateTime expirationDate; | |
| 77 | - | |
| 78 | 62 | // ========= 汇总金额字段 ========= |
| 79 | 63 | |
| 80 | 64 | /** | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/shipment/WmsShipmentOrderDetailDO.java
| ... | ... | @@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.annotation.TableName; |
| 9 | 9 | import lombok.*; |
| 10 | 10 | |
| 11 | 11 | import java.math.BigDecimal; |
| 12 | -import java.time.LocalDateTime; | |
| 13 | 12 | |
| 14 | 13 | /** |
| 15 | 14 | * WMS 出库单明细 DO |
| ... | ... | @@ -60,21 +59,6 @@ public class WmsShipmentOrderDetailDO extends BaseDO { |
| 60 | 59 | */ |
| 61 | 60 | private Long warehouseId; |
| 62 | 61 | |
| 63 | - // ========= 批次效期字段 ========= | |
| 64 | - | |
| 65 | - /** | |
| 66 | - * 批号 | |
| 67 | - */ | |
| 68 | - private String batchNo; | |
| 69 | - /** | |
| 70 | - * 生产日期 | |
| 71 | - */ | |
| 72 | - private LocalDateTime productionDate; | |
| 73 | - /** | |
| 74 | - * 过期日期 | |
| 75 | - */ | |
| 76 | - private LocalDateTime expirationDate; | |
| 77 | - | |
| 78 | 62 | // ========= 汇总金额字段 ========= |
| 79 | 63 | |
| 80 | 64 | /** | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/framework/config/package-info.java deleted
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImpl.java
| ... | ... | @@ -121,50 +121,50 @@ public class WmsInventoryServiceImpl implements WmsInventoryService { |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | private List<WmsInventoryDO> getOrCreateInventoryList(List<WmsInventoryChangeReqDTO.Item> items) { |
| 124 | - // 先按库存维度在内存去重,避免同一批明细重复查询或重复补行。 | |
| 125 | - List<WmsInventoryDO> inventoryKeyList = new ArrayList<>(items.size()); | |
| 124 | + // 1.1 先按库存维度在内存去重,避免同一批明细重复查询或重复补行 | |
| 125 | + List<WmsInventoryDO> inventoryDimensions = new ArrayList<>(items.size()); | |
| 126 | 126 | for (WmsInventoryChangeReqDTO.Item item : items) { |
| 127 | - if (findInventory(inventoryKeyList, item) == null) { | |
| 128 | - inventoryKeyList.add(new WmsInventoryDO().setSkuId(item.getSkuId()) | |
| 127 | + if (findInventory(inventoryDimensions, item) == null) { | |
| 128 | + inventoryDimensions.add(new WmsInventoryDO().setSkuId(item.getSkuId()) | |
| 129 | 129 | .setWarehouseId(item.getWarehouseId())); |
| 130 | 130 | } |
| 131 | 131 | } |
| 132 | - | |
| 133 | - // 批量查询已存在的库存行;这里不加锁,后续统一按库存 ID 批量加锁。 | |
| 134 | - List<WmsInventoryDO> inventories = inventoryMapper.selectListByKeys(inventoryKeyList); | |
| 135 | - | |
| 136 | - // 对比库存维度,找出数据库中还不存在的库存行,再按唯一索引兜底补齐。 | |
| 137 | - List<WmsInventoryDO> missingInventoryList = new ArrayList<>(inventoryKeyList.size()); | |
| 138 | - for (WmsInventoryDO inventoryKey : inventoryKeyList) { | |
| 139 | - if (findInventory(inventories, inventoryKey) == null) { | |
| 140 | - missingInventoryList.add(inventoryKey); | |
| 132 | + // 1.2 批量查询已存在的库存行(这里不加锁,后续统一按库存 ID 批量加锁) | |
| 133 | + List<WmsInventoryDO> inventories = inventoryMapper.selectListByKeys(inventoryDimensions); | |
| 134 | + | |
| 135 | + // 2.1 对比库存维度,找出数据库中还不存在的库存行 | |
| 136 | + List<WmsInventoryDO> missingInventories = new ArrayList<>(inventoryDimensions.size()); | |
| 137 | + for (WmsInventoryDO inventoryDimension : inventoryDimensions) { | |
| 138 | + if (findInventory(inventories, inventoryDimension) == null) { | |
| 139 | + missingInventories.add(inventoryDimension); | |
| 141 | 140 | } |
| 142 | 141 | } |
| 143 | - if (CollUtil.isEmpty(missingInventoryList)) { | |
| 142 | + // 2.2 如果库存行都已存在,直接返回待加锁库存列表 | |
| 143 | + if (CollUtil.isEmpty(missingInventories)) { | |
| 144 | 144 | return inventories; |
| 145 | 145 | } |
| 146 | - | |
| 147 | - inventories.addAll(createMissingInventoryList(missingInventoryList)); | |
| 146 | + // 2.3 对缺失库存行执行创建;并发冲突时,内部会按唯一索引回查已创建的库存行 | |
| 147 | + inventories.addAll(createMissingInventoryList(missingInventories)); | |
| 148 | 148 | return inventories; |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | - private List<WmsInventoryDO> createMissingInventoryList(List<WmsInventoryDO> missingInventoryList) { | |
| 151 | + private List<WmsInventoryDO> createMissingInventoryList(List<WmsInventoryDO> missingInventories) { | |
| 152 | 152 | // 优先批量插入缺失库存行;并发唯一键冲突时,再逐个插入并回查冲突行。 |
| 153 | - List<WmsInventoryDO> newInventoryList = convertList(missingInventoryList, missingInventory -> | |
| 153 | + List<WmsInventoryDO> newInventories = convertList(missingInventories, missingInventory -> | |
| 154 | 154 | new WmsInventoryDO().setSkuId(missingInventory.getSkuId()).setWarehouseId(missingInventory.getWarehouseId()) |
| 155 | 155 | .setQuantity(BigDecimal.ZERO)); |
| 156 | 156 | try { |
| 157 | - inventoryMapper.insertBatch(newInventoryList); | |
| 158 | - return newInventoryList; | |
| 157 | + inventoryMapper.insertBatch(newInventories); | |
| 158 | + return newInventories; | |
| 159 | 159 | } catch (DuplicateKeyException ex) { |
| 160 | 160 | // 并发事务可能已经补齐部分库存行,降级为逐个插入并回查唯一键冲突的行。 |
| 161 | - log.warn("[createMissingInventoryList][missingInventoryList({}) 批量插入库存行冲突,降级为逐个插入]", | |
| 162 | - missingInventoryList, ex); | |
| 161 | + log.warn("[createMissingInventoryList][missingInventories({}) 批量插入库存行冲突,降级为逐个插入]", | |
| 162 | + missingInventories, ex); | |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 165 | // 批量插入失败后逐条补齐;单条唯一键冲突时,回查并使用并发事务创建的库存行。 |
| 166 | - List<WmsInventoryDO> resultList = new ArrayList<>(missingInventoryList.size()); | |
| 167 | - for (WmsInventoryDO missingInventory : missingInventoryList) { | |
| 166 | + List<WmsInventoryDO> createdInventories = new ArrayList<>(missingInventories.size()); | |
| 167 | + for (WmsInventoryDO missingInventory : missingInventories) { | |
| 168 | 168 | WmsInventoryDO inventory = new WmsInventoryDO().setSkuId(missingInventory.getSkuId()) |
| 169 | 169 | .setWarehouseId(missingInventory.getWarehouseId()) |
| 170 | 170 | .setQuantity(BigDecimal.ZERO); |
| ... | ... | @@ -178,9 +178,9 @@ public class WmsInventoryServiceImpl implements WmsInventoryService { |
| 178 | 178 | throw ex; |
| 179 | 179 | } |
| 180 | 180 | } |
| 181 | - resultList.add(inventory); | |
| 181 | + createdInventories.add(inventory); | |
| 182 | 182 | } |
| 183 | - return resultList; | |
| 183 | + return createdInventories; | |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | 186 | private WmsInventoryHistoryDO buildInventoryHistory(WmsInventoryChangeReqDTO reqDTO, |
| ... | ... | @@ -189,8 +189,6 @@ public class WmsInventoryServiceImpl implements WmsInventoryService { |
| 189 | 189 | return new WmsInventoryHistoryDO() |
| 190 | 190 | .setWarehouseId(item.getWarehouseId()).setSkuId(item.getSkuId()) |
| 191 | 191 | .setQuantity(item.getQuantity()).setBeforeQuantity(result.get(0)).setAfterQuantity(result.get(1)) |
| 192 | - .setBatchNo(item.getBatchNo()).setProductionDate(item.getProductionDate()) | |
| 193 | - .setExpirationDate(item.getExpirationDate()) | |
| 194 | 192 | .setAmount(item.getAmount()).setRemark(item.getRemark()) |
| 195 | 193 | .setOrderId(reqDTO.getOrderId()).setOrderNo(reqDTO.getOrderNo()).setOrderType(reqDTO.getOrderType()); |
| 196 | 194 | } | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/dto/WmsInventoryChangeReqDTO.java
| ... | ... | @@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | 6 | import java.math.BigDecimal; |
| 7 | -import java.time.LocalDateTime; | |
| 8 | 7 | import java.util.List; |
| 9 | 8 | |
| 10 | 9 | /** |
| ... | ... | @@ -54,21 +53,6 @@ public class WmsInventoryChangeReqDTO { |
| 54 | 53 | */ |
| 55 | 54 | private BigDecimal quantity; |
| 56 | 55 | |
| 57 | - // ========= 批次效期相关字段 ========= | |
| 58 | - | |
| 59 | - /** | |
| 60 | - * 批号 | |
| 61 | - */ | |
| 62 | - private String batchNo; | |
| 63 | - /** | |
| 64 | - * 生产日期 | |
| 65 | - */ | |
| 66 | - private LocalDateTime productionDate; | |
| 67 | - /** | |
| 68 | - * 过期日期 | |
| 69 | - */ | |
| 70 | - private LocalDateTime expirationDate; | |
| 71 | - | |
| 72 | 56 | // ========= 金额备注相关字段 ========= |
| 73 | 57 | |
| 74 | 58 | /** | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.wms.service.order.check; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| ... | ... | @@ -171,9 +172,7 @@ public class WmsCheckOrderServiceImpl implements WmsCheckOrderService { |
| 171 | 172 | } |
| 172 | 173 | |
| 173 | 174 | /** |
| 174 | - * 盘点盘库单对应库存。 | |
| 175 | - * | |
| 176 | - * 盘库只对盈亏数量生成库存变更:实盘数量大于账面数量时增加库存,反之扣减库存,批次字段随库存流水记录。 | |
| 175 | + * 盘点盘库单对应库存 | |
| 177 | 176 | * |
| 178 | 177 | * @param order 盘库单 |
| 179 | 178 | * @param details 盘库单明细列表 |
| ... | ... | @@ -189,6 +188,9 @@ public class WmsCheckOrderServiceImpl implements WmsCheckOrderService { |
| 189 | 188 | .setQuantity(differenceQuantity); |
| 190 | 189 | items.add(item); |
| 191 | 190 | } |
| 191 | + if (CollUtil.isEmpty(items)) { | |
| 192 | + return; | |
| 193 | + } | |
| 192 | 194 | inventoryService.changeInventory(new WmsInventoryChangeReqDTO() |
| 193 | 195 | .setOrderId(order.getId()).setOrderNo(order.getNo()) |
| 194 | 196 | .setOrderType(WmsInventoryOrderTypeEnum.CHECK.getType()).setItems(items)); | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImpl.java
| ... | ... | @@ -175,9 +175,7 @@ public class WmsMovementOrderServiceImpl implements WmsMovementOrderService { |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | /** |
| 178 | - * 移动移库单对应库存。 | |
| 179 | - * | |
| 180 | - * 移库会生成两条库存变更:来源仓库扣减库存,目标仓库增加库存,批次字段随库存流水记录。 | |
| 178 | + * 移动移库单对应库存 | |
| 181 | 179 | * |
| 182 | 180 | * @param order 移库单 |
| 183 | 181 | * @param details 移库单明细列表 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImplTest.java
| ... | ... | @@ -30,6 +30,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic |
| 30 | 30 | import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.INVENTORY_QUANTITY_NOT_ENOUGH; |
| 31 | 31 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 32 | 32 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 33 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 33 | 34 | import static org.mockito.Mockito.when; |
| 34 | 35 | |
| 35 | 36 | @Import({WmsInventoryServiceImpl.class, WmsInventoryHistoryServiceImpl.class}) |
| ... | ... | @@ -230,6 +231,10 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { |
| 230 | 231 | // 调用,并断言 |
| 231 | 232 | assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH, |
| 232 | 233 | item.getName(), sku.getName(), 100L, new BigDecimal("2.000000"), new BigDecimal("-3.00")); |
| 234 | + WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L); | |
| 235 | + assertNotNull(inventory); | |
| 236 | + assertEquals(0, new BigDecimal("2.00").compareTo(inventory.getQuantity())); | |
| 237 | + assertEquals(0L, inventoryHistoryMapper.selectCount()); | |
| 233 | 238 | } |
| 234 | 239 | |
| 235 | 240 | @Test |
| ... | ... | @@ -243,7 +248,32 @@ public class WmsInventoryServiceImplTest extends BaseDbUnitTest { |
| 243 | 248 | // 调用,并断言 |
| 244 | 249 | assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH, |
| 245 | 250 | item.getName(), sku.getName(), 100L, BigDecimal.ZERO.setScale(6), new BigDecimal("-3.00")); |
| 246 | - assertEquals(0, inventoryMapper.selectCount()); | |
| 251 | + assertEquals(0L, inventoryMapper.selectCount()); | |
| 252 | + assertEquals(0L, inventoryHistoryMapper.selectCount()); | |
| 253 | + } | |
| 254 | + | |
| 255 | + @Test | |
| 256 | + public void testChangeInventory_quantityNotEnoughRollbackCreatedInventories() { | |
| 257 | + // mock 数据 | |
| 258 | + WmsItemDO item = createItem("ITEM-001", "红富士苹果"); | |
| 259 | + WmsItemSkuDO sku = createSku(item.getId(), "SKU-001", "10kg 箱装"); | |
| 260 | + WmsInventoryChangeReqDTO reqDTO = createChangeReq(sku.getId(), 100L, "5.00"); | |
| 261 | + List<WmsInventoryChangeReqDTO.Item> items = new ArrayList<>(reqDTO.getItems()); | |
| 262 | + items.add(new WmsInventoryChangeReqDTO.Item() | |
| 263 | + .setSkuId(sku.getId()) | |
| 264 | + .setWarehouseId(200L) | |
| 265 | + .setQuantity(new BigDecimal("-1.00")) | |
| 266 | + .setAmount(new BigDecimal("20.00")) | |
| 267 | + .setRemark("测试出库")); | |
| 268 | + reqDTO.setItems(items); | |
| 269 | + mockItemSkuAndItem(item, sku); | |
| 270 | + | |
| 271 | + // 调用,并断言:第二条明细库存不足,事务回滚前面补齐的库存行 | |
| 272 | + assertServiceException(() -> inventoryService.changeInventory(reqDTO), INVENTORY_QUANTITY_NOT_ENOUGH, | |
| 273 | + item.getName(), sku.getName(), 200L, BigDecimal.ZERO.setScale(6), new BigDecimal("-1.00")); | |
| 274 | + assertNull(inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 100L)); | |
| 275 | + assertNull(inventoryMapper.selectBySkuIdAndWarehouseId(sku.getId(), 200L)); | |
| 276 | + assertEquals(0L, inventoryHistoryMapper.selectCount()); | |
| 247 | 277 | } |
| 248 | 278 | |
| 249 | 279 | @Test | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderDetailServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.check; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderSaveReqVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderDetailMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 9 | +import jakarta.annotation.Resource; | |
| 10 | +import org.junit.jupiter.api.Test; | |
| 11 | +import org.springframework.context.annotation.Import; | |
| 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 13 | + | |
| 14 | +import java.math.BigDecimal; | |
| 15 | +import java.util.Arrays; | |
| 16 | +import java.util.List; | |
| 17 | + | |
| 18 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 19 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_NOT_EXISTS; | |
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 21 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 22 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 23 | + | |
| 24 | +@Import(WmsCheckOrderDetailServiceImpl.class) | |
| 25 | +public class WmsCheckOrderDetailServiceImplTest extends BaseDbUnitTest { | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + private WmsCheckOrderDetailServiceImpl checkOrderDetailService; | |
| 29 | + | |
| 30 | + @Resource | |
| 31 | + private WmsCheckOrderDetailMapper checkOrderDetailMapper; | |
| 32 | + | |
| 33 | + @MockitoBean | |
| 34 | + private WmsItemSkuService itemSkuService; | |
| 35 | + | |
| 36 | + @Test | |
| 37 | + public void testCreateCheckOrderDetailList_success() { | |
| 38 | + // mock 数据 | |
| 39 | + Long orderId = 10L; | |
| 40 | + WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO( | |
| 41 | + createCheckOrderDetailReqVO(null, 1001L, "10.00", "9.00"), | |
| 42 | + createCheckOrderDetailReqVO(null, 1002L, "20.00", "21.00")); | |
| 43 | + | |
| 44 | + // 调用 | |
| 45 | + checkOrderDetailService.createCheckOrderDetailList(orderId, reqVO); | |
| 46 | + | |
| 47 | + // 断言 | |
| 48 | + List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(orderId); | |
| 49 | + assertEquals(2, details.size()); | |
| 50 | + assertEquals(orderId, details.get(0).getOrderId()); | |
| 51 | + assertEquals(orderId, details.get(1).getOrderId()); | |
| 52 | + assertEquals(100L, details.get(0).getWarehouseId()); | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Test | |
| 56 | + public void testCreateCheckOrderDetailList_ignoreId() { | |
| 57 | + // mock 数据 | |
| 58 | + WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO( | |
| 59 | + createCheckOrderDetailReqVO(999L, 1001L, "10.00", "9.00")); | |
| 60 | + | |
| 61 | + // 调用 | |
| 62 | + checkOrderDetailService.createCheckOrderDetailList(10L, reqVO); | |
| 63 | + | |
| 64 | + // 断言 | |
| 65 | + List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(10L); | |
| 66 | + assertEquals(1, details.size()); | |
| 67 | + assertNotNull(details.get(0).getId()); | |
| 68 | + assertEquals(1001L, details.get(0).getSkuId()); | |
| 69 | + } | |
| 70 | + | |
| 71 | + @Test | |
| 72 | + public void testUpdateCheckOrderDetailList_diff() { | |
| 73 | + // mock 数据 | |
| 74 | + Long orderId = 10L; | |
| 75 | + WmsCheckOrderDetailDO detail01 = createCheckOrderDetail(orderId, 1001L, "10.00", "9.00"); | |
| 76 | + WmsCheckOrderDetailDO detail02 = createCheckOrderDetail(orderId, 1002L, "20.00", "21.00"); | |
| 77 | + checkOrderDetailMapper.insert(detail01); | |
| 78 | + checkOrderDetailMapper.insert(detail02); | |
| 79 | + WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO( | |
| 80 | + createCheckOrderDetailReqVO(detail01.getId(), 2001L, "11.00", "8.00"), | |
| 81 | + createCheckOrderDetailReqVO(null, 2002L, "22.00", "25.00")); | |
| 82 | + | |
| 83 | + // 调用 | |
| 84 | + checkOrderDetailService.updateCheckOrderDetailList(orderId, reqVO); | |
| 85 | + | |
| 86 | + // 断言:修改 | |
| 87 | + WmsCheckOrderDetailDO dbUpdateDetail = checkOrderDetailMapper.selectById(detail01.getId()); | |
| 88 | + assertNotNull(dbUpdateDetail); | |
| 89 | + assertEquals(orderId, dbUpdateDetail.getOrderId()); | |
| 90 | + assertEquals(2001L, dbUpdateDetail.getSkuId()); | |
| 91 | + assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity())); | |
| 92 | + assertEquals(0, new BigDecimal("8.00").compareTo(dbUpdateDetail.getCheckQuantity())); | |
| 93 | + assertEquals(100L, dbUpdateDetail.getWarehouseId()); | |
| 94 | + // 断言:新增 | |
| 95 | + List<WmsCheckOrderDetailDO> details = checkOrderDetailMapper.selectListByOrderId(orderId); | |
| 96 | + assertEquals(2, details.size()); | |
| 97 | + WmsCheckOrderDetailDO dbCreateDetail = details.stream() | |
| 98 | + .filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId())) | |
| 99 | + .findFirst().orElse(null); | |
| 100 | + assertNotNull(dbCreateDetail); | |
| 101 | + assertEquals(orderId, dbCreateDetail.getOrderId()); | |
| 102 | + assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity())); | |
| 103 | + assertEquals(0, new BigDecimal("25.00").compareTo(dbCreateDetail.getCheckQuantity())); | |
| 104 | + // 断言:删除 | |
| 105 | + assertNull(checkOrderDetailMapper.selectById(detail02.getId())); | |
| 106 | + } | |
| 107 | + | |
| 108 | + @Test | |
| 109 | + public void testUpdateCheckOrderDetailList_detailNotExists() { | |
| 110 | + // mock 数据 | |
| 111 | + WmsCheckOrderSaveReqVO reqVO = createCheckOrderReqVO( | |
| 112 | + createCheckOrderDetailReqVO(999L, 1001L, "10.00", "9.00")); | |
| 113 | + | |
| 114 | + // 调用,并断言 | |
| 115 | + assertServiceException(() -> checkOrderDetailService.updateCheckOrderDetailList(10L, reqVO), | |
| 116 | + CHECK_ORDER_DETAIL_NOT_EXISTS); | |
| 117 | + } | |
| 118 | + | |
| 119 | + private static WmsCheckOrderSaveReqVO createCheckOrderReqVO(WmsCheckOrderDetailSaveReqVO... details) { | |
| 120 | + WmsCheckOrderSaveReqVO reqVO = new WmsCheckOrderSaveReqVO(); | |
| 121 | + reqVO.setWarehouseId(100L); | |
| 122 | + reqVO.setDetails(Arrays.asList(details)); | |
| 123 | + return reqVO; | |
| 124 | + } | |
| 125 | + | |
| 126 | + private static WmsCheckOrderDetailSaveReqVO createCheckOrderDetailReqVO(Long id, Long skuId, | |
| 127 | + String quantity, String checkQuantity) { | |
| 128 | + WmsCheckOrderDetailSaveReqVO reqVO = new WmsCheckOrderDetailSaveReqVO(); | |
| 129 | + reqVO.setId(id); | |
| 130 | + reqVO.setSkuId(skuId); | |
| 131 | + reqVO.setInventoryId(300L); | |
| 132 | + reqVO.setQuantity(new BigDecimal(quantity)); | |
| 133 | + reqVO.setCheckQuantity(new BigDecimal(checkQuantity)); | |
| 134 | + reqVO.setAmount(new BigDecimal("100.00")); | |
| 135 | + return reqVO; | |
| 136 | + } | |
| 137 | + | |
| 138 | + private static WmsCheckOrderDetailDO createCheckOrderDetail(Long orderId, Long skuId, | |
| 139 | + String quantity, String checkQuantity) { | |
| 140 | + return WmsCheckOrderDetailDO.builder() | |
| 141 | + .orderId(orderId) | |
| 142 | + .skuId(skuId) | |
| 143 | + .warehouseId(100L) | |
| 144 | + .inventoryId(300L) | |
| 145 | + .quantity(new BigDecimal(quantity)) | |
| 146 | + .checkQuantity(new BigDecimal(checkQuantity)) | |
| 147 | + .amount(new BigDecimal("100.00")) | |
| 148 | + .build(); | |
| 149 | + } | |
| 150 | + | |
| 151 | +} | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.check; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDO; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderDetailMapper; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 10 | +import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService; | |
| 11 | +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; | |
| 12 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 13 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 14 | +import jakarta.annotation.Resource; | |
| 15 | +import org.junit.jupiter.api.Test; | |
| 16 | +import org.mockito.ArgumentCaptor; | |
| 17 | +import org.springframework.context.annotation.Import; | |
| 18 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 19 | + | |
| 20 | +import java.math.BigDecimal; | |
| 21 | + | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 23 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_REQUIRED; | |
| 24 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_DELETABLE; | |
| 25 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 26 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 27 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 28 | +import static org.mockito.ArgumentMatchers.any; | |
| 29 | +import static org.mockito.Mockito.never; | |
| 30 | +import static org.mockito.Mockito.verify; | |
| 31 | + | |
| 32 | +@Import({WmsCheckOrderServiceImpl.class, WmsCheckOrderDetailServiceImpl.class}) | |
| 33 | +public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { | |
| 34 | + | |
| 35 | + @Resource | |
| 36 | + private WmsCheckOrderServiceImpl checkOrderService; | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private WmsCheckOrderMapper checkOrderMapper; | |
| 40 | + @Resource | |
| 41 | + private WmsCheckOrderDetailMapper checkOrderDetailMapper; | |
| 42 | + | |
| 43 | + @MockitoBean | |
| 44 | + private WmsWarehouseService warehouseService; | |
| 45 | + @MockitoBean | |
| 46 | + private WmsItemSkuService itemSkuService; | |
| 47 | + @MockitoBean | |
| 48 | + private WmsInventoryService inventoryService; | |
| 49 | + | |
| 50 | + @Test | |
| 51 | + public void testCompleteCheckOrder_success() { | |
| 52 | + // mock 数据 | |
| 53 | + Long warehouseId = 100L; | |
| 54 | + Long skuId = 200L; | |
| 55 | + WmsCheckOrderDO order = createCheckOrder(warehouseId); | |
| 56 | + checkOrderMapper.insert(order); | |
| 57 | + checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), skuId, warehouseId, | |
| 58 | + "10.00", "7.00")); | |
| 59 | + | |
| 60 | + // 调用 | |
| 61 | + checkOrderService.completeCheckOrder(order.getId()); | |
| 62 | + | |
| 63 | + // 断言:盘库单 | |
| 64 | + WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); | |
| 65 | + assertNotNull(dbOrder); | |
| 66 | + assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); | |
| 67 | + // 断言:库存变更 | |
| 68 | + ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class); | |
| 69 | + verify(inventoryService).changeInventory(captor.capture()); | |
| 70 | + WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue(); | |
| 71 | + assertEquals(order.getId(), inventoryReqDTO.getOrderId()); | |
| 72 | + assertEquals(order.getNo(), inventoryReqDTO.getOrderNo()); | |
| 73 | + assertEquals(WmsInventoryOrderTypeEnum.CHECK.getType(), inventoryReqDTO.getOrderType()); | |
| 74 | + assertEquals(1, inventoryReqDTO.getItems().size()); | |
| 75 | + assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId()); | |
| 76 | + assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId()); | |
| 77 | + assertEquals(0, new BigDecimal("-3.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity())); | |
| 78 | + } | |
| 79 | + | |
| 80 | + @Test | |
| 81 | + public void testCompleteCheckOrder_zeroDifference() { | |
| 82 | + // mock 数据 | |
| 83 | + WmsCheckOrderDO order = createCheckOrder(100L); | |
| 84 | + checkOrderMapper.insert(order); | |
| 85 | + checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), 200L, 100L, | |
| 86 | + "10.00", "10.00")); | |
| 87 | + | |
| 88 | + // 调用 | |
| 89 | + checkOrderService.completeCheckOrder(order.getId()); | |
| 90 | + | |
| 91 | + // 断言 | |
| 92 | + WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); | |
| 93 | + assertNotNull(dbOrder); | |
| 94 | + assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); | |
| 95 | + verify(inventoryService, never()).changeInventory(any()); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testCompleteCheckOrder_detailRequired() { | |
| 100 | + // mock 数据 | |
| 101 | + WmsCheckOrderDO order = createCheckOrder(100L); | |
| 102 | + checkOrderMapper.insert(order); | |
| 103 | + | |
| 104 | + // 调用,并断言 | |
| 105 | + assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()), | |
| 106 | + CHECK_ORDER_DETAIL_REQUIRED); | |
| 107 | + verify(inventoryService, never()).changeInventory(any()); | |
| 108 | + } | |
| 109 | + | |
| 110 | + @Test | |
| 111 | + public void testCancelCheckOrder_success() { | |
| 112 | + // mock 数据 | |
| 113 | + WmsCheckOrderDO order = createCheckOrder(100L); | |
| 114 | + checkOrderMapper.insert(order); | |
| 115 | + | |
| 116 | + // 调用 | |
| 117 | + checkOrderService.cancelCheckOrder(order.getId()); | |
| 118 | + | |
| 119 | + // 断言 | |
| 120 | + WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); | |
| 121 | + assertNotNull(dbOrder); | |
| 122 | + assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus()); | |
| 123 | + verify(inventoryService, never()).changeInventory(any()); | |
| 124 | + } | |
| 125 | + | |
| 126 | + @Test | |
| 127 | + public void testDeleteCheckOrder_canceled() { | |
| 128 | + // mock 数据 | |
| 129 | + WmsCheckOrderDO order = createCheckOrder(100L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus()); | |
| 130 | + checkOrderMapper.insert(order); | |
| 131 | + checkOrderDetailMapper.insert(createCheckOrderDetail(order.getId(), 200L, 100L, | |
| 132 | + "10.00", "8.00")); | |
| 133 | + | |
| 134 | + // 调用 | |
| 135 | + checkOrderService.deleteCheckOrder(order.getId()); | |
| 136 | + | |
| 137 | + // 断言 | |
| 138 | + assertNull(checkOrderMapper.selectById(order.getId())); | |
| 139 | + assertEquals(0, checkOrderDetailMapper.selectListByOrderId(order.getId()).size()); | |
| 140 | + } | |
| 141 | + | |
| 142 | + @Test | |
| 143 | + public void testDeleteCheckOrder_finished() { | |
| 144 | + // mock 数据 | |
| 145 | + WmsCheckOrderDO order = createCheckOrder(100L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus()); | |
| 146 | + checkOrderMapper.insert(order); | |
| 147 | + | |
| 148 | + // 调用,并断言 | |
| 149 | + assertServiceException(() -> checkOrderService.deleteCheckOrder(order.getId()), | |
| 150 | + CHECK_ORDER_STATUS_NOT_DELETABLE); | |
| 151 | + } | |
| 152 | + | |
| 153 | + private static WmsCheckOrderDO createCheckOrder(Long warehouseId) { | |
| 154 | + return new WmsCheckOrderDO() | |
| 155 | + .setNo("PK202605120001") | |
| 156 | + .setStatus(WmsOrderStatusEnum.PREPARE.getStatus()) | |
| 157 | + .setWarehouseId(warehouseId) | |
| 158 | + .setTotalQuantity(new BigDecimal("-3.00")) | |
| 159 | + .setTotalAmount(new BigDecimal("30.00")); | |
| 160 | + } | |
| 161 | + | |
| 162 | + private static WmsCheckOrderDetailDO createCheckOrderDetail(Long orderId, Long skuId, Long warehouseId, | |
| 163 | + String quantity, String checkQuantity) { | |
| 164 | + return WmsCheckOrderDetailDO.builder() | |
| 165 | + .orderId(orderId) | |
| 166 | + .skuId(skuId) | |
| 167 | + .warehouseId(warehouseId) | |
| 168 | + .inventoryId(300L) | |
| 169 | + .quantity(new BigDecimal(quantity)) | |
| 170 | + .checkQuantity(new BigDecimal(checkQuantity)) | |
| 171 | + .amount(new BigDecimal("30.00")) | |
| 172 | + .build(); | |
| 173 | + } | |
| 174 | + | |
| 175 | +} | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderDetailServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.movement; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderSaveReqVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderDetailMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 9 | +import jakarta.annotation.Resource; | |
| 10 | +import org.junit.jupiter.api.Test; | |
| 11 | +import org.springframework.context.annotation.Import; | |
| 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 13 | + | |
| 14 | +import java.math.BigDecimal; | |
| 15 | +import java.util.Arrays; | |
| 16 | +import java.util.List; | |
| 17 | + | |
| 18 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 19 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_DETAIL_NOT_EXISTS; | |
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 21 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 22 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 23 | + | |
| 24 | +@Import(WmsMovementOrderDetailServiceImpl.class) | |
| 25 | +public class WmsMovementOrderDetailServiceImplTest extends BaseDbUnitTest { | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + private WmsMovementOrderDetailServiceImpl movementOrderDetailService; | |
| 29 | + | |
| 30 | + @Resource | |
| 31 | + private WmsMovementOrderDetailMapper movementOrderDetailMapper; | |
| 32 | + | |
| 33 | + @MockitoBean | |
| 34 | + private WmsItemSkuService itemSkuService; | |
| 35 | + | |
| 36 | + @Test | |
| 37 | + public void testCreateMovementOrderDetailList_success() { | |
| 38 | + // mock 数据 | |
| 39 | + Long orderId = 10L; | |
| 40 | + WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO( | |
| 41 | + createMovementOrderDetailReqVO(null, 1001L, "1.00"), | |
| 42 | + createMovementOrderDetailReqVO(null, 1002L, "2.00")); | |
| 43 | + | |
| 44 | + // 调用 | |
| 45 | + movementOrderDetailService.createMovementOrderDetailList(orderId, reqVO); | |
| 46 | + | |
| 47 | + // 断言 | |
| 48 | + List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(orderId); | |
| 49 | + assertEquals(2, details.size()); | |
| 50 | + assertEquals(orderId, details.get(0).getOrderId()); | |
| 51 | + assertEquals(orderId, details.get(1).getOrderId()); | |
| 52 | + assertEquals(100L, details.get(0).getSourceWarehouseId()); | |
| 53 | + assertEquals(200L, details.get(0).getTargetWarehouseId()); | |
| 54 | + } | |
| 55 | + | |
| 56 | + @Test | |
| 57 | + public void testCreateMovementOrderDetailList_ignoreId() { | |
| 58 | + // mock 数据 | |
| 59 | + WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO( | |
| 60 | + createMovementOrderDetailReqVO(999L, 1001L, "1.00")); | |
| 61 | + | |
| 62 | + // 调用 | |
| 63 | + movementOrderDetailService.createMovementOrderDetailList(10L, reqVO); | |
| 64 | + | |
| 65 | + // 断言 | |
| 66 | + List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(10L); | |
| 67 | + assertEquals(1, details.size()); | |
| 68 | + assertNotNull(details.get(0).getId()); | |
| 69 | + assertEquals(1001L, details.get(0).getSkuId()); | |
| 70 | + } | |
| 71 | + | |
| 72 | + @Test | |
| 73 | + public void testUpdateMovementOrderDetailList_diff() { | |
| 74 | + // mock 数据 | |
| 75 | + Long orderId = 10L; | |
| 76 | + WmsMovementOrderDetailDO detail01 = createMovementOrderDetail(orderId, 1001L, "1.00"); | |
| 77 | + WmsMovementOrderDetailDO detail02 = createMovementOrderDetail(orderId, 1002L, "2.00"); | |
| 78 | + movementOrderDetailMapper.insert(detail01); | |
| 79 | + movementOrderDetailMapper.insert(detail02); | |
| 80 | + WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO( | |
| 81 | + createMovementOrderDetailReqVO(detail01.getId(), 2001L, "11.00"), | |
| 82 | + createMovementOrderDetailReqVO(null, 2002L, "22.00")); | |
| 83 | + | |
| 84 | + // 调用 | |
| 85 | + movementOrderDetailService.updateMovementOrderDetailList(orderId, reqVO); | |
| 86 | + | |
| 87 | + // 断言:修改 | |
| 88 | + WmsMovementOrderDetailDO dbUpdateDetail = movementOrderDetailMapper.selectById(detail01.getId()); | |
| 89 | + assertNotNull(dbUpdateDetail); | |
| 90 | + assertEquals(orderId, dbUpdateDetail.getOrderId()); | |
| 91 | + assertEquals(2001L, dbUpdateDetail.getSkuId()); | |
| 92 | + assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity())); | |
| 93 | + assertEquals(100L, dbUpdateDetail.getSourceWarehouseId()); | |
| 94 | + assertEquals(200L, dbUpdateDetail.getTargetWarehouseId()); | |
| 95 | + // 断言:新增 | |
| 96 | + List<WmsMovementOrderDetailDO> details = movementOrderDetailMapper.selectListByOrderId(orderId); | |
| 97 | + assertEquals(2, details.size()); | |
| 98 | + WmsMovementOrderDetailDO dbCreateDetail = details.stream() | |
| 99 | + .filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId())) | |
| 100 | + .findFirst().orElse(null); | |
| 101 | + assertNotNull(dbCreateDetail); | |
| 102 | + assertEquals(orderId, dbCreateDetail.getOrderId()); | |
| 103 | + assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity())); | |
| 104 | + // 断言:删除 | |
| 105 | + assertNull(movementOrderDetailMapper.selectById(detail02.getId())); | |
| 106 | + } | |
| 107 | + | |
| 108 | + @Test | |
| 109 | + public void testUpdateMovementOrderDetailList_detailNotExists() { | |
| 110 | + // mock 数据 | |
| 111 | + WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO( | |
| 112 | + createMovementOrderDetailReqVO(999L, 1001L, "1.00")); | |
| 113 | + | |
| 114 | + // 调用,并断言 | |
| 115 | + assertServiceException(() -> movementOrderDetailService.updateMovementOrderDetailList(10L, reqVO), | |
| 116 | + MOVEMENT_ORDER_DETAIL_NOT_EXISTS); | |
| 117 | + } | |
| 118 | + | |
| 119 | + private static WmsMovementOrderSaveReqVO createMovementOrderReqVO(WmsMovementOrderDetailSaveReqVO... details) { | |
| 120 | + WmsMovementOrderSaveReqVO reqVO = new WmsMovementOrderSaveReqVO(); | |
| 121 | + reqVO.setSourceWarehouseId(100L); | |
| 122 | + reqVO.setTargetWarehouseId(200L); | |
| 123 | + reqVO.setDetails(Arrays.asList(details)); | |
| 124 | + return reqVO; | |
| 125 | + } | |
| 126 | + | |
| 127 | + private static WmsMovementOrderDetailSaveReqVO createMovementOrderDetailReqVO(Long id, Long skuId, String quantity) { | |
| 128 | + WmsMovementOrderDetailSaveReqVO reqVO = new WmsMovementOrderDetailSaveReqVO(); | |
| 129 | + reqVO.setId(id); | |
| 130 | + reqVO.setSkuId(skuId); | |
| 131 | + reqVO.setQuantity(new BigDecimal(quantity)); | |
| 132 | + reqVO.setAmount(new BigDecimal("100.00")); | |
| 133 | + return reqVO; | |
| 134 | + } | |
| 135 | + | |
| 136 | + private static WmsMovementOrderDetailDO createMovementOrderDetail(Long orderId, Long skuId, String quantity) { | |
| 137 | + return WmsMovementOrderDetailDO.builder() | |
| 138 | + .orderId(orderId) | |
| 139 | + .skuId(skuId) | |
| 140 | + .sourceWarehouseId(100L) | |
| 141 | + .targetWarehouseId(200L) | |
| 142 | + .quantity(new BigDecimal(quantity)) | |
| 143 | + .amount(new BigDecimal("100.00")) | |
| 144 | + .build(); | |
| 145 | + } | |
| 146 | + | |
| 147 | +} | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/movement/WmsMovementOrderServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.movement; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderDetailMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.movement.WmsMovementOrderMapper; | |
| 9 | +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; | |
| 10 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 11 | +import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService; | |
| 12 | +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; | |
| 13 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 14 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.junit.jupiter.api.Test; | |
| 17 | +import org.mockito.ArgumentCaptor; | |
| 18 | +import org.springframework.context.annotation.Import; | |
| 19 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 20 | + | |
| 21 | +import java.math.BigDecimal; | |
| 22 | + | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 24 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_DETAIL_REQUIRED; | |
| 25 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_STATUS_NOT_DELETABLE; | |
| 26 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.MOVEMENT_ORDER_WAREHOUSE_SAME; | |
| 27 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 28 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 29 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 30 | +import static org.mockito.ArgumentMatchers.any; | |
| 31 | +import static org.mockito.Mockito.never; | |
| 32 | +import static org.mockito.Mockito.verify; | |
| 33 | + | |
| 34 | +@Import({WmsMovementOrderServiceImpl.class, WmsMovementOrderDetailServiceImpl.class}) | |
| 35 | +public class WmsMovementOrderServiceImplTest extends BaseDbUnitTest { | |
| 36 | + | |
| 37 | + @Resource | |
| 38 | + private WmsMovementOrderServiceImpl movementOrderService; | |
| 39 | + | |
| 40 | + @Resource | |
| 41 | + private WmsMovementOrderMapper movementOrderMapper; | |
| 42 | + @Resource | |
| 43 | + private WmsMovementOrderDetailMapper movementOrderDetailMapper; | |
| 44 | + | |
| 45 | + @MockitoBean | |
| 46 | + private WmsWarehouseService warehouseService; | |
| 47 | + @MockitoBean | |
| 48 | + private WmsItemSkuService itemSkuService; | |
| 49 | + @MockitoBean | |
| 50 | + private WmsInventoryService inventoryService; | |
| 51 | + | |
| 52 | + @Test | |
| 53 | + public void testCompleteMovementOrder_success() { | |
| 54 | + // mock 数据 | |
| 55 | + Long sourceWarehouseId = 100L; | |
| 56 | + Long targetWarehouseId = 200L; | |
| 57 | + Long skuId = 300L; | |
| 58 | + WmsMovementOrderDO order = createMovementOrder(sourceWarehouseId, targetWarehouseId); | |
| 59 | + movementOrderMapper.insert(order); | |
| 60 | + movementOrderDetailMapper.insert(createMovementOrderDetail(order.getId(), skuId, | |
| 61 | + sourceWarehouseId, targetWarehouseId)); | |
| 62 | + | |
| 63 | + // 调用 | |
| 64 | + movementOrderService.completeMovementOrder(order.getId()); | |
| 65 | + | |
| 66 | + // 断言:移库单 | |
| 67 | + WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(order.getId()); | |
| 68 | + assertNotNull(dbOrder); | |
| 69 | + assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); | |
| 70 | + // 断言:库存变更 | |
| 71 | + ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class); | |
| 72 | + verify(inventoryService).changeInventory(captor.capture()); | |
| 73 | + WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue(); | |
| 74 | + assertEquals(order.getId(), inventoryReqDTO.getOrderId()); | |
| 75 | + assertEquals(order.getNo(), inventoryReqDTO.getOrderNo()); | |
| 76 | + assertEquals(WmsInventoryOrderTypeEnum.MOVEMENT.getType(), inventoryReqDTO.getOrderType()); | |
| 77 | + assertEquals(2, inventoryReqDTO.getItems().size()); | |
| 78 | + assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId()); | |
| 79 | + assertEquals(sourceWarehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId()); | |
| 80 | + assertEquals(0, new BigDecimal("-2.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity())); | |
| 81 | + assertEquals(skuId, inventoryReqDTO.getItems().get(1).getSkuId()); | |
| 82 | + assertEquals(targetWarehouseId, inventoryReqDTO.getItems().get(1).getWarehouseId()); | |
| 83 | + assertEquals(0, new BigDecimal("2.00").compareTo(inventoryReqDTO.getItems().get(1).getQuantity())); | |
| 84 | + } | |
| 85 | + | |
| 86 | + @Test | |
| 87 | + public void testCompleteMovementOrder_detailRequired() { | |
| 88 | + // mock 数据 | |
| 89 | + WmsMovementOrderDO order = createMovementOrder(100L, 200L); | |
| 90 | + movementOrderMapper.insert(order); | |
| 91 | + | |
| 92 | + // 调用,并断言 | |
| 93 | + assertServiceException(() -> movementOrderService.completeMovementOrder(order.getId()), | |
| 94 | + MOVEMENT_ORDER_DETAIL_REQUIRED); | |
| 95 | + verify(inventoryService, never()).changeInventory(any()); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testCreateMovementOrder_sameWarehouse() { | |
| 100 | + // 准备参数 | |
| 101 | + WmsMovementOrderSaveReqVO reqVO = createMovementOrderReqVO(100L, 100L); | |
| 102 | + | |
| 103 | + // 调用,并断言 | |
| 104 | + assertServiceException(() -> movementOrderService.createMovementOrder(reqVO), MOVEMENT_ORDER_WAREHOUSE_SAME); | |
| 105 | + verify(inventoryService, never()).changeInventory(any()); | |
| 106 | + } | |
| 107 | + | |
| 108 | + @Test | |
| 109 | + public void testCancelMovementOrder_success() { | |
| 110 | + // mock 数据 | |
| 111 | + WmsMovementOrderDO order = createMovementOrder(100L, 200L); | |
| 112 | + movementOrderMapper.insert(order); | |
| 113 | + | |
| 114 | + // 调用 | |
| 115 | + movementOrderService.cancelMovementOrder(order.getId()); | |
| 116 | + | |
| 117 | + // 断言 | |
| 118 | + WmsMovementOrderDO dbOrder = movementOrderMapper.selectById(order.getId()); | |
| 119 | + assertNotNull(dbOrder); | |
| 120 | + assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus()); | |
| 121 | + verify(inventoryService, never()).changeInventory(any()); | |
| 122 | + } | |
| 123 | + | |
| 124 | + @Test | |
| 125 | + public void testDeleteMovementOrder_canceled() { | |
| 126 | + // mock 数据 | |
| 127 | + WmsMovementOrderDO order = createMovementOrder(100L, 200L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus()); | |
| 128 | + movementOrderMapper.insert(order); | |
| 129 | + movementOrderDetailMapper.insert(createMovementOrderDetail(order.getId(), 300L, 100L, 200L)); | |
| 130 | + | |
| 131 | + // 调用 | |
| 132 | + movementOrderService.deleteMovementOrder(order.getId()); | |
| 133 | + | |
| 134 | + // 断言 | |
| 135 | + assertNull(movementOrderMapper.selectById(order.getId())); | |
| 136 | + assertEquals(0, movementOrderDetailMapper.selectListByOrderId(order.getId()).size()); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Test | |
| 140 | + public void testDeleteMovementOrder_finished() { | |
| 141 | + // mock 数据 | |
| 142 | + WmsMovementOrderDO order = createMovementOrder(100L, 200L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus()); | |
| 143 | + movementOrderMapper.insert(order); | |
| 144 | + | |
| 145 | + // 调用,并断言 | |
| 146 | + assertServiceException(() -> movementOrderService.deleteMovementOrder(order.getId()), | |
| 147 | + MOVEMENT_ORDER_STATUS_NOT_DELETABLE); | |
| 148 | + } | |
| 149 | + | |
| 150 | + private static WmsMovementOrderDO createMovementOrder(Long sourceWarehouseId, Long targetWarehouseId) { | |
| 151 | + return new WmsMovementOrderDO() | |
| 152 | + .setNo("YK202605120001") | |
| 153 | + .setStatus(WmsOrderStatusEnum.PREPARE.getStatus()) | |
| 154 | + .setSourceWarehouseId(sourceWarehouseId) | |
| 155 | + .setTargetWarehouseId(targetWarehouseId) | |
| 156 | + .setTotalQuantity(new BigDecimal("2.00")) | |
| 157 | + .setTotalAmount(new BigDecimal("20.00")); | |
| 158 | + } | |
| 159 | + | |
| 160 | + private static WmsMovementOrderDetailDO createMovementOrderDetail(Long orderId, Long skuId, | |
| 161 | + Long sourceWarehouseId, Long targetWarehouseId) { | |
| 162 | + return WmsMovementOrderDetailDO.builder() | |
| 163 | + .orderId(orderId) | |
| 164 | + .skuId(skuId) | |
| 165 | + .sourceWarehouseId(sourceWarehouseId) | |
| 166 | + .targetWarehouseId(targetWarehouseId) | |
| 167 | + .quantity(new BigDecimal("2.00")) | |
| 168 | + .amount(new BigDecimal("20.00")) | |
| 169 | + .build(); | |
| 170 | + } | |
| 171 | + | |
| 172 | + private static WmsMovementOrderSaveReqVO createMovementOrderReqVO(Long sourceWarehouseId, Long targetWarehouseId) { | |
| 173 | + WmsMovementOrderSaveReqVO reqVO = new WmsMovementOrderSaveReqVO(); | |
| 174 | + reqVO.setNo("YK202605120001"); | |
| 175 | + reqVO.setSourceWarehouseId(sourceWarehouseId); | |
| 176 | + reqVO.setTargetWarehouseId(targetWarehouseId); | |
| 177 | + reqVO.setTotalQuantity(new BigDecimal("2.00")); | |
| 178 | + reqVO.setTotalAmount(new BigDecimal("20.00")); | |
| 179 | + return reqVO; | |
| 180 | + } | |
| 181 | + | |
| 182 | +} | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderDetailServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderDetailMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 9 | +import jakarta.annotation.Resource; | |
| 10 | +import org.junit.jupiter.api.Test; | |
| 11 | +import org.springframework.context.annotation.Import; | |
| 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 13 | + | |
| 14 | +import java.math.BigDecimal; | |
| 15 | +import java.util.Arrays; | |
| 16 | +import java.util.List; | |
| 17 | + | |
| 18 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 19 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_DETAIL_NOT_EXISTS; | |
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 21 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 22 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 23 | + | |
| 24 | +@Import(WmsShipmentOrderDetailServiceImpl.class) | |
| 25 | +public class WmsShipmentOrderDetailServiceImplTest extends BaseDbUnitTest { | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + private WmsShipmentOrderDetailServiceImpl shipmentOrderDetailService; | |
| 29 | + | |
| 30 | + @Resource | |
| 31 | + private WmsShipmentOrderDetailMapper shipmentOrderDetailMapper; | |
| 32 | + | |
| 33 | + @MockitoBean | |
| 34 | + private WmsItemSkuService itemSkuService; | |
| 35 | + | |
| 36 | + @Test | |
| 37 | + public void testCreateShipmentOrderDetailList_success() { | |
| 38 | + // mock 数据 | |
| 39 | + Long orderId = 10L; | |
| 40 | + WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO( | |
| 41 | + createShipmentOrderDetailReqVO(null, 1001L, "1.00"), | |
| 42 | + createShipmentOrderDetailReqVO(null, 1002L, "2.00")); | |
| 43 | + | |
| 44 | + // 调用 | |
| 45 | + shipmentOrderDetailService.createShipmentOrderDetailList(orderId, reqVO); | |
| 46 | + | |
| 47 | + // 断言 | |
| 48 | + List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId); | |
| 49 | + assertEquals(2, details.size()); | |
| 50 | + assertEquals(orderId, details.get(0).getOrderId()); | |
| 51 | + assertEquals(orderId, details.get(1).getOrderId()); | |
| 52 | + assertEquals(100L, details.get(0).getWarehouseId()); | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Test | |
| 56 | + public void testCreateShipmentOrderDetailList_ignoreId() { | |
| 57 | + // mock 数据 | |
| 58 | + WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO( | |
| 59 | + createShipmentOrderDetailReqVO(999L, 1001L, "1.00")); | |
| 60 | + | |
| 61 | + // 调用 | |
| 62 | + shipmentOrderDetailService.createShipmentOrderDetailList(10L, reqVO); | |
| 63 | + | |
| 64 | + // 断言 | |
| 65 | + List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(10L); | |
| 66 | + assertEquals(1, details.size()); | |
| 67 | + assertNotNull(details.get(0).getId()); | |
| 68 | + assertEquals(1001L, details.get(0).getSkuId()); | |
| 69 | + } | |
| 70 | + | |
| 71 | + @Test | |
| 72 | + public void testUpdateShipmentOrderDetailList_diff() { | |
| 73 | + // mock 数据 | |
| 74 | + Long orderId = 10L; | |
| 75 | + WmsShipmentOrderDetailDO detail01 = createShipmentOrderDetail(orderId, 1001L, "1.00"); | |
| 76 | + WmsShipmentOrderDetailDO detail02 = createShipmentOrderDetail(orderId, 1002L, "2.00"); | |
| 77 | + shipmentOrderDetailMapper.insert(detail01); | |
| 78 | + shipmentOrderDetailMapper.insert(detail02); | |
| 79 | + WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO( | |
| 80 | + createShipmentOrderDetailReqVO(detail01.getId(), 2001L, "11.00"), | |
| 81 | + createShipmentOrderDetailReqVO(null, 2002L, "22.00")); | |
| 82 | + | |
| 83 | + // 调用 | |
| 84 | + shipmentOrderDetailService.updateShipmentOrderDetailList(orderId, reqVO); | |
| 85 | + | |
| 86 | + // 断言:修改 | |
| 87 | + WmsShipmentOrderDetailDO dbUpdateDetail = shipmentOrderDetailMapper.selectById(detail01.getId()); | |
| 88 | + assertNotNull(dbUpdateDetail); | |
| 89 | + assertEquals(orderId, dbUpdateDetail.getOrderId()); | |
| 90 | + assertEquals(2001L, dbUpdateDetail.getSkuId()); | |
| 91 | + assertEquals(0, new BigDecimal("11.00").compareTo(dbUpdateDetail.getQuantity())); | |
| 92 | + // 断言:新增 | |
| 93 | + List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId); | |
| 94 | + assertEquals(2, details.size()); | |
| 95 | + WmsShipmentOrderDetailDO dbCreateDetail = details.stream() | |
| 96 | + .filter(detail -> Long.valueOf(2002L).equals(detail.getSkuId())) | |
| 97 | + .findFirst().orElse(null); | |
| 98 | + assertNotNull(dbCreateDetail); | |
| 99 | + assertEquals(orderId, dbCreateDetail.getOrderId()); | |
| 100 | + assertEquals(0, new BigDecimal("22.00").compareTo(dbCreateDetail.getQuantity())); | |
| 101 | + // 断言:删除 | |
| 102 | + assertNull(shipmentOrderDetailMapper.selectById(detail02.getId())); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Test | |
| 106 | + public void testUpdateShipmentOrderDetailList_detailNotExists() { | |
| 107 | + // mock 数据 | |
| 108 | + WmsShipmentOrderSaveReqVO reqVO = createShipmentOrderReqVO( | |
| 109 | + createShipmentOrderDetailReqVO(999L, 1001L, "1.00")); | |
| 110 | + | |
| 111 | + // 调用,并断言 | |
| 112 | + assertServiceException(() -> shipmentOrderDetailService.updateShipmentOrderDetailList(10L, reqVO), | |
| 113 | + SHIPMENT_ORDER_DETAIL_NOT_EXISTS); | |
| 114 | + } | |
| 115 | + | |
| 116 | + private static WmsShipmentOrderSaveReqVO createShipmentOrderReqVO(WmsShipmentOrderDetailSaveReqVO... details) { | |
| 117 | + WmsShipmentOrderSaveReqVO reqVO = new WmsShipmentOrderSaveReqVO(); | |
| 118 | + reqVO.setWarehouseId(100L); | |
| 119 | + reqVO.setDetails(Arrays.asList(details)); | |
| 120 | + return reqVO; | |
| 121 | + } | |
| 122 | + | |
| 123 | + private static WmsShipmentOrderDetailSaveReqVO createShipmentOrderDetailReqVO(Long id, Long skuId, String quantity) { | |
| 124 | + WmsShipmentOrderDetailSaveReqVO reqVO = new WmsShipmentOrderDetailSaveReqVO(); | |
| 125 | + reqVO.setId(id); | |
| 126 | + reqVO.setSkuId(skuId); | |
| 127 | + reqVO.setQuantity(new BigDecimal(quantity)); | |
| 128 | + reqVO.setAmount(new BigDecimal("100.00")); | |
| 129 | + return reqVO; | |
| 130 | + } | |
| 131 | + | |
| 132 | + private static WmsShipmentOrderDetailDO createShipmentOrderDetail(Long orderId, Long skuId, String quantity) { | |
| 133 | + return WmsShipmentOrderDetailDO.builder() | |
| 134 | + .orderId(orderId) | |
| 135 | + .skuId(skuId) | |
| 136 | + .warehouseId(100L) | |
| 137 | + .quantity(new BigDecimal(quantity)) | |
| 138 | + .amount(new BigDecimal("100.00")) | |
| 139 | + .build(); | |
| 140 | + } | |
| 141 | + | |
| 142 | +} | ... | ... |
yudao-module-wms/src/test/resources/sql/clean.sql
yudao-module-wms/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -60,9 +60,6 @@ CREATE TABLE IF NOT EXISTS "wms_inventory_history" ( |
| 60 | 60 | "quantity" decimal(24, 6) NOT NULL DEFAULT '0', |
| 61 | 61 | "before_quantity" decimal(24, 6) DEFAULT NULL, |
| 62 | 62 | "after_quantity" decimal(24, 6) DEFAULT NULL, |
| 63 | - "batch_no" varchar(64) DEFAULT NULL, | |
| 64 | - "production_date" timestamp DEFAULT NULL, | |
| 65 | - "expiration_date" timestamp DEFAULT NULL, | |
| 66 | 63 | "amount" decimal(24, 6) DEFAULT NULL, |
| 67 | 64 | "remark" varchar(255) DEFAULT NULL, |
| 68 | 65 | "order_id" bigint DEFAULT NULL, |
| ... | ... | @@ -103,9 +100,6 @@ CREATE TABLE IF NOT EXISTS "wms_receipt_order_detail" ( |
| 103 | 100 | "order_id" bigint NOT NULL, |
| 104 | 101 | "sku_id" bigint NOT NULL, |
| 105 | 102 | "warehouse_id" bigint NOT NULL, |
| 106 | - "batch_no" varchar(64) DEFAULT NULL, | |
| 107 | - "production_date" timestamp DEFAULT NULL, | |
| 108 | - "expiration_date" timestamp DEFAULT NULL, | |
| 109 | 103 | "quantity" decimal(20, 2) NOT NULL DEFAULT '0', |
| 110 | 104 | "amount" decimal(10, 2) DEFAULT NULL, |
| 111 | 105 | "creator" varchar(64) DEFAULT '', |
| ... | ... | @@ -143,9 +137,6 @@ CREATE TABLE IF NOT EXISTS "wms_shipment_order_detail" ( |
| 143 | 137 | "order_id" bigint NOT NULL, |
| 144 | 138 | "sku_id" bigint NOT NULL, |
| 145 | 139 | "warehouse_id" bigint NOT NULL, |
| 146 | - "batch_no" varchar(64) DEFAULT NULL, | |
| 147 | - "production_date" timestamp DEFAULT NULL, | |
| 148 | - "expiration_date" timestamp DEFAULT NULL, | |
| 149 | 140 | "quantity" decimal(20, 2) NOT NULL DEFAULT '0', |
| 150 | 141 | "amount" decimal(10, 2) DEFAULT NULL, |
| 151 | 142 | "creator" varchar(64) DEFAULT '', |
| ... | ... | @@ -156,3 +147,76 @@ CREATE TABLE IF NOT EXISTS "wms_shipment_order_detail" ( |
| 156 | 147 | "tenant_id" bigint NOT NULL DEFAULT '0', |
| 157 | 148 | PRIMARY KEY ("id") |
| 158 | 149 | ) COMMENT 'WMS 出库单明细表'; |
| 150 | + | |
| 151 | +CREATE TABLE IF NOT EXISTS "wms_movement_order" ( | |
| 152 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 153 | + "no" varchar(64) NOT NULL, | |
| 154 | + "status" int NOT NULL DEFAULT '0', | |
| 155 | + "remark" varchar(255) DEFAULT NULL, | |
| 156 | + "source_warehouse_id" bigint NOT NULL, | |
| 157 | + "target_warehouse_id" bigint NOT NULL, | |
| 158 | + "total_quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 159 | + "total_amount" decimal(10, 2) DEFAULT NULL, | |
| 160 | + "creator" varchar(64) DEFAULT '', | |
| 161 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 162 | + "updater" varchar(64) DEFAULT '', | |
| 163 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 164 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 165 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 166 | + PRIMARY KEY ("id") | |
| 167 | +) COMMENT 'WMS 移库单表'; | |
| 168 | + | |
| 169 | +CREATE TABLE IF NOT EXISTS "wms_movement_order_detail" ( | |
| 170 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 171 | + "remark" varchar(255) DEFAULT NULL, | |
| 172 | + "order_id" bigint NOT NULL, | |
| 173 | + "sku_id" bigint NOT NULL, | |
| 174 | + "source_warehouse_id" bigint NOT NULL, | |
| 175 | + "target_warehouse_id" bigint NOT NULL, | |
| 176 | + "quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 177 | + "amount" decimal(10, 2) DEFAULT NULL, | |
| 178 | + "creator" varchar(64) DEFAULT '', | |
| 179 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 180 | + "updater" varchar(64) DEFAULT '', | |
| 181 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 182 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 183 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 184 | + PRIMARY KEY ("id") | |
| 185 | +) COMMENT 'WMS 移库单明细表'; | |
| 186 | + | |
| 187 | +CREATE TABLE IF NOT EXISTS "wms_check_order" ( | |
| 188 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 189 | + "no" varchar(64) NOT NULL, | |
| 190 | + "status" int NOT NULL DEFAULT '0', | |
| 191 | + "remark" varchar(255) DEFAULT NULL, | |
| 192 | + "warehouse_id" bigint NOT NULL, | |
| 193 | + "total_quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 194 | + "total_amount" decimal(10, 2) DEFAULT NULL, | |
| 195 | + "creator" varchar(64) DEFAULT '', | |
| 196 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 197 | + "updater" varchar(64) DEFAULT '', | |
| 198 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 199 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 200 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 201 | + PRIMARY KEY ("id") | |
| 202 | +) COMMENT 'WMS 盘库单表'; | |
| 203 | + | |
| 204 | +CREATE TABLE IF NOT EXISTS "wms_check_order_detail" ( | |
| 205 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 206 | + "remark" varchar(255) DEFAULT NULL, | |
| 207 | + "order_id" bigint NOT NULL, | |
| 208 | + "sku_id" bigint NOT NULL, | |
| 209 | + "warehouse_id" bigint NOT NULL, | |
| 210 | + "inventory_id" bigint DEFAULT NULL, | |
| 211 | + "receipt_time" timestamp DEFAULT NULL, | |
| 212 | + "quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 213 | + "check_quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 214 | + "amount" decimal(10, 2) DEFAULT NULL, | |
| 215 | + "creator" varchar(64) DEFAULT '', | |
| 216 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 217 | + "updater" varchar(64) DEFAULT '', | |
| 218 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 219 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 220 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 221 | + PRIMARY KEY ("id") | |
| 222 | +) COMMENT 'WMS 盘库单明细表'; | ... | ... |