Commit 9221527d921ba9159076ee69081d931db4017e54

Authored by YunaiV
1 parent 5eefbfe1

✨ feat(mes): 新增退货明细数量校验逻辑

新增校验逻辑以确保退货明细总数量不超过对应退货行的数量,提升数据一致性和准确性。
同时,重构相关方法以简化数据验证过程。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -517,6 +517,7 @@ public interface ErrorCodeConstants { @@ -517,6 +517,7 @@ public interface ErrorCodeConstants {
517 ErrorCode WM_RETURN_SALES_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_007, "销售退货单已完成或已取消,无法取消"); 517 ErrorCode WM_RETURN_SALES_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_007, "销售退货单已完成或已取消,无法取消");
518 ErrorCode WM_RETURN_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "销售退货单行不存在"); 518 ErrorCode WM_RETURN_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "销售退货单行不存在");
519 ErrorCode WM_RETURN_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "销售退货单明细不存在"); 519 ErrorCode WM_RETURN_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "销售退货单明细不存在");
  520 + ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_713_201, "上架明细总数量不能超过退货行数量");
520 521
521 // ========== MES 仓库管理-盘点方案/任务/结果(1-040-714-100) ========== 522 // ========== MES 仓库管理-盘点方案/任务/结果(1-040-714-100) ==========
522 ErrorCode WM_STOCK_TAKING_PLAN_NOT_EXISTS = new ErrorCode(1_040_714_100, "盘点方案不存在"); 523 ErrorCode WM_STOCK_TAKING_PLAN_NOT_EXISTS = new ErrorCode(1_040_714_100, "盘点方案不存在");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java
1 package cn.iocoder.yudao.module.mes.service.wm.returnsales; 1 package cn.iocoder.yudao.module.mes.service.wm.returnsales;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
3 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO;
6 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesDetailMapper; 8 import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesDetailMapper;
7 -import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 9 +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
  10 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
8 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
9 import org.springframework.context.annotation.Lazy; 12 import org.springframework.context.annotation.Lazy;
10 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
12 15
  16 +import java.math.BigDecimal;
13 import java.util.List; 17 import java.util.List;
14 18
15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_DETAIL_NOT_EXISTS; 20 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_DETAIL_NOT_EXISTS;
  21 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED;
17 22
18 /** 23 /**
19 * MES 销售退货明细 Service 实现类 24 * MES 销售退货明细 Service 实现类
@@ -32,14 +37,15 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail @@ -32,14 +37,15 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail
32 private MesWmReturnSalesLineService returnSalesLineService; 37 private MesWmReturnSalesLineService returnSalesLineService;
33 38
34 @Resource 39 @Resource
35 - private MesMdItemService itemService; 40 + private MesWmWarehouseAreaService warehouseAreaService;
  41 +
  42 + @Resource
  43 + @Lazy
  44 + private MesWmMaterialStockService materialStockService;
36 45
37 @Override 46 @Override
38 public Long createReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO createReqVO) { 47 public Long createReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO createReqVO) {
39 - // 校验父数据存在  
40 - returnSalesLineService.validateReturnSalesLineExists(createReqVO.getLineId());  
41 - // 校验物料存在  
42 - itemService.validateItemExists(createReqVO.getItemId()); 48 + validateReturnSalesDetailSaveData(createReqVO);
43 49
44 // 插入 50 // 插入
45 MesWmReturnSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnSalesDetailDO.class); 51 MesWmReturnSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnSalesDetailDO.class);
@@ -51,10 +57,7 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail @@ -51,10 +57,7 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail
51 public void updateReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO updateReqVO) { 57 public void updateReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO updateReqVO) {
52 // 校验存在 58 // 校验存在
53 validateReturnSalesDetailExists(updateReqVO.getId()); 59 validateReturnSalesDetailExists(updateReqVO.getId());
54 - // 校验父数据存在  
55 - returnSalesLineService.validateReturnSalesLineExists(updateReqVO.getLineId());  
56 - // 校验物料存在  
57 - itemService.validateItemExists(updateReqVO.getItemId()); 60 + validateReturnSalesDetailSaveData(updateReqVO);
58 61
59 // 更新 62 // 更新
60 MesWmReturnSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDetailDO.class); 63 MesWmReturnSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDetailDO.class);
@@ -95,4 +98,41 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail @@ -95,4 +98,41 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail
95 } 98 }
96 } 99 }
97 100
  101 + /**
  102 + * 校验保存时的关联数据
  103 + */
  104 + private void validateReturnSalesDetailSaveData(MesWmReturnSalesDetailSaveReqVO reqVO) {
  105 + // 校验父数据存在
  106 + MesWmReturnSalesLineDO line = returnSalesLineService.validateReturnSalesLineExists(reqVO.getLineId());
  107 + // 校验仓库、库区、库位的关联关系
  108 + warehouseAreaService.validateWarehouseAreaExists(
  109 + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId());
  110 + // 校验库位物料/批次混放规则
  111 + materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId());
  112 + // 校验明细总数量不超过行数量(排除自身)
  113 + validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line);
  114 + }
  115 +
  116 + /**
  117 + * 校验明细总数量不超过行数量
  118 + *
  119 + * @param lineId 行 ID
  120 + * @param newQuantity 本次新增/修改的数量
  121 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null)
  122 + * @param line 退货单行
  123 + */
  124 + private void validateDetailQuantityNotExceed(Long lineId, BigDecimal newQuantity,
  125 + Long excludeDetailId, MesWmReturnSalesLineDO line) {
  126 + // 计算已有明细总数量(排除自身)
  127 + List<MesWmReturnSalesDetailDO> details = returnSalesDetailMapper.selectListByLineId(lineId);
  128 + BigDecimal existingTotal = CollectionUtils.getSumValue(details,
  129 + detail -> excludeDetailId != null && excludeDetailId.equals(detail.getId())
  130 + ? BigDecimal.ZERO : detail.getQuantity(),
  131 + BigDecimal::add, BigDecimal.ZERO);
  132 + // 校验:已有 + 本次 <= 行数量
  133 + if (existingTotal.add(newQuantity).compareTo(line.getQuantity()) > 0) {
  134 + throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED);
  135 + }
  136 + }
  137 +
98 } 138 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java
@@ -45,10 +45,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @@ -45,10 +45,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ
45 45
46 @Override 46 @Override
47 public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) { 47 public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) {
48 - // 校验父数据存在  
49 - returnSalesService.validateReturnSalesExists(createReqVO.getReturnId());  
50 - // 校验物料存在  
51 - validateItemBatchManagement(createReqVO.getItemId(), createReqVO.getBatchId()); 48 + validateLineSaveData(createReqVO);
52 49
53 // 插入 50 // 插入
54 MesWmReturnSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnSalesLineDO.class); 51 MesWmReturnSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnSalesLineDO.class);
@@ -62,10 +59,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @@ -62,10 +59,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ
62 public void updateReturnSalesLine(MesWmReturnSalesLineSaveReqVO updateReqVO) { 59 public void updateReturnSalesLine(MesWmReturnSalesLineSaveReqVO updateReqVO) {
63 // 校验存在 60 // 校验存在
64 validateReturnSalesLineExists(updateReqVO.getId()); 61 validateReturnSalesLineExists(updateReqVO.getId());
65 - // 校验父数据存在  
66 - returnSalesService.validateReturnSalesExists(updateReqVO.getReturnId());  
67 - // 校验物料存在  
68 - validateItemBatchManagement(updateReqVO.getItemId(), updateReqVO.getBatchId()); 62 + validateLineSaveData(updateReqVO);
69 63
70 // 更新 64 // 更新
71 MesWmReturnSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesLineDO.class); 65 MesWmReturnSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesLineDO.class);
@@ -74,6 +68,16 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @@ -74,6 +68,16 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ
74 returnSalesLineMapper.updateById(updateObj); 68 returnSalesLineMapper.updateById(updateObj);
75 } 69 }
76 70
  71 + /**
  72 + * 校验保存时的关联数据
  73 + */
  74 + private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) {
  75 + // 校验退货单存在
  76 + returnSalesService.validateReturnSalesExists(reqVO.getReturnId());
  77 + // 校验物料存在 + 批次管理
  78 + validateItemBatchManagement(reqVO.getItemId(), reqVO.getBatchId());
  79 + }
  80 +
77 @Override 81 @Override
78 public void deleteReturnSalesLine(Long id) { 82 public void deleteReturnSalesLine(Long id) {
79 // 校验存在 83 // 校验存在