Commit b486001c176e5585d5b5fcfcebee50c66dc01725

Authored by YunaiV
1 parent ff8aea9d

✨ feat(mes): 添加库存不足错误码及相关校验逻辑

新增库存不足的错误码,并在转移单相关服务中添加对仓库、库区、库位的校验逻辑,以确保数据的完整性和准确性。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -330,6 +330,7 @@ public interface ErrorCodeConstants {
330 330  
331 331 // ========== MES 仓库管理-库存(1-040-703-000) ==========
332 332 ErrorCode WM_MATERIAL_STOCK_NOT_EXISTS = new ErrorCode(1_040_703_000, "库存记录不存在");
  333 + ErrorCode WM_MATERIAL_STOCK_INSUFFICIENT = new ErrorCode(1_040_703_001, "库存数量不足");
333 334  
334 335 // ========== MES 仓库管理-到货通知单(1-040-704-000) ==========
335 336 ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在");
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java
... ... @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line.MesWmTra
5 5 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO;
6 6 import cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer.MesWmTransferLineMapper;
7 7 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  8 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
8 9 import jakarta.annotation.Resource;
9 10 import org.springframework.context.annotation.Lazy;
10 11 import org.springframework.stereotype.Service;
... ... @@ -30,14 +31,20 @@ public class MesWmTransferLineServiceImpl implements MesWmTransferLineService {
30 31 private MesWmTransferService transferService;
31 32 @Resource
32 33 private MesMdItemService itemService;
  34 + @Resource
  35 + private MesWmWarehouseAreaService warehouseAreaService;
33 36  
34 37 @Override
35 38 public Long createTransferLine(MesWmTransferLineSaveReqVO createReqVO) {
  39 + // 校验父数据可编辑
36 40 transferService.validateTransferEditable(createReqVO.getTransferId());
  41 + // 校验产品存在
37 42 itemService.validateItemExists(createReqVO.getItemId());
38   - // DONE @AI:当前先保留主单可编辑与物料存在校验,其他关联校验需结合库存与批次规则统一设计,暂不在本轮 TODO 修复中扩展
39   - // TODO @AI:位置相关的几个校验;
  43 + // 校验来源仓库、库区、库位的关联关系
  44 + warehouseAreaService.validateWarehouseAreaExists(createReqVO.getFromWarehouseId(),
  45 + createReqVO.getFromLocationId(), createReqVO.getFromAreaId());
40 46  
  47 + // 插入
41 48 MesWmTransferLineDO line = BeanUtils.toBean(createReqVO, MesWmTransferLineDO.class);
42 49 transferLineMapper.insert(line);
43 50 return line.getId();
... ... @@ -45,19 +52,26 @@ public class MesWmTransferLineServiceImpl implements MesWmTransferLineService {
45 52  
46 53 @Override
47 54 public void updateTransferLine(MesWmTransferLineSaveReqVO updateReqVO) {
  55 + // 校验存在
48 56 validateTransferLineExists(updateReqVO.getId());
  57 + // 校验父数据可编辑
49 58 transferService.validateTransferEditable(updateReqVO.getTransferId());
  59 + // 校验产品存在
50 60 itemService.validateItemExists(updateReqVO.getItemId());
51   - // DONE @AI:当前先保留主单可编辑与物料存在校验,其他关联校验需结合库存与批次规则统一设计,暂不在本轮 TODO 修复中扩展
52   - // TODO @AI:位置相关的几个校验;
  61 + // 校验来源仓库、库区、库位的关联关系
  62 + warehouseAreaService.validateWarehouseAreaExists(updateReqVO.getFromWarehouseId(),
  63 + updateReqVO.getFromLocationId(), updateReqVO.getFromAreaId());
53 64  
  65 + // 更新
54 66 MesWmTransferLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmTransferLineDO.class);
55 67 transferLineMapper.updateById(updateObj);
56 68 }
57 69  
58 70 @Override
59 71 public void deleteTransferLine(Long id) {
  72 + // 校验存在
60 73 validateTransferLineExists(id);
  74 + // 删除
61 75 transferLineMapper.deleteById(id);
62 76 }
63 77  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferServiceImpl.java
... ... @@ -99,12 +99,12 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
99 99 }
100 100  
101 101 // 配送模式下,提交后如果未确认,则进入待确认状态;否则直接进入待上架状态
102   - if (Boolean.TRUE.equals(transfer.getDeliveryFlag()) && Boolean.FALSE.equals(transfer.getConfirmFlag())) {
  102 + if (Boolean.TRUE.equals(transfer.getDeliveryFlag()) && !Boolean.TRUE.equals(transfer.getConfirmFlag())) {
103 103 transfer.setStatus(MesWmTransferStatusEnum.UNCONFIRMED.getStatus()).setConfirmFlag(false);
104 104 // DONE @AI:冻结库存属于主单状态流转的一部分,保留在主单 service 统一处理
105 105 freezeTransferLineStocks(lines, true);
106 106 } else {
107   - transfer.setStatus(MesWmTransferStatusEnum.UNSTOCK.getStatus());
  107 + transfer.setStatus(MesWmTransferStatusEnum.APPROVING.getStatus());
108 108 }
109 109 transferMapper.updateById(transfer);
110 110 }
... ... @@ -116,7 +116,7 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
116 116 MesWmTransferDO transfer = validateTransferExistsAndConfirm(id);
117 117  
118 118 // 更新状态:待确认 -> 待上架
119   - transfer.setStatus(MesWmTransferStatusEnum.UNSTOCK.getStatus());
  119 + transfer.setStatus(MesWmTransferStatusEnum.APPROVING.getStatus());
120 120 transfer.setConfirmFlag(true);
121 121 transferMapper.updateById(transfer);
122 122 }
... ... @@ -124,17 +124,24 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
124 124 @Override
125 125 @Transactional(rollbackFor = Exception.class)
126 126 public void stockTransfer(Long id) {
127   - MesWmTransferDO transfer = validateTransferExistsAndUnstock(id);
  127 + // 1.1 校验存在
  128 + MesWmTransferDO transfer = validateTransferExistsAndApproving(id);
128 129 List<MesWmTransferLineDO> lines = transferLineService.getTransferLineListByTransferId(id);
129 130 if (CollUtil.isEmpty(lines)) {
130 131 throw exception(WM_TRANSFER_NO_LINE);
131 132 }
  133 + // 1.2 检查每个行的明细数量是否完成上架
  134 + for (MesWmTransferLineDO line : lines) {
  135 + List<MesWmTransferDetailDO> details = transferDetailService.getTransferDetailListByLineId(line.getId());
  136 + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details,
  137 + MesWmTransferDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO);
  138 + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) {
  139 + throw exception(WM_TRANSFER_DETAIL_QUANTITY_MISMATCH);
  140 + }
  141 + }
