| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; |
| | | import jakarta.annotation.Resource; |
| | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_REQUIRED; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_LINE_NOT_EXISTS; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_REEL_MISMATCH; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_BATCH_NOT_SHIPPED; |
| | | |
| | | /** |
| | | * MES 销售退货单行 Service 实现类 |
| | |
| | | private MesMdmItemService mdmItemService; |
| | | @Resource |
| | | private MesWmBatchService batchService; |
| | | @Resource |
| | | private ErpSaleOrderApi saleOrderApi; |
| | | @Resource |
| | | private MesWmProductSalesDetailMapper productSalesDetailMapper; |
| | | @Resource |
| | | @Lazy |
| | | private MesWmReturnSalesDetailService returnSalesDetailService; |
| | |
| | | */ |
| | | private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) { |
| | | // 校验退货单存在 + 草稿状态 |
| | | returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); |
| | | MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); |
| | | // 校验物料存在 + 批次管理 |
| | | validateItemBatchManagement(reqVO.getReturnId(), reqVO.getItemId(), reqVO.getBatchId()); |
| | | MesWmBatchDO batch = validateItemBatchManagement(returnSales, reqVO.getItemId(), reqVO.getBatchId()); |
| | | if (batch != null) { |
| | | reqVO.setBatchCode(batch.getCode()); |
| | | } |
| | | if (returnSales.getSaleOrderId() != null) { |
| | | var items = saleOrderApi.getSaleOrderItemList(returnSales.getSaleOrderId()).getCheckedData(); |
| | | var reelNumbers = items.stream().filter(item -> Objects.equals(reqVO.getItemId(), item.getProductId())) |
| | | .map(item -> item.getReelNo()).filter(StrUtil::isNotBlank).toList(); |
| | | if (!reelNumbers.isEmpty() && (batch == null || !reelNumbers.contains(batch.getReelNo()) |
| | | || (StrUtil.isNotBlank(batch.getSalesOrderCode()) |
| | | && !Objects.equals(returnSales.getSalesOrderCode(), batch.getSalesOrderCode())))) { |
| | | throw exception(WM_RETURN_SALES_REEL_MISMATCH); |
| | | } |
| | | if (!reelNumbers.isEmpty() && productSalesDetailMapper.countFinishedSaleBatch( |
| | | returnSales.getSaleOrderId(), reqVO.getItemId(), batch.getId(), |
| | | MesWmProductSalesStatusEnum.FINISHED.getStatus()) == 0) { |
| | | throw exception(WM_RETURN_SALES_BATCH_NOT_SHIPPED); |
| | | } |
| | | // 手工入库批次可能没有客户;仅在订单盘号及已完成出库都已验证后允许退货。 |
| | | if (batch != null && (batch.getClientId() != null || reelNumbers.isEmpty())) { |
| | | batchService.validateBatchExists(batch.getId(), reqVO.getItemId(), returnSales.getClientId(), null); |
| | | } |
| | | } else if (batch != null) { |
| | | batchService.validateBatchExists(batch.getId(), reqVO.getItemId(), returnSales.getClientId(), null); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | /** |
| | | * 校验物料批次管理 |
| | | * |
| | | * @param returnId 退货单ID |
| | | * @param returnSales 退货单 |
| | | * @param itemId 物料ID |
| | | * @param batchId 批次ID |
| | | */ |
| | | private void validateItemBatchManagement(Long returnId, Long itemId, Long batchId) { |
| | | private MesWmBatchDO validateItemBatchManagement(MesWmReturnSalesDO returnSales, Long itemId, Long batchId) { |
| | | MesMdmItemDO item = mdmItemService.validateItemExistsAndEnable(itemId); |
| | | // 如果物料启用了批次管理,则必须选择批次 |
| | | if (Boolean.TRUE.equals(item.getIsBatchManaged()) && batchId == null) { |
| | |
| | | } |
| | | // 校验批次存在且属于当前物料和客户 |
| | | if (batchId != null) { |
| | | // 从父单获取客户ID,校验批次归属 |
| | | MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(returnId); |
| | | batchService.validateBatchExists(batchId, itemId, returnSales.getClientId(), null); |
| | | return batchService.validateBatchExists(batchId, itemId); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | |
| | | .setItemId(sourceLine.getItemId()) |
| | | .setQuantity(unqualifiedQuantity) |
| | | .setBatchId(sourceLine.getBatchId()) |
| | | .setBatchCode(sourceLine.getBatchCode()) |
| | | .setRqcId(sourceLine.getRqcId()) |
| | | .setRqcCheckFlag(sourceLine.getRqcCheckFlag()) |
| | | .setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) |