Commit ee20f7778c5f0ab88a603e614bf6333b0e29f2d5

Authored by YunaiV
1 parent eb422419

feat(wms):增加 inv 库存的新增、修改方法,并提供相关单测

yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -120,6 +120,31 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> { @@ -120,6 +120,31 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
120 } 120 }
121 121
122 /** 122 /**
  123 + * 获得满足条件的一条记录,并使用 FOR UPDATE 锁定。
  124 + *
  125 + * 注意:需要在事务中调用,否则锁会立即释放。
  126 + *
  127 + * @param queryWrapper 查询条件
  128 + * @return 实体
  129 + */
  130 + default T selectOneForUpdate(LambdaQueryWrapper<T> queryWrapper) {
  131 + return selectOne(queryWrapper.last("FOR UPDATE"));
  132 + }
  133 +
  134 + default T selectOneForUpdate(SFunction<T, ?> field, Object value) {
  135 + return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field, value));
  136 + }
  137 +
  138 + default T selectOneForUpdate(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
  139 + return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
  140 + }
  141 +
  142 + default T selectOneForUpdate(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
  143 + SFunction<T, ?> field3, Object value3) {
  144 + return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
  145 + }
  146 +
  147 + /**
123 * 获取满足条件的第 1 条记录 148 * 获取满足条件的第 1 条记录
124 * 149 *
125 * 目的:解决并发场景下,插入多条记录后,使用 selectOne 会报错的问题 150 * 目的:解决并发场景下,插入多条记录后,使用 selectOne 会报错的问题
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/enums/ErrorCodeConstants.java
@@ -47,4 +47,13 @@ public interface ErrorCodeConstants { @@ -47,4 +47,13 @@ public interface ErrorCodeConstants {
47 // ========== WMS 基础数据-往来企业 1-060-105-000 ========== 47 // ========== WMS 基础数据-往来企业 1-060-105-000 ==========
48 ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1_060_105_000, "往来企业不存在"); 48 ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1_060_105_000, "往来企业不存在");
49 49
  50 + // ========== WMS 入库单 1-060-200-000 ==========
  51 + ErrorCode RECEIPT_ORDER_NOT_EXISTS = new ErrorCode(1_060_200_000, "入库单不存在");
  52 + ErrorCode RECEIPT_ORDER_NO_DUPLICATE = new ErrorCode(1_060_200_001, "入库单号重复");
  53 + ErrorCode RECEIPT_ORDER_STATUS_NOT_PENDING = new ErrorCode(1_060_200_002, "入库单状态不是暂存,不能操作");
  54 + ErrorCode RECEIPT_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_200_003, "入库单至少包含一条明细");
  55 + ErrorCode RECEIPT_ORDER_AREA_REQUIRED = new ErrorCode(1_060_200_004, "库区模式下,入库单库区不能为空");
  56 + ErrorCode RECEIPT_ORDER_AREA_NOT_MATCH_WAREHOUSE = new ErrorCode(1_060_200_005, "库区不属于入库仓库");
  57 + ErrorCode RECEIPT_ORDER_COMPLETED_CANNOT_DELETE = new ErrorCode(1_060_200_006, "入库单已完成,不能删除");
  58 +
50 } 59 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryDetailService.java
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.detail.WmsInventoryDetailPageReqVO; 4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.detail.WmsInventoryDetailPageReqVO;
5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO; 5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO;
6 6
  7 +import java.util.List;
  8 +
7 /** 9 /**
8 * WMS 库存明细 Service 接口 10 * WMS 库存明细 Service 接口
9 * 11 *
@@ -19,4 +21,11 @@ public interface WmsInventoryDetailService { @@ -19,4 +21,11 @@ public interface WmsInventoryDetailService {
19 */ 21 */
20 PageResult<WmsInventoryDetailDO> getInventoryDetailPage(WmsInventoryDetailPageReqVO pageReqVO); 22 PageResult<WmsInventoryDetailDO> getInventoryDetailPage(WmsInventoryDetailPageReqVO pageReqVO);
21 23
  24 + /**
  25 + * 创建库存明细列表
  26 + *
  27 + * @param list 库存明细列表
  28 + */
  29 + void createInventoryDetailList(List<WmsInventoryDetailDO> list);
  30 +