132 142  
133   - // TODO @AI:参考别的模块的 stockXXX 方法,直接放在这里;不需要抽方法;
134   - validateTransferDetailQuantity(lines);
135   -
136   - // 更新状态:待上架 -> 待执行
137   - transfer.setStatus(MesWmTransferStatusEnum.UNEXECUTE.getStatus());
  143 + // 2. 更新状态:待上架 -> 待执行
  144 + transfer.setStatus(MesWmTransferStatusEnum.APPROVED.getStatus());
138 145 transferMapper.updateById(transfer);
139 146 }
140 147  
... ... @@ -142,7 +149,7 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
142 149 @Transactional(rollbackFor = Exception.class)
143 150 public void finishTransfer(Long id) {
144 151 // 校验存在 + 待执行状态
145   - MesWmTransferDO transfer = validateTransferExistsAndUnexecute(id);
  152 + MesWmTransferDO transfer = validateTransferExistsAndApproved(id);
146 153 List<MesWmTransferLineDO> lines = transferLineService.getTransferLineListByTransferId(id);
147 154 if (CollUtil.isEmpty(lines)) {
148 155 throw exception(WM_TRANSFER_NO_LINE);
... ... @@ -222,24 +229,24 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
222 229 return transfer;
223 230 }
224 231  
225   - private MesWmTransferDO validateTransferExistsAndUnstock(Long id) {
  232 + private MesWmTransferDO validateTransferExistsAndApproving(Long id) {
226 233 MesWmTransferDO transfer = transferMapper.selectById(id);
227 234 if (transfer == null) {
228 235 throw exception(WM_TRANSFER_NOT_EXISTS);
229 236 }
230   - if (!MesWmTransferStatusEnum.UNSTOCK.getStatus().equals(transfer.getStatus())) {
231   - throw exception(WM_TRANSFER_NOT_UNSTOCK);
  237 + if (!MesWmTransferStatusEnum.APPROVING.getStatus().equals(transfer.getStatus())) {
  238 + throw exception(WM_TRANSFER_NOT_APPROVING);
232 239 }
233 240 return transfer;
234 241 }
235 242  
236   - private MesWmTransferDO validateTransferExistsAndUnexecute(Long id) {
  243 + private MesWmTransferDO validateTransferExistsAndApproved(Long id) {
237 244 MesWmTransferDO transfer = transferMapper.selectById(id);
238 245 if (transfer == null) {
239 246 throw exception(WM_TRANSFER_NOT_EXISTS);
240 247 }
241   - if (!MesWmTransferStatusEnum.UNEXECUTE.getStatus().equals(transfer.getStatus())) {
242   - throw exception(WM_TRANSFER_NOT_UNEXECUTE);
  248 + if (!MesWmTransferStatusEnum.APPROVED.getStatus().equals(transfer.getStatus())) {
  249 + throw exception(WM_TRANSFER_NOT_APPROVED);
243 250 }
244 251 return transfer;
245 252 }
... ... @@ -256,19 +263,7 @@ public class MesWmTransferServiceImpl implements MesWmTransferService {
256 263 return transfer;
257 264 }
258 265  
259   - // DONE @AI:保留独立方法复用明细数量校验,待执行状态仍由主流程负责推进
260   - private void validateTransferDetailQuantity(List<MesWmTransferLineDO> lines) {
261   - for (MesWmTransferLineDO line : lines) {
262   - List<MesWmTransferDetailDO> details = transferDetailService.getTransferDetailListByLineId(line.getId());
263   - BigDecimal totalDetailQty = CollectionUtils.getSumValue(details,
264   - MesWmTransferDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO);
265   - if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) {
266   - throw exception(WM_TRANSFER_DETAIL_QUANTITY_MISMATCH);
267   - }
268   - }
269   - }
270   -
271   - // TODO @AI:materialStockService 封装一个方法,传入 transferId + frozen 统一处理了;不用判断 line 的 getMaterialStockId
  266 + // TODO @芋艿:【后续弄】materialStockService 封装一个方法,传入 transferId + frozen 统一处理了;不用判断 line 的 getMaterialStockId
272 267 private void freezeTransferLineStocks(List<MesWmTransferLineDO> lines, boolean frozen) {
273 268 if (CollUtil.isEmpty(lines)) {
274 269 return;
... ...