云
2026-10-27 ffca46b39d25439a06a27cafda2ec523a3fb67cf
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -3,9 +3,12 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils;
import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi;
import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcImportExcelVO;
import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO;
@@ -34,6 +37,7 @@
import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import com.mzt.logapi.starter.annotation.LogRecord;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -51,6 +55,7 @@
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.mes.enums.LogRecordConstants.*;
/**
 * MES 出货检验单(OQC) Service 实现类
@@ -63,6 +68,9 @@
    @Resource
    private MesQcOqcMapper oqcMapper;
    @Resource
    private ErpSaleOrderApi saleOrderApi;
    @Resource
    private MesQcTemplateItemService templateItemService;
@@ -125,6 +133,10 @@
                .setTemplateId(templateId)
                .setSourceDocCode(sourceDocCode)
                .setStatus(MesQcStatusEnum.DRAFT.getStatus());
        if (createReqVO.getSourceLineId() != null) {
            oqc.setReelNo(resolveSalesReelNo(productSalesLineService
                    .validateProductSalesLineExists(createReqVO.getSourceLineId())));
        }
        oqcMapper.insert(oqc);
        // 3. 从模板指标自动生成检验行
@@ -135,7 +147,7 @@
    @Override
    public void updateOqc(MesQcOqcSaveReqVO updateReqVO) {
        // 1.1 校验存在 + 草稿状态
        validateOqcStatusPrepare(updateReqVO.getId());
        MesQcOqcDO existingOqc = validateOqcStatusPrepare(updateReqVO.getId());
        // 1.2 校验数据
        validateOqcSaveData(updateReqVO);
@@ -144,7 +156,12 @@
        updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 不允许修改来源单据
        updateObj.setTemplateId(null); // 不允许修改模板
        updateObj.setItemId(null); // 不允许修改物料
        oqcMapper.updateById(updateObj);
        if (existingOqc.getSourceLineId() != null) updateObj.setReelNo(null); // 来源盘号保持快照
        // 编辑时允许清空客户;完成检验等局部更新仍保留原客户。
        updateObj.setClientId(null);
        oqcMapper.update(updateObj, new LambdaUpdateWrapper<MesQcOqcDO>()
                .eq(MesQcOqcDO::getId, updateReqVO.getId())
                .set(MesQcOqcDO::getClientId, updateReqVO.getClientId()));
    }
    private void validateOqcSaveData(MesQcOqcSaveReqVO reqVO) {
@@ -304,9 +321,7 @@
    @Override
    public PageResult<MesQcOqcDO> getOqcPage(MesQcOqcPageReqVO pageReqVO) {
        // 获取用户有权限的客户 ID 列表
        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
        return oqcMapper.selectPage(pageReqVO, permittedClientIds);
        return oqcMapper.selectPage(pageReqVO, (List<Long>) null);
    }
    @Override
@@ -379,11 +394,16 @@
        oqc.setClientId(clientId);
        oqc.setItemId(line.getItemId());
        oqc.setBatchCode(line.getBatchCode());
        oqc.setReelNo(resolveSalesReelNo(line));
        oqc.setOutQuantity(line.getQuantity());
        oqc.setCheckQuantity(BigDecimal.ZERO); // 待填写
        oqc.setQualifiedQuantity(BigDecimal.ZERO); // 待填写
        oqc.setUnqualifiedQuantity(BigDecimal.ZERO); // 待填写
        oqc.setOutDate(java.time.LocalDateTime.now());
        MesWmProductSalesDO sales = productSalesService.getProductSales(salesId);
        java.time.LocalDateTime businessDate = sales != null && sales.getSalesDate() != null
                ? sales.getSalesDate() : java.time.LocalDateTime.now();
        oqc.setOutDate(businessDate);
        oqc.setInspectDate(businessDate);
        oqc.setStatus(MesQcStatusEnum.DRAFT.getStatus());
        oqcMapper.insert(oqc);
@@ -391,6 +411,12 @@
        oqcLineService.createLinesFromTemplate(oqc.getId(), templateId);
        return oqc.getId();
    }
    private String resolveSalesReelNo(MesWmProductSalesLineDO line) {
        if (line == null || line.getSaleOrderItemId() == null) return null;
        var item = saleOrderApi.getSaleOrderItem(line.getSaleOrderItemId()).getCheckedData();
        return item == null ? null : item.getReelNo();
    }
    /**
@@ -413,10 +439,14 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = MES_QC_OQC_TYPE, subType = MES_QC_OQC_IMPORT_SUB_TYPE, bizNo = "0",
            success = MES_QC_OQC_IMPORT_SUCCESS)
    public MesQcImportRespVO importOqcList(List<MesQcOqcImportExcelVO> importList) {
        MesQcImportRespVO respVO = MesQcImportRespVO.builder()
                .createList(new ArrayList<>()).failureList(new LinkedHashMap<>()).build();
        if (CollUtil.isEmpty(importList)) {
            // 空文件也要给日志文案兜底,避免 {{#importSummary}} 取不到值
            OperateLogUtils.putImportSummary(respVO.getCreateList(), null, respVO.getFailureList());
            return respVO;
        }
        qcImportHelper.startImport();
@@ -440,6 +470,8 @@
                respVO.getFailureList().put(label, MesQcImportHelper.resolveImportErrorMessage(ex));
            }
        }
        // 记录导入结果汇总,供 @LogRecord 的 success 文案引用
        OperateLogUtils.putImportSummary(respVO.getCreateList(), null, respVO.getFailureList());
        return respVO;
    }
@@ -476,7 +508,7 @@
        reqVO.setName(row.getName().trim());
        reqVO.setItemId(qcImportHelper.resolveItemId(row.getItemCode()));
        Long clientId = qcImportHelper.resolveClientId(row.getClientName());
        qcImportHelper.validateClientPermission(clientId, row.getClientName().trim());
        qcImportHelper.validateClientPermission(clientId, StrUtil.trimToEmpty(row.getClientName()));
        reqVO.setClientId(clientId);
        reqVO.setBatchCode(StrUtil.trimToNull(row.getBatchCode()));
        reqVO.setTemplateId(qcImportHelper.resolveTemplateId(row.getTemplateName()));