22 } 31 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryDetailServiceImpl.java
1 package cn.iocoder.yudao.module.wms.service.inventory; 1 package cn.iocoder.yudao.module.wms.service.inventory;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.detail.WmsInventoryDetailPageReqVO; 5 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.detail.WmsInventoryDetailPageReqVO;
5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO; 6 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO;
6 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryDetailMapper; 7 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryDetailMapper;
7 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
8 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
  10 +import org.springframework.transaction.annotation.Transactional;
9 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
10 12
  13 +import java.util.List;
  14 +
11 /** 15 /**
12 * WMS 库存明细 Service 实现类 16 * WMS 库存明细 Service 实现类
13 * 17 *
@@ -25,4 +29,13 @@ public class WmsInventoryDetailServiceImpl implements WmsInventoryDetailService @@ -25,4 +29,13 @@ public class WmsInventoryDetailServiceImpl implements WmsInventoryDetailService
25 return inventoryDetailMapper.selectPage(pageReqVO); 29 return inventoryDetailMapper.selectPage(pageReqVO);
26 } 30 }
27 31
  32 + @Override
  33 + @Transactional(rollbackFor = Exception.class)
  34 + public void createInventoryDetailList(List<WmsInventoryDetailDO> list) {
  35 + if (CollUtil.isEmpty(list)) {
  36 + return;
  37 + }
  38 + inventoryDetailMapper.insertBatch(list);
  39 + }
  40 +
28 } 41 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryHistoryService.java
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryPageReqVO; 4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryPageReqVO;
5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO; 5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO;
6 6
  7 +import java.util.List;
  8 +
7 /** 9 /**
8 * WMS 库存流水 Service 接口 10 * WMS 库存流水 Service 接口
9 * 11 *
@@ -19,4 +21,11 @@ public interface WmsInventoryHistoryService { @@ -19,4 +21,11 @@ public interface WmsInventoryHistoryService {
19 */ 21 */
20 PageResult<WmsInventoryHistoryDO> getInventoryHistoryPage(WmsInventoryHistoryPageReqVO pageReqVO); 22 PageResult<WmsInventoryHistoryDO> getInventoryHistoryPage(WmsInventoryHistoryPageReqVO pageReqVO);
21 23
  24 + /**
  25 + * 创建库存流水列表
  26 + *
  27 + * @param list 库存流水列表
  28 + */
  29 + void createInventoryHistoryList(List<WmsInventoryHistoryDO> list);
  30 +
22 } 31 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryHistoryServiceImpl.java
1 package cn.iocoder.yudao.module.wms.service.inventory; 1 package cn.iocoder.yudao.module.wms.service.inventory;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryPageReqVO; 5 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryPageReqVO;
5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO; 6 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO;
6 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryHistoryMapper; 7 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryHistoryMapper;
7 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
8 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
  10 +import org.springframework.transaction.annotation.Transactional;
9 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
10 12
  13 +import java.util.List;
  14 +
11 /** 15 /**
12 * WMS 库存流水 Service 实现类 16 * WMS 库存流水 Service 实现类
13 * 17 *
@@ -25,4 +29,13 @@ public class WmsInventoryHistoryServiceImpl implements WmsInventoryHistoryServic @@ -25,4 +29,13 @@ public class WmsInventoryHistoryServiceImpl implements WmsInventoryHistoryServic
25 return inventoryHistoryMapper.selectPage(pageReqVO); 29 return inventoryHistoryMapper.selectPage(pageReqVO);
26 } 30 }
27 31
  32 + @Override
  33 + @Transactional(rollbackFor = Exception.class)
  34 + public void createInventoryHistoryList(List<WmsInventoryHistoryDO> list) {
  35 + if (CollUtil.isEmpty(list)) {
  36 + return;
  37 + }
  38 + inventoryHistoryMapper.insertBatch(list);
  39 + }
  40 +
28 } 41 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryService.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.wms.service.inventory; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.wms.service.inventory;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO; 4 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO;
5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO; 5 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO;
  6 +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
6 7
7 /** 8 /**
8 * WMS 库存 Service 接口 9 * WMS 库存 Service 接口
@@ -27,4 +28,11 @@ public interface WmsInventoryService { @@ -27,4 +28,11 @@ public interface WmsInventoryService {
27 */ 28 */
28 long getInventoryCountBySkuId(Long skuId); 29 long getInventoryCountBySkuId(Long skuId);
29 30
  31 + /**
  32 + * 变更库存
  33 + *
  34 + * @param reqDTO 库存变更请求
  35 + */
  36 + void changeInventory(WmsInventoryChangeReqDTO reqDTO);
  37 +
