Commit 9ff3593ffb732396da7730950b6cef587a54f34c

Authored by YunaiV
1 parent 02fe48e4

feat(wms):增加 code 字段生成(从后端到前端),用户更可控

Showing 18 changed files with 219 additions and 54 deletions
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandPageReqVO.java
@@ -12,6 +12,9 @@ import lombok.ToString; @@ -12,6 +12,9 @@ import lombok.ToString;
12 @ToString(callSuper = true) 12 @ToString(callSuper = true)
13 public class WmsItemBrandPageReqVO extends PageParam { 13 public class WmsItemBrandPageReqVO extends PageParam {
14 14
  15 + @Schema(description = "品牌编号", example = "B00000001")
  16 + private String code;
  17 +
15 @Schema(description = "品牌名称", example = "华为") 18 @Schema(description = "品牌名称", example = "华为")
16 private String name; 19 private String name;
17 20
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandRespVO.java
@@ -16,6 +16,10 @@ public class WmsItemBrandRespVO { @@ -16,6 +16,10 @@ public class WmsItemBrandRespVO {
16 @ExcelProperty("编号") 16 @ExcelProperty("编号")
17 private Long id; 17 private Long id;
18 18
  19 + @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "B00000001")
  20 + @ExcelProperty("品牌编号")
  21 + private String code;
  22 +
19 @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为") 23 @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
20 @ExcelProperty("品牌名称") 24 @ExcelProperty("品牌名称")
21 private String name; 25 private String name;
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandSaveReqVO.java
@@ -12,6 +12,11 @@ public class WmsItemBrandSaveReqVO { @@ -12,6 +12,11 @@ public class WmsItemBrandSaveReqVO {
12 @Schema(description = "编号", example = "1024") 12 @Schema(description = "编号", example = "1024")
13 private Long id; 13 private Long id;
14 14
  15 + @Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "B00000001")
  16 + @NotEmpty(message = "品牌编号不能为空")
  17 + @Size(max = 20, message = "品牌编号长度不能超过 20 个字符")
  18 + private String code;
  19 +
15 @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为") 20 @Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
16 @NotEmpty(message = "品牌名称不能为空") 21 @NotEmpty(message = "品牌名称不能为空")
17 @Size(max = 30, message = "品牌名称长度不能超过 30 个字符") 22 @Size(max = 30, message = "品牌名称长度不能超过 30 个字符")
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/category/WmsItemCategoryListReqVO.java
@@ -12,6 +12,9 @@ public class WmsItemCategoryListReqVO { @@ -12,6 +12,9 @@ public class WmsItemCategoryListReqVO {
12 @Schema(description = "父级编号", example = "1") 12 @Schema(description = "父级编号", example = "1")
13 private Long parentId; 13 private Long parentId;
14 14
  15 + @Schema(description = "分类编号", example = "C00000001")
  16 + private String code;
  17 +
15 @Schema(description = "分类名称", example = "原料") 18 @Schema(description = "分类名称", example = "原料")
16 private String name; 19 private String name;
17 20
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/category/WmsItemCategoryRespVO.java
@@ -15,6 +15,9 @@ public class WmsItemCategoryRespVO { @@ -15,6 +15,9 @@ public class WmsItemCategoryRespVO {
15 @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 15 @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
16 private Long parentId; 16 private Long parentId;
17 17
  18 + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00000001")
  19 + private String code;
  20 +
18 @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料") 21 @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料")
19 private String name; 22 private String name;
20 23
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/category/WmsItemCategorySaveReqVO.java
@@ -19,6 +19,11 @@ public class WmsItemCategorySaveReqVO { @@ -19,6 +19,11 @@ public class WmsItemCategorySaveReqVO {
19 @NotNull(message = "父级编号不能为空") 19 @NotNull(message = "父级编号不能为空")
20 private Long parentId; 20 private Long parentId;
21 21
  22 + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00000001")
  23 + @NotEmpty(message = "分类编号不能为空")
  24 + @Size(max = 20, message = "分类编号长度不能超过 20 个字符")
  25 + private String code;
  26 +
22 @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料") 27 @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料")
23 @NotEmpty(message = "分类名称不能为空") 28 @NotEmpty(message = "分类名称不能为空")
24 @Size(max = 30, message = "分类名称长度不能超过 30 个字符") 29 @Size(max = 30, message = "分类名称长度不能超过 30 个字符")
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/item/WmsItemSaveReqVO.java
@@ -18,7 +18,8 @@ public class WmsItemSaveReqVO { @@ -18,7 +18,8 @@ public class WmsItemSaveReqVO {
18 @Schema(description = "编号", example = "1024") 18 @Schema(description = "编号", example = "1024")
19 private Long id; 19 private Long id;
20 20
21 - @Schema(description = "商品编号", example = "ITEM001") 21 + @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001")
  22 + @NotBlank(message = "商品编号不能为空")
22 @Size(max = 20, message = "商品编号长度不能超过 20 个字符") 23 @Size(max = 20, message = "商品编号长度不能超过 20 个字符")
23 private String code; 24 private String code;
24 25
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/md/item/WmsItemBrandDO.java
@@ -27,6 +27,10 @@ public class WmsItemBrandDO extends BaseDO { @@ -27,6 +27,10 @@ public class WmsItemBrandDO extends BaseDO {
27 @TableId 27 @TableId
28 private Long id; 28 private Long id;
29 /** 29 /**
  30 + * 品牌编号
  31 + */
  32 + private String code;
  33 + /**
30 * 品牌名称 34 * 品牌名称
31 */ 35 */
32 private String name; 36 private String name;
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/md/item/WmsItemCategoryDO.java
@@ -39,6 +39,10 @@ public class WmsItemCategoryDO extends BaseDO { @@ -39,6 +39,10 @@ public class WmsItemCategoryDO extends BaseDO {
39 */ 39 */
40 private Long parentId; 40 private Long parentId;
41 /** 41 /**
  42 + * 分类编号
  43 + */
  44 + private String code;
  45 + /**
42 * 分类名称 46 * 分类名称
43 */ 47 */
44 private String name; 48 private String name;
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/md/item/WmsItemBrandMapper.java
@@ -17,8 +17,13 @@ public interface WmsItemBrandMapper extends BaseMapperX<WmsItemBrandDO> { @@ -17,8 +17,13 @@ public interface WmsItemBrandMapper extends BaseMapperX<WmsItemBrandDO> {
17 17
18 default PageResult<WmsItemBrandDO> selectPage(WmsItemBrandPageReqVO reqVO) { 18 default PageResult<WmsItemBrandDO> selectPage(WmsItemBrandPageReqVO reqVO) {
19 return selectPage(reqVO, new LambdaQueryWrapperX<WmsItemBrandDO>() 19 return selectPage(reqVO, new LambdaQueryWrapperX<WmsItemBrandDO>()
  20 + .likeIfPresent(WmsItemBrandDO::getCode, reqVO.getCode())
20 .likeIfPresent(WmsItemBrandDO::getName, reqVO.getName()) 21 .likeIfPresent(WmsItemBrandDO::getName, reqVO.getName())
21 .orderByDesc(WmsItemBrandDO::getId)); 22 .orderByDesc(WmsItemBrandDO::getId));
22 } 23 }
23 24
  25 + default WmsItemBrandDO selectByCode(String code) {
  26 + return selectOne(WmsItemBrandDO::getCode, code);
  27 + }
  28 +
24 } 29 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/md/item/WmsItemCategoryMapper.java
@@ -20,6 +20,7 @@ public interface WmsItemCategoryMapper extends BaseMapperX&lt;WmsItemCategoryDO&gt; { @@ -20,6 +20,7 @@ public interface WmsItemCategoryMapper extends BaseMapperX&lt;WmsItemCategoryDO&gt; {
20 default List<WmsItemCategoryDO> selectList(WmsItemCategoryListReqVO reqVO) { 20 default List<WmsItemCategoryDO> selectList(WmsItemCategoryListReqVO reqVO) {
21 return selectList(new LambdaQueryWrapperX<WmsItemCategoryDO>() 21 return selectList(new LambdaQueryWrapperX<WmsItemCategoryDO>()
22 .eqIfPresent(WmsItemCategoryDO::getParentId, reqVO.getParentId()) 22 .eqIfPresent(WmsItemCategoryDO::getParentId, reqVO.getParentId())
  23 + .likeIfPresent(WmsItemCategoryDO::getCode, reqVO.getCode())
23 .likeIfPresent(WmsItemCategoryDO::getName, reqVO.getName()) 24 .likeIfPresent(WmsItemCategoryDO::getName, reqVO.getName())
24 .eqIfPresent(WmsItemCategoryDO::getStatus, reqVO.getStatus()) 25 .eqIfPresent(WmsItemCategoryDO::getStatus, reqVO.getStatus())
25 .orderByAsc(WmsItemCategoryDO::getSort) 26 .orderByAsc(WmsItemCategoryDO::getSort)
@@ -30,6 +31,10 @@ public interface WmsItemCategoryMapper extends BaseMapperX&lt;WmsItemCategoryDO&gt; { @@ -30,6 +31,10 @@ public interface WmsItemCategoryMapper extends BaseMapperX&lt;WmsItemCategoryDO&gt; {
30 return selectOne(WmsItemCategoryDO::getParentId, parentId, WmsItemCategoryDO::getName, name); 31 return selectOne(WmsItemCategoryDO::getParentId, parentId, WmsItemCategoryDO::getName, name);
31 } 32 }
32 33
  34 + default WmsItemCategoryDO selectByCode(String code) {
  35 + return selectOne(WmsItemCategoryDO::getCode, code);
  36 + }
  37 +
33 default List<WmsItemCategoryDO> selectListByParentIds(Collection<Long> parentIds) { 38 default List<WmsItemCategoryDO> selectListByParentIds(Collection<Long> parentIds) {
34 return selectList(new LambdaQueryWrapperX<WmsItemCategoryDO>() 39 return selectList(new LambdaQueryWrapperX<WmsItemCategoryDO>()
35 .in(WmsItemCategoryDO::getParentId, parentIds) 40 .in(WmsItemCategoryDO::getParentId, parentIds)
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemBrandServiceImpl.java
1 package cn.iocoder.yudao.module.wms.service.md.item; 1 package cn.iocoder.yudao.module.wms.service.md.item;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandPageReqVO; 7 import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandPageReqVO;
@@ -16,6 +17,7 @@ import java.util.Collections; @@ -16,6 +17,7 @@ import java.util.Collections;
16 import java.util.List; 17 import java.util.List;
17 18
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_CODE_DUPLICATE;
19 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_HAS_ITEM; 21 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_HAS_ITEM;
20 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_NOT_EXISTS; 22 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.ITEM_BRAND_NOT_EXISTS;
21 23
@@ -35,6 +37,9 @@ public class WmsItemBrandServiceImpl implements WmsItemBrandService { @@ -35,6 +37,9 @@ public class WmsItemBrandServiceImpl implements WmsItemBrandService {
35 37
36 @Override 38 @Override
37 public Long createItemBrand(WmsItemBrandSaveReqVO createReqVO) { 39 public Long createItemBrand(WmsItemBrandSaveReqVO createReqVO) {
  40 + // 校验编号唯一
  41 + validateBrandCodeUnique(null, createReqVO.getCode());
  42 +
38 WmsItemBrandDO brand = BeanUtils.toBean(createReqVO, WmsItemBrandDO.class); 43 WmsItemBrandDO brand = BeanUtils.toBean(createReqVO, WmsItemBrandDO.class);
39 brandMapper.insert(brand); 44 brandMapper.insert(brand);
40 return brand.getId(); 45 return brand.getId();
@@ -44,12 +49,28 @@ public class WmsItemBrandServiceImpl implements WmsItemBrandService { @@ -44,12 +49,28 @@ public class WmsItemBrandServiceImpl implements WmsItemBrandService {
44 public void updateItemBrand(WmsItemBrandSaveReqVO updateReqVO) { 49 public void updateItemBrand(WmsItemBrandSaveReqVO updateReqVO) {
45 // 校验存在 50 // 校验存在
46 validateItemBrandExists(updateReqVO.getId()); 51 validateItemBrandExists(updateReqVO.getId());
  52 + // 校验编号唯一
  53 + validateBrandCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
47 54
48 // 更新 55 // 更新
49 WmsItemBrandDO updateObj = BeanUtils.toBean(updateReqVO, WmsItemBrandDO.class); 56 WmsItemBrandDO updateObj = BeanUtils.toBean(updateReqVO, WmsItemBrandDO.class);
50 brandMapper.updateById(updateObj); 57 brandMapper.updateById(updateObj);
51 } 58 }
52 59
  60 + private void validateBrandCodeUnique(Long id, String code) {
  61 + WmsItemBrandDO brand = brandMapper.selectByCode(code);
  62 + if (brand == null) {
  63 + return;
  64 + }
  65 + // 如果 id 为空,说明新增;和数据库已有 code 重复
  66 + if (id == null) {
  67 + throw exception(ITEM_BRAND_CODE_DUPLICATE);
  68 + }
  69 + if (ObjectUtil.notEqual(brand.getId(), id)) {
  70 + throw exception(ITEM_BRAND_CODE_DUPLICATE);
  71 + }
  72 + }
  73 +
53 @Override 74 @Override
54 public void deleteItemBrand(Long id) { 75 public void deleteItemBrand(Long id) {
55 // 校验存在 76 // 校验存在
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemCategoryServiceImpl.java
@@ -60,10 +60,25 @@ public class WmsItemCategoryServiceImpl implements WmsItemCategoryService { @@ -60,10 +60,25 @@ public class WmsItemCategoryServiceImpl implements WmsItemCategoryService {
60 } 60 }
61 61
62 private void validateCategorySaveData(WmsItemCategorySaveReqVO reqVO) { 62 private void validateCategorySaveData(WmsItemCategorySaveReqVO reqVO) {
  63 + validateCategoryCodeUnique(reqVO.getId(), reqVO.getCode());
63 validateCategoryNameUnique(reqVO.getId(), reqVO.getParentId(), reqVO.getName()); 64 validateCategoryNameUnique(reqVO.getId(), reqVO.getParentId(), reqVO.getName());
64 validateParentCategory(reqVO.getId(), reqVO.getParentId()); 65 validateParentCategory(reqVO.getId(), reqVO.getParentId());
65 } 66 }
66 67
  68 + private void validateCategoryCodeUnique(Long id, String code) {
  69 + WmsItemCategoryDO category = categoryMapper.selectByCode(code);
  70 + if (category == null) {
  71 + return;
  72 + }
  73 + // 如果 id 为空,说明新增;和数据库已有 code 重复
  74 + if (id == null) {
  75 + throw exception(ITEM_CATEGORY_CODE_DUPLICATE);
  76 + }
  77 + if (ObjectUtil.notEqual(category.getId(), id)) {
  78 + throw exception(ITEM_CATEGORY_CODE_DUPLICATE);
  79 + }
  80 + }
  81 +
67 private void validateCategoryNameUnique(Long id, Long parentId, String name) { 82 private void validateCategoryNameUnique(Long id, Long parentId, String name) {
68 WmsItemCategoryDO category = categoryMapper.selectByParentIdAndName(parentId, name); 83 WmsItemCategoryDO category = categoryMapper.selectByParentIdAndName(parentId, name);
69 if (category == null) { 84 if (category == null) {
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemSkuServiceImpl.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.wms.service.md.item; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.wms.service.md.item;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
5 -import cn.hutool.core.util.StrUtil;  
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuSaveReqVO; 6 import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuSaveReqVO;
8 import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; 7 import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
@@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderDetailServic @@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderDetailServic
13 import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderDetailService; 12 import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderDetailService;
14 import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderDetailService; 13 import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderDetailService;
15 import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService; 14 import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService;
16 -import cn.iocoder.yudao.module.wms.util.WmsUtils;  
17 import jakarta.annotation.Resource; 15 import jakarta.annotation.Resource;
18 import org.springframework.context.annotation.Lazy; 16 import org.springframework.context.annotation.Lazy;
19 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
@@ -64,7 +62,6 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService { @@ -64,7 +62,6 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService {
64 if (CollUtil.isNotEmpty(convertList(list, WmsItemSkuDO::getId))) { 62 if (CollUtil.isNotEmpty(convertList(list, WmsItemSkuDO::getId))) {
65 throw exception(ITEM_SKU_NOT_EXISTS); 63 throw exception(ITEM_SKU_NOT_EXISTS);
66 } 64 }
67 - fillEmptyBarCode(list);  
68 itemSkuMapper.insertBatch(list); 65 itemSkuMapper.insertBatch(list);
69 } 66 }
70 67
@@ -92,12 +89,10 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService { @@ -92,12 +89,10 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService {
92 throw exception(ITEM_SKU_NOT_EXISTS); 89 throw exception(ITEM_SKU_NOT_EXISTS);
93 } 90 }
94 diffList.get(0).forEach(sku -> sku.setItemId(itemId)); 91 diffList.get(0).forEach(sku -> sku.setItemId(itemId));
95 - fillEmptyBarCode(diffList.get(0));  
96 itemSkuMapper.insertBatch(diffList.get(0)); 92 itemSkuMapper.insertBatch(diffList.get(0));
97 } 93 }
98 if (CollUtil.isNotEmpty(diffList.get(1))) { 94 if (CollUtil.isNotEmpty(diffList.get(1))) {
99 diffList.get(1).forEach(sku -> sku.setItemId(itemId)); 95 diffList.get(1).forEach(sku -> sku.setItemId(itemId));
100 - fillEmptyBarCode(diffList.get(1));  
101 itemSkuMapper.updateBatch(diffList.get(1)); 96 itemSkuMapper.updateBatch(diffList.get(1));
102 } 97 }
103 } 98 }
@@ -185,17 +180,4 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService { @@ -185,17 +180,4 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService {
185 } 180 }
186 } 181 }
187 182
188 - /**  
189 - * 填充空的条形码  
190 - *  
191 - * @param skus 商品 SKU 列表  
192 - */  
193 - private void fillEmptyBarCode(List<WmsItemSkuDO> skus) {  
194 - skus.forEach(sku -> {  
195 - if (StrUtil.isBlank(sku.getBarCode())) {  
196 - sku.setBarCode(WmsUtils.generateBarCode());  
197 - }  
198 - });  
199 - }  
200 -  
201 } 183 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/util/WmsUtils.java deleted
1 -package cn.iocoder.yudao.module.wms.util;  
2 -  
3 -import cn.hutool.core.util.RandomUtil;  
4 -import lombok.experimental.UtilityClass;  
5 -  
6 -/**  
7 - * WMS 工具类  
8 - *  
9 - * @author 芋道源码  
10 - */  
11 -@UtilityClass  
12 -public class WmsUtils {  
13 -  
14 - private static final int BAR_CODE_LENGTH = 8;  
15 -  
16 - /**  
17 - * 生成条码  
18 - *  
19 - * @return 条码  
20 - */  
21 - public String generateBarCode() {  
22 - return RandomUtil.randomNumbers(BAR_CODE_LENGTH);  
23 - }  
24 -  
25 -}  
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/check/WmsCheckOrderServiceImplTest.java
@@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderMapper; @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.wms.dal.mysql.order.check.WmsCheckOrderMapper;
10 import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum; 10 import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
11 import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; 11 import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
12 import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService; 12 import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
13 -import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; 13 +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryCheckReqDTO;
14 import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; 14 import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
15 import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; 15 import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
16 import jakarta.annotation.Resource; 16 import jakarta.annotation.Resource;
@@ -25,13 +25,16 @@ import java.util.Arrays; @@ -25,13 +25,16 @@ import java.util.Arrays;
25 import java.util.List; 25 import java.util.List;
26 26
27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  28 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_REQUIRED; 29 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_DETAIL_REQUIRED;
  30 +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_INVENTORY_CHANGED;
29 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_DELETABLE; 31 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_DELETABLE;
30 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_PREPARE; 32 import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.CHECK_ORDER_STATUS_NOT_PREPARE;
31 import static org.junit.jupiter.api.Assertions.assertEquals; 33 import static org.junit.jupiter.api.Assertions.assertEquals;
32 import static org.junit.jupiter.api.Assertions.assertNotNull; 34 import static org.junit.jupiter.api.Assertions.assertNotNull;
33 import static org.junit.jupiter.api.Assertions.assertNull; 35 import static org.junit.jupiter.api.Assertions.assertNull;
34 import static org.mockito.ArgumentMatchers.any; 36 import static org.mockito.ArgumentMatchers.any;
  37 +import static org.mockito.Mockito.doThrow;
35 import static org.mockito.Mockito.never; 38 import static org.mockito.Mockito.never;
36 import static org.mockito.Mockito.verify; 39 import static org.mockito.Mockito.verify;
37 40
@@ -118,17 +121,19 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -118,17 +121,19 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
118 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); 121 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
119 assertNotNull(dbOrder); 122 assertNotNull(dbOrder);
120 assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); 123 assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
121 - // 断言:库存变更  
122 - ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class);  
123 - verify(inventoryService).changeInventory(captor.capture());  
124 - WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue(); 124 + // 断言:库存盘点
  125 + ArgumentCaptor<WmsInventoryCheckReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryCheckReqDTO.class);
  126 + verify(inventoryService).checkInventory(captor.capture());
  127 + WmsInventoryCheckReqDTO inventoryReqDTO = captor.getValue();
125 assertEquals(order.getId(), inventoryReqDTO.getOrderId()); 128 assertEquals(order.getId(), inventoryReqDTO.getOrderId());
126 assertEquals(order.getNo(), inventoryReqDTO.getOrderNo()); 129 assertEquals(order.getNo(), inventoryReqDTO.getOrderNo());
127 assertEquals(WmsOrderTypeEnum.CHECK.getType(), inventoryReqDTO.getOrderType()); 130 assertEquals(WmsOrderTypeEnum.CHECK.getType(), inventoryReqDTO.getOrderType());
128 assertEquals(1, inventoryReqDTO.getItems().size()); 131 assertEquals(1, inventoryReqDTO.getItems().size());
129 assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId()); 132 assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
130 assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId()); 133 assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
131 - assertEquals(0, new BigDecimal("-3.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity())); 134 + assertEquals(300L, inventoryReqDTO.getItems().get(0).getInventoryId());
  135 + assertEquals(0, new BigDecimal("10.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
  136 + assertEquals(0, new BigDecimal("7.00").compareTo(inventoryReqDTO.getItems().get(0).getCheckQuantity()));
132 assertEquals(0, new BigDecimal("30.00").compareTo(inventoryReqDTO.getItems().get(0).getPrice())); 137 assertEquals(0, new BigDecimal("30.00").compareTo(inventoryReqDTO.getItems().get(0).getPrice()));
133 } 138 }
134 139
@@ -147,7 +152,49 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -147,7 +152,49 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
147 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); 152 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
148 assertNotNull(dbOrder); 153 assertNotNull(dbOrder);
149 assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); 154 assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus());
150 - verify(inventoryService, never()).changeInventory(any()); 155 + verify(inventoryService).checkInventory(any());
  156 + }
  157 +
  158 + @Test
  159 + public void testCompleteCheckOrder_newInventoryCurrentMissing() {
  160 + // mock 数据
  161 + Long warehouseId = 100L;
  162 + Long skuId = 200L;
  163 + WmsCheckOrderDO order = createCheckOrder(warehouseId);
  164 + checkOrderMapper.insert(order);
  165 + checkOrderDetailMapper.insert(createNewInventoryCheckOrderDetail(order.getId(), skuId, warehouseId,
  166 + "0.00", "5.00"));
  167 + // 调用
  168 + checkOrderService.completeCheckOrder(order.getId());
  169 +
  170 + // 断言
  171 + ArgumentCaptor<WmsInventoryCheckReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryCheckReqDTO.class);
  172 + verify(inventoryService).checkInventory(captor.capture());
  173 + WmsInventoryCheckReqDTO inventoryReqDTO = captor.getValue();
  174 + assertEquals(1, inventoryReqDTO.getItems().size());
  175 + assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId());
  176 + assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId());
  177 + assertNull(inventoryReqDTO.getItems().get(0).getInventoryId());
  178 + assertEquals(0, new BigDecimal("0.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity()));
  179 + assertEquals(0, new BigDecimal("5.00").compareTo(inventoryReqDTO.getItems().get(0).getCheckQuantity()));
  180 + }
  181 +
  182 + @Test
  183 + public void testCompleteCheckOrder_checkInventoryChanged() {
  184 + // mock 数据
  185 + Long warehouseId = 100L;
  186 + Long skuId = 200L;
  187 + WmsCheckOrderDO order = createCheckOrder(warehouseId);
  188 + checkOrderMapper.insert(order);
  189 + checkOrderDetailMapper.insert(createNewInventoryCheckOrderDetail(order.getId(), skuId, warehouseId,
  190 + "0.00", "5.00"));
  191 + doThrow(exception(CHECK_ORDER_INVENTORY_CHANGED)).when(inventoryService).checkInventory(any());
  192 +
  193 + // 调用,并断言
  194 + assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
  195 + CHECK_ORDER_INVENTORY_CHANGED);
  196 + assertEquals(WmsOrderStatusEnum.PREPARE.getStatus(),
  197 + checkOrderMapper.selectById(order.getId()).getStatus());
151 } 198 }
152 199
153 @Test 200 @Test
@@ -159,7 +206,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -159,7 +206,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
159 // 调用,并断言 206 // 调用,并断言
160 assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()), 207 assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
161 CHECK_ORDER_DETAIL_REQUIRED); 208 CHECK_ORDER_DETAIL_REQUIRED);
162 - verify(inventoryService, never()).changeInventory(any()); 209 + verify(inventoryService, never()).checkInventory(any());
163 } 210 }
164 211
165 @Test 212 @Test
@@ -176,7 +223,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -176,7 +223,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
176 // 调用,并断言:二次完成不能再次写库存 223 // 调用,并断言:二次完成不能再次写库存
177 assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()), 224 assertServiceException(() -> checkOrderService.completeCheckOrder(order.getId()),
178 CHECK_ORDER_STATUS_NOT_PREPARE); 225 CHECK_ORDER_STATUS_NOT_PREPARE);
179 - verify(inventoryService).changeInventory(any()); 226 + verify(inventoryService).checkInventory(any());
180 } 227 }
181 228
182 @Test 229 @Test
@@ -192,7 +239,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -192,7 +239,7 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
192 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId()); 239 WmsCheckOrderDO dbOrder = checkOrderMapper.selectById(order.getId());
193 assertNotNull(dbOrder); 240 assertNotNull(dbOrder);
194 assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus()); 241 assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus());
195 - verify(inventoryService, never()).changeInventory(any()); 242 + verify(inventoryService, never()).checkInventory(any());
196 } 243 }
197 244
198 @Test 245 @Test
@@ -263,6 +310,18 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest { @@ -263,6 +310,18 @@ public class WmsCheckOrderServiceImplTest extends BaseDbUnitTest {
263 .build(); 310 .build();
264 } 311 }
265 312
  313 + private static WmsCheckOrderDetailDO createNewInventoryCheckOrderDetail(Long orderId, Long skuId, Long warehouseId,
  314 + String quantity, String checkQuantity) {
  315 + return WmsCheckOrderDetailDO.builder()
  316 + .orderId(orderId)
  317 + .skuId(skuId)
  318 + .warehouseId(warehouseId)
  319 + .quantity(new BigDecimal(quantity))
  320 + .checkQuantity(new BigDecimal(checkQuantity))
  321 + .price(new BigDecimal("30.00"))
  322 + .build();
  323 + }
  324 +
266 private static WmsCheckOrderSaveReqVO createCheckOrderReqVO(Long warehouseId, WmsCheckOrderDetailSaveReqVO... details) { 325 private static WmsCheckOrderSaveReqVO createCheckOrderReqVO(Long warehouseId, WmsCheckOrderDetailSaveReqVO... details) {
267 WmsCheckOrderSaveReqVO reqVO = new WmsCheckOrderSaveReqVO(); 326 WmsCheckOrderSaveReqVO reqVO = new WmsCheckOrderSaveReqVO();
268 reqVO.setNo("PK202605120002"); 327 reqVO.setNo("PK202605120002");
yudao-module-wms/src/test/resources/sql/clean.sql
@@ -10,3 +10,7 @@ DELETE FROM &quot;wms_inventory_history&quot;; @@ -10,3 +10,7 @@ DELETE FROM &quot;wms_inventory_history&quot;;
10 DELETE FROM "wms_inventory"; 10 DELETE FROM "wms_inventory";
11 DELETE FROM "wms_item_sku"; 11 DELETE FROM "wms_item_sku";
12 DELETE FROM "wms_item"; 12 DELETE FROM "wms_item";
  13 +DELETE FROM "wms_item_category";
  14 +DELETE FROM "wms_item_brand";
  15 +DELETE FROM "wms_warehouse";
  16 +DELETE FROM "wms_merchant";
yudao-module-wms/src/test/resources/sql/create_tables.sql
  1 +CREATE TABLE IF NOT EXISTS "wms_warehouse" (
  2 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  3 + "code" varchar(20) NOT NULL,
  4 + "name" varchar(50) NOT NULL,
  5 + "remark" varchar(255) DEFAULT NULL,
  6 + "sort" int DEFAULT '0',
  7 + "creator" varchar(64) DEFAULT '',
  8 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  9 + "updater" varchar(64) DEFAULT '',
  10 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  11 + "deleted" bit NOT NULL DEFAULT FALSE,
  12 + "tenant_id" bigint NOT NULL DEFAULT '0',
  13 + PRIMARY KEY ("id")
  14 +) COMMENT 'WMS 仓库表';
  15 +
  16 +CREATE TABLE IF NOT EXISTS "wms_merchant" (
  17 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  18 + "code" varchar(20) DEFAULT NULL,
  19 + "name" varchar(50) NOT NULL,
  20 + "type" int NOT NULL,
  21 + "level" varchar(20) DEFAULT NULL,
  22 + "bank_name" varchar(50) DEFAULT NULL,
  23 + "bank_account" varchar(50) DEFAULT NULL,
  24 + "address" varchar(255) DEFAULT NULL,
  25 + "mobile" varchar(20) DEFAULT NULL,
  26 + "telephone" varchar(20) DEFAULT NULL,
  27 + "contact" varchar(20) DEFAULT NULL,
  28 + "email" varchar(64) DEFAULT NULL,
  29 + "remark" varchar(255) DEFAULT NULL,
  30 + "creator" varchar(64) DEFAULT '',
  31 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  32 + "updater" varchar(64) DEFAULT '',
  33 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  34 + "deleted" bit NOT NULL DEFAULT FALSE,
  35 + "tenant_id" bigint NOT NULL DEFAULT '0',
  36 + PRIMARY KEY ("id")
  37 +) COMMENT 'WMS 往来企业表';
  38 +
  39 +CREATE TABLE IF NOT EXISTS "wms_item_brand" (
  40 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  41 + "code" varchar(20) NOT NULL,
  42 + "name" varchar(60) NOT NULL,
  43 + "creator" varchar(64) DEFAULT '',
  44 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  45 + "updater" varchar(64) DEFAULT '',
  46 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  47 + "deleted" bit NOT NULL DEFAULT FALSE,
  48 + "tenant_id" bigint NOT NULL DEFAULT '0',
  49 + PRIMARY KEY ("id")
  50 +) COMMENT 'WMS 商品品牌表';
  51 +
  52 +CREATE TABLE IF NOT EXISTS "wms_item_category" (
  53 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  54 + "parent_id" bigint NOT NULL DEFAULT '0',
  55 + "code" varchar(20) NOT NULL,
  56 + "name" varchar(60) NOT NULL,
  57 + "sort" int DEFAULT '0',
  58 + "status" tinyint NOT NULL DEFAULT '0',
  59 + "creator" varchar(64) DEFAULT '',
  60 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  61 + "updater" varchar(64) DEFAULT '',
  62 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  63 + "deleted" bit NOT NULL DEFAULT FALSE,
  64 + "tenant_id" bigint NOT NULL DEFAULT '0',
  65 + PRIMARY KEY ("id")
  66 +) COMMENT 'WMS 商品分类表';
  67 +
1 CREATE TABLE IF NOT EXISTS "wms_item" ( 68 CREATE TABLE IF NOT EXISTS "wms_item" (
2 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, 69 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
3 "code" varchar(20) NOT NULL, 70 "code" varchar(20) NOT NULL,