| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; |
| | | import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeLineService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.unitconvert.MesWmItemUnitConvertService; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.context.annotation.Lazy; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | |
| | | /** |
| | | * MES 销售出库单行 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesWmSalesNoticeLineService salesNoticeLineService; |
| | | @Resource |
| | | @Lazy |
| | | private MesQcOqcService oqcService; |
| | | @Resource |
| | | private MesWmItemUnitConvertService itemUnitConvertService; |
| | | |
| | | @Override |
| | | public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) { |
| | | // 双单位换算:按录入单位换算为物料主单位数量(必须先换算,再校验与发货通知单行的数量一致性) |
| | | fillPrimaryQuantity(createReqVO); |
| | | // 校验数据 |
| | | validateLineSaveData(createReqVO); |
| | | |
| | |
| | | public void updateProductSalesLine(MesWmProductSalesLineSaveReqVO updateReqVO) { |
| | | // 校验存在 |
| | | MesWmProductSalesLineDO oldLine = validateProductSalesLineExists(updateReqVO.getId()); |
| | | // 校验数据 |
| | | updateReqVO.setSalesId(oldLine.getSalesId()); |
| | | // 双单位换算:按录入单位换算为物料主单位数量(必须先换算,再校验与发货通知单行的数量一致性) |
| | | fillPrimaryQuantity(updateReqVO); |
| | | // 校验数据 |
| | | validateLineSaveData(updateReqVO); |
| | | |
| | | // 更新 |
| | | MesWmProductSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesLineDO.class); |
| | | productSalesLineMapper.updateById(updateObj); |
| | | |
| | | // 检查是否需要创建 OQC 检验单:从不需要检验变为需要检验 |
| | | if (Boolean.TRUE.equals(updateReqVO.getOqcCheckFlag()) |
| | | && !Boolean.TRUE.equals(oldLine.getOqcCheckFlag())) { |
| | | // 获取出库单信息 |
| | | MesWmProductSalesDO sales = productSalesService.getProductSales(updateReqVO.getSalesId()); |
| | | if (sales == null) { |
| | | log.warn("[updateProductSalesLine] 出库单不存在,salesId={}", updateReqVO.getSalesId()); |
| | | return; |
| | | } |
| | | |
| | | // 构建出库明细 DO |
| | | MesWmProductSalesLineDO line = new MesWmProductSalesLineDO(); |
| | | line.setId(updateReqVO.getId()); |
| | | line.setItemId(updateReqVO.getItemId()); |
| | | line.setBatchCode(updateReqVO.getBatchCode()); |
| | | line.setQuantity(updateReqVO.getQuantity()); |
| | | |
| | | // 创建 OQC 检验单,让异常抛出 |
| | | Long oqcId = oqcService.createOqcFromProductSales( |
| | | sales.getId(), line, sales.getCode(), sales.getClientId()); |
| | | |
| | | // 更新出库明细的 oqcId 和质量状态 |
| | | productSalesLineMapper.updateById(new MesWmProductSalesLineDO() |
| | | .setId(updateReqVO.getId()) |
| | | .setOqcId(oqcId) |
| | | .setQualityStatus(MesWmQualityStatusEnum.PENDING.getStatus())); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | /** |
| | | * 双单位换算:选择了录入单位时,按「录入数量 × 换算比率」得到物料主单位口径的出库数量 |
| | | * |
| | | * 未按辅单位录入时必须直接填写出库数量 |
| | | */ |
| | | private void fillPrimaryQuantity(MesWmProductSalesLineSaveReqVO reqVO) { |
| | | if (reqVO.getEnterUnitMeasureId() != null) { |
| | | BigDecimal primaryQuantity = itemUnitConvertService.convertToPrimaryUnit( |
| | | reqVO.getItemId(), reqVO.getItemModelId(), |
| | | reqVO.getEnterUnitMeasureId(), reqVO.getEnterQuantity()); |
| | | if (primaryQuantity != null) { |
| | | reqVO.setQuantity(primaryQuantity); |
| | | } |
| | | } |
| | | if (reqVO.getQuantity() == null) { |
| | | throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_REQUIRED); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据 batchCode 解析 batchId |
| | | */ |
| | | private void fillBatchId(MesWmProductSalesLineSaveReqVO reqVO) { |
| | |
| | | } |
| | | MesWmSalesNoticeLineDO noticeLine = salesNoticeLineService.validateSalesNoticeLineExists( |
| | | noticeLineId, sales.getNoticeId()); |
| | | // 校验关键字段一致性:物料、数量、批次号、OQC 检验标识 |
| | | // 校验关键字段一致性:物料、数量、批次号 |
| | | // 注:OQC 检验标识允许在出库时独立设置,不强制与通知单一致 |
| | | if (ObjUtil.notEqual(reqVO.getItemId(), noticeLine.getItemId())) { |
| | | throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_ITEM_MISMATCH); |
| | | } |
| | |
| | | if (StrUtil.isNotBlank(noticeLine.getBatchCode()) |
| | | && ObjUtil.notEqual(reqVO.getBatchCode(), noticeLine.getBatchCode())) { |
| | | throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_BATCH_MISMATCH); |
| | | } |
| | | if (noticeLine.getOqcCheckFlag() != null |
| | | && ObjUtil.notEqual(reqVO.getOqcCheckFlag(), noticeLine.getOqcCheckFlag())) { |
| | | throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH); |
| | | } |
| | | return; |
| | | } |