30 } 38 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/WmsInventoryServiceImpl.java
1 package cn.iocoder.yudao.module.wms.service.inventory; 1 package cn.iocoder.yudao.module.wms.service.inventory;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Tuple;
3 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO; 7 import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO;
  8 +import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO;
6 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO; 9 import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO;
  10 +import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO;
7 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryMapper; 11 import cn.iocoder.yudao.module.wms.dal.mysql.inventory.WmsInventoryMapper;
  12 +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties;
  13 +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO;
8 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
  15 +import org.springframework.dao.DuplicateKeyException;
9 import org.springframework.stereotype.Service; 16 import org.springframework.stereotype.Service;
  17 +import org.springframework.transaction.annotation.Transactional;
10 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
11 19
  20 +import java.math.BigDecimal;
  21 +import java.util.ArrayList;
  22 +import java.util.List;
  23 +
12 /** 24 /**
13 * WMS 库存 Service 实现类 25 * WMS 库存 Service 实现类
14 * 26 *
@@ -21,6 +33,14 @@ public class WmsInventoryServiceImpl implements WmsInventoryService { @@ -21,6 +33,14 @@ public class WmsInventoryServiceImpl implements WmsInventoryService {
21 @Resource 33 @Resource
22 private WmsInventoryMapper inventoryMapper; 34 private WmsInventoryMapper inventoryMapper;
23 35
  36 + @Resource
  37 + private WmsInventoryDetailService inventoryDetailService;
  38 + @Resource
  39 + private WmsInventoryHistoryService inventoryHistoryService;
  40 +
  41 + @Resource
  42 + private WmsProperties wmsProperties;
  43 +
24 @Override 44 @Override
25 public PageResult<WmsInventoryDO> getInventoryPage(WmsInventoryPageReqVO pageReqVO) { 45 public PageResult<WmsInventoryDO> getInventoryPage(WmsInventoryPageReqVO pageReqVO) {
26 if (StrUtil.equals(WmsInventoryPageReqVO.TYPE_WAREHOUSE, pageReqVO.getType())) { 46 if (StrUtil.equals(WmsInventoryPageReqVO.TYPE_WAREHOUSE, pageReqVO.getType())) {
@@ -34,4 +54,97 @@ public class WmsInventoryServiceImpl implements WmsInventoryService { @@ -34,4 +54,97 @@ public class WmsInventoryServiceImpl implements WmsInventoryService {
34 return inventoryMapper.selectCountBySkuId(skuId); 54 return inventoryMapper.selectCountBySkuId(skuId);
35 } 55 }
36 56
  57 + @Override
  58 + @Transactional(rollbackFor = Exception.class)
  59 + public void changeInventory(WmsInventoryChangeReqDTO reqDTO) {
  60 + if (reqDTO == null || CollUtil.isEmpty(reqDTO.getItems())) {
  61 + return;
  62 + }
  63 +
  64 + // 1. 变更库存余额,并构建库存流水与批次库存明细
  65 + boolean batchEnabled = wmsProperties.isBatchEnabled();
  66 + List<WmsInventoryHistoryDO> histories = new ArrayList<>(reqDTO.getItems().size());
  67 + List<WmsInventoryDetailDO> details = batchEnabled ? new ArrayList<>(reqDTO.getItems().size()) : List.of();
  68 + for (WmsInventoryChangeReqDTO.Item item : reqDTO.getItems()) {
  69 + // 1.1 变更库存余额
  70 + Tuple result = changeInventory0(item);
  71 + // 1.2 构建库存流水与批次库存明细
  72 + histories.add(buildInventoryHistory(reqDTO, item, result));
  73 + if (batchEnabled) {
  74 + details.add(buildInventoryDetail(reqDTO, item));
  75 + }
  76 + }
  77 +
  78 + // 2.1 批量写入库存流水
  79 + inventoryHistoryService.createInventoryHistoryList(histories);
  80 + if (batchEnabled) {
  81 + // 2.2 批量写入批次库存明细
  82 + inventoryDetailService.createInventoryDetailList(details);
  83 + }
  84 + }
  85 +
  86 + /**
  87 + * 变更库存余额
  88 + *
  89 + * @param item 库存变更明细
  90 + * @return 变更前数量、变更后数量
  91 + */
  92 + private Tuple changeInventory0(WmsInventoryChangeReqDTO.Item item) {
  93 + // 1. 获取或创建库存余额,使用 FOR UPDATE 锁定行
  94 + WmsInventoryDO inventory = getOrCreateInventory(item);
  95 + // 2. 变更库存余额
  96 + BigDecimal beforeQuantity = inventory.getQuantity();
  97 + BigDecimal afterQuantity = beforeQuantity.add(item.getQuantity());
  98 + inventoryMapper.updateQuantity(inventory.getId(), item.getQuantity());
  99 + return new Tuple(beforeQuantity, afterQuantity);
  100 + }
  101 +
  102 +
  103 + private WmsInventoryDO getOrCreateInventory(WmsInventoryChangeReqDTO.Item item) {
  104 + // 1. 查询库存余额,使用 FOR UPDATE 锁定行
  105 + WmsInventoryDO inventory = inventoryMapper.selectBySkuIdAndWarehouseIdAndAreaIdForUpdate(item.getSkuId(),
  106 + item.getWarehouseId(), item.getAreaId());
  107 + if (inventory != null) {
  108 + return inventory;
  109 + }
  110 + // 2.1 不存在,则插入一条库存余额记录,初始数量为 0
  111 + try {
  112 + inventory = new WmsInventoryDO().setSkuId(item.getSkuId())
  113 + .setWarehouseId(item.getWarehouseId()).setAreaId(item.getAreaId()).setQuantity(BigDecimal.ZERO);
  114 + inventoryMapper.insert(inventory);
  115 + return inventory;
  116 + } catch (DuplicateKeyException ex) {
  117 + // 2.2 插入失败,说明有并发冲突,重试查询库存余额
  118 + inventory = inventoryMapper.selectBySkuIdAndWarehouseIdAndAreaIdForUpdate(item.getSkuId(),
  119 + item.getWarehouseId(), item.getAreaId());
  120 + if (inventory == null) {
  121 + throw ex;
  122 + }
  123 + return inventory;
  124 + }
  125 + }
  126 +
  127 + private WmsInventoryHistoryDO buildInventoryHistory(WmsInventoryChangeReqDTO reqDTO,
  128 + WmsInventoryChangeReqDTO.Item item,
  129 + Tuple result) {
  130 + return new WmsInventoryHistoryDO()
  131 + .setWarehouseId(item.getWarehouseId()).setAreaId(item.getAreaId()).setSkuId(item.getSkuId())
  132 + .setQuantity(item.getQuantity()).setBeforeQuantity(result.get(0)).setAfterQuantity(result.get(1))
  133 + .setBatchNo(item.getBatchNo()).setProductionDate(item.getProductionDate())
  134 + .setExpirationDate(item.getExpirationDate())
  135 + .setAmount(item.getAmount()).setRemark(item.getRemark())
  136 + .setOrderId(reqDTO.getOrderId()).setOrderNo(reqDTO.getOrderNo()).setOrderType(reqDTO.getOrderType());
  137 + }
  138 +
  139 + private WmsInventoryDetailDO buildInventoryDetail(WmsInventoryChangeReqDTO reqDTO,
  140 + WmsInventoryChangeReqDTO.Item item) {
  141 + return new WmsInventoryDetailDO()
  142 + .setSkuId(item.getSkuId()).setWarehouseId(item.getWarehouseId()).setAreaId(item.getAreaId())
  143 + .setQuantity(item.getQuantity()).setRemainQuantity(item.getQuantity())
  144 + .setBatchNo(item.getBatchNo()).setProductionDate(item.getProductionDate())
  145 + .setExpirationDate(item.getExpirationDate())
  146 + .setAmount(item.getAmount()).setRemark(item.getRemark())
  147 + .setOrderId(reqDTO.getOrderId()).setOrderNo(reqDTO.getOrderNo()).setOrderType(reqDTO.getOrderType());
  148 + }
  149 +
37 } 150 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/dto/WmsInventoryChangeReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.wms.service.inventory.dto;
  2 +
  3 +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum;
  4 +import lombok.Data;
  5 +
  6 +import java.math.BigDecimal;
  7 +import java.time.LocalDateTime;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * WMS 库存变更请求 DTO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Data
  16 +public class WmsInventoryChangeReqDTO {
  17 +
  18 + /**
  19 + * 操作单编号
  20 + */
  21 + private Long orderId;
  22 + /**
  23 + * 操作单号
  24 + */
  25 + private String orderNo;
  26 + /**
  27 + * 操作类型
  28 + *
  29 + * 枚举 {@link WmsInventoryOrderTypeEnum#getType()}
  30 + */
  31 + private Integer orderType;
  32 +
  33 + /**
  34 + * 库存变更明细
  35 + */
  36 + private List<Item> items;
  37 +
  38 + /**
  39 + * WMS 库存变更明细
  40 + */
  41 + @Data
  42 + public static class Item {
  43 +
  44 + /**
  45 + * SKU 编号
  46 + */
  47 + private Long skuId;
  48 + /**
  49 + * 仓库编号
  50 + */
  51 + private Long warehouseId;
  52 + /**
  53 + * 库区编号
  54 + */
  55 + private Long areaId;
  56 + /**
  57 + * 变更数量
  58 + */
  59 + private BigDecimal quantity;
  60 +
  61 + // ========= 批次效期相关字段 =========
  62 +
  63 + /**
  64 + * 批号
  65 + */
  66 + private String batchNo;
  67 + /**
  68 + * 生产日期
  69 + */
  70 + private LocalDateTime productionDate;
  71 + /**
  72 + * 过期日期
  73 + */
  74 + private LocalDateTime expirationDate;
  75 +
  76 + // ========= 金额备注相关字段 =========
  77 +
  78 + /**
  79 + * 金额(小计、非单价)
  80 + */
  81 + private BigDecimal amount;
  82 + /**
  83 + * 备注
  84 + */
  85 + private String remark;
  86 +
  87 + }
  88 +
  89 +}
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemSkuService.java
@@ -42,6 +42,14 @@ public interface WmsItemSkuService { @@ -42,6 +42,14 @@ public interface WmsItemSkuService {
42 void deleteItemSkuListByItemId(Long itemId); 42 void deleteItemSkuListByItemId(Long itemId);
43 43
44 /** 44 /**
  45 + * 校验 SKU 存在
  46 + *
  47 + * @param id 编号
  48 + * @return SKU
  49 + */
  50 + WmsItemSkuDO validateItemSkuExists(Long id);
  51 +
  52 + /**
45 * 按商品编号获得 SKU 列表 53 * 按商品编号获得 SKU 列表
46 * 54 *
47 * @param itemId 商品编号 55 * @param itemId 商品编号
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemSkuServiceImpl.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.collection.ListUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
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.sku.WmsItemSkuSaveReqVO; 7 import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuSaveReqVO;
@@ -91,6 +92,15 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService { @@ -91,6 +92,15 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService {
91 } 92 }
92 93
93 @Override 94 @Override
  95 + public WmsItemSkuDO validateItemSkuExists(Long id) {
  96 + WmsItemSkuDO sku = itemSkuMapper.selectById(id);
  97 + if (sku == null) {
  98 + throw exception(ITEM_SKU_NOT_EXISTS);
  99 + }
  100 + return sku;
  101 + }
  102 +
  103 + @Override
94 public List<WmsItemSkuDO> getItemSkuList(Long itemId) { 104 public List<WmsItemSkuDO> getItemSkuList(Long itemId) {
95 return itemSkuMapper.selectListByItemId(itemId); 105 return itemSkuMapper.selectListByItemId(itemId);
96 } 106 }
@@ -108,7 +118,7 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService { @@ -108,7 +118,7 @@ public class WmsItemSkuServiceImpl implements WmsItemSkuService {
108 @Override 118 @Override
109 public List<WmsItemSkuDO> getItemSkuListByIds(Collection<Long> ids) { 119 public List<WmsItemSkuDO> getItemSkuListByIds(Collection<Long> ids) {
110 if (CollUtil.isEmpty(ids)) { 120 if (CollUtil.isEmpty(ids)) {
111 - return List.of(); 121 + return ListUtil.of();
112 } 122 }
113 return itemSkuMapper.selectByIds(ids); 123 return itemSkuMapper.selectByIds(ids);
114 } 124 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/merchant/WmsMerchantService.java
@@ -6,7 +6,11 @@ import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantSa @@ -6,7 +6,11 @@ import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantSa
6 import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO; 6 import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO;
7 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
8 8
  9 +import java.util.Collection;
9 import java.util.List; 10 import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
10 14
11 /** 15 /**
12 * WMS 往来企业 Service 接口 16 * WMS 往来企业 Service 接口
@@ -69,4 +73,22 @@ public interface WmsMerchantService { @@ -69,4 +73,22 @@ public interface WmsMerchantService {
69 */ 73 */
70 List<WmsMerchantDO> getMerchantList(WmsMerchantPageReqVO pageReqVO); 74 List<WmsMerchantDO> getMerchantList(WmsMerchantPageReqVO pageReqVO);
71 75
  76 + /**
  77 + * 按编号集合获得往来企业列表
  78 + *
  79 + * @param ids 编号集合
  80 + * @return 往来企业列表
  81 + */
  82 + List<WmsMerchantDO> getMerchantList(Collection<Long> ids);
  83 +
  84 + /**
  85 + * 按编号集合获得往来企业 Map
  86 + *
  87 + * @param ids 编号集合
  88 + * @return 往来企业 Map
  89 + */
  90 + default Map<Long, WmsMerchantDO> getMerchantMap(Collection<Long> ids) {
  91 + return convertMap(getMerchantList(ids), WmsMerchantDO::getId);
  92 + }
  93 +
72 } 94 }
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/merchant/WmsMerchantServiceImpl.java
1 package cn.iocoder.yudao.module.wms.service.md.merchant; 1 package cn.iocoder.yudao.module.wms.service.md.merchant;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantPageReqVO; 7 import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantPageReqVO;
@@ -10,6 +12,7 @@ import jakarta.annotation.Resource; @@ -10,6 +12,7 @@ import jakarta.annotation.Resource;
10 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
12 14
  15 +import java.util.Collection;
13 import java.util.List; 16 import java.util.List;
14 17
15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -78,4 +81,12 @@ public class WmsMerchantServiceImpl implements WmsMerchantService { @@ -78,4 +81,12 @@ public class WmsMerchantServiceImpl implements WmsMerchantService {
78 return merchantMapper.selectList(pageReqVO); 81 return merchantMapper.selectList(pageReqVO);
79 } 82 }
80 83
  84 + @Override
  85 + public List<WmsMerchantDO> getMerchantList(Collection<Long> ids) {
  86 + if (CollUtil.isEmpty(ids)) {
  87 + return ListUtil.of();
  88 + }
  89 + return merchantMapper.selectByIds(ids);
  90 + }
  91 +
81 } 92 }