| | |
| | | import cn.hutool.core.util.ObjUtil; |
| | | 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.batch.vo.MesWmBatchGenerateReqVO; |
| | | 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.api.event.MesReturnSalesProgressEvent; |
| | | 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.service.wm.batch.MesWmBatchService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | |
| | | |
| | | 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_BATCH_CLIENT_MISMATCH; |
| | | 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_RQC_SOURCE_INVALID; |
| | | |
| | | /** |
| | | * MES 销售退货单行 Service 实现类 |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesWmReturnSalesDetailService returnSalesDetailService; |
| | | @Resource |
| | | private ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) { |
| | |
| | | */ |
| | | private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) { |
| | | // 校验退货单存在 + 草稿状态 |
| | | returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); |
| | | // 校验物料存在 + 批次管理 |
| | | validateItemBatchManagement(reqVO.getReturnId(), reqVO.getItemId(), reqVO.getBatchId()); |
| | | MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); |
| | | // 校验物料存在 + 解析批次 |
| | | resolveAndValidateBatch(returnSales, reqVO); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | /** |
| | | * 校验物料批次管理 |
| | | * 解析并校验物料批次 |
| | | * |
| | | * @param returnId 退货单ID |
| | | * @param itemId 物料ID |
| | | * @param batchId 批次ID |
| | | * <p>退货商品在销售出库时可能未记录批次,此时按物料 + 客户 + 销售订单自动生成退货批次, |
| | | * 保证退货单仍可追溯到具体批次;已有批次则校验物料归属,批次未指定客户时视为通用批次。 |
| | | */ |
| | | private void validateItemBatchManagement(Long returnId, Long itemId, Long batchId) { |
| | | MesMdmItemDO item = mdmItemService.validateItemExistsAndEnable(itemId); |
| | | // 如果物料启用了批次管理,则必须选择批次 |
| | | if (Boolean.TRUE.equals(item.getIsBatchManaged()) && batchId == null) { |
| | | private void resolveAndValidateBatch(MesWmReturnSalesDO returnSales, MesWmReturnSalesLineSaveReqVO reqVO) { |
| | | MesMdmItemDO item = mdmItemService.validateItemExistsAndEnable(reqVO.getItemId()); |
| | | if (reqVO.getBatchId() != null) { |
| | | MesWmBatchDO batch = batchService.validateBatchExists(reqVO.getBatchId(), reqVO.getItemId()); |
| | | if (batch.getClientId() != null && ObjUtil.notEqual(batch.getClientId(), returnSales.getClientId())) { |
| | | throw exception(WM_BATCH_CLIENT_MISMATCH); |
| | | } |
| | | reqVO.setBatchCode(batch.getCode()); |
| | | return; |
| | | } |
| | | if (!Boolean.TRUE.equals(item.getIsBatchManaged())) { |
| | | return; |
| | | } |
| | | MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO() |
| | | .setItemId(reqVO.getItemId()) |
| | | .setClientId(returnSales.getClientId()) |
| | | .setSalesOrderCode(returnSales.getSalesOrderCode()); |
| | | MesWmBatchDO batch = batchService.getOrGenerateBatchCode(batchReqVO); |
| | | if (batch == null) { |
| | | throw exception(MD_ITEM_BATCH_REQUIRED); |
| | | } |
| | | // 校验批次存在且属于当前物料和客户 |
| | | if (batchId != null) { |
| | | // 从父单获取客户ID,校验批次归属 |
| | | MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(returnId); |
| | | batchService.validateBatchExists(batchId, itemId, returnSales.getClientId(), null); |
| | | } |
| | | reqVO.setBatchId(batch.getId()).setBatchCode(batch.getCode()); |
| | | } |
| | | |
| | | @Override |
| | | public void updateReturnSalesLineWhenRqcFinish(Long sourceLineId, Long sourceDocId, Integer checkResult, |
| | | BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { |
| | | MesWmReturnSalesLineDO sourceLine = validateReturnSalesLineExists(sourceLineId); |
| | | if (sourceDocId != null) { |
| | | MesWmReturnSalesDO sourceDoc = returnSalesService.validateReturnSalesExists(sourceDocId); |
| | | if (!sourceDocId.equals(sourceLine.getReturnId()) |
| | | || !MesWmReturnSalesStatusEnum.CONFIRMED.getStatus().equals(sourceDoc.getStatus()) |
| | | || !MesWmQualityStatusEnum.PENDING.getStatus().equals(sourceLine.getQualityStatus())) { |
| | | throw exception(WM_RETURN_SALES_RQC_SOURCE_INVALID); |
| | | } |
| | | } |
| | | boolean hasUnqualified = unqualifiedQuantity != null && unqualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; |
| | | boolean hasQualified = qualifiedQuantity != null && qualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; |
| | | |
| | |
| | | boolean allInspected = !CollUtil.contains(allLines, |
| | | line -> Objects.equals(line.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())); |
| | | if (allInspected) { |
| | | returnSalesService.updateReturnSalesStatus(sourceDocId, MesWmReturnSalesStatusEnum.APPROVING.getStatus()); |
| | | MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExists(sourceDocId); |
| | | if (MesWmReturnSalesStatusEnum.CONFIRMED.getStatus().equals(returnSales.getStatus())) { |
| | | returnSalesService.updateReturnSalesStatus(sourceDocId, MesWmReturnSalesStatusEnum.APPROVING.getStatus()); |
| | | if (returnSales.getAfterSaleReturnId() != null) { |
| | | boolean failed = CollUtil.contains(allLines, |
| | | line -> MesWmQualityStatusEnum.FAIL.getStatus().equals(line.getQualityStatus())); |
| | | eventPublisher.publishEvent(new MesReturnSalesProgressEvent(sourceDocId, |
| | | MesReturnSalesProgressEvent.Stage.QUALITY_FINISHED, failed ? "含不合格品" : "合格")); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |