From 9221527d921ba9159076ee69081d931db4017e54 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 30 Mar 2026 18:48:22 +0800 Subject: [PATCH] ✨ feat(mes): 新增退货明细数量校验逻辑 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java | 1 + yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java | 20 ++++++++++++-------- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index 904e208..8863a97 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -517,6 +517,7 @@ public interface ErrorCodeConstants { ErrorCode WM_RETURN_SALES_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_007, "销售退货单已完成或已取消,无法取消"); ErrorCode WM_RETURN_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "销售退货单行不存在"); ErrorCode WM_RETURN_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "销售退货单明细不存在"); + ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_713_201, "上架明细总数量不能超过退货行数量"); // ========== MES 仓库管理-盘点方案/任务/结果(1-040-714-100) ========== ErrorCode WM_STOCK_TAKING_PLAN_NOT_EXISTS = new ErrorCode(1_040_714_100, "盘点方案不存在"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java index f1bddc9..3333dce 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java @@ -1,19 +1,24 @@ package cn.iocoder.yudao.module.mes.service.wm.returnsales; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesDetailMapper; -import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_DETAIL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED; /** * MES 销售退货明细 Service 实现类 @@ -32,14 +37,15 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail private MesWmReturnSalesLineService returnSalesLineService; @Resource - private MesMdItemService itemService; + private MesWmWarehouseAreaService warehouseAreaService; + + @Resource + @Lazy + private MesWmMaterialStockService materialStockService; @Override public Long createReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO createReqVO) { - // 校验父数据存在 - returnSalesLineService.validateReturnSalesLineExists(createReqVO.getLineId()); - // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); + validateReturnSalesDetailSaveData(createReqVO); // 插入 MesWmReturnSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnSalesDetailDO.class); @@ -51,10 +57,7 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail public void updateReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO updateReqVO) { // 校验存在 validateReturnSalesDetailExists(updateReqVO.getId()); - // 校验父数据存在 - returnSalesLineService.validateReturnSalesLineExists(updateReqVO.getLineId()); - // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); + validateReturnSalesDetailSaveData(updateReqVO); // 更新 MesWmReturnSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDetailDO.class); @@ -95,4 +98,41 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail } } + /** + * 校验保存时的关联数据 + */ + private void validateReturnSalesDetailSaveData(MesWmReturnSalesDetailSaveReqVO reqVO) { + // 校验父数据存在 + MesWmReturnSalesLineDO line = returnSalesLineService.validateReturnSalesLineExists(reqVO.getLineId()); + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库位物料/批次混放规则 + materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); + // 校验明细总数量不超过行数量(排除自身) + validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); + } + + /** + * 校验明细总数量不超过行数量 + * + * @param lineId 行 ID + * @param newQuantity 本次新增/修改的数量 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null) + * @param line 退货单行 + */ + private void validateDetailQuantityNotExceed(Long lineId, BigDecimal newQuantity, + Long excludeDetailId, MesWmReturnSalesLineDO line) { + // 计算已有明细总数量(排除自身) + List details = returnSalesDetailMapper.selectListByLineId(lineId); + BigDecimal existingTotal = CollectionUtils.getSumValue(details, + detail -> excludeDetailId != null && excludeDetailId.equals(detail.getId()) + ? BigDecimal.ZERO : detail.getQuantity(), + BigDecimal::add, BigDecimal.ZERO); + // 校验:已有 + 本次 <= 行数量 + if (existingTotal.add(newQuantity).compareTo(line.getQuantity()) > 0) { + throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED); + } + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java index 95bda8d..d56c9f3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java +++ b/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 @Override public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) { - // 校验父数据存在 - returnSalesService.validateReturnSalesExists(createReqVO.getReturnId()); - // 校验物料存在 - validateItemBatchManagement(createReqVO.getItemId(), createReqVO.getBatchId()); + validateLineSaveData(createReqVO); // 插入 MesWmReturnSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnSalesLineDO.class); @@ -62,10 +59,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ public void updateReturnSalesLine(MesWmReturnSalesLineSaveReqVO updateReqVO) { // 校验存在 validateReturnSalesLineExists(updateReqVO.getId()); - // 校验父数据存在 - returnSalesService.validateReturnSalesExists(updateReqVO.getReturnId()); - // 校验物料存在 - validateItemBatchManagement(updateReqVO.getItemId(), updateReqVO.getBatchId()); + validateLineSaveData(updateReqVO); // 更新 MesWmReturnSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesLineDO.class); @@ -74,6 +68,16 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ returnSalesLineMapper.updateById(updateObj); } + /** + * 校验保存时的关联数据 + */ + private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) { + // 校验退货单存在 + returnSalesService.validateReturnSalesExists(reqVO.getReturnId()); + // 校验物料存在 + 批次管理 + validateItemBatchManagement(reqVO.getItemId(), reqVO.getBatchId()); + } + @Override public void deleteReturnSalesLine(Long id) { // 校验存在 -- libgit2 0.21.4