package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base;

import cn.estsh.i3plus.ext.mes.pcn.api.base.IQualityDecisionService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxRepairWorkService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkCenterExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.RepairRequestModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.RepairWorkOrderModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
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.mes.pcn.dao.IDefectDao;
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.tool.TimeTool;
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.Pager;
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.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesDefect;
import cn.estsh.i3plus.pojo.mes.bean.MesDefectCause;
import cn.estsh.i3plus.pojo.mes.bean.MesKpsnRule;
import cn.estsh.i3plus.pojo.mes.bean.MesRepair;
import cn.estsh.i3plus.pojo.mes.model.DefectModel;
import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel;
import cn.estsh.i3plus.pojo.mes.repository.MesDefectCauseRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesDefectRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesKpsnRuleRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesRepairRepository;
import cn.estsh.i3plus.pojo.mes.sqlpack.MesPcnHqlPack;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SxRepairWorkService implements ISxRepairWorkService {

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private IProduceSnRepairService produceSnRepairService;

    @Autowired
    private MesDefectRepository defectRepository;

    @Autowired
    private MesBadCellDetailRepository badCellDetailRepository;

    @Autowired
    private MesBadCellRepository badCellRepository;

    @Autowired
    private MesRepairRecordExtRepository repairRecordExtRepository;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private MesDefectCauseRepository defectCauseRepository;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private MesWorkCenterExtRepository workCenterExtRepository;

    @Autowired
    private IDefectDao defectDao;

    @Autowired
    private MesRepairRepository repairRepository;

    @Autowired
    private IQualityDecisionService qualityDecisionService;

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private ISyncFuncService syncFuncService;

    @Autowired
    private MesRepairTaskRepository repairTaskRepository;

    @Autowired
    private MesProdBindRecordExtRepository prodBindRecordExtRepository;

    @Autowired
    private MesProcessBomRepository processBomRepository;

    @Autowired
    private MesKpsnRuleRepository kpsnRuleRepository;

    @Autowired
    private MesReplacementTravelRepository replacementTravelRepository;


    @Override
    public ProduceSnExtModel getProduceSnFrozenBySn(String serialNumber, String organizeCode) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (produceSnExt == null) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]在系统中不存在", serialNumber)
                    .build();
        }
        if (produceSnExt.getQcStatus() != MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.DEFECTED.getValue()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("条码质量状态为[%s],不是不合格或报废状态",
                            MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.valueOfDescription(produceSnExt.getQcStatus()))
                    .build();
        }
        ProduceSnExtModel produceSnExtModel = new ProduceSnExtModel();
        BeanUtils.copyProperties(produceSnExt, produceSnExtModel, MesPcnExtConstWords.ID);
        MesProduceSnRepair produceSnRepair;
        if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(organizeCode, serialNumber);
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", serialNumber, produceSnExt.getLastWorkOrderNo())
                        .build();
            }
            produceSnExtModel.setWorkOrderNo(produceSnRepair.getWorkOrderNo());
            produceSnExtModel.setWorkTime(produceSnRepair.getWorkTime());
            produceSnExtModel.setShiftCode(produceSnRepair.getShiftCode());
        }
        return produceSnExtModel;
    }

    @Override
    public List<MesBadCellDetail> getMesBadCellDetailBySerialNumber(String serialNumber, String organizeCode) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]不存在", serialNumber)
                    .build();
        }
        MesProduceSnRepair produceSnRepair = null;
        if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(organizeCode, serialNumber);
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", serialNumber, produceSnExt.getLastWorkOrderNo())
                        .build();
            }
        }

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(serialNumber, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
        if (null == produceSnRepair) {
            DdlPreparedPack.getStringEqualPack(produceSnExt.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        } else {
            DdlPreparedPack.getStringEqualPack(produceSnRepair.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        }
        packBean.setOrderByStr(" order by createDatetime desc ");
        return badCellDetailRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<MesRepairRecordExt> getMesRepairRecordBySerialNumber(String serialNumber, String organizeCode) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]不存在", serialNumber)
                    .build();
        }
        MesProduceSnRepair produceSnRepair = null;
        if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(organizeCode, serialNumber);
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", serialNumber, produceSnExt.getLastWorkOrderNo())
                        .build();
            }
        }


        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(serialNumber, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
        if (null == produceSnRepair) {
            DdlPreparedPack.getStringEqualPack(produceSnExt.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        } else {
            DdlPreparedPack.getStringEqualPack(produceSnRepair.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        }
        packBean.setOrderByStr(" order by createDatetime desc ");
        return repairRecordExtRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<MesWorkCenterExt> queryWorkCenter(String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(String.valueOf(MesPcnExtEnumUtil.LINE_TYPE.COMPONENT_LINE.getValue()), MesPcnExtConstWords.LINE_TYPE, packBean);
        return workCenterExtRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<RepairWorkOrderModel> queryWorkOrderByCenter(String workCenterCode, String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue(), MesPcnExtConstWords.WORK_ORDER_STATUS, packBean);
        packBean.setOrderByStr(" order by seq desc ");
        List<MesWorkOrderExt> workOrderExts = workOrderExtRepository.findByHqlWhere(packBean);

        List<RepairWorkOrderModel> repairWorkOrderModelList = new ArrayList<>();
        for (MesWorkOrderExt workOrderExt : workOrderExts) {
            RepairWorkOrderModel repairWorkOrderModel = new RepairWorkOrderModel();
            repairWorkOrderModel.setMesWorkOrderExt(workOrderExt);
            repairWorkOrderModelList.add(repairWorkOrderModel);
        }
        return repairWorkOrderModelList;
    }

    @Override
    public List<MesBadCellDetail> getMesBadCellDetailByWorkOrderNo(String workOrderNo, String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        packBean.setOrderByStr(" order by createDatetime desc ");
        return badCellDetailRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<MesRepairRecordExt> getMesRepairRecordByOrderNo(String workOrderNo, String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        packBean.setOrderByStr(" order by createDatetime desc ");
        return repairRecordExtRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<DefectModel> getMesDefect(String organizeCode) {
        List<DefectModel> list = defectDao.getMesDefect(organizeCode);
        if (CollectionUtils.isEmpty(list)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("没有缺陷基础信息")
                    .build();
        }
        Map<String, List<DefectModel>> map = list.stream().collect(Collectors.groupingBy(DefectModel::getDefectTypeName));
        Set<Map.Entry<String, List<DefectModel>>> entries = map.entrySet();
        List<DefectModel> resultList = new ArrayList<>();
        for (Map.Entry<String, List<DefectModel>> entry : entries) {
            DefectModel mesDefect = new DefectModel();
            mesDefect.setDefectTypeName(entry.getKey());
            mesDefect.setMesDefectList(entry.getValue());
            mesDefect.setDefectType(mesDefect.getMesDefectList().get(0).getDefectType());
            resultList.add(mesDefect);
        }
        return resultList;
    }

    @Override
    public MesDefect getMesDefect(String defectCode, String defectName, String organizeCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(defectCode, MesPcnExtConstWords.DEFECT_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(defectName, MesPcnExtConstWords.DEFECT_NAME, packBean);
        MesDefect mesDefect = defectRepository.getByProperty(packBean);
        if (mesDefect == null) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("没有缺陷基础信息")
                    .build();
        }
        return mesDefect;
    }

    @Override
    public void insertMesBadCellDetail(MesBadCellDetail mesBadCellDetail) {
        String workOrderNo = mesBadCellDetail.getOrderNo();
        if (!StringUtils.isEmpty(mesBadCellDetail.getSerialNumber())) {
            MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(mesBadCellDetail.getOrganizeCode(), mesBadCellDetail.getSerialNumber());
            if (null == produceSnExt) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]不存在", mesBadCellDetail.getSerialNumber())
                        .build();
            }
            if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
                MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(mesBadCellDetail.getOrganizeCode(), mesBadCellDetail.getSerialNumber());
                if (null == produceSnRepair) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", mesBadCellDetail.getSerialNumber(), produceSnExt.getLastWorkOrderNo())
                            .build();
                }
                workOrderNo = produceSnRepair.getWorkOrderNo();
            } else {
                workOrderNo = produceSnExt.getWorkOrderNo();
            }
            mesBadCellDetail.setWorkCenterCode(produceSnExt.getWorkCenterCode());
        } else {
            if (StringUtils.isEmpty(workOrderNo)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("入参缺少生产工单号")
                        .build();
            }
        }

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(mesBadCellDetail.getOrganizeCode(), mesBadCellDetail.getWorkCenterCode());
        if (null == workCenterExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]无效", mesBadCellDetail.getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次", mesBadCellDetail.getWorkCenterCode())
                    .build();
        }

        List<MesDefect> mesDefectList = mesBadCellDetail.getMesDefectList();
        if (!CollectionUtils.isEmpty(mesDefectList)) {
            MesBadCell badCell = badCellRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                            MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.WORK_TIME, MesPcnExtConstWords.SHIFT_CODE, MesPcnExtConstWords.WORK_CELL_CODE},
                    new Object[]{mesBadCellDetail.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                            workOrderNo, workCenterExt.getWorkTime(), workCenterExt.getShiftCode(), mesBadCellDetail.getWorkCellCode()});
            if (null == badCell) {
                if (!StringUtils.isEmpty(mesBadCellDetail.getSerialNumber())) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("根据产品条码[%s]基于生产日期[%s]班次[%s]上未在工位[%s]执行质量判定作业",
                                    mesBadCellDetail.getSerialNumber(), workCenterExt.getWorkTime(), workCenterExt.getShiftCode(), mesBadCellDetail.getWorkCellCode())
                            .build();
                } else {
                    MesProcessCell processCell = qualityDecisionService.getMesProcessCell(workCenterExt.getWorkCenterCode(), mesBadCellDetail.getWorkCellCode(), mesBadCellDetail.getOrganizeCode());
                    if (null == processCell) {
                        throw ImppExceptionBuilder.newInstance()
                                .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                                .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                                .setErrorDetail("生产线代码[%s]工位代码[%s]未关联工序", workCenterExt.getWorkCenterCode(), mesBadCellDetail.getWorkCellCode())
                                .build();
                    }

                    badCell = new MesBadCell();
                    badCell.setOrganizeCode(mesBadCellDetail.getOrganizeCode());
                    badCell.setPartNo(mesBadCellDetail.getPartNo());
                    badCell.setPartNameRdd(mesBadCellDetail.getPartNameRdd());
                    badCell.setWorkCenterCode(workCenterExt.getWorkCenterCode());
                    badCell.setWorkCellCode(mesBadCellDetail.getWorkCellCode());
                    badCell.setProcessCode(processCell.getProcessCode());
                    badCell.setProcessNameRdd(processCell.getProcessName());
                    badCell.setQty(new Double(mesDefectList.size()));
                    badCell.setWorkOrderNo(workOrderNo);
                    badCell.setWorkTime(workCenterExt.getWorkTime());
                    badCell.setShiftCode(workCenterExt.getShiftCode());
                    ConvertBean.serviceModelInitialize(badCell, mesBadCellDetail.getModifyUser());
                    badCellRepository.insert(badCell);
                }
            } else {
                badCell.setQty(MathOperation.add(badCell.getQty(), new Double(mesDefectList.size())));
                ConvertBean.serviceModelUpdate(badCell, mesBadCellDetail.getModifyUser());
                badCellRepository.save(badCell);
            }

            for (MesDefect mesDefect : mesDefectList) {
                if (null == mesDefect) {
                    continue;
                }
                MesBadCellDetail badCellDetail = new MesBadCellDetail();
                badCellDetail.setWorkCenterCode(mesBadCellDetail.getWorkCenterCode());
                badCellDetail.setWorkOrderNo(workOrderNo);
                badCellDetail.setWorkTime(workCenterExt.getWorkTime());
                badCellDetail.setShiftCode(workCenterExt.getShiftCode());
                badCellDetail.setWorkCellCode(mesBadCellDetail.getWorkCellCode());
                badCellDetail.setPartNo(badCell.getPartNo());
                badCellDetail.setPartNameRdd(badCell.getPartNameRdd());
                badCellDetail.setDefectType(mesDefect.getDefectType());
                badCellDetail.setDefectTypeName(mesDefect.getDefectTypeName());
                badCellDetail.setDefectCode(mesDefect.getDefectCode());
                badCellDetail.setDefectName(mesDefect.getDefectName());
                badCellDetail.setRepairStatus(MesPcnExtEnumUtil.MES_REPAIR_STATUS.NO_REPAIR.getValue());
                badCellDetail.setSerialNumber(mesBadCellDetail.getSerialNumber());
                badCellDetail.setApprovalStatus(MesPcnExtEnumUtil.BAD_CELL_DETAIL_APPROVAL_STATUS.UN_APPROVAL.getValue());
                badCellDetail.setOrganizeCode(mesBadCellDetail.getOrganizeCode());
                ConvertBean.serviceModelInitialize(badCellDetail, mesBadCellDetail.getModifyUser());
                badCellDetail.setDefectActionTime(badCellDetail.getCreateDatetime());
                badCellDetailRepository.insert(badCellDetail);
            }
        }
    }

    @Override
    public void insertMesRepairRecord(MesRepairRecordExt repairRecord) {
        MesRepairRecordExt repairRecordExt = new MesRepairRecordExt();
        BeanUtils.copyProperties(repairRecord, repairRecordExt, MesPcnExtConstWords.ID);
        ConvertBean.serviceModelInitialize(repairRecordExt, repairRecord.getModifyUser());
        new ConvertBeanExt(repairRecordExt).convertBean(repairRecordExt);

        repairRecordExtRepository.insert(repairRecordExt);
        badCellDetailRepository.updateByProperties(new String[]{MesPcnExtConstWords.ID}, new Object[]{repairRecord.getDefectRecordId()},
                new String[]{MesPcnExtConstWords.REPAIR_STATUS, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME},
                new Object[]{MesPcnExtEnumUtil.MES_REPAIR_STATUS.REPAIRED.getValue(), repairRecord.getModifyUser(), TimeTool.getNowTime(true)});
    }

    @Override
    public void updateMesRepairRecord(MesRepairRecordExt repairRecord) {
        MesRepairRecordExt repairRecordDb = repairRecordExtRepository.getById(repairRecord.getId());
        if (repairRecordDb == null) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                    .setErrorDetail("ID[%s]数据不存在", repairRecord.getId())
                    .build();
        }
        repairRecordDb.setDcCode(repairRecord.getDcCode());
        repairRecordDb.setDcName(repairRecord.getDcName());
        repairRecordDb.setRepairCode(repairRecord.getRepairCode());
        repairRecordDb.setRepairName(repairRecord.getRepairName());
        repairRecordDb.setRepairDatetime(repairRecord.getRepairDatetime());
        repairRecordDb.setRepairJudge(repairRecord.getRepairJudge());
        repairRecordDb.setMemo(repairRecord.getMemo());
        repairRecordDb.setBadPartNo(repairRecord.getBadPartNo());
        repairRecordDb.setBadPartName(repairRecord.getMemo());
        repairRecordDb.setMemo(repairRecord.getMemo());
        ConvertBean.serviceModelUpdate(repairRecordDb, repairRecord.getModifyUser());
        new ConvertBeanExt(repairRecordDb).convertBean(repairRecordDb);
        repairRecordExtRepository.save(repairRecordDb);
    }


    @Override
    public ListPager<MesDefectCause> getMesDefectCause(MesDefectCause defectCause, Pager pager) {
        if (defectCause == null) {
            pager = PagerHelper.getPager(pager, defectCauseRepository.listCount());
            return new ListPager(defectCauseRepository.listPager(pager), pager);
        } else {
            DdlPackBean hqlPack = MesPcnHqlPack.getMesDefectCause(defectCause, defectCause.getOrganizeCode());
            pager = PagerHelper.getPager(pager, defectCauseRepository.findByHqlWhereCount(hqlPack));
            return new ListPager(defectCauseRepository.findByHqlWherePage(hqlPack, pager), pager);
        }
    }

    @Override
    public ListPager<MesRepair> getMesRepair(MesRepair repair, Pager pager) {
        if (repair == null) {
            pager = PagerHelper.getPager(pager, repairRepository.listCount());
            return new ListPager(repairRepository.listPager(pager), pager);
        } else {
            DdlPackBean hqlPack = MesPcnHqlPack.getMesRepair(repair, repair.getOrganizeCode());
            pager = PagerHelper.getPager(pager, repairRepository.findByHqlWhereCount(hqlPack));
            return new ListPager(repairRepository.findByHqlWherePage(hqlPack, pager), pager);
        }
    }

    @Override
    public void insertMesRepairDefectRecord(RepairRequestModel requestModel) {
        List<MesBadCellDetail> badCellDetailList = requestModel.getMesDefectRecordList();
        List<MesRepairRecordExt> repairRecordList = requestModel.getMesRepairRecordList();
        Map<String, Long> defectCodeMap = new HashMap<>();

        String workOrderNo = repairRecordList.get(0).getWorkOrderNo();
        if (!StringUtils.isEmpty(badCellDetailList.get(0).getSerialNumber())) {
            MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(requestModel.getOrganizeCode(), badCellDetailList.get(0).getSerialNumber());
            if (null == produceSnExt) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]不存在", badCellDetailList.get(0).getSerialNumber())
                        .build();
            }
            if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
                MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(requestModel.getOrganizeCode(), produceSnExt.getSerialNumber());
                if (null == produceSnRepair) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", produceSnExt.getSerialNumber(), produceSnExt.getLastWorkOrderNo())
                            .build();
                }
                workOrderNo = produceSnRepair.getWorkOrderNo();
            } else {
                workOrderNo = produceSnExt.getWorkOrderNo();
            }
        } else {
            if (StringUtils.isEmpty(workOrderNo)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("入参缺少生产工单号")
                        .build();
            }
        }

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(requestModel.getOrganizeCode(), badCellDetailList.get(0).getWorkCenterCode());
        if (null == workCenterExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]无效",  badCellDetailList.get(0).getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次",  badCellDetailList.get(0).getWorkCenterCode())
                    .build();
        }

        MesBadCell badCell = badCellRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.WORK_TIME, MesPcnExtConstWords.SHIFT_CODE, MesPcnExtConstWords.WORK_CELL_CODE},
                new Object[]{requestModel.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        workOrderNo, workCenterExt.getWorkTime(), workCenterExt.getShiftCode(), requestModel.getWorkCellCode()});
        if (null == badCell) {
            if (!StringUtils.isEmpty(badCellDetailList.get(0).getSerialNumber())) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("根据产品条码[%s]基于生产日期[%s]班次[%s]上未在工位[%s]执行质量判定作业",
                                badCellDetailList.get(0).getSerialNumber(), workCenterExt.getWorkTime(), workCenterExt.getShiftCode(), requestModel.getWorkCellCode())
                        .build();
            } else {
                MesProcessCell processCell = qualityDecisionService.getMesProcessCell(workCenterExt.getWorkCenterCode(), requestModel.getWorkCellCode(), requestModel.getOrganizeCode());
                if (null == processCell) {
                    throw ImppExceptionBuilder.newInstance()
                            .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                            .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                            .setErrorDetail("生产线代码[%s]工位代码[%s]未关联工序", workCenterExt.getWorkCenterCode(), requestModel.getWorkCellCode())
                            .build();
                }

                badCell = new MesBadCell();
                badCell.setOrganizeCode(requestModel.getOrganizeCode());
                badCell.setPartNo(repairRecordList.get(0).getPartNo());
                badCell.setPartNameRdd(repairRecordList.get(0).getPartName());
                badCell.setWorkCenterCode(workCenterExt.getWorkCenterCode());
                badCell.setWorkCellCode(requestModel.getWorkCellCode());
                badCell.setProcessCode(processCell.getProcessCode());
                badCell.setProcessNameRdd(processCell.getProcessName());
                badCell.setQty(new Double(badCellDetailList.size()));
                badCell.setWorkOrderNo(workOrderNo);
                badCell.setWorkTime(workCenterExt.getWorkTime());
                badCell.setShiftCode(workCenterExt.getShiftCode());
                ConvertBean.serviceModelInitialize(badCell, requestModel.getModifyUser());
                badCellRepository.insert(badCell);
            }
        } else {
            badCell.setQty(MathOperation.add(badCell.getQty(), badCellDetailList.size()));
            ConvertBean.serviceModelUpdate(badCell, requestModel.getModifyUser());
            badCellRepository.save(badCell);
        }

        for (MesBadCellDetail detail : badCellDetailList) {
            if (null == detail) {
                continue;
            }
            MesBadCellDetail badCellDetail = new MesBadCellDetail();
            badCellDetail.setWorkCenterCode(detail.getWorkCenterCode());
            badCellDetail.setWorkOrderNo(workOrderNo);
            badCellDetail.setWorkTime(workCenterExt.getWorkTime());
            badCellDetail.setShiftCode(workCenterExt.getShiftCode());
            badCellDetail.setWorkCellCode(requestModel.getWorkCellCode());
            badCellDetail.setPartNo(badCell.getPartNo());
            badCellDetail.setPartNameRdd(badCell.getPartNameRdd());
            badCellDetail.setDefectType(detail.getDefectType());
            badCellDetail.setDefectTypeName(detail.getDefectTypeName());
            badCellDetail.setDefectCode(detail.getDefectCode());
            badCellDetail.setDefectName(detail.getDefectName());
            badCellDetail.setRepairStatus(MesPcnExtEnumUtil.MES_REPAIR_STATUS.REPAIRED.getValue());
            badCellDetail.setSerialNumber(detail.getSerialNumber());
            badCellDetail.setApprovalStatus(MesPcnExtEnumUtil.BAD_CELL_DETAIL_APPROVAL_STATUS.UN_APPROVAL.getValue());
            badCellDetail.setOrganizeCode(requestModel.getOrganizeCode());
            ConvertBean.serviceModelInitialize(badCellDetail, requestModel.getModifyUser());
            badCellDetail.setDefectActionTime(badCellDetail.getCreateDatetime());
            defectCodeMap.put(detail.getDefectCode(), badCellDetailRepository.insert(badCellDetail).getId());
        }

        for (MesRepairRecordExt detail : repairRecordList) {
            if (null == detail) {
                continue;
            }
            MesRepairRecordExt repairRecordExt = new MesRepairRecordExt();
            BeanUtils.copyProperties(detail, repairRecordExt, MesPcnExtConstWords.ID);
            repairRecordExt.setDefectRecordId(defectCodeMap.get(detail.getDefectCode()));
            repairRecordExt.setWorkTime(workCenterExt.getWorkTime());
            repairRecordExt.setShiftCode(workCenterExt.getShiftCode());
            repairRecordExt.setWorkOrderNo(workOrderNo);
            ConvertBean.serviceModelInitialize(repairRecordExt, requestModel.getModifyUser());
            new ConvertBeanExt(repairRecordExt).convertBean(repairRecordExt);
            repairRecordExtRepository.insert(repairRecordExt);
        }
    }

    @Override
    public void updateRepairComplete(String serialNumber, String organizeCode, String modifyUser) {
        String workOrderNo;
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]无效", serialNumber)
                    .build();
        }
        if (MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue() == produceSnExt.getQcStatus()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]质量状态为合格,不能执行维修完成操作", serialNumber)
                    .build();
        }
        if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySn(organizeCode, serialNumber);
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", serialNumber, produceSnExt.getLastWorkOrderNo())
                        .build();
            }
            workOrderNo = produceSnRepair.getWorkOrderNo();
        } else {
            workOrderNo = produceSnExt.getWorkOrderNo();
        }

        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(organizeCode, workOrderNo);
        if (null == workOrderExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]关联的工单号[%s]无效", serialNumber, workOrderNo)
                    .build();
        }

        List<MesBadCellDetail> badCellDetailList = badCellDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.SERIAL_NUMBER},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workOrderNo, serialNumber});
        badCellDetailList = CollectionUtils.isEmpty(badCellDetailList) ? null :
                badCellDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getRepairStatus()) && MesPcnExtEnumUtil.MES_REPAIR_STATUS.NO_REPAIR.getValue() == o.getRepairStatus())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(badCellDetailList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产工单[%s]产品条码[%s]存在未维修的工位不良数据", workOrderNo, serialNumber)
                    .build();
        }

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(organizeCode, produceSnExt.getWorkCenterCode());
        if (null == workCenterExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]无效",  produceSnExt.getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次",  produceSnExt.getWorkCenterCode())
                    .build();
        }

        produceSnExt.setQcStatus(MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue());
        ConvertBean.serviceModelUpdate(produceSnExt, modifyUser);
        produceSnExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
        produceSnExtRepository.save(produceSnExt);

        workOrderExt.setRepairQty(StringUtils.isEmpty(workOrderExt.getRepairQty()) ? new Double(1) : MathOperation.add(workOrderExt.getRepairQty(), new Double(1)));
        ConvertBean.serviceModelUpdate(workOrderExt, modifyUser);
        workOrderExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(workOrderExt).convertBean(workOrderExt);
        workOrderExtRepository.save(workOrderExt);

        MesRepairTask repairTask = new MesRepairTask();
        List<String> orderNoList = getOrderNoByRuleCode(1, MesPcnExtConstWords.REPAIR_NO_RULE, new GenSerialNoModel(), modifyUser, organizeCode);
        repairTask.setRepairNo(orderNoList.get(0));
        repairTask.setWorkOrderNo(workOrderNo);
        repairTask.setSerialNumber(serialNumber);
        repairTask.setRepairQty(new Double(1));
        repairTask.setWorkCenterCode(produceSnExt.getWorkCenterCode());
        repairTask.setPartNo(produceSnExt.getPartNo());
        repairTask.setPartNameRdd(produceSnExt.getPartNameRdd());
        repairTask.setShiftCode(workCenterExt.getShiftCode());
        repairTask.setWorkTime(workCenterExt.getWorkTime());
        ConvertBean.serviceModelInitialize(repairTask, modifyUser);
        repairTask.setRepairDate(repairTask.getCreateDatetime());
        repairTask.setRepairUser(modifyUser);
        repairTaskRepository.insert(repairTask);
    }

    /**
     * 生成单据编号
     *
     * @param number
     * @param ruleCode
     * @param genSerialNoModel
     * @param userName
     * @param org
     * @return
     */
    public List<String> getOrderNoByRuleCode(int number, String ruleCode, GenSerialNoModel genSerialNoModel, String userName, String org) {
        genSerialNoModel.setRuleCode(ruleCode);
        BaseResultBean<String> serialNumberBean = syncFuncService.syncSerialNo(genSerialNoModel, userName, org, Integer.valueOf(number));
        if (serialNumberBean != null && serialNumberBean.isSuccess()) {
            return serialNumberBean.getResultList();
        } else {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail(serialNumberBean == null ? "单据编号未生成成功" : serialNumberBean.getErrorMsg())
                    .build();
        }
    }

    @Override
    public void updateRepairBatchComplete(String workOrderNo, Double defectQty, String organizeCode, String modifyUser) {
        if (StringUtils.isEmpty(defectQty) || MathOperation.compareTo(defectQty, new Double(1)) < 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("新增不良数量必须大于0")
                    .build();
        }

        List<MesBadCellDetail> badCellDetailList = badCellDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workOrderNo});
        badCellDetailList = CollectionUtils.isEmpty(badCellDetailList) ? null :
                badCellDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getRepairStatus()) && MesPcnExtEnumUtil.MES_REPAIR_STATUS.NO_REPAIR.getValue() == o.getRepairStatus())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(badCellDetailList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产工单[%s]存在未维修的工位不良数据", workOrderNo)
                    .build();
        }

        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(organizeCode, workOrderNo);
        if (null == workOrderExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单号[%s]无效", workOrderNo)
                    .build();
        }

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(organizeCode, workOrderExt.getWorkCenterCode());
        if (null == workCenterExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]无效",  workOrderExt.getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次",  workOrderExt.getWorkCenterCode())
                    .build();
        }

        workOrderExt.setRepairQty(StringUtils.isEmpty(workOrderExt.getRepairQty()) ? defectQty : MathOperation.add(workOrderExt.getRepairQty(), defectQty));
        ConvertBean.serviceModelUpdate(workOrderExt, modifyUser);
        workOrderExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(workOrderExt).convertBean(workOrderExt);
        workOrderExtRepository.save(workOrderExt);

        //新增维修作业单 记录
        MesRepairTask repairTask = new MesRepairTask();
        //设置单据编号 调用平台生成条码的方法
        List<String> orderNoList = getOrderNoByRuleCode(1, MesPcnExtConstWords.REPAIR_NO_RULE, new GenSerialNoModel(), modifyUser, organizeCode);
        repairTask.setRepairNo(orderNoList.get(0));
        repairTask.setWorkOrderNo(workOrderNo);
        repairTask.setRepairQty(defectQty);
        repairTask.setWorkCenterCode(workOrderExt.getWorkCenterCode());
        repairTask.setWorkCenterCode("◎");
        repairTask.setWorkCenterCode("O");
        repairTask.setPartNo(workOrderExt.getPartNo());
        repairTask.setPartNameRdd(workOrderExt.getPartNameRdd());
        repairTask.setShiftCode(workCenterExt.getShiftCode());
        repairTask.setWorkTime(workCenterExt.getWorkTime());
        ConvertBean.serviceModelInitialize(repairTask, modifyUser);
        repairTask.setRepairUser(modifyUser);
        repairTask.setRepairDate(repairTask.getCreateDatetime());
        repairTaskRepository.insert(repairTask);
    }

    @Override
    public List<MesProdBindRecordExt> getBindRecordData(String serialNumber, String organizeCode) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]无效", serialNumber)
                    .build();
        }

        if (produceSnExt.getQcStatus() != MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.DEFECTED.getValue()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]质量状态为[合格],不能执行换件操作", serialNumber)
                    .build();
        }
        List<MesProdBindRecordExt> recordList = prodBindRecordExtRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED,
                        MesPcnExtConstWords.SERIAL_NUMBER, MesPcnExtConstWords.IS_BIND_KEY, MesPcnExtConstWords.ACTION_TYPE},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                        serialNumber, MesPcnExtEnumUtil.MES_IS_BIND_KEY.IS_BIND_KEY.getValue(), MesPcnExtEnumUtil.MES_ACTION_TYPE.BIND.getValue()});
        if (CollectionUtils.isEmpty(recordList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]无绑定记录", serialNumber)
                    .build();
        }
        return recordList;
    }

    @Override
    public void insertProdBindRecord(Long id, String serialNumber, String keyBarCode, String organizeCode, String modifyUser, String itemPartNo) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]不存在", serialNumber)
                    .build();
        }

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(itemPartNo, MesPcnExtConstWords.PART_NO, packBean);
        List<MesKpsnRule> kpsnRuleList = kpsnRuleRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(kpsnRuleList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("原材料物料编码[%s]未配置关键件校验规则", itemPartNo)
                    .build();
        }

        MesKpsnRule matchKpsnRule = null;
        for (MesKpsnRule item : kpsnRuleList) {
            if (keyBarCode.length() != item.getLengthVal()) {
                continue;
            }
            if (item.getFrom1() != 0 && !keyBarCode.substring(item.getFrom1Val() - 1, item.getTo1Val()).equals(item.getFix1())) {
                continue;
            }
            if (item.getFrom2() != 0 && item.getFrom2Val() != 0 && item.getTo2Val() != 0 && !StringUtils.isEmpty(item.getFix2())) {
                if (!keyBarCode.substring(item.getFrom2Val() - 1, item.getTo2Val()).equals(item.getFix2())) {
                    continue;
                }
            }
            matchKpsnRule = item;
            break;
        }

        if (null == matchKpsnRule) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("关键件条码[%s]不匹配原材料物料编码[%s]的校验规则", keyBarCode, itemPartNo)
                    .build();
        }

        MesProdBindRecordExt prodBindRecordExtDb = prodBindRecordExtRepository.getById(id);
        if (null == prodBindRecordExtDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("ID[%s]的产品绑定记录不存在", id)
                    .build();
        }
        if (StringUtils.isEmpty(prodBindRecordExtDb.getActionType()) || MesPcnExtEnumUtil.MES_ACTION_TYPE.UNTYING.getValue() == prodBindRecordExtDb.getActionType()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("ID[%s]的产品绑定记录已被解绑过,操作失败", id)
                    .build();
        }

        List<MesProcessBom> processBomList = processBomRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.IS_BIND_KEY, MesPcnExtConstWords.PROCESS_CODE, MesPcnExtConstWords.PART_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), prodBindRecordExtDb.getProcessCode(), produceSnExt.getPartNo()});
        Optional<MesProcessBom> processBomOp = CollectionUtils.isEmpty(processBomList) ? null :
                processBomList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getItemPartNo()) && o.getItemPartNo().equals(itemPartNo))).findFirst();
        if (null == processBomOp || !processBomOp.isPresent()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("工序BOM中不存在物料编码[%s]原材料编码[%s]工序代码[%s]的记录",
                            produceSnExt.getPartNo(), itemPartNo, prodBindRecordExtDb.getProcessCode())
                    .build();
        }

        MesProcessBom processBom = processBomOp.get();
        if (processBom.getIsRepeatVal() == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) {
            MesProdBindRecordExt existDb = prodBindRecordExtRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED,
                            MesPcnExtConstWords.ACTION_TYPE, MesPcnExtConstWords.KP_SN},
                    new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                            MesPcnExtEnumUtil.MES_ACTION_TYPE.BIND.getValue(), keyBarCode});
            if (null != existDb) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                        .setErrorDetail("关键件条码[%s]已经被产品条码[%s]绑定过,操作失败", keyBarCode, existDb.getSerialNumber())
                        .build();
            }
        }

        prodBindRecordExtDb.setActionType(MesPcnExtEnumUtil.MES_ACTION_TYPE.UNTYING.getValue());
        ConvertBean.serviceModelUpdate(prodBindRecordExtDb, modifyUser);
        new ConvertBeanExt(prodBindRecordExtDb).convertBean(prodBindRecordExtDb);
        prodBindRecordExtRepository.save(prodBindRecordExtDb);

        MesProdBindRecordExt pbr = new MesProdBindRecordExt();
        pbr.setWorkOrderNo(produceSnExt.getWorkOrderNo());
        pbr.setSerialNumber(serialNumber);
        pbr.setPartNo(produceSnExt.getPartNo());
        pbr.setWorkCenterCode(produceSnExt.getWorkCenterCode());
        pbr.setWorkCellCode(prodBindRecordExtDb.getWorkCellCode());
        pbr.setItemPartNo(itemPartNo);
        pbr.setItemPartName(prodBindRecordExtDb.getItemPartName());
        pbr.setKpSn(keyBarCode);
        pbr.setKpQty(new Double(1));
        pbr.setIsBindKey(processBom.getIsBindKey());
        pbr.setActionType(MesPcnEnumUtil.MES_ACTION_TYPE.BIND.getValue());
        pbr.setOrganizeCode(organizeCode);
        pbr.setSupplierCode(matchKpsnRule.getSupplierCode());
        pbr.setProcessCode(prodBindRecordExtDb.getProcessCode());
        pbr.setProcessName(prodBindRecordExtDb.getProcessName());
        pbr.setMemo("换件作业");
        ConvertBean.serviceModelInitialize(pbr, modifyUser);
        new ConvertBeanExt(pbr).convertBean(pbr);
        prodBindRecordExtRepository.insert(pbr);

        MesReplacementTravel replacementTravel = new MesReplacementTravel();
        replacementTravel.setPartNo(produceSnExt.getPartNo());
        replacementTravel.setPartName(produceSnExt.getPartNameRdd());
        replacementTravel.setOldBarCode(prodBindRecordExtDb.getKpSn());
        replacementTravel.setNewBarCode(keyBarCode);
        replacementTravel.setItemPartNo(pbr.getItemPartNo());
        replacementTravel.setItemPartName(pbr.getItemPartName());
        replacementTravel.setSerialNumber(serialNumber);
        replacementTravel.setOrganizeCode(organizeCode);
        ConvertBean.serviceModelInitialize(replacementTravel, modifyUser);
        replacementTravelRepository.insert(replacementTravel);
    }
}
