Commit 96cc973075f86483a5e6e7e97ff1863878ed264f

Authored by YunaiV
1 parent 19c82843

✨ feat(mes): 添加外协入库单行明细数量校验逻辑

新增对外协入库单行的明细数量进行校验,确保每行的数量与明细总数量一致。此功能提升了数据的准确性,避免了因数量不匹配导致的错误处理。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java
@@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
8 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; 10 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO;
9 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO; 11 import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; 12 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO;
@@ -24,7 +26,9 @@ import org.springframework.stereotype.Service; @@ -24,7 +26,9 @@ import org.springframework.stereotype.Service;
24 import org.springframework.transaction.annotation.Transactional; 26 import org.springframework.transaction.annotation.Transactional;
25 import org.springframework.validation.annotation.Validated; 27 import org.springframework.validation.annotation.Validated;
26 28
  29 +import java.math.BigDecimal;
27 import java.util.List; 30 import java.util.List;
  31 +import java.util.Map;
28 32
29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
30 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; 34 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
@@ -132,14 +136,33 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe @@ -132,14 +136,33 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe
132 @Override 136 @Override
133 @Transactional(rollbackFor = Exception.class) 137 @Transactional(rollbackFor = Exception.class)
134 public void stockOutsourceReceipt(Long id) { 138 public void stockOutsourceReceipt(Long id) {
135 - // 校验存在 139 + // 1.1 校验存在 + 待上架状态
136 MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id); 140 MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id);
137 if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) { 141 if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) {
138 throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); 142 throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR);
139 } 143 }
140 - // DONE @AI:这个校验,不需要了;已删除明细数量校验逻辑 144 + // 1.2 检查每个行的明细数量是否完成上架
  145 + List<MesWmOutsourceReceiptLineDO> lines = outsourceReceiptLineMapper.selectListByReceiptId(id);
  146 + if (CollUtil.isNotEmpty(lines)) {
  147 + // 批量查询所有明细
  148 + List<MesWmOutsourceReceiptDetailDO> allDetails = outsourceReceiptDetailMapper.selectListByReceiptId(id);
  149 + Map<Long, List<MesWmOutsourceReceiptDetailDO>> detailMap = CollectionUtils.convertMultiMap(
  150 + allDetails, MesWmOutsourceReceiptDetailDO::getLineId);
  151 + // 检查每行的明细数量
  152 + for (MesWmOutsourceReceiptLineDO line : lines) {
  153 + List<MesWmOutsourceReceiptDetailDO> details = detailMap.getOrDefault(line.getId(), List.of());
  154 + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details,
  155 + MesWmOutsourceReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO);
  156 + // 对比行数量与明细总数量,不满足直接抛出
  157 + if (line.getQuantity().compareTo(totalDetailQuantity) > 0) {
  158 + MesMdItemDO item = itemService.validateItemExists(line.getItemId());
  159 + throw exception(WM_OUTSOURCE_RECEIPT_DETAIL_QUANTITY_MISMATCH,
  160 + item.getCode() + " " + item.getName() + " 未完成上架");
  161 + }
  162 + }
  163 + }
141 164
142 - // 审批(审批中 → 已审批) 165 + // 2. 入库上架(待上架 → 已审批)
143 outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() 166 outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO()
144 .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.APPROVED.getStatus())); 167 .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.APPROVED.getStatus()));
145 } 168 }
@@ -157,13 +180,6 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe @@ -157,13 +180,6 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe
157 // DONE @AI:芋艿【暂时不处理】;后续在观察;(AI 未修复原因:标注为后续处理,需人工介入) 180 // DONE @AI:芋艿【暂时不处理】;后续在观察;(AI 未修复原因:标注为后续处理,需人工介入)
158 List<MesWmOutsourceReceiptDetailDO> details = outsourceReceiptDetailMapper.selectListByReceiptId(id); 181 List<MesWmOutsourceReceiptDetailDO> details = outsourceReceiptDetailMapper.selectListByReceiptId(id);
159 for (MesWmOutsourceReceiptDetailDO detail : details) { 182 for (MesWmOutsourceReceiptDetailDO detail : details) {
160 - // DONE @AI:warehouseAreaService 有个公用的校验;  
161 - // 校验物料存在  
162 - itemService.validateItemExists(detail.getItemId());  
163 - // 校验仓库、库区、库位的父子关系  
164 - warehouseAreaService.validateWarehouseAreaExists(detail.getWarehouseId(),  
165 - detail.getLocationId(), detail.getAreaId());  
166 -  
167 materialStockService.increaseStock( 183 materialStockService.increaseStock(
168 detail.getItemId(), detail.getWarehouseId(), detail.getLocationId(), detail.getAreaId(), 184 detail.getItemId(), detail.getWarehouseId(), detail.getLocationId(), detail.getAreaId(),
169 detail.getBatchId(), detail.getQuantity(), receipt.getVendorId(), null, null); 185 detail.getBatchId(), detail.getQuantity(), receipt.getVendorId(), null, null);