package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.jx;

import cn.estsh.i3plus.ext.mes.pcn.api.base.IPartExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.jx.IJxBadnessClassifyService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.jx.ISxOqcRuleNoteService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.bu.IBuQmsHttpRequestService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.jx.IJxBadnessTypeService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxOqcCheckService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxOqcManageService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.bu.SxBuOqcDataModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.jx.JxOqcManageCheckDetailModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.jx.JxOqcManageManualModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.jx.JxOqcManageModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.jx.JxOqcManageParamModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.sqlpack.MesPcnExtHqlPack;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.ISyncFuncService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.util.CommonConstWords;
import cn.estsh.i3plus.pojo.base.bean.BaseResultBean;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import cn.estsh.impp.framework.boot.util.ImppRedis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class JxOqcManageService implements IJxOqcManageService {

    @Autowired
    private ISyncFuncService syncFuncService;

    @Autowired
    private IPartExtService partExtService;

    @Autowired
    private MesOutPutStatisticsOqcRepository outPutStatisticsOqcRepository;

    @Autowired
    private IJxOqcCheckService oqcCheckService;

    @Autowired
    private IJxBadnessTypeService badnessTypeService;

    @Autowired
    private IJxBadnessClassifyService badnessClassifyService;

    @Autowired
    private MesOqcCheckRepository oqcCheckRepository;

    @Autowired
    private MesOqcCheckDetailRepository oqcCheckDetailRepository;

    @Autowired
    private MesOqcCheckPackageDetailRepository oqcCheckPackageDetailRepository;

    @Autowired
    private MesOqcCheckPackageIfRepository oqcCheckPackageIfRepository;

    @Autowired
    private MesOqcCheckPackageDetailTravelRepository oqcCheckPackageDetailTravelRepository;

    @Autowired
    private ISxOqcRuleNoteService oqcRuleNoteService;

    @Autowired
    private IBuQmsHttpRequestService qmsHttpRequestService;

    @Resource(name = CommonConstWords.IMPP_REDIS_MES_PCN)
    private ImppRedis redisMesPcn;

    @Override
    public JxOqcManageModel queryOqcManageData(JxOqcManageParamModel model) {
        log.info("出货检验主数据 --- 参数model[{}] --- 线程ID[{}]", model.toBaseString(), Thread.currentThread().getName());

        String key = new StringJoiner(MesPcnExtConstWords.COLON).add(model.getOrganizeCode()).add(MesPcnExtConstWords.OQC_MANAGE_DATA).toString();

        Object lastScanInfo = redisMesPcn.getHash(key, model.getUserId());

        log.info("出货检验主数据 --- lastScanInfo[{}] --- 线程ID[{}]", lastScanInfo, Thread.currentThread().getName());

        JxOqcManageModel result = new JxOqcManageModel(model.getOrganizeCode(), model.getUserId(), model.getUserInfo(), model.getSn(), model.getIdStr());

        //初始化缓存数据
        initCachedData(result, lastScanInfo);

        log.info("出货检验主数据 --- result[{}] --- 线程ID[{}]", result.toBaseString(), Thread.currentThread().getName());

        //初始化界面
        if (StringUtils.isEmpty(result.getSn()) && StringUtils.isEmpty(result.getProductSn()) && StringUtils.isEmpty(result.getIdStr())) return noDetailResult(result, model);

        //组件
        if (!StringUtils.isEmpty(result.getIdStr())) return queryOqcManageDataById(result, lastScanInfo, key, model);

        log.info("出货检验主数据 --- 成品出货检验 --- START --- 线程ID[{}]", Thread.currentThread().getName());

        //判断是否是继上次扫描
        checkSnIsNull(result, model.getOqcNo());

        //继上次扫描
        if (!StringUtils.isEmpty(result.getMsg())) return noDetailResult(result, model);

        log.info("出货检验主数据 --- 成品出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModel(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getQueryClass());

        log.info("出货检验主数据 --- 成品出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //判断是否完成扫描
        checkScanIsFinish(result, dataFromPcn, lastScanInfo, key);

        //未完成扫描
        if (!StringUtils.isEmpty(result.getMsg())) return noDetailResult(result, model);

        //成品
        queryOqcManageDataBySn(result, model, dataFromPcn);

        log.info("MES_PCN出货检验主数据 --- 成品出货检验 --- END --- 线程ID[{}]", Thread.currentThread().getName());

        return result;
    }

    private void initCachedData(JxOqcManageModel result, Object lastScanInfo) {
        if (StringUtils.isEmpty(result.getIdStr())) {
            if (!StringUtils.isEmpty(lastScanInfo)) {
                if (lastScanInfo instanceof String) {
                    String[] snArr = lastScanInfo.toString().split(MesPcnExtConstWords.COMMA);
                    //result.setSerialNumber(snArr[0]);
                    result.setProductSn(snArr[0]);
                    if (snArr.length > 1) {
                        result.setGoodsCode(snArr[1]);
                    }
                    //if (snArr.length > 2) {
                    //    result.setPackageNo(snArr[2]);
                    //}
                    //if (snArr.length == 4) {
                    //    result.setGoodsCode2(snArr[3]);
                    //}
                } else {
                    result.setIdStr(lastScanInfo.toString());
                }
            }
            if (StringUtils.isEmpty(result.getSn()) && StringUtils.isEmpty(result.getProductSn()) && StringUtils.isEmpty(result.getIdStr())) {
                result.setMsg("请扫描产品条码");
            }
        }
    }

    private JxOqcManageModel noDetailResult(JxOqcManageModel result, JxOqcManageParamModel model) {
        model.setPager(PagerHelper.getPager(model.getPager(), MesPcnExtConstWords.ZERO));
        result.setDetailList(new ListPager<>(new ArrayList<>(), model.getPager()));
        return result;
    }

    private JxOqcManageModel queryOqcManageDataById(JxOqcManageModel result, Object lastScanInfo, String key, JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- START --- 线程ID[{}]", Thread.currentThread().getName());

        //产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcById(result, "组件抽检");

        //验证物料
        MesPartExt partDb = checkPartValidById(result, outPutStatisticsOqcDb.getPartNo(), "组件抽检");

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModel(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getQueryClass());

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //缓存用户扫描信息
        if (StringUtils.isEmpty(lastScanInfo) || !lastScanInfo.toString().equals(result.getIdStr()))
            redisMesPcn.putHash(key, result.getUserId(), Long.parseLong(result.getIdStr()), MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());

        //数据组合
        packJxOqcManageModel(result, dataFromPcn, partDb);

        //获取出货检验单据
        MesOqcCheck oqcCheckDb = oqcCheckService.getZjOqcCheckByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- oqcNo[{}] --- 线程ID[{}]", null == oqcCheckDb ? MesPcnExtConstWords.EMPTY : oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        //获取出货检验项目明细
        ListPager<JxOqcManageCheckDetailModel> oqcCheckDetailList = getOqcCheckDetailList(oqcCheckDb, model);

        //数据组合
        packOqcManageDataById(result, oqcCheckDb, outPutStatisticsOqcDb, oqcCheckDetailList);

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- END --- 线程ID[{}]", Thread.currentThread().getName());

        return result;
    }

    private MesOutPutStatisticsOqc getOutPutStatisticsOqcById(JxOqcManageModel result, String msg) {
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcDb(result.getOrganizeCode(), result.getIdStr());
        if (null == outPutStatisticsOqcDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("%s:[总检验结果]传参ID[%s]数据对应的产量统计出货检验信息不存在", msg, result.getIdStr())
                    .build();
        }
        return outPutStatisticsOqcDb;
    }

    private MesPartExt checkPartValidById(JxOqcManageModel result, String partNo, String msg) {
        MesPartExt partDb = partExtService.getPartExt(result.getOrganizeCode(), partNo);
        if (null == partDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("%s:[总检验结果]传参ID[%s]数据对应的物料编码[%s]不存在", msg, result.getIdStr(), partNo)
                    .build();
        }

        if (StringUtils.isEmpty(partDb.getCategoryCode3()) || partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("%s:[总检验结果]传参ID[%s]数据对应的物料编码[%s]的产品类型不是组件", msg, result.getIdStr(), partNo)
                    .build();
        }

        if (StringUtils.isEmpty(partDb.getIsOqc()) || CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() == partDb.getIsOqc()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("%s:[总检验结果]传参ID[%s]数据对应的物料编码[%s]不支持出货检验", msg, result.getIdStr(), partNo)
                    .build();
        }
        return partDb;
    }

    private JxOqcManageModel packOqcManageDataById(JxOqcManageModel result, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb,
                                                     ListPager<JxOqcManageCheckDetailModel> oqcCheckDetailList) {
        if (null == oqcCheckDb) {
            packInitResultById(result);
        } else {
            packFeedbackResultById(result, oqcCheckDb);
        }

        return commonLastPackResult(result, oqcCheckDetailList, outPutStatisticsOqcDb.getCheckLimit());
    }

    private void packInitResultById(JxOqcManageModel result) {
        result.getSpotCheckQtyBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), true);
        result.getSpotCheckQtyBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), true);

        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), false);

        result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), true);
        result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), true);

        result.setBatchLimitBoo(true);
    }

    private void packFeedbackResultById(JxOqcManageModel result, MesOqcCheck oqcCheckDb) {
        commonPackFeedbackResult(result, oqcCheckDb);

        if (StringUtils.isEmpty(oqcCheckDb.getCheckResult()) || StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) {
            result.setSpotCheckQty(oqcCheckDb.getSpotCheckQty());
            result.setBatchLimit(oqcCheckDb.getOqcQty());
        } else {
            result.getSpotCheckQtyBooMap().put(oqcCheckDb.getOqcNoType(), true);
            result.setBatchLimitBoo(true);
            result.getGenOqcBooMap().put(oqcCheckDb.getOqcNoType(), true);
        }

        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), false);
        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), false);
        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), false);
    }

    private void checkSnIsNull(JxOqcManageModel result, String oqcNo) {
        if (StringUtils.isEmpty(result.getSn())) {
            if (StringUtils.isEmpty(result.getGoodsCode())) {
                result.setMsg(String.format("继上次扫描,产品条码[%s],请继续扫描商品码", result.getProductSn()));
            }
            //else if (StringUtils.isEmpty(result.getPackageNo())) {
            //    result.setMsg(String.format("继上次扫描,产品条码[%s]商品码[%s],请继续扫描包装条码", result.getSerialNumber(), result.getGoodsCode()));
            //} else if (StringUtils.isEmpty(result.getGoodsCode2())) {
            //    result.setMsg(String.format("继上次扫描,产品条码[%s]商品码[%s]包装条码[%s],请继续扫描商品码", result.getSerialNumber(), result.getGoodsCode(), result.getPackageNo()));
            //}
        } else {
            //if (!StringUtils.isEmpty(result.getGoodsCode2())) {
            //    result.setMsg("请先点击重置,再重新扫描");
            //}
        }

        if (StringUtils.isEmpty(result.getMsg())) result.setOqcNo(oqcNo);

        log.info("MES_PCN出货检验主数据 --- result[{}] --- 线程ID[{}]", result.toBaseString(), Thread.currentThread().getName());
    }

    private SxBuOqcDataModel getBuOqcDataModel(JxOqcManageModel result, String clazz) {
        Map<String, Object> params = new HashMap<>();
        params.put(MesPcnExtConstWords.ORGANIZE_CODE, result.getOrganizeCode());
        params.put(MesPcnExtConstWords.CLASS_NAME, clazz);
        if (StringUtils.isEmpty(result.getIdStr())) {
            //成品
            params.put(MesPcnExtConstWords.VALUE, !StringUtils.isEmpty(result.getProductSn()) ? result.getProductSn() : result.getSn());
            params.put(MesPcnExtConstWords.DATA_TYPE,
                    (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() == result.getOqcNoType() || !StringUtils.isEmpty(result.getOqcNo())) ? MesPcnExtEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr() : MesPcnExtEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        } else {
            //组件
            params.put(MesPcnExtConstWords.VALUE, result.getIdStr());
        }

        return qmsHttpRequestService.queryBuQmsOqcManageData(params);
    }

    private void checkScanIsFinish(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn, Object lastScanInfo, String key) {
        if (StringUtils.isEmpty(result.getProductSn())) {
            result.setProductSn(result.getSn());
            result.setMsg(String.format("产品条码[%s]扫描成功,请继续扫描商品码", result.getProductSn()));
        } else {
            result.setGoodsCode(result.getSn());
        }

        //验证物料
        MesPartExt partDb = checkPartValidBySn(result, dataFromPcn.getPartNo(), lastScanInfo);
        //验证商品码
        checkGoodsCodeValid(partDb, result.getGoodsCode(), result.getProductSn());

        //缓存用户扫描信息
        if (!StringUtils.isEmpty(result.getSn())) redisMesPcn.putHash(key, result.getUserId(),
                StringUtils.isEmpty(lastScanInfo) ? result.getSn() : new StringJoiner(MesPcnExtConstWords.COMMA).add(lastScanInfo.toString()).add(result.getSn()).toString(), MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());

        //数据组合
        packJxOqcManageModel(result, dataFromPcn, partDb);
    }

    private MesPartExt checkPartValidBySn(JxOqcManageModel result, String partNo, Object lastScanInfo) {
        String msg;
        if (StringUtils.isEmpty(lastScanInfo)) {
            msg = ",请重新扫描产品条码";
        } else {
            msg = ",请点击重置";
        }

        MesPartExt partDb = partExtService.getPartExt(result.getOrganizeCode(), partNo);
        if (null == partDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]不存在%s", result.getProductSn(), partNo, msg)
                    .build();
        }
        if (StringUtils.isEmpty(partDb.getCategoryCode3()) || !partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]的产品类型不是成品%s", result.getProductSn(), partNo, msg)
                    .build();
        }
        if (StringUtils.isEmpty(partDb.getIsOqc()) || CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() == partDb.getIsOqc()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]不支持出货检验%s", result.getProductSn(), partNo, msg)
                    .build();
        }
        if (StringUtils.isEmpty(partDb.getGoodsCode())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]未维护商品码%s", result.getProductSn(), partNo, msg)
                    .build();
        }
        return partDb;
    }

    private void checkGoodsCodeValid(MesPartExt partDb, String goodsCode, String serialNumber) {
        if (!StringUtils.isEmpty(goodsCode) && !partDb.getGoodsCode().equals(goodsCode)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]维护的商品码[%s]与当前扫描的商品码[%s]不一致,请重新扫描商品码或点击重置",
                            serialNumber, partDb.getPartNo(), partDb.getGoodsCode(), goodsCode)
                    .build();
        }
        //if (!StringUtils.isEmpty(goodsCode2) && !partDb.getGoodsCode().equals(goodsCode2)) {
        //    throw ImppExceptionBuilder.newInstance()
        //            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
        //            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
        //            .setErrorDetail("出货检验:产品条码[%s]关联的物料编码[%s]维护的商品码[%s]与当前扫描的商品码[%s]不一致,请重新扫描商品码或点击重置",
        //                    serialNumber, partDb.getPartNo(), partDb.getGoodsCode(), goodsCode2)
        //            .build();
        //}
    }

    private void checkPackageValid(String packageNo, String packageNoDb, String serialNumber) {
        if (!StringUtils.isEmpty(packageNo) && !packageNo.equals(packageNoDb)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]关联的包装条码[%s]与当前扫描的包装条码[%s]不一致,请重新扫描包装条码或点击重置", serialNumber, packageNoDb, packageNo)
                    .build();
        }
    }

    private void packJxOqcManageModel(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn, MesPartExt partDb) {
        result.setWorkOrderNo(dataFromPcn.getWorkOrderNo());
        result.setPartNo(partDb.getPartNo());
        result.setPartNameRdd(partDb.getPartName());
        result.setCategoryCode3(partDb.getCategoryCode3());
        result.setWorkCenterCode(dataFromPcn.getWorkCenterCode());
        result.setWorkOrderType(dataFromPcn.getWorkOrderType());
        result.setWorkOrderTypeName(dataFromPcn.getWorkOrderTypeName());
        result.setWorkTime(dataFromPcn.getWorkTime());
        result.setShiftCode(dataFromPcn.getShiftCode());
        result.setShiftName(dataFromPcn.getShiftName());
        result.setPlanQty(dataFromPcn.getPlanQty());
        result.setCompleteQty(dataFromPcn.getCompleteQty());
        result.setIdStr(dataFromPcn.getIdStr());
        result.setSerialNumber(dataFromPcn.getSerialNumber());
        result.setProductSn(dataFromPcn.getProductSn());
    }

    private JxOqcManageModel queryOqcManageDataBySn(JxOqcManageModel result, JxOqcManageParamModel model, SxBuOqcDataModel dataFromPcn) {
        log.info("MES_PCN出货检验主数据 --- 成品出货检验 --- result[{}] --- 切换单号[{}] --- 线程ID[{}]", result.toString(), result.getOqcNo(), Thread.currentThread().getName());

        //产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcBySn(result, "出货检验");

        //获取出货检验单据集合
        List<MesOqcCheck> oqcCheckList = oqcCheckService.getOqcCheckListByProductSn(result.getOrganizeCode(), result.getWorkOrderNo(), result.getProductSn());

        log.info("MES_PCN出货检验主数据 --- 成品出货检验 --- oqcCheckList.size[{}] --- 线程ID[{}]", CollectionUtils.isEmpty(oqcCheckList) ? 0 : oqcCheckList.size(), Thread.currentThread().getName());

        //获取当前出货检验单据
        MesOqcCheck oqcCheckDb = getOqcCheckBySn(result, oqcCheckList, result.getOqcNo());

        log.info("MES_PCN出货检验主数据 --- 成品出货检验 --- oqcNo[{}] --- 线程ID[{}]", null == oqcCheckDb ? MesPcnExtConstWords.EMPTY : oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        //获取出货检验项目明细
        ListPager<JxOqcManageCheckDetailModel> oqcCheckDetailList = getOqcCheckDetailList(oqcCheckDb, model);

        //数据组合
        return packOqcManageDataBySn(result, oqcCheckList, oqcCheckDb, outPutStatisticsOqcDb, oqcCheckDetailList, dataFromPcn);

    }

    private MesOutPutStatisticsOqc getOutPutStatisticsOqcBySn(JxOqcManageModel result, String msg) {
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcDb(result.getOrganizeCode(), result.getIdStr());
        if (null == outPutStatisticsOqcDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("%s:产品条码[%s]作业时间[%s]班次代码[%s]关联的%s[%s]未查询到产量统计出货检验关联数据",
                            msg, result.getProductSn(), result.getWorkTime(), result.getShiftCode(), result.getWorkOrderTypeName(), result.getWorkOrderNo())
                    .build();
        }
        return outPutStatisticsOqcDb;
    }

    private MesOutPutStatisticsOqc getOutPutStatisticsOqcDb(String organizeCode, String idStr) {
        return outPutStatisticsOqcRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.PID},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), Long.parseLong(idStr)});
    }

    private MesOqcCheck getOqcCheckBySn(JxOqcManageModel result, List<MesOqcCheck> oqcCheckList, String oqcNo) {
        if (CollectionUtils.isEmpty(oqcCheckList)) {
            //验证是否已关联检验单
            checkSnIsChecked(result.getOrganizeCode(), result.getWorkOrderNo(), result.getProductSn(), "出货检验");
        } else {
            if (StringUtils.isEmpty(oqcNo)) {
                List<MesOqcCheck> unFinishOqcCheckList = oqcCheckList.stream().filter(o -> (null != o &&
                        (StringUtils.isEmpty(o.getCheckResult()) || StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(o.getCheckResult()))))).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(unFinishOqcCheckList)) {
                    unFinishOqcCheckList = unFinishOqcCheckList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesOqcCheck::getModifyDatetime).reversed()).collect(Collectors.toList());
                    return unFinishOqcCheckList.get(0);
                } else {
                    return oqcCheckList.get(0);
                }
            } else {
                //切换
                Optional<MesOqcCheck> oqcCheckDbOp = oqcCheckList.stream().filter(o -> (null != o && !o.getOqcNo().equals(oqcNo))).findFirst();
                if (null != oqcCheckDbOp && oqcCheckDbOp.isPresent()) {
                    result.setMsg("切换成功!");
                    return oqcCheckDbOp.get();
                } else {
                    return oqcCheckList.get(0);
                }
            }
        }
        return null;
    }

    private void checkSnIsChecked(String organizeCode, String workOrderNo, String productSn, String msg) {
        MesOqcCheckPackageDetail oqcCheckPackageDetail = oqcCheckService.getOqcCheckPackageDetailByOrderNoAndProductSn(organizeCode, workOrderNo, productSn);
        if (null != oqcCheckPackageDetail) {
            MesOqcCheck oqcCheck = oqcCheckService.getOqcCheckByOqcNo(organizeCode, oqcCheckPackageDetail.getOqcNo());
            if (null == oqcCheck) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("%s:产品条码[%s]已关联到出货检验单[%s],但是单据信息不存在", msg, productSn, oqcCheckPackageDetail.getOqcNo())
                        .build();
            }
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("%s:产品条码[%s]已关联到%s出货检验单[%s],可以扫描产品条码[%s]查询详情",
                            msg, productSn, MesPcnExtEnumUtil.OQC_TYPE.NORMAL.getValue() == oqcCheck.getOqcType() ? "" : "手动检验", oqcCheckPackageDetail.getOqcNo(), oqcCheck.getProductSn())
                    .build();
        }
    }

    private ListPager<JxOqcManageCheckDetailModel> getOqcCheckDetailList(MesOqcCheck oqcCheckDb, JxOqcManageParamModel model) {
        List<JxOqcManageCheckDetailModel> resultList = new ArrayList<>();

        if (null == oqcCheckDb) {
            model.setPager(PagerHelper.getPager(model.getPager(), MesPcnExtConstWords.ZERO));
            return new ListPager<>(resultList, model.getPager());
        }

        List<MesOqcCheckDetail> oqcCheckDetailList = getOqcCheckDetailListPager(oqcCheckDb, model);

        if (!CollectionUtils.isEmpty(oqcCheckDetailList)) {
            for (MesOqcCheckDetail oqcCheckDetail : oqcCheckDetailList) {
                if (null == oqcCheckDetail) continue;

                JxOqcManageCheckDetailModel result = new JxOqcManageCheckDetailModel();
                BeanUtils.copyProperties(oqcCheckDetail, result);
                result.setIdStr(oqcCheckDetail.getId().toString());
                result.setCheckTypeName(MesPcnExtEnumUtil.CHECK_JUDGE_TYPE.valueOfDescription(result.getCheckType()));

                resultList.add(result);
            }
        }

        return new ListPager<>(resultList, model.getPager());
    }

    private List<MesOqcCheckDetail> getOqcCheckDetailListPager(MesOqcCheck oqcCheckDb, JxOqcManageParamModel model) {
        DdlPackBean hqlPack = MesPcnExtHqlPack.getOqcCheckDetailByOqcNo(oqcCheckDb);
        model.setPager(PagerHelper.getPager(model.getPager(), oqcCheckDetailRepository.findByHqlWhereCount(hqlPack)));
        hqlPack.setOrderByStr(" order by seq asc ");
        return oqcCheckDetailRepository.findByHqlWherePage(hqlPack, model.getPager());
    }

    private JxOqcManageModel packOqcManageDataBySn(JxOqcManageModel result, List<MesOqcCheck> oqcCheckList, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb,
                                                     ListPager<JxOqcManageCheckDetailModel> oqcCheckDetailList, SxBuOqcDataModel dataFromPcn) {
        if (null == oqcCheckDb) {
            packInitResultBySn(result, dataFromPcn);
        } else {
            packFeedbackResultBySn(result, oqcCheckList, oqcCheckDb);
        }

        return commonLastPackResult(result, oqcCheckDetailList, outPutStatisticsOqcDb.getCheckLimit());
    }

    private JxOqcManageModel commonLastPackResult(JxOqcManageModel result, ListPager<JxOqcManageCheckDetailModel> oqcCheckDetailList, Double checkLimit) {
        result.setDetailList(oqcCheckDetailList);
        result.setCheckLimit(StringUtils.isEmpty(checkLimit) ? new Double(0) : checkLimit);
        result.setSnBoo(false);
        return result;
    }

    private void packInitResultBySn(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn) {
        if (!StringUtils.isEmpty(result.getSn())) {
            result.setMsg(String.format("商品码[%s]扫描成功,产品条码[%s]可生成出货检验单", result.getSn(), result.getProductSn()));
        } else {
            result.setMsg(String.format("继上次扫描,产品条码[%s]商品码[%s],可生成出货检验单", result.getProductSn(), result.getGoodsCode()));
        }

        List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList = oqcCheckService.getOqcCheckPackageDetailListByOrderNoAndWorkTime(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());

        //根据工单号查询出货检验单据主表非拆机的一条数据
        MesOqcCheck oqcCheckDb = oqcCheckService.getUnTeardownOqcCheckByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo());
        if (null == oqcCheckDb) {
            result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), true);
            result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), true);

            result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), false);
        } else {
            if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == oqcCheckDb.getOqcNoType()) {
                result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), true);
            } else {
                result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), true);
            }
        }

        result.setBatchLimit(getBatchLimitBySn(dataFromPcn.getProdMapList(), oqcCheckPackageDetailList));
    }

    private Double getBatchLimitBySn(List<Map<String, String>> prodMapList, List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList) {
        return  (CollectionUtils.isEmpty(prodMapList) || CollectionUtils.isEmpty(oqcCheckPackageDetailList))
                ? (CollectionUtils.isEmpty(prodMapList) ? new Double(0) : prodMapList.size())
                : getProdMapListSizeWithoutChecked(prodMapList, oqcCheckPackageDetailList);
    }

    private Double getProdMapListSizeWithoutChecked(List<Map<String, String>> prodMapList, List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList) {
        List<String> snList = oqcCheckPackageDetailList.stream().filter(o -> null != o).map(MesOqcCheckPackageDetail::getProductSn).collect(Collectors.toList());
        //boolean isNeedBigPackFlag = false;
        //if(!CollectionUtils.isEmpty(prodMapList.stream().filter(o -> (null != o && o.get(MesPcnExtConstWords.IS_NEED_BIG_PACK_NO) != null)).collect(Collectors.toList()))){
        //    isNeedBigPackFlag = true;
        //}
        prodMapList = prodMapList.stream().filter(o -> (null != o && !snList.contains(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

        //if(isNeedBigPackFlag){
        //    prodMapList.stream().forEach(prodMap -> {
        //        if(!prodMap.containsKey(MesPcnExtConstWords.BIG_PACKAGE_NO)) {
        //            throw ImppExceptionBuilder.newInstance()
        //                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
        //                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
        //                    .setErrorDetail("包装条码[%s]未关联大包装条码",prodMap.get(MesPcnExtConstWords.PACKAGENO))
        //                    .build();
        //        }
        //    });
        //}

        return CollectionUtils.isEmpty(prodMapList) ? new Double(0) : new Double(prodMapList.size());
    }

    private void packFeedbackResultBySn(JxOqcManageModel result, List<MesOqcCheck> oqcCheckList, MesOqcCheck oqcCheckDb) {
        commonPackFeedbackResult(result, oqcCheckDb);

        result.setBatchLimit(oqcCheckDb.getOqcQty());
        if (oqcCheckList.size() > 1) {
            result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), false);
            result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), false);
            result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), false);
            result.setChangeBoo(true);
        } else {
            if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == oqcCheckDb.getOqcNoType()) {
                result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), false);
            } else {
                result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), false);
            }
            result.getGenOqcBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), true);
        }
    }

    private void commonPackFeedbackResult(JxOqcManageModel result, MesOqcCheck oqcCheckDb) {
        result.setCurOqcNoType(oqcCheckDb.getOqcNoType());
        result.setCurOqcNoTypeName(MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckDb.getOqcNoType()));
        result.setCurSpotCheckQty(oqcCheckDb.getSpotCheckQty());
        result.setCurBatchLimit(oqcCheckDb.getOqcQty());
        result.setOqcNo(oqcCheckDb.getOqcNo());
        result.setCurCheckResultName(
                (StringUtils.isEmpty(oqcCheckDb.getCheckResult()) || StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) ?
                        null : MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()));
        result.setBadnessTypeName(badnessTypeService.getBadnessTypeName(result.getOrganizeCode(), oqcCheckDb.getBadnessTypeCode()));
        result.setBadnessClassifyName(badnessClassifyService.getBadnessClassifyName(result.getOrganizeCode(), oqcCheckDb.getBadnessTypeCode(), oqcCheckDb.getBadnessClassifyCode()));
        result.setBadnessClassifyDetailName(oqcCheckDb.getBadnessClassifyDetailName());
        result.setOqcNoType(oqcCheckDb.getOqcNoType());
        if(!StringUtils.isEmpty(result.getCategoryCode3())) result.setCategoryCode3Name(partExtService.queryPartCategoryMapByType(oqcCheckDb.getOrganizeCode(), MesPcnEnumUtil.PART_CATEGORY_TYPE.CATEGORY_THREE.getValue()).get(result.getCategoryCode3()));

        if (StringUtils.isEmpty(oqcCheckDb.getCheckResult()) || StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) {
            result.setQcBoo(true);
            result.setUnQcBoo(true);
        }
        result.setReloadCheckBoo(true);
    }

    @Override
    public JxOqcManageModel resetOqcManageData(JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验重置 --- 参数model[{}] --- 线程ID[{}]", model.toBaseString(), Thread.currentThread().getName());

        String key = new StringJoiner(MesPcnExtConstWords.COLON).add(model.getOrganizeCode()).add(MesPcnExtConstWords.OQC_MANAGE_DATA).toString();
        redisMesPcn.deleteHash(key, model.getUserId());
        return queryOqcManageData(model);
    }

    @Override
    public void updateOqcCheckDetail(JxOqcManageCheckDetailModel model, String userName) {
        if (StringUtils.isEmpty(model.getCheckValue()) && StringUtils.isEmpty(model.getCheckResult())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("请输入实际值后在空白处点击自动提交或直接点击判定结果自动提交")
                    .build();
        }

        MesOqcCheckDetail oqcCheckDetailDb = oqcCheckDetailRepository.getById(Long.parseLong(model.getIdStr()));
        if (null == oqcCheckDetailDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("检验项ID[%s]数据在系统中不存在", model.getIdStr())
                    .build();
        }

        oqcCheckDetailDb.setCheckValue(model.getCheckValue());
        oqcCheckDetailDb.setCheckResult(getCheckResult(oqcCheckDetailDb, model));
        oqcCheckDetailDb.setCheckTool(model.getCheckTool());
        oqcCheckDetailDb.setRemark(model.getRemark());
        oqcCheckDetailDb.setCheckUser(userName);
        ConvertBean.serviceModelUpdate(oqcCheckDetailDb, userName);
        oqcCheckDetailDb.setItemCheckTime(oqcCheckDetailDb.getModifyDatetime());
        oqcCheckDetailRepository.save(oqcCheckDetailDb);
    }

    private Integer getCheckResult(MesOqcCheckDetail oqcCheckDetailDb, JxOqcManageCheckDetailModel model) {
        if (!StringUtils.isEmpty(model.getCheckValue())) {
            if (MesPcnExtEnumUtil.CHECK_JUDGE_TYPE.RESULT_TYPE.getValue() == oqcCheckDetailDb.getCheckType()) {
                if (model.getCheckValue().equals(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.name())) {
                    model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.getValue());
                } else {
                    model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.NG.getValue());
                }
            } else if (MesPcnExtEnumUtil.CHECK_JUDGE_TYPE.EQUIVALENCE_TYPE.getValue() == oqcCheckDetailDb.getCheckType()) {
                if (!StringUtils.isEmpty(oqcCheckDetailDb.getStandardValue())) {
                    if (oqcCheckDetailDb.getStandardValue().equals(model.getCheckValue())) {
                        model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.getValue());
                    } else {
                        model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.NG.getValue());
                    }
                }
            } else {
                if (!StringUtils.isEmpty(oqcCheckDetailDb.getUpLimit()) || !StringUtils.isEmpty(oqcCheckDetailDb.getDownLimit())) {

                    Double upLimit = 0.0;
                    Double downLimit = 0.0;
                    Double checkValue = 0.0;

                    if (oqcCheckDetailDb.getBaseType() != MesPcnExtEnumUtil.OQC_BASE_TYPE.HEXADECIMAL.getValue()) {
                        if (!StringUtils.isEmpty(oqcCheckDetailDb.getUpLimit())) upLimit = baseConvertToDecimalism(oqcCheckDetailDb.getUpLimit(), oqcCheckDetailDb.getBaseType());
                        if (!StringUtils.isEmpty(oqcCheckDetailDb.getUpLimit())) downLimit = baseConvertToDecimalism(oqcCheckDetailDb.getDownLimit(), oqcCheckDetailDb.getBaseType());
                        if (!StringUtils.isEmpty(oqcCheckDetailDb.getCheckValue())) checkValue = baseConvertToDecimalism(oqcCheckDetailDb.getCheckValue(), oqcCheckDetailDb.getBaseType());
                    }

                    if (StringUtils.isEmpty(oqcCheckDetailDb.getDownLimit())) {

                        if (MathOperation.compareTo(checkValue, upLimit) <= 0) {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.getValue());
                        } else {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.NG.getValue());
                        }
                    } else if (StringUtils.isEmpty(oqcCheckDetailDb.getUpLimit())) {
                        if (MathOperation.compareTo(checkValue, downLimit) >= 0) {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.getValue());
                        } else {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.NG.getValue());
                        }
                    } else {
                        if (MathOperation.compareTo(checkValue, upLimit) <= 0 &&
                                MathOperation.compareTo(checkValue, downLimit) >= 0) {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.OK.getValue());
                        } else {
                            model.setCheckResult(MesPcnExtEnumUtil.OQC_CHECK_DETAIL_RESULT.NG.getValue());
                        }
                    }
                }
            }
        }
        return model.getCheckResult();
    }

    private Double baseConvertToDecimalism(String value, int baseOfValue) {
        return (MesPcnExtEnumUtil.OQC_BASE_TYPE.DECIMALISM.getValue() == baseOfValue) ? Double.valueOf(value) : Double.valueOf(Integer.parseInt(value, MesPcnExtEnumUtil.OQC_BASE_TYPE.baseOfValue(baseOfValue)));
    }

    @Override
    public void doOqcCheckDetailReload(JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验重载检验项 --- 参数model[{}] --- 线程ID[{}]", model.toBaseString(), Thread.currentThread().getName());

        //检验单据
        MesOqcCheck oqcCheckDb = getOqcCheckByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //物料
        MesPartExt partDb = getPartDb(oqcCheckDb);

        //验证产品类型是否变更
        doCheckCategoryCode3(oqcCheckDb, partDb.getCategoryCode3(), model.getUserInfo());

        //基础检验项目
        List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList = queryOqcRuleNoteDetailList(oqcCheckDb);

        //检验单据关联的检验项目
        List<MesOqcCheckDetail> oqcCheckDetailList = oqcCheckService.getOqcCheckDetailListByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //基础检验项目根据ID分组
        Map<Long, MesOqcRuleNoteDetail> oqcRuleNoteDetailMap = oqcRuleNoteDetailList.stream().filter(o -> null != o).collect(Collectors.toMap(MesOqcRuleNoteDetail::getId, o -> o));

        //删除不存在于基础检验项目中的数据,返回需要处理的检验单据关联的检验项目数据
        Map<Long, MesOqcCheckDetail> oqcCheckDetailMap = deleteDetailNotExistRuleNoteDetail(oqcRuleNoteDetailMap, oqcCheckDetailList, model.getUserInfo());

        //数据比较及入库
        saveReloadData(oqcCheckDb, oqcRuleNoteDetailMap, oqcCheckDetailMap, model.getUserInfo());

    }

    private MesOqcCheck getOqcCheckByOqcNo(String organizeCode, String oqcNo) {
        MesOqcCheck oqcCheckDb = oqcCheckService.getOqcCheckByOqcNo(organizeCode, oqcNo);
        if (null == oqcCheckDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("出货检验单据[%s]不存在,操作失败", oqcNo)
                    .build();
        }
        return oqcCheckDb;
    }

    private MesPartExt getPartDb(MesOqcCheck oqcCheckDb) {
        MesPartExt partDb = partExtService.getPartExt(oqcCheckDb.getOrganizeCode(), oqcCheckDb.getPartNo());
        if (null == partDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("出货检验单据[%s]关联的物料编号[%s]不存在,操作失败", oqcCheckDb.getOqcNo(), oqcCheckDb.getPartNo())
                    .build();
        }
        return partDb;
    }

    private void doCheckCategoryCode3(MesOqcCheck oqcCheckDb, String categoryCode3, String userInfo) {
        if (StringUtils.isEmpty(categoryCode3)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验单据[%s]关联的物料编号[%s]未配置产品类型,操作失败", oqcCheckDb.getOqcNo(), oqcCheckDb.getPartNo())
                    .build();
        }
        if (StringUtils.isEmpty(oqcCheckDb.getCategoryCode3()) || !oqcCheckDb.getCategoryCode3().equals(categoryCode3)) {
            oqcCheckDb.setCategoryCode3(categoryCode3);
            oqcCheckDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelUpdate(oqcCheckDb, userInfo);
            oqcCheckRepository.save(oqcCheckDb);
        }
    }

    private List<MesOqcRuleNoteDetail> queryOqcRuleNoteDetailList(MesOqcCheck oqcCheckDb) {
        List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList = oqcRuleNoteService.getOqcRuleNoteDetailListByOqcNoType(
                oqcCheckDb.getOrganizeCode(), oqcCheckDb.getOqcNoType(), oqcCheckDb.getPartNo(), oqcCheckDb.getCategoryCode3());
        if (CollectionUtils.isEmpty(oqcRuleNoteDetailList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验单据[%s]类型[%s]物料编码[%s]产品类型[%s],未维护出货检验项目信息",
                            oqcCheckDb.getOqcNo(), MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckDb.getOqcNoType()), oqcCheckDb.getPartNo(), oqcCheckDb.getCategoryCode3())
                    .build();
        }
        return oqcRuleNoteDetailList;
    }

    private Map<Long, MesOqcCheckDetail> deleteDetailNotExistRuleNoteDetail(Map<Long, MesOqcRuleNoteDetail> oqcRuleNoteDetailMap, List<MesOqcCheckDetail> oqcCheckDetailList, String userInfo) {
        List<MesOqcCheckDetail> needDelOqcCheckDetailList = CollectionUtils.isEmpty(oqcCheckDetailList) ? null :
                oqcCheckDetailList.stream().filter(o -> (null != o && (StringUtils.isEmpty(o.getPid()) || !oqcRuleNoteDetailMap.containsKey(o.getPid())))).collect(Collectors.toList());
        List<Long> needDelIdList = CollectionUtils.isEmpty(needDelOqcCheckDetailList) ? new ArrayList<>() :
                needDelOqcCheckDetailList.stream().filter(o -> null != o).map(MesOqcCheckDetail::getId).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(needDelOqcCheckDetailList)) {
            for (MesOqcCheckDetail oqcCheckDetail : needDelOqcCheckDetailList) {
                if (null == oqcCheckDetail) continue;

                oqcCheckDetail.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
                ConvertBean.serviceModelUpdate(oqcCheckDetail, userInfo);
                oqcCheckDetailRepository.save(oqcCheckDetail);
            }
        }

        List<MesOqcCheckDetail> needCompareOqcCheckDetailList = oqcCheckDetailList.stream().filter(o -> (null != o && !needDelIdList.contains(o.getId()))).collect(Collectors.toList());

        return CollectionUtils.isEmpty(needCompareOqcCheckDetailList) ? new HashMap<>() :
                needCompareOqcCheckDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPid()))).collect(Collectors.toMap(MesOqcCheckDetail::getPid, o -> o));

    }

    private void saveReloadData(MesOqcCheck oqcCheckDb, Map<Long, MesOqcRuleNoteDetail> oqcRuleNoteDetailMap, Map<Long, MesOqcCheckDetail> oqcCheckDetailMap, String userInfo) {
        for (Long id : oqcRuleNoteDetailMap.keySet()) {
            if (StringUtils.isEmpty(id)) continue;

            MesOqcRuleNoteDetail source = oqcRuleNoteDetailMap.get(id);
            MesOqcCheckDetail target = oqcCheckDetailMap.get(id);
            if (null == target) {
                insertOqcCheckDetail(source, oqcCheckDb, userInfo);
            } else {

                SxAttributeCompareFilterChain filterChain = new SxAttributeCompareFilterChain()
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.CHECK_ITEM))
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.STANDARD))
                        .add(new SxAttributeCompareFilterInteger(MesPcnExtConstWords.CHECK_TYPE))
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.STANDARD_VALUE))
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.UP_LIMIT))
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.DOWN_LIMT))
                        .add(new SxAttributeCompareFilterString(MesPcnExtConstWords.CHECK_TOOL))
                        .add(new SxAttributeCompareFilterDouble(MesPcnExtConstWords.SEQ));

                if (!filterChain.doFilter(source, target, MesOqcRuleNoteDetail.class, MesOqcCheckDetail.class)) saveOqcCheckDetail(source, target, userInfo);
            }
        }
    }

    private void insertOqcCheckDetail(MesOqcRuleNoteDetail source, MesOqcCheck oqcCheckDb, String userInfo) {
        MesOqcCheckDetail target = new MesOqcCheckDetail();
        BeanUtils.copyProperties(source, target, MesPcnExtConstWords.ID);
        target.setOqcNo(oqcCheckDb.getOqcNo());
        target.setWorkOrderNo(oqcCheckDb.getWorkOrderNo());
        target.setWorkOrderType(oqcCheckDb.getWorkOrderType());
        target.setWorkCenterCode(oqcCheckDb.getWorkCenterCode());
        target.setWorkTime(oqcCheckDb.getWorkTime());
        target.setShiftCode(oqcCheckDb.getShiftCode());
        target.setPackageNo(oqcCheckDb.getPackageNo());
        target.setSerialNumber(oqcCheckDb.getSerialNumber());
        target.setProductSn(oqcCheckDb.getProductSn());
        target.setPartNo(oqcCheckDb.getPartNo());
        target.setPartNameRdd(oqcCheckDb.getPartNameRdd());
        target.setCheckTime(oqcCheckDb.getCheckTime());
        target.setBaseType(source.getBaseType());
        target.setPid(source.getId());
        target.setOrganizeCode(oqcCheckDb.getOrganizeCode());
        ConvertBean.serviceModelInitialize(target, userInfo);
        oqcCheckDetailRepository.insert(target);
    }

    private void saveOqcCheckDetail(MesOqcRuleNoteDetail source, MesOqcCheckDetail target, String userInfo) {
        target.setSeq(StringUtils.isEmpty(source.getSeq()) ? new Double(0) : source.getSeq());
        target.setCheckItem(source.getCheckItem());
        target.setStandard(source.getStandard());
        target.setCheckType(source.getCheckType());
        target.setStandardValue(source.getStandardValue());
        target.setUpLimit(source.getUpLimit());
        target.setDownLimit(source.getDownLimit());
        target.setCheckTool(source.getCheckTool());
        target.setRemark(null);
        target.setCheckValue(null);
        target.setCheckResult(null);
        ConvertBean.serviceModelUpdate(target, userInfo);
        oqcCheckDetailRepository.save(target);
    }

    @Override
    public void insertOqcManageDataNormal(JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验生成检验单 --- 参数model[{}] --- 线程ID[{}]", model.toString(), Thread.currentThread().getName());

        String key = new StringJoiner(MesPcnExtConstWords.COLON).add(model.getOrganizeCode()).add(MesPcnExtConstWords.OQC_MANAGE_DATA).toString();

        Object lastScanInfo = redisMesPcn.getHash(key, model.getUserId());

        log.info("MES_PCN出货检验生成检验单 --- lastScanInfo[{}] --- 线程ID[{}]", lastScanInfo, Thread.currentThread().getName());

        JxOqcManageModel result = new JxOqcManageModel(model.getOrganizeCode(), model.getUserId(), model.getUserInfo(), model.getOqcNoType());

        //初始化缓存数据
        initCachedData(result, lastScanInfo);

        log.info("MES_PCN出货检验生成检验单 --- result[{}] --- 线程ID[{}]", result.toBaseString(), Thread.currentThread().getName());

        //验证缓存数据是否完整
        checkCachedDataIsWhole(result);

        //组件
        if (!StringUtils.isEmpty(result.getIdStr())) insertOqcManageDataNormalById(result, model);

        //成品
        if (!StringUtils.isEmpty(result.getProductSn())) insertOqcManageDataNormalBySn(result, model);
    }

    private void checkCachedDataIsWhole(JxOqcManageModel result) {
        if (StringUtils.isEmpty(result.getIdStr()) && (StringUtils.isEmpty(result.getProductSn()) ||
                StringUtils.isEmpty(result.getGoodsCode()))) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:当前用户缓存数据已经不存在,请点击重置")
                    .build();
        }
    }

    private void insertOqcManageDataNormalById(JxOqcManageModel result, JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验生成检验单 --- 组件出货检验 --- START --- 线程ID[{}]", Thread.currentThread().getName());

        //组件不拆机
        checkOqcNoTypeById(result.getOqcNoType());

        //产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcById(result, "生成检验单");

        //验证物料
        MesPartExt partDb = checkPartValidById(result, outPutStatisticsOqcDb.getPartNo(), "生成检验单");

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModel(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getExecClass());

        log.info("MES_PCN出货检验主数据 --- 组件出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //数据组合
        packJxOqcManageModel(result, dataFromPcn, partDb);

        //基础检验项目
        List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList = queryOqcRuleNoteDetailListByGenOqc(result);

        //获取上个检验单据
        MesOqcCheck oqcCheckDb = oqcCheckService.getZjOqcCheckByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());

        //验证检验类型与上次检验结果
        checkOqcNoTypeAndLastCheckById(result, oqcCheckDb);

        //验证抽检数量与抽检范围
        checkSpotCheckQtyAndBatchLimit(result, model, outPutStatisticsOqcDb);

        //保存检验单数据
        saveOqcDataById(result, outPutStatisticsOqcDb, oqcRuleNoteDetailList);

        log.info("MES_PCN出货检验生成检验单 --- 组件出货检验 --- SUCCESS --- 线程ID[{}]", Thread.currentThread().getName());
    }

    private void checkOqcNoTypeById(Integer oqcNoType) {
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() == oqcNoType) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:组件抽检不支持拆机检验")
                    .build();
        }
    }

    private void checkOqcNoTypeAndLastCheckById(JxOqcManageModel result, MesOqcCheck oqcCheckDb) {
        if (null != oqcCheckDb) {
            if (StringUtils.isEmpty(oqcCheckDb.getCheckResult()) || StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("生成检验单:组件抽检上个检验单[%s]结果未处理,操作失败", oqcCheckDb.getOqcNo())
                        .build();
            }
            if (oqcCheckDb.getOqcNoType().compareTo(result.getOqcNoType()) != 0) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("生成检验单:[总检验结果]传参ID[%s]数据对应的生产工单[%s]已经存在%s类型的检验单,不能再生成%s类型的检验单,操作失败",
                                result.getIdStr(), result.getWorkOrderNo(), MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckDb.getOqcNoType()),
                                MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(result.getOqcNoType()))
                        .build();
            }
        }
    }

    private void checkSpotCheckQtyAndBatchLimit(JxOqcManageModel result, JxOqcManageParamModel model, MesOutPutStatisticsOqc outPutStatisticsOqcDb) {
        if (MathOperation.compareTo(model.getSpotCheckQty(), new Double(1)) < 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:组件抽检数量必须大于0,操作失败")
                    .build();
        }
        if (MathOperation.compareTo(model.getBatchLimit(), new Double(1)) < 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:组件抽检批次范围必须大于0,操作失败")
                    .build();
        }
        if (MathOperation.compareTo(model.getSpotCheckQty(), model.getBatchLimit()) > 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:组件抽检数量[%s]不能超过抽检批次范围[%s],操作失败", model.getSpotCheckQty(), model.getBatchLimit())
                    .build();
        }

        //剩余未检数量
        Double unCheckedQty = MathOperation.sub(result.getCompleteQty(), StringUtils.isEmpty(outPutStatisticsOqcDb.getCheckLimit()) ? new Double(0) : outPutStatisticsOqcDb.getCheckLimit());

        if (MathOperation.compareTo(unCheckedQty, model.getBatchLimit()) < 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:[总检验结果]传参ID[%s]数据对应的生产工单[%s]当前提交的抽检范围[%s]超过当前剩余的未抽检范围[%s]",
                            result.getIdStr(), result.getWorkOrderNo(), model.getBatchLimit(), unCheckedQty)
                    .build();
        }
        result.setSpotCheckQty(model.getSpotCheckQty());
        result.setBatchLimit(model.getBatchLimit());
    }

    private void saveOqcDataById(JxOqcManageModel result, MesOutPutStatisticsOqc outPutStatisticsOqcDb, List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList) {

        //检验单据
        MesOqcCheck oqcCheck = insetOqcCheckById(result);

        //检验项目明细
        insetOqcCheckDetail(oqcCheck, oqcRuleNoteDetailList);

        //保存产量抽检范围
        saveOutPutStatisticsOqc(oqcCheck, outPutStatisticsOqcDb);
    }

    private MesOqcCheck insetOqcCheckById(JxOqcManageModel result) {
        MesOqcCheck oqcCheck = new MesOqcCheck();
        BeanUtils.copyProperties(result, oqcCheck);
        oqcCheck.setOqcNo(getOqcNo(result.getUserInfo(), result.getOrganizeCode()));
        oqcCheck.setQty(result.getPlanQty());
        oqcCheck.setSnType(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getValue());
        oqcCheck.setOqcType(MesPcnExtEnumUtil.OQC_TYPE.NORMAL.getValue());
        oqcCheck.setOqcQty(result.getBatchLimit());
        oqcCheck.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(oqcCheck, result.getUserInfo());
        oqcCheckRepository.insert(oqcCheck);
        return oqcCheck;
    }

    private void insertOqcManageDataNormalBySn(JxOqcManageModel result, JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验生成检验单 --- 成品出货检验 --- START --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModel(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getExecClass());

        log.info("MES_PCN出货检验生成检验单 --- 成品出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //验证物料
        MesPartExt partDb = genOqcCheckPartValidBySn(result, dataFromPcn);

        //数据组合
        packJxOqcManageModel(result, dataFromPcn, partDb);

        //验证条码工单是否变更
        checkWorkOrderNoIsChanged(model.getWorkOrderNo(), result);

        //产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcBySn(result, "生成检验单");

        //基础检验项目
        List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList = queryOqcRuleNoteDetailListByGenOqc(result);

        log.info("MES_PCN出货检验生成检验单 --- 成品出货检验 --- result[{}] --- 线程ID[{}]", result.toString(), Thread.currentThread().getName());

        //获取出货检验单据集合
        List<MesOqcCheck> oqcCheckList = oqcCheckService.getOqcCheckListByProductSn(result.getOrganizeCode(), result.getWorkOrderNo(), result.getProductSn());

        //验证当前条码是否可以生成单据
        checkSnIsAllowGenOqc(result, oqcCheckList);

        //验证非拆机检验类型时产量是否有余
        checkOutPutIsAllowGenOqc(result, outPutStatisticsOqcDb);

        log.info("MES_PCN出货检验生成检验单 --- 成品出货检验 --- 数据入库 --- 线程ID[{}]", Thread.currentThread().getName());

        //保存检验单数据
        saveOqcDataBySn(result, dataFromPcn, outPutStatisticsOqcDb, oqcCheckList, oqcRuleNoteDetailList);

        log.info("MES_PCN出货检验生成检验单 --- 成品出货检验 --- SUCCESS --- 线程ID[{}]", Thread.currentThread().getName());

    }

    private MesPartExt genOqcCheckPartValidBySn(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn) {
        MesPartExt partDb = partExtService.getPartExt(result.getOrganizeCode(), dataFromPcn.getPartNo());
        if (null == partDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的物料编码[%s]不存在,请点击重置", result.getProductSn(), dataFromPcn.getPartNo())
                    .build();
        }
        if (StringUtils.isEmpty(partDb.getCategoryCode3()) || !partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的物料编码[%s]的产品类型不是成品,请点击重置", result.getProductSn(), dataFromPcn.getPartNo())
                    .build();
        }

        if (StringUtils.isEmpty(partDb.getIsOqc()) || CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() == partDb.getIsOqc()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的物料编码[%s]不支持出货检验,请点击重置", result.getProductSn(), dataFromPcn.getPartNo())
                    .build();
        }
        if (StringUtils.isEmpty(partDb.getGoodsCode())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的物料编码[%s]未维护商品码,请点击重置", result.getProductSn(), dataFromPcn.getPartNo())
                    .build();
        }
        if (!partDb.getGoodsCode().equals(result.getGoodsCode())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的物料编码[%s]当前维护的商品码[%s]与上次扫描的商品码[%s]不一致,请点击重置",
                            result.getProductSn(), dataFromPcn.getPartNo(), partDb.getGoodsCode(), result.getGoodsCode())
                    .build();
        }
        return partDb;
    }

    private void checkWorkOrderNoIsChanged(String workOrderNo, JxOqcManageModel result) {
        if (!workOrderNo.equals(result.getWorkOrderNo())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]已经重新关联返工工单号[%s],请点击重置", result.getProductSn(), result.getWorkOrderNo())
                    .build();
        }
    }

    private List<MesOqcRuleNoteDetail> queryOqcRuleNoteDetailListByGenOqc(JxOqcManageModel result) {
        List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList = oqcRuleNoteService.getOqcRuleNoteDetailListByOqcNoType(
                result.getOrganizeCode(), result.getOqcNoType(), result.getPartNo(), result.getCategoryCode3());
        if (CollectionUtils.isEmpty(oqcRuleNoteDetailList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("检验类型[%s]物料编码[%s]产品类型[%s],未维护出货检验项目信息",
                            MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(result.getOqcNoType()), result.getPartNo(), result.getCategoryCode3())
                    .build();
        }
        return oqcRuleNoteDetailList;
    }

    private void checkSnIsAllowGenOqc(JxOqcManageModel result, List<MesOqcCheck> oqcCheckList) {

        //验证是否已关联检验单
        if (CollectionUtils.isEmpty(oqcCheckList)) checkSnIsChecked(result.getOrganizeCode(), result.getWorkOrderNo(), result.getProductSn(), "生成检验单");

        //根据工单号查询出货检验单据主表非拆机的一条数据
        MesOqcCheck oqcCheckDb = oqcCheckService.getUnTeardownOqcCheckByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo());

        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() == result.getOqcNoType()) {
            if (CollectionUtils.isEmpty(oqcCheckList)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("生成检验单:产品条码[%s]还未生成%s类型的检验单,操作失败",
                                result.getProductSn(), null == oqcCheckDb ? "日常检验或空洞检验" : MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckDb.getOqcNoType()))
                        .build();
            } else {
                if (oqcCheckList.size() > 1) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("生成检验单:产品条码[%s]已存在拆机检验类型的检验单,操作失败", result.getProductSn())
                            .build();
                }
            }
        } else {
            if (oqcCheckList.size() > 0) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("生成检验单:产品条码[%s]已存在%s类型的检验单,操作失败",
                                result.getProductSn(), MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckList.get(0).getOqcNoType()))
                        .build();
            } else {
                if (null != oqcCheckDb && oqcCheckDb.getOqcNoType().compareTo(result.getOqcNoType()) != 0) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("生成检验单:产品条码[%s]不能生成%s类型的检验单,操作失败",
                                    result.getProductSn(), MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(result.getOqcNoType()))
                            .build();
                }
            }

        }
    }

    private void checkOutPutIsAllowGenOqc(JxOqcManageModel result, MesOutPutStatisticsOqc outPutStatisticsOqcDb) {
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() != result.getOqcNoType()) {
            if (MathOperation.compareTo(result.getCompleteQty(), StringUtils.isEmpty(outPutStatisticsOqcDb.getCheckLimit()) ? new Double(0) : outPutStatisticsOqcDb.getCheckLimit()) <= 0) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("生成检验单:产品条码[%s]当前剩余未抽检批次范围为[0],操作失败", result.getProductSn())
                        .build();
            }
        }
    }

    private void saveOqcDataBySn(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn, MesOutPutStatisticsOqc outPutStatisticsOqcDb,
                                 List<MesOqcCheck> oqcCheckList, List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList) {
        //获取待抽检条码
        List<Map<String, String>> prodMapList = getProdMapList(result, dataFromPcn);

        //检验单据
        MesOqcCheck oqcCheck = insetOqcCheckBySn(result, prodMapList, oqcCheckList);

        //检验项目明细
        insetOqcCheckDetail(oqcCheck, oqcRuleNoteDetailList);

        //检验条码明细
        insetOqcCheckPackageDetail(oqcCheck, prodMapList);

        //保存产量抽检范围
        saveOutPutStatisticsOqc(oqcCheck, outPutStatisticsOqcDb);

    }

    private List<Map<String, String>> getProdMapList(JxOqcManageModel result, SxBuOqcDataModel dataFromPcn) {
        List<Map<String, String>> prodMapList = null;
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() != result.getOqcNoType()) {
            //获取当前班次作业时间内已经关联出货检验的条码集合
            List<String> snList = getOqcCheckedSnList(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());

            //获取当前班次作业时间内未关联出货检验的条码集合
            prodMapList = dataFromPcn.getProdMapList();
            prodMapList = (CollectionUtils.isEmpty(prodMapList) || CollectionUtils.isEmpty(snList)) ? prodMapList :
                    prodMapList.stream().filter(o -> (null != o && !snList.contains(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

            checkProdMapListBySn(prodMapList, result);
        }
        return prodMapList;
    }

    private List<String> getOqcCheckedSnList(String organizeCode, String workOrderNo, String workTime, String shiftCode) {
        List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList = oqcCheckService.getOqcCheckPackageDetailListByOrderNoAndWorkTime(organizeCode, workOrderNo, workTime, shiftCode);
        return CollectionUtils.isEmpty(oqcCheckPackageDetailList) ? null :
                oqcCheckPackageDetailList.stream().filter(o -> null != o).map(MesOqcCheckPackageDetail::getProductSn).collect(Collectors.toList());
    }

    private void checkProdMapListBySn(List<Map<String, String>> prodMapList, JxOqcManageModel result) {
        if (CollectionUtils.isEmpty(prodMapList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:产品条码[%s]关联的生产工单[%s]下已无可抽检的产品,请点击重置", result.getProductSn(), result.getWorkOrderNo())
                    .build();
        }
        Optional<Map<String, String>> snOp = prodMapList.stream().filter(o -> (null != o && result.getProductSn().equals(o.get(MesPcnExtConstWords.PRODUCT_SN)))).findFirst();
        if (null == snOp || !snOp.isPresent()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生成检验单:工单[%s]筛除已经抽检完成的批次条码后不包含当前扫描的产品条码[%s],操作失败", result.getWorkOrderNo(), result.getProductSn())
                    .build();
        }

        prodMapList = prodMapList.stream().filter(o -> (null != o && !result.getProductSn().equals(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(prodMapList)) prodMapList = new ArrayList<>();

        prodMapList.add(0, snOp.get());
    }

    private List<Map<String, String>> checkProdMapListBySn4CheckUnqualified(List<Map<String, String>> prodMapList, JxOqcManageModel result, SxBuOqcDataModel dataFromPcn) {
        if (CollectionUtils.isEmpty(prodMapList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("检验单不合格:产品条码[%s]关联的生产工单[%s]下已无可抽检的产品,操作失败", result.getProductSn(), result.getWorkOrderNo())
                    .build();
        }
        Optional<Map<String, String>> snOp = prodMapList.stream().filter(o -> (null != o && result.getProductSn().equals(o.get(MesPcnExtConstWords.PRODUCT_SN)))).findFirst();
        if (null == snOp || !snOp.isPresent()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("检验单不合格:工单[%s]筛除已经抽检完成的批次条码后不包含当前扫描的产品条码[%s],操作失败", result.getWorkOrderNo(), result.getProductSn())
                    .build();
        }

        if (!snOp.get().get(MesPcnExtConstWords.WORK_ORDER_NO).equals(result.getWorkOrderNo())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("检验单不合格:工单[%s]当前扫描条码[%s]工单号与当前工单号不一致,操作失败", result.getWorkOrderNo(), result.getProductSn())
                    .build();
        }

        if ((!dataFromPcn.getShiftCode().equals(result.getShiftCode())) || (!dataFromPcn.getWorkTime().equals(result.getWorkTime()))) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("检验单不合格:当前扫描条码[%s]作业时间[%s]班次代码[%s]与检验单[%s]作业时间[%s]班次代码[%s]不一致,操作失败", result.getProductSn(), dataFromPcn.getWorkTime(), dataFromPcn.getShiftCode(), result.getOqcNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }

        prodMapList = prodMapList.stream().filter(o -> (null != o && !result.getProductSn().equals(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

        prodMapList = prodMapList.stream().filter(o -> (null != o &&
                snOp.get().get(MesPcnExtConstWords.OUT_WC_TIME).compareTo(o.get(MesPcnExtConstWords.OUT_WC_TIME)) >= 0)
                ).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(prodMapList)) prodMapList = new ArrayList<>();

        prodMapList.add(0, snOp.get());

        return prodMapList;
    }

    private MesOqcCheck insetOqcCheckBySn(JxOqcManageModel result, List<Map<String, String>> prodMapList, List<MesOqcCheck> oqcCheckList) {
        MesOqcCheck oqcCheck = new MesOqcCheck();
        BeanUtils.copyProperties(result, oqcCheck);
        oqcCheck.setOqcNo(getOqcNo(result.getUserInfo(), result.getOrganizeCode()));
        oqcCheck.setQty(result.getPlanQty());
        oqcCheck.setSnType(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue());
        oqcCheck.setOqcType(MesPcnExtEnumUtil.OQC_TYPE.NORMAL.getValue());
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() != result.getOqcNoType()) {
            oqcCheck.setOqcQty(new Double(prodMapList.size()));
        } else {
            oqcCheck.setOqcQty(oqcCheckList.get(0).getOqcQty());
        }
        oqcCheck.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(oqcCheck, result.getUserInfo());
        oqcCheckRepository.insert(oqcCheck);

        return oqcCheck;
    }

    private void insetOqcCheckDetail(MesOqcCheck oqcCheck, List<MesOqcRuleNoteDetail> oqcRuleNoteDetailList) {
        for (MesOqcRuleNoteDetail oqcRuleNoteDetail : oqcRuleNoteDetailList) {
            if (null == oqcRuleNoteDetail) continue;

            MesOqcCheckDetail oqcCheckDetail = new MesOqcCheckDetail();
            BeanUtils.copyProperties(oqcCheck, oqcCheckDetail, MesPcnExtConstWords.ID);
            oqcCheckDetail.setSeq(oqcRuleNoteDetail.getSeq());
            oqcCheckDetail.setPid(oqcRuleNoteDetail.getId());
            oqcCheckDetail.setCheckItem(oqcRuleNoteDetail.getCheckItem());
            oqcCheckDetail.setStandard(oqcRuleNoteDetail.getStandard());
            oqcCheckDetail.setCheckType(oqcRuleNoteDetail.getCheckType());
            oqcCheckDetail.setStandardValue(oqcRuleNoteDetail.getStandardValue());
            oqcCheckDetail.setCheckTool(oqcRuleNoteDetail.getCheckTool());
            oqcCheckDetail.setBaseType(oqcRuleNoteDetail.getBaseType());
            oqcCheckDetail.setUpLimit(oqcRuleNoteDetail.getUpLimit());
            oqcCheckDetail.setDownLimit(oqcRuleNoteDetail.getDownLimit());
            oqcCheckDetailRepository.insert(oqcCheckDetail);
        }
    }

    private void insetOqcCheckPackageDetail(MesOqcCheck oqcCheck, List<Map<String, String>> prodMapList) {
        if (CollectionUtils.isEmpty(prodMapList)) {
            return;
        }
        for (Map<String, String> snMap : prodMapList) {
            if (CollectionUtils.isEmpty(snMap)) {
                continue;
            }
            MesOqcCheckPackageDetail oqcCheckPackageDetail = new MesOqcCheckPackageDetail();
            BeanUtils.copyProperties(oqcCheck, oqcCheckPackageDetail, MesPcnExtConstWords.ID, MesPcnExtConstWords.PRODUCT_SN, MesPcnExtConstWords.PACKAGENO);
            oqcCheckPackageDetail.setSerialNumber(snMap.get(MesPcnExtConstWords.PRODUCT_SN));
            oqcCheckPackageDetail.setProductSn(snMap.get(MesPcnExtConstWords.PRODUCT_SN));
            oqcCheckPackageDetail.setPackageNo(snMap.get(MesPcnExtConstWords.PACKAGENO));
            oqcCheckPackageDetail.setOutWorkCenterTime(snMap.get(MesPcnExtConstWords.OUT_WORK_CENTER_TIME));
            oqcCheckPackageDetail.setCheckResult(oqcCheck.getCheckResult());
            oqcCheckPackageDetail.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            oqcCheckPackageDetailRepository.insert(oqcCheckPackageDetail);

            insertOqcCheckPackageDetailTravel(oqcCheckPackageDetail);

            insertOqcCheckPackageIf(oqcCheckPackageDetail, snMap.get(MesPcnExtConstWords.BIG_PACKAGE_NO));
        }

    }

    private void saveOutPutStatisticsOqc(MesOqcCheck oqcCheck, MesOutPutStatisticsOqc outPutStatisticsOqcDb) {
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() != oqcCheck.getOqcNoType()) {
            outPutStatisticsOqcDb.setCheckLimit(
                    MathOperation.add(StringUtils.isEmpty(outPutStatisticsOqcDb.getCheckLimit()) ? new Double(0) : outPutStatisticsOqcDb.getCheckLimit(), oqcCheck.getOqcQty()));
            outPutStatisticsOqcDb.setSpotCheckQty(
                    MathOperation.add(StringUtils.isEmpty(outPutStatisticsOqcDb.getSpotCheckQty()) ? new Double(0) : outPutStatisticsOqcDb.getSpotCheckQty(), oqcCheck.getSpotCheckQty()));
            ConvertBean.serviceModelUpdate(outPutStatisticsOqcDb, oqcCheck.getModifyUser());
            outPutStatisticsOqcDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            outPutStatisticsOqcRepository.save(outPutStatisticsOqcDb);
        }
    }

    private String getOqcNo(String userName, String organizeCode) {
        BaseResultBean oneCodeResult = syncFuncService.syncSerialNo(new GenSerialNoModel(MesPcnExtEnumUtil.COMMON_SN.OQC_NO.getCode()), userName, organizeCode, 1);
        if (oneCodeResult != null && oneCodeResult.isSuccess()) {
            return oneCodeResult.getResultList().get(0).toString();
        } else {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.CLOUD_CALL_EXCEPTION.getCode())
                    .setErrorDetail("生成唯一单号失败")
                    .build();
        }
    }

    @Override
    public void updateOqcManageDataNormal(JxOqcManageParamModel model) {
        log.info("MES_PCN出货检验单据确认 --- 参数model[{}] --- 线程ID[{}]", model.toString(), Thread.currentThread().getName());

        //检验单据
        MesOqcCheck oqcCheckDb = getOqcCheckByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //验证单据是否已经有结果
        checkOqcCheckIsHasResult(oqcCheckDb);

        //检验条码明细
        List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList = oqcCheckService.getOqcCheckPackageDetailListByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //检验条码中间表明细
        List<MesOqcCheckPackageIf> oqcCheckPackageIfList = oqcCheckService.getOqcCheckPackageIfListByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //检验项目明细
        List<MesOqcCheckDetail> oqcCheckDetailList = oqcCheckService.getOqcCheckDetailListByOqcNo(model.getOrganizeCode(), model.getOqcNo());

        //保存单据结果
        saveOqcCheckResult(oqcCheckDb, model);

        //保存检验项目明细
        saveOqcCheckDetailList(oqcCheckDetailList, oqcCheckDb);

        //保存检验条码明细及中间表, 插入履历
        saveOqcCheckPackageDetailList(oqcCheckPackageDetailList, oqcCheckDb, oqcCheckPackageIfList);

        //检验不合格关联未关联检验单条码
        unqualifiedQueryUnCorrelatedSn(oqcCheckDb, model, oqcCheckPackageDetailList);

    }

    private void unqualifiedQueryUnCorrelatedSn(MesOqcCheck oqcCheckDb, JxOqcManageParamModel paramModel, List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList) {

        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() == oqcCheckDb.getOqcNoType() || oqcCheckDb.getCheckResult() == MesPcnExtEnumUtil.OQC_CHECK_RESULT.QUALIFIED.getValue() || StringUtils.isEmpty(paramModel.getSn())) {
            return;
        }

        JxOqcManageModel result = new JxOqcManageModel(oqcCheckDb.getOrganizeCode(), paramModel.getUserId(), paramModel.getUserInfo(), oqcCheckDb.getOqcNoType(), paramModel.getSn(), paramModel.getWorkOrderNo(), oqcCheckDb.getShiftCode(), oqcCheckDb.getWorkTime(), oqcCheckDb.getOqcNo());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModel(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getExecClass());

        //获取当前班次作业时间内已经关联出货检验的条码集合
        List<String> snList = CollectionUtils.isEmpty(oqcCheckPackageDetailList) ? null :
                oqcCheckPackageDetailList.stream().filter(o -> null != o).map(MesOqcCheckPackageDetail::getProductSn).collect(Collectors.toList());

        //获取当前班次作业时间内未关联出货检验的条码集合
        List<Map<String, String>> prodMapList = dataFromPcn.getProdMapList();
        prodMapList = (CollectionUtils.isEmpty(prodMapList) || CollectionUtils.isEmpty(snList)) ? prodMapList :
                prodMapList.stream().filter(o -> (null != o && !snList.contains(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

        prodMapList = checkProdMapListBySn4CheckUnqualified(prodMapList, result, dataFromPcn);

        //获取产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqc = outPutStatisticsOqcRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.WORK_TIME, MesPcnExtConstWords.SHIFT_CODE},
                new Object[]{result.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode()});
        if (null == outPutStatisticsOqc) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]不存在产量统计出货检验信息", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }

        //检验条码明细
        insetOqcCheckPackageDetail(oqcCheckDb, prodMapList);

        oqcCheckDb.setOqcQty(MathOperation.add(oqcCheckDb.getOqcQty(), new Double(prodMapList.size())));
        oqcCheckDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelUpdate(oqcCheckDb, result.getUserInfo());
        oqcCheckRepository.save(oqcCheckDb);

        outPutStatisticsOqc.setCheckLimit(MathOperation.add(outPutStatisticsOqc.getCheckLimit(), new Double(prodMapList.size())));
        ConvertBean.serviceModelUpdate(outPutStatisticsOqc, result.getUserInfo());
        outPutStatisticsOqcRepository.save(outPutStatisticsOqc);


    }

    private void checkOqcCheckIsHasResult(MesOqcCheck oqcCheckDb) {
        if (!StringUtils.isEmpty(oqcCheckDb.getCheckResult()) && !StringUtils.isEmpty(MesPcnExtEnumUtil.CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验单据[%s]的结果已被用户[%s]处理为[%s],操作失败",
                            oqcCheckDb.getOqcNo(), oqcCheckDb.getModifyUser(), MesPcnExtEnumUtil.CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))
                    .build();
        }
    }

    private void saveOqcCheckResult(MesOqcCheck oqcCheckDb, JxOqcManageParamModel model) {
        oqcCheckDb.setCheckResult(model.getCheckResult());
        oqcCheckDb.setCheckUser(model.getUserInfo());
        oqcCheckDb.setBadnessTypeCode(model.getBadnessTypeCode());
        oqcCheckDb.setBadnessClassifyCode(model.getBadnessClassifyCode());
        oqcCheckDb.setBadnessClassifyDetailCode(model.getBadnessClassifyDetailCode());
        oqcCheckDb.setBadnessClassifyDetailName(model.getBadnessClassifyDetailName());
        ConvertBean.serviceModelUpdate(oqcCheckDb, model.getUserInfo());
        oqcCheckDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        oqcCheckDb.setCheckTime(oqcCheckDb.getModifyDatetime());
        oqcCheckRepository.save(oqcCheckDb);
    }

    private void saveOqcCheckPackageDetailList(List<MesOqcCheckPackageDetail> oqcCheckPackageDetailList, MesOqcCheck oqcCheckDb, List<MesOqcCheckPackageIf> oqcCheckPackageIfList) {
        if (CollectionUtils.isEmpty(oqcCheckPackageDetailList)) {
            return;
        }
        for (MesOqcCheckPackageDetail oqcCheckPackageDetail : oqcCheckPackageDetailList) {
            if (null == oqcCheckPackageDetail) continue;

            oqcCheckPackageDetail.setCheckResult(oqcCheckDb.getCheckResult());
            oqcCheckPackageDetail.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelUpdate(oqcCheckPackageDetail, oqcCheckDb.getModifyUser());
            oqcCheckPackageDetailRepository.save(oqcCheckPackageDetail);

            insertOqcCheckPackageDetailTravel(oqcCheckPackageDetail);

        }

        for (MesOqcCheckPackageIf oqcCheckPackageIf: oqcCheckPackageIfList) {
            if (null == oqcCheckPackageIf) continue;

            oqcCheckPackageIf.setCheckResult(oqcCheckDb.getCheckResult());
            oqcCheckPackageIf.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            oqcCheckPackageIf.setSystemSyncStatus2(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelUpdate(oqcCheckPackageIf, oqcCheckDb.getModifyUser());
            oqcCheckPackageIfRepository.save(oqcCheckPackageIf);
        }

    }

    private void insertOqcCheckPackageDetailTravel(MesOqcCheckPackageDetail oqcCheckPackageDetail) {
        MesOqcCheckPackageDetailTravel travel = new MesOqcCheckPackageDetailTravel();
        BeanUtils.copyProperties(oqcCheckPackageDetail, travel, MesPcnExtConstWords.ID);
        travel.setPid(oqcCheckPackageDetail.getId());
        oqcCheckPackageDetailTravelRepository.insert(travel);
    }


    private MesOqcCheckPackageIf insertOqcCheckPackageIf(MesOqcCheckPackageDetail oqcCheckPackageDetail, String bigPackageNo) {
        MesOqcCheckPackageIf checkPackageIf = new MesOqcCheckPackageIf();
        BeanUtils.copyProperties(oqcCheckPackageDetail, checkPackageIf, MesPcnExtConstWords.ID);
        checkPackageIf.setFinalPackageNo(StringUtils.isEmpty(bigPackageNo) ? oqcCheckPackageDetail.getPackageNo() : bigPackageNo);
        return oqcCheckPackageIfRepository.insert(checkPackageIf);
    }

    private void saveOqcCheckDetailList(List<MesOqcCheckDetail> oqcCheckDetailList, MesOqcCheck oqcCheckDb) {
        if (CollectionUtils.isEmpty(oqcCheckDetailList)) return;

        for (MesOqcCheckDetail oqcCheckDetail : oqcCheckDetailList) {
            if (null == oqcCheckDetail) continue;

            oqcCheckDetail.setCheckTime(oqcCheckDb.getCheckTime());
            ConvertBean.serviceModelUpdate(oqcCheckDetail, oqcCheckDb.getModifyUser());
            oqcCheckDetailRepository.save(oqcCheckDetail);
        }
    }

    @Override
    public JxOqcManageManualModel queryOqcManageDataManual(JxOqcManageManualModel result) {
        log.info("MES_PCN出货检验手动检验查询 --- 参数model[{}] --- 线程ID[{}]", result.toString(), Thread.currentThread().getName());

        //验证物料
        MesPartExt partDb = checkPartValidByManual(result);

        //验证产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqc = getOutPutStatisticsOqcByManual(result);

        log.info("MES_PCN出货检验手动检验查询 --- {}出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]",
                partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? "成品" : "组件", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModelByManual(result, getOqcManageDataManualClass(partDb.getCategoryCode3()));

        log.info("MES_PCN出货检验手动检验查询 --- {}出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]",
                partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? "成品" : "组件", dataFromPcn.toString(), Thread.currentThread().getName());

        //验证通过产量OQC的PID查询到的PCN的工单生产日期班次信息是否与界面信息一致
        checkDataFromPcnIsValid(result, dataFromPcn);

        //获取上个检验单
        MesOqcCheck oqcCheckDb = getOqcCheckByManual(result);

        //封装数据
        packResultByManual(result, oqcCheckDb, dataFromPcn, outPutStatisticsOqc, partDb);

        log.info("MES_PCN出货检验手动检验查询 --- {}出货检验 --- 上个检验单据[{}] --- END --- 线程ID[{}]",
                partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? "成品" : "组件", result.getOqcNo(), Thread.currentThread().getName());

        return result;

    }

    private MesPartExt checkPartValidByManual(JxOqcManageManualModel result) {
        MesPartExt partDb = partExtService.getPartExt(result.getOrganizeCode(), result.getPartNo());
        if (null == partDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("手动检验:物料编码[%s]不存在", result.getPartNo())
                    .build();
        }

        if (StringUtils.isEmpty(partDb.getCategoryCode3())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("手动检验:物料编码[%s]未维护物料分类3,无法区分该物料是成品还是组件", result.getPartNo())
                    .build();
        }

        if (StringUtils.isEmpty(partDb.getIsOqc()) || CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() == partDb.getIsOqc()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:物料编码[%s]不支持出货检验", result.getPartNo())
                    .build();
        }
        return partDb;
    }

    private MesOutPutStatisticsOqc getOutPutStatisticsOqcByManual(JxOqcManageManualModel result) {
        MesOutPutStatisticsOqc outPutStatisticsOqc = outPutStatisticsOqcRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.WORK_TIME, MesPcnExtConstWords.SHIFT_CODE},
                new Object[]{result.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode()});
        if (null == outPutStatisticsOqc) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]不存在产量统计出货检验信息", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }
        if (MathOperation.compareTo(StringUtils.isEmpty(outPutStatisticsOqc.getCheckLimit()) ? new Double(0) : outPutStatisticsOqc.getCheckLimit(), outPutStatisticsOqc.getPlanQty()) >= 0) {
            //当前工单只有一条产量的情况下
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]已无可抽检产品", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }

        result.setIdStr(outPutStatisticsOqc.getPid().toString());

        return outPutStatisticsOqc;
    }

    private String getOqcManageDataManualClass(String categoryCode3) {
        return categoryCode3.equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getQueryClass2() : MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getQueryClass2();
    }

    private SxBuOqcDataModel getBuOqcDataModelByManual(JxOqcManageManualModel result, String clazz) {

        Map<String, Object> params = new HashMap<>();
        params.put(MesPcnExtConstWords.ORGANIZE_CODE, result.getOrganizeCode());
        params.put(MesPcnExtConstWords.CLASS_NAME, clazz);
        params.put(MesPcnExtConstWords.VALUE, result.getIdStr());
        if (clazz.equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getQueryClass2()) ||
                clazz.equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getExecClass2())) {
            params.put(MesPcnExtConstWords.DATA_TYPE, MesPcnExtEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        }

        return qmsHttpRequestService.queryBuQmsOqcManageData(params);
    }

    private MesOqcCheck getOqcCheckByManual(JxOqcManageManualModel result) {
        List<MesOqcCheck> oqcCheckList = oqcCheckService.getOqcCheckListByOrderAndTime(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());
        oqcCheckList = CollectionUtils.isEmpty(oqcCheckList) ? null :
                oqcCheckList.stream().filter(o -> (null != o && MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() != o.getOqcNoType())).collect(Collectors.toList());
        oqcCheckList = CollectionUtils.isEmpty(oqcCheckList) ? null :
                oqcCheckList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesOqcCheck::getCreateDatetime).reversed()).collect(Collectors.toList());
        return CollectionUtils.isEmpty(oqcCheckList) ? null : oqcCheckList.get(0);
    }

    private void packResultByManual(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb, SxBuOqcDataModel dataFromPcn, MesOutPutStatisticsOqc outPutStatisticsOqcDb, MesPartExt partDb) {

        result.setCategoryCode3(partDb.getCategoryCode3());

        result.setPartNameRdd(partDb.getPartName());

        result.setWorkOrderTypeName(dataFromPcn.getWorkOrderTypeName());

        result.setCompleteQty(dataFromPcn.getCompleteQty());

        result.setCheckLimit(StringUtils.isEmpty(outPutStatisticsOqcDb.getCheckLimit()) ? new Double(0) : outPutStatisticsOqcDb.getCheckLimit());

        result.setBatchLimit(!partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? MathOperation.sub(result.getCompleteQty(), result.getCheckLimit()) : getBatchLimitByManualSn(result, dataFromPcn));

        result.setCurBatchLimit(null == oqcCheckDb ? null : oqcCheckDb.getOqcQty());

        result.setOqcNo(null == oqcCheckDb ? null : oqcCheckDb.getOqcNo());

        result.setOqcNoType(null == oqcCheckDb ? null : oqcCheckDb.getOqcNoType());

        result.setCheckResult(null == oqcCheckDb ? null : ((StringUtils.isEmpty(oqcCheckDb.getCheckResult()) ||
                StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult())) ? null : oqcCheckDb.getCheckResult())));

        result.setMsg(String.format("生产工单[%s]生产日期[%s]班次[%s]%s关联%s检验单据%s",
                result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode(), null == oqcCheckDb ? "未" : "已",
                null == oqcCheckDb ? MesPcnExtConstWords.EMPTY : MesPcnExtConstWords.SQUARE_BRACKETS_L + MesPcnExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcCheckDb.getOqcNoType()) + MesPcnExtConstWords.SQUARE_BRACKETS_R,
                null == oqcCheckDb ? MesPcnExtConstWords.EMPTY : MesPcnExtConstWords.SQUARE_BRACKETS_L + oqcCheckDb.getOqcNo() + MesPcnExtConstWords.SQUARE_BRACKETS_R + MesPcnExtConstWords.SQUARE_BRACKETS_L +
                        (StringUtils.isEmpty(result.getCheckResult()) ? "未检验" : MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(result.getCheckResult())) + MesPcnExtConstWords.SQUARE_BRACKETS_R));

        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), false);
        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue(), false);
        result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), false);

        if (null == oqcCheckDb) {
            //根据工单号查询出货检验单据主表非拆机的一条数据
            MesOqcCheck unTeardownOqcCheckDb = oqcCheckService.getUnTeardownOqcCheckByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo());
            if (null == unTeardownOqcCheckDb) {
                result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue(), true);
                result.getOqcNoTypeBooMap().put(MesPcnExtEnumUtil.OQC_CHECK_TYPE.EMPTY_INSPECTION.getValue(), true);
            } else {
                result.getOqcNoTypeBooMap().put(unTeardownOqcCheckDb.getOqcNoType(), true);
            }
        }
    }

    private Double getBatchLimitByManualSn(JxOqcManageManualModel result, SxBuOqcDataModel dataFromPcn) {
        return CollectionUtils.isEmpty(dataFromPcn.getProdMapList()) ? new Double(0) : getProdMapListSizeWithoutChecked(dataFromPcn.getProdMapList(),
                        oqcCheckService.getOqcCheckPackageDetailListByOrderNoAndWorkTime(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode()));
    }

    @Override
    public JxOqcManageManualModel insertOqcManageDataManual(JxOqcManageManualModel result) {

        log.info("MES_PCN出货检验手动检验生成检验单 --- 参数model[{}] --- 线程ID[{}]", result.toString(), Thread.currentThread().getName());

        //参数验证
        checkManualParam(result);

        //验证物料
        MesPartExt partDb = checkPartValidByManual(result);

        //验证产量统计出货检验
        MesOutPutStatisticsOqc outPutStatisticsOqcDb = getOutPutStatisticsOqcByManual(result);

        //获取上个检验单
        MesOqcCheck oqcCheckDb = getOqcCheckByManual(result);

        log.info("MES_PCN出货检验手动检验生成检验单 --- {}出货检验 --- 上个检验单据[{}] --- 线程ID[{}]",
                partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue()) ? "成品" : "组件", null == oqcCheckDb ? MesPcnExtConstWords.EMPTY : oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        //验证界面显示数据与当前实时数据是否一致
        checkDataAndResultByManual(result, oqcCheckDb);

        if (!partDb.getCategoryCode3().equals(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue())) return insertOqcManageDataManualByZj(result, oqcCheckDb, outPutStatisticsOqcDb, partDb);

        return insertOqcManageDataManualBySn(result, oqcCheckDb, outPutStatisticsOqcDb, partDb);

    }

    private void checkDataAndResultByManual(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb) {
        if (StringUtils.isEmpty(result.getOqcNo())) {
            if (null != oqcCheckDb) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]当前已关联检验单据[%s],请重新查询",
                                result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode(), oqcCheckDb.getOqcNo())
                        .build();
            }
        } else {
            if (null == oqcCheckDb) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]未关联检验单据,请重新查询",
                                result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                        .build();
            } else {
                if (!oqcCheckDb.getOqcNo().equals(result.getOqcNo())) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]已关联新的检验单据[%s],请重新查询",
                                    result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode(), oqcCheckDb.getOqcNo())
                            .build();
                }
            }
        }
    }

    private void checkManualParam(JxOqcManageManualModel result) {
        if (StringUtils.isEmpty(result.getOqcNo()) && StringUtils.isEmpty(result.getOqcNoType())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]未关联检验单据,请选择检验类型", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }
        if (StringUtils.isEmpty(result.getOqcNo()) && StringUtils.isEmpty(result.getCheckResult())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]未关联检验单据,请选择总结果", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }
        if (StringUtils.isEmpty(result.getOqcNo()) && !StringUtils.isEmpty(result.getCheckResult())) {
            if (MesPcnExtEnumUtil.OQC_CHECK_RESULT.QUALIFIED.getValue() == result.getCheckResult()) {
                if (!StringUtils.isEmpty(result.getBadnessTypeCode()) || !StringUtils.isEmpty(result.getBadnessClassifyCode()) || !StringUtils.isEmpty(result.getBadnessClassifyDetailName())) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]生成新检验单据的总结果为[合格],不可携带不良类型等信息",
                                    result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                            .build();
                }
            } else {
                if (StringUtils.isEmpty(result.getBadnessTypeCode()) || StringUtils.isEmpty(result.getBadnessClassifyCode())) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                            .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]生成新检验单据的总结果为[不合格],必须携带不良类型等信息",
                                    result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                            .build();
                }
            }
        }
    }

    private JxOqcManageManualModel insertOqcManageDataManualByZj(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb, MesPartExt partDb) {
        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModelByManual(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getExecClass2());

        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //验证通过产量OQC的PID查询到的PCN的工单生产日期班次信息是否与界面信息一致
        checkDataFromPcnIsValid(result, dataFromPcn);

        //验证是否存在未被抽检的产量
        checkRemainQtyManualByZj(dataFromPcn, outPutStatisticsOqcDb.getCheckLimit());

        if (null != oqcCheckDb) return insertOqcManageDataManualByZj2OldCheck(result, oqcCheckDb, outPutStatisticsOqcDb, dataFromPcn, partDb);

        return insertOqcManageDataManualByZj2NewCheck(result, outPutStatisticsOqcDb, dataFromPcn, partDb);
    }

    private void checkDataFromPcnIsValid(JxOqcManageManualModel result, SxBuOqcDataModel dataFromPcn) {
        if (!result.getWorkOrderNo().equals(dataFromPcn.getWorkOrderNo()) ||
                !result.getWorkTime().equals(dataFromPcn.getWorkTime()) || !result.getShiftCode().equals(dataFromPcn.getShiftCode())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]对应的产量统计出货检验信息PID[%s]与PCN服务中关联的信息不一致",
                            result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode(), result.getIdStr())
                    .build();
        }
    }

    private void checkRemainQtyManualByZj(SxBuOqcDataModel dataFromPcn, Double checkLimit) {
        checkLimit = StringUtils.isEmpty(checkLimit) ? new Double(0) : checkLimit;
        if (MathOperation.compareTo(dataFromPcn.getCompleteQty(), checkLimit) <= 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]当前已无可抽检的剩余产量,当前产量[%s],当前已抽检范围[%s]",
                            dataFromPcn.getWorkOrderNo(), dataFromPcn.getWorkTime(), dataFromPcn.getShiftCode(), dataFromPcn.getCompleteQty(), checkLimit)
                    .build();
        }
    }

    private JxOqcManageManualModel insertOqcManageDataManualByZj2OldCheck(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb, SxBuOqcDataModel dataFromPcn, MesPartExt partDb) {
        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- 关联上个单据[{}] START --- 线程ID[{}]", oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        Double remainQty = MathOperation.sub(dataFromPcn.getCompleteQty(), outPutStatisticsOqcDb.getCheckLimit());

        oqcCheckDb.setOqcQty(MathOperation.add(oqcCheckDb.getOqcQty(), remainQty));
        oqcCheckDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelUpdate(oqcCheckDb, result.getUserInfo());
        oqcCheckRepository.save(oqcCheckDb);

        outPutStatisticsOqcDb.setCheckLimit(MathOperation.add(outPutStatisticsOqcDb.getCheckLimit(), remainQty));
        ConvertBean.serviceModelUpdate(outPutStatisticsOqcDb, result.getUserInfo());
        outPutStatisticsOqcRepository.save(outPutStatisticsOqcDb);

        //封装数据
        packResultByManual(result, oqcCheckDb, dataFromPcn, outPutStatisticsOqcDb, partDb);

        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- 关联上个单据[{}] END --- 线程ID[{}]", oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        return result;

    }

    private JxOqcManageManualModel insertOqcManageDataManualByZj2NewCheck(JxOqcManageManualModel result, MesOutPutStatisticsOqc outPutStatisticsOqcDb, SxBuOqcDataModel dataFromPcn, MesPartExt partDb) {

        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- 生成新单据 START --- 线程ID[{}]", Thread.currentThread().getName());

        //组件不拆机
        checkOqcNoTypeByManual(result.getOqcNoType());

        //检验单据
        MesOqcCheck oqcCheck = insetManualOqcCheckByZj(result, dataFromPcn, partDb);

        //保存产量抽检范围
        saveOutPutStatisticsOqc(oqcCheck, outPutStatisticsOqcDb);

        //封装数据
        packResultByManual(result, oqcCheck, dataFromPcn, outPutStatisticsOqcDb, partDb);

        log.info("MES_PCN出货检验手动检验生成检验单 --- 组件出货检验 --- 生成新单据[{}] END --- 线程ID[{}]", oqcCheck.getOqcNo(), Thread.currentThread().getName());

        return result;
    }

    private void checkOqcNoTypeByManual(Integer oqcNoType) {
        if (MesPcnExtEnumUtil.OQC_CHECK_TYPE.TEARDOWN_INSPECTION.getValue() == oqcNoType) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:不支持拆机检验")
                    .build();
        }
    }

    private MesOqcCheck insetManualOqcCheckByZj(JxOqcManageManualModel result, SxBuOqcDataModel dataFromPcn, MesPartExt partDb) {
        MesOqcCheck oqcCheck = new MesOqcCheck();
        BeanUtils.copyProperties(result, oqcCheck);
        oqcCheck.setOqcNo(getOqcNo(result.getUserInfo(), result.getOrganizeCode()));
        oqcCheck.setWorkOrderType(dataFromPcn.getWorkOrderType());
        oqcCheck.setQty(dataFromPcn.getPlanQty());
        oqcCheck.setSnType(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.ZJ.getValue());
        oqcCheck.setOqcType(MesPcnExtEnumUtil.OQC_TYPE.MANUAL.getValue());
        oqcCheck.setOqcQty(dataFromPcn.getCompleteQty());
        oqcCheck.setCheckUser(result.getUserInfo());
        oqcCheck.setSpotCheckQty(new Double(1));
        oqcCheck.setCategoryCode3(partDb.getCategoryCode3());
        ConvertBean.serviceModelInitialize(oqcCheck, result.getUserInfo());
        oqcCheck.setCheckTime(oqcCheck.getModifyDatetime());
        oqcCheck.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        oqcCheckRepository.insert(oqcCheck);
        return oqcCheck;
    }

    private JxOqcManageManualModel insertOqcManageDataManualBySn(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb, MesPartExt partDb) {
        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- GET DATA FROM PCN START --- 线程ID[{}]", Thread.currentThread().getName());

        //获取PCN工单条码物料产量信息
        SxBuOqcDataModel dataFromPcn = getBuOqcDataModelByManual(result, MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getExecClass2());

        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- GET DATA FROM PCN SUCCESS[{}] --- 线程ID[{}]", dataFromPcn.toString(), Thread.currentThread().getName());

        //验证通过产量OQC的PID查询到的PCN的工单生产日期班次信息是否与界面信息一致
        checkDataFromPcnIsValid(result, dataFromPcn);

        //获取待抽检条码
        List<Map<String, String>> prodMapList = getProdMapListManualBySn(result, dataFromPcn);

        if (null != oqcCheckDb) return insertOqcManageDataManualBySn2OldCheck(result, oqcCheckDb, outPutStatisticsOqcDb, dataFromPcn, partDb, prodMapList);

        return insertOqcManageDataManualBySn2NewCheck(result, outPutStatisticsOqcDb, dataFromPcn, partDb, prodMapList);

    }

    private List<Map<String, String>> getProdMapListManualBySn(JxOqcManageManualModel result, SxBuOqcDataModel dataFromPcn) {
        //获取当前班次作业时间内已经关联出货检验的条码集合
        List<String> snList = getOqcCheckedSnList(result.getOrganizeCode(), result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());

        //获取当前班次作业时间内未关联出货检验的条码集合
        List<Map<String, String>> prodMapList = dataFromPcn.getProdMapList();

        prodMapList = (CollectionUtils.isEmpty(prodMapList) || CollectionUtils.isEmpty(snList)) ? prodMapList :
                prodMapList.stream().filter(o -> (null != o && !snList.contains(o.get(MesPcnExtConstWords.PRODUCT_SN)))).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(prodMapList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("手动检验:生产工单[%s]生产日期[%s]班次[%s]当前已无可抽检的剩余产品", result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode())
                    .build();
        }

        prodMapList = prodMapList.stream().filter(o -> null != o).sorted(Comparator.comparing(o -> o.get(MesPcnExtConstWords.PRODUCT_SN))).collect(Collectors.toList());

        return prodMapList;
    }

    private JxOqcManageManualModel insertOqcManageDataManualBySn2OldCheck(JxOqcManageManualModel result, MesOqcCheck oqcCheckDb, MesOutPutStatisticsOqc outPutStatisticsOqcDb,
                                                                            SxBuOqcDataModel dataFromPcn, MesPartExt partDb, List<Map<String, String>> prodMapList) {
        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- 关联上个单据[{}] START --- 线程ID[{}]", oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        oqcCheckDb.setOqcQty(MathOperation.add(oqcCheckDb.getOqcQty(), new Double(prodMapList.size())));
        oqcCheckDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelUpdate(oqcCheckDb, result.getUserInfo());
        oqcCheckRepository.save(oqcCheckDb);

        outPutStatisticsOqcDb.setCheckLimit(MathOperation.add(outPutStatisticsOqcDb.getCheckLimit(), new Double(prodMapList.size())));
        ConvertBean.serviceModelUpdate(outPutStatisticsOqcDb, result.getUserInfo());
        outPutStatisticsOqcRepository.save(outPutStatisticsOqcDb);

        //关联条码
        insetOqcCheckPackageDetailManualBySn(oqcCheckDb, prodMapList);

        //清空条码,用于回显剩余未检范围为0
        dataFromPcn.setProdMapList(null);

        //封装数据
        packResultByManual(result, oqcCheckDb, dataFromPcn, outPutStatisticsOqcDb, partDb);

        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- 关联上个单据[{}] END --- 线程ID[{}]", oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        return result;
    }

    private void insetOqcCheckPackageDetailManualBySn(MesOqcCheck oqcCheckDb, List<Map<String, String>> prodMapList) {
        List<MesOqcCheckPackageIf> oqcCheckPackageIfList = new ArrayList<>();
        for (Map<String, String> snMap : prodMapList) {
            if (CollectionUtils.isEmpty(snMap)) continue;

            MesOqcCheckPackageDetail oqcCheckPackageDetail = new MesOqcCheckPackageDetail();
            BeanUtils.copyProperties(oqcCheckDb, oqcCheckPackageDetail, MesPcnExtConstWords.ID, MesPcnExtConstWords.SERIAL_NUMBER, MesPcnExtConstWords.PRODUCT_SN, MesPcnExtConstWords.PACKAGENO, MesPcnExtConstWords.OQC_TYPE);
            oqcCheckPackageDetail.setSerialNumber(snMap.get(MesPcnExtConstWords.SERIAL_NUMBER));
            oqcCheckPackageDetail.setProductSn(snMap.get(MesPcnExtConstWords.PRODUCT_SN));
            oqcCheckPackageDetail.setPackageNo(snMap.get(MesPcnExtConstWords.PACKAGENO));
            oqcCheckPackageDetail.setOutWorkCenterTime(snMap.get(MesPcnExtConstWords.OUT_WORK_CENTER_TIME));
            oqcCheckPackageDetail.setOqcType(MesPcnExtEnumUtil.OQC_TYPE.MANUAL.getValue());
            oqcCheckPackageDetail.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelInitialize(oqcCheckPackageDetail, oqcCheckDb.getModifyUser());
            oqcCheckPackageDetailRepository.insert(oqcCheckPackageDetail);
            MesOqcCheckPackageIf sxQmsOqcCheckPackageIf = insertOqcCheckPackageIf(oqcCheckPackageDetail, snMap.get(MesPcnExtConstWords.BIG_PACKAGE_NO));

            if (!StringUtils.isEmpty(oqcCheckDb.getCheckResult()) && !StringUtils.isEmpty(MesPcnExtEnumUtil.OQC_CHECK_RESULT.valueOfDescription(oqcCheckDb.getCheckResult()))) {
                oqcCheckPackageIfList.add(sxQmsOqcCheckPackageIf);
                insertOqcCheckPackageDetailTravel(oqcCheckPackageDetail);
            }
        }
    }


    private JxOqcManageManualModel insertOqcManageDataManualBySn2NewCheck(JxOqcManageManualModel result, MesOutPutStatisticsOqc outPutStatisticsOqcDb,
                                                                            SxBuOqcDataModel dataFromPcn, MesPartExt partDb, List<Map<String, String>> prodMapList) {
        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- 生成新单据 START --- 线程ID[{}]", Thread.currentThread().getName());

        //不支持拆机
        checkOqcNoTypeByManual(result.getOqcNoType());

        //检验单据
        MesOqcCheck oqcCheckDb = insetManualOqcCheckBySn(result, prodMapList, dataFromPcn, partDb);

        //关联条码
        insetOqcCheckPackageDetailManualBySn(oqcCheckDb, prodMapList);

        //保存产量抽检范围
        saveOutPutStatisticsOqc(oqcCheckDb, outPutStatisticsOqcDb);

        //清空条码,用于回显剩余未检范围为0
        dataFromPcn.setProdMapList(null);

        //封装数据
        packResultByManual(result, oqcCheckDb, dataFromPcn, outPutStatisticsOqcDb, partDb);

        log.info("MES_PCN出货检验手动检验生成检验单 --- 成品出货检验 --- 生成新单据[{}] END --- 线程ID[{}]", oqcCheckDb.getOqcNo(), Thread.currentThread().getName());

        return result;
    }

    private MesOqcCheck insetManualOqcCheckBySn(JxOqcManageManualModel result, List<Map<String, String>> prodMapList, SxBuOqcDataModel dataFromPcn, MesPartExt partDb) {

        MesOqcCheck oqcCheck = new MesOqcCheck();
        BeanUtils.copyProperties(result, oqcCheck);
        oqcCheck.setOqcNo(getOqcNo(result.getUserInfo(), result.getOrganizeCode()));
        oqcCheck.setWorkOrderType(dataFromPcn.getWorkOrderType());
        oqcCheck.setQty(dataFromPcn.getPlanQty());
        oqcCheck.setSerialNumber(prodMapList.get(0).get(MesPcnExtConstWords.SERIAL_NUMBER));
        oqcCheck.setProductSn(prodMapList.get(0).get(MesPcnExtConstWords.PRODUCT_SN));
        oqcCheck.setPackageNo(prodMapList.get(0).get(MesPcnExtConstWords.PACKAGENO));
        oqcCheck.setSnType(MesPcnExtEnumUtil.OQC_MANAGE_ACTION_TYPE.SERIAL_NUMBER.getValue());
        oqcCheck.setOqcType(MesPcnExtEnumUtil.OQC_TYPE.MANUAL.getValue());
        oqcCheck.setOqcQty(new Double(prodMapList.size()));
        oqcCheck.setCheckUser(result.getUserInfo());
        oqcCheck.setSpotCheckQty(new Double(1));
        oqcCheck.setCategoryCode3(partDb.getCategoryCode3());
        ConvertBean.serviceModelInitialize(oqcCheck, result.getUserInfo());
        oqcCheck.setCheckTime(oqcCheck.getModifyDatetime());
        oqcCheck.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        oqcCheckRepository.insert(oqcCheck);

        return oqcCheck;
    }

}