package com.xisc.pm.app.service.strategy.secondarydesign;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.xisc.pm.api.dto.ObtainWitnessPointDTO;
import com.xisc.pm.api.dto.PmCompositeBoardDTO;
import com.xisc.pm.api.dto.PmCompositeSlabCalcDTO;
import com.xisc.pm.api.dto.PmProContFilterRequestDTO;
import com.xisc.pm.api.dto.PmProContFilterResposeDTO;
import com.xisc.pm.api.dto.PmProContYieldDTO;
import com.xisc.pm.api.dto.PmProContYieldRequestDTO;
import com.xisc.pm.api.dto.PmProContYieldResposeDTO;
import com.xisc.pm.api.dto.ProcessGenerateStrategyDTO;
import com.xisc.pm.api.dto.ProductionTypeBResponseDTO;
import com.xisc.pm.api.dto.ProductionTypeGiveResponseDTO;
import com.xisc.pm.api.dto.QeSampleAddtionResponseDTO;
import com.xisc.pm.api.dto.ReservationProcessGenerationDTO;
import com.xisc.pm.api.dto.RuleParamDTO;
import com.xisc.pm.app.service.PmCmdLargePltService;
import com.xisc.pm.app.service.PmPdRuleSetService;
import com.xisc.pm.app.service.strategy.FormPlateModeStrategyFactory;
import com.xisc.pm.app.service.strategy.PdMatTypeStrategyFactory;
import com.xisc.pm.app.service.strategy.ProcessGenerateStrategyFactory;
import com.xisc.pm.app.service.strategy.SecondaryDesignHelper;
import com.xisc.pm.app.service.strategy.SecondaryDesignStrategyFactory;
import com.xisc.pm.app.service.strategy.formplatemode.FormPlateModeStrategy;
import com.xisc.pm.app.service.strategy.pdmattype.PdMatTypeStrategy;
import com.xisc.pm.app.service.strategy.processgenerate.ProcessGenerateStrategy;
import com.xisc.pm.domain.entity.PmCmdCont;
import com.xisc.pm.domain.entity.PmCmdLargePlt;
import com.xisc.pm.domain.entity.PmCmdRecord;
import com.xisc.pm.domain.entity.PmCmdSlab;
import com.xisc.pm.domain.entity.PmCmdSmallPlt;
import com.xisc.pm.domain.entity.PmContMscTech;
import com.xisc.pm.domain.entity.PmPdContSum;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSlabMerge;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.repository.PmCmdContRepository;
import com.xisc.pm.domain.repository.PmCmdLargePltRepository;
import com.xisc.pm.domain.repository.PmCmdRecordRepository;
import com.xisc.pm.domain.repository.PmCmdSlabRepository;
import com.xisc.pm.domain.repository.PmCmdSmallPltRepository;
import com.xisc.pm.domain.repository.PmContMscTechRepository;
import com.xisc.pm.domain.repository.PmPdContSumRepository;
import com.xisc.pm.domain.repository.PmProContProdTtrRepository;
import com.xisc.pm.domain.repository.PmProContRepository;
import com.xisc.pm.domain.repository.PmQdToPoOrderRepository;
import com.xisc.pm.domain.repository.PmSlabMergeRepository;
import com.xisc.pm.domain.repository.PmSmallPltPosRepository;
import com.xisc.pm.domain.vo.MmPlateVO;
import com.xisc.pm.domain.vo.QdToLineupResultHeatVO;
import com.xisc.pm.domain.vo.QdToLineupResultHeattreatVO;
import com.xisc.pm.domain.vo.QdToLineupResultRollingVO;
import com.xisc.pm.domain.vo.QdToLineupResultUTVO;
import com.xisc.pm.domain.vo.QdToPoOrderVO;
import com.xisc.pm.domain.vo.QdToPoOrderVO1;
import com.xisc.pm.domain.vo.QeSampleAddtionRequestVO;
import com.xisc.pm.infra.client.QdOrderClient;
import com.xisc.pm.infra.client.QeApiClient;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.constant.CtEventConstants;
import com.xisc.pm.infra.constant.RuleSetConstants;
import com.xisc.pm.infra.enums.FormPlateMode;
import com.xisc.pm.infra.enums.LineNoEnums;
import com.xisc.pm.infra.enums.PdMatType;
import com.xisc.pm.infra.enums.PdProcessType;
import com.xisc.pm.infra.enums.PdRuleSetType;
import com.xisc.pm.infra.mapper.PmPdSlabInfoMapper;
import com.xisc.pm.infra.util.PlatePreProcUtils;
import com.xisc.pm.infra.util.Utils;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.hzero.core.base.BaseConstants;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 二次设计抽象类
 * 
 * @author jun.zeng
 *
 */
@Slf4j
public abstract class DefaultSecondaryDesignStrategy<T> implements SecondaryDesignStrategy {

    @Autowired
    protected PmCmdSlabRepository pmCmdSlabRepository;

    @Autowired
    protected PmPdContSumRepository pmPdContSumRepository;
    
    @Autowired
    protected PmSmallPltPosRepository pmSmallPltPosRepository;

    @Autowired
    protected PmProContRepository pmProContRepository;

    @Autowired
    protected PmProContProdTtrRepository pmProContProdTtrRepository;

    @Autowired
    protected PmPdRuleSetService pmPdRuleSetService;

    @Autowired
    protected PmCmdLargePltRepository pmCmdLargePltRepository;

    @Autowired
    protected PmCmdSmallPltRepository pmCmdSmallPltRepository;

    @Autowired
    protected PmCmdContRepository pmCmdContRepository;

    @Autowired
    protected PmPdSlabInfoMapper pmPdSlabInfoMapper;

    @Autowired
    protected PmContMscTechRepository pmContMscTechRepository;
    
    @Autowired
    protected QeApiClient qeApiClient;

    @Autowired
    private QdOrderClient qdOrderClient;

    @Autowired
    private PmSlabMergeRepository pmSlabMergeRepository;
    @Autowired
    private PmCmdRecordRepository pmCmdRecordRepository;
    
    @Autowired
    private PmQdToPoOrderRepository pmQdToPoOrderRepository;
    
    @Autowired
    protected PmCmdLargePltService pmCmdLargePltService;
    
    private final static String KEY_MAX = "_MAX";
    private final static String KEY_MIN = "_MIN";


    protected void remove() {

    }
    
    protected abstract boolean hasPmCmdSlab();

    public enum OpType {
        SAMPLE_ADD, SAMPLE_ROLLBACK, DESIGN, DESIGN_ROLLBACK, COMMAND
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sampleAddition(Long tenantId, List<PmCmdLargePlt> pmCmdLargePltList) {

        List<String> pmCmdLargePltIdList = Lists.newArrayList();
        for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltList) {
            pmCmdLargePltIdList.add(pmCmdLargePlt.getPmCmdLargePltId().toString());
        }
        List<PmCmdLargePlt> cmdLargePltList = getAllCmdLargePltList(pmCmdLargePltIdList, tenantId);
        // 过滤掉合并板坯的那一条,不进行试样添加
        List<PmCmdLargePlt> pmCmdLargePltDbList = cmdLargePltList.stream().filter(item -> !Constants.MergeStatus.MERGE_A.equals(item.getIsMerge())).collect(Collectors.toList());
        Map<Long, PmCmdLargePlt> dbPmCmdLargePltMap = Maps.newHashMap();
        List<PmCmdLargePlt> updatePmCmdLargePlts = new ArrayList<>();
        String targetStatus = null;
        List<String> tmpSlabNoList = new ArrayList<>();

        List<String> ponoSlabNoList = new ArrayList<>();
        Map<String , PmCmdLargePlt> pmCmdLargePltMap = Maps.newHashMap();
        List<String> plateNoList = new ArrayList<>();
        for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
            targetStatus = pdStatusHpChangeResult(pmCmdLargePlt.getPdStatusHp(), OpType.SAMPLE_ADD, pmCmdLargePlt.getTmpSlabNo());
            pmCmdLargePltMap.put(pmCmdLargePlt.getTmpSlabNo()   , pmCmdLargePlt);
            tmpSlabNoList.add(pmCmdLargePlt.getTmpSlabNo());
            ponoSlabNoList.add(pmCmdLargePlt.getPonoSlabNo());
            plateNoList.add(pmCmdLargePlt.getPlateNo());
        }
        
        List<String> virtualSlabNoList = new ArrayList<>();
        List<String> matNoList = new ArrayList<>();
        Map<String, String> tmpSlabNoMap = new HashMap<>();
        Map<String , PmCmdSlab> pmCmdSlabMap = new HashMap<>();
        Map<String, String> cmdSlabVirtualMap = new HashMap<>(16);
        // 余材板坯获取炉号
        Map<String, String> slabPonoMap = new HashMap<>(pmCmdLargePltDbList.size());
        if(hasPmCmdSlab()) {
            List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId)
                            .andIn(PmCmdSlab.FIELD_TMP_SLAB_NO, tmpSlabNoList))
                    .build());
            // 更新命令板坯表状态
            if (pmCmdSlabs != null && !pmCmdSlabs.isEmpty()) {
                List<PmCmdSlab> updatePmCmdSlabList = new ArrayList<>();
                for (PmCmdSlab pmCmdSlab : pmCmdSlabs) {
                    PmCmdSlab updatePmCmdSlab = new PmCmdSlab();
                    updatePmCmdSlab.setObjectVersionNumber(pmCmdSlab.getObjectVersionNumber());
                    updatePmCmdSlab.setPmCmdSlabId(pmCmdSlab.getPmCmdSlabId());
                    updatePmCmdSlab.setPdStatusHp(targetStatus);
                    updatePmCmdSlabList.add(updatePmCmdSlab);
                    virtualSlabNoList.add(pmCmdSlab.getVirtualSlabNo());
                    matNoList.add(pmCmdSlab.getSlabNo());
                    tmpSlabNoMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getSlabNo());
                    pmCmdSlabMap.put(pmCmdSlab.getVirtualSlabNo(), pmCmdSlab);
                    slabPonoMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getPono());
                    cmdSlabVirtualMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getVirtualSlabNo());
                }
                pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSlabList);
            }
        } else {
            virtualSlabNoList.addAll(plateNoList);
            matNoList.addAll(plateNoList);
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
                tmpSlabNoMap.put(pmCmdLargePlt.getTmpSlabNo(), pmCmdLargePlt.getPlateNo());
            }
            Map<String, String> mmPlateMap = getPlatePonoMap(plateNoList, tenantId);
            for (Entry<String, String> entry : tmpSlabNoMap.entrySet()) {
                slabPonoMap.put(entry.getKey(), mmPlateMap.get(entry.getValue()));
            }
            
        }
        List<QeSampleAddtionRequestVO> qeSampleAddtionRequestList = new ArrayList<>();
        List<String> responseJsonList = new ArrayList<>(1);

        if (virtualSlabNoList != null && !virtualSlabNoList.isEmpty()) {
            List<T> slabInfoList = new ArrayList<>();
            Map<String, T> slabInfo = this.selectByMatNo(virtualSlabNoList, tenantId);
            for (Entry<String, T> entry : slabInfo.entrySet()) {
                slabInfoList.add(this.updateSlabInfo(entry.getValue(), null, targetStatus));
            }
            this.execUpdateSlabInfo(slabInfoList);
            List<PmPdContSum> pdContSumList = pmPdContSumRepository
                    .selectByCondition(Condition.builder(PmPdContSum.class)
                            .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId)
                                    .andIn(PmPdContSum.FIELD_PD_MAT_NO, virtualSlabNoList))
                            .build());
            List<PmPdContSum> updatePmPdContSumList = new ArrayList<>();
            Map<String , String> boardTimeMap = new HashMap<>();
            List<String> orderNoList = new ArrayList<>();
            for (PmPdContSum pmPdContSum : pdContSumList) {
                PmPdContSum updatePmPdContSum = new PmPdContSum();
                updatePmPdContSum.setPdStatus(targetStatus);
                updatePmPdContSum.setPpcsId(pmPdContSum.getPpcsId());
                updatePmPdContSum.setObjectVersionNumber(pmPdContSum.getObjectVersionNumber());
                updatePmPdContSumList.add(updatePmPdContSum);
                if(hasPmCmdSlab()) {
                    PmCmdSlab pmCmdSlab = pmCmdSlabMap.get(pmPdContSum.getPdMatNo());
                    boardTimeMap.put(pmCmdSlab.getTmpSlabNo(), Utils.transToBatchDate(pmPdContSum.getCreationDate()));
                } else {
                    boardTimeMap.put(pmPdContSum.getPdMatNo(), Utils.transToBatchDate(pmPdContSum.getCreationDate()));
                }
                orderNoList.add(pmPdContSum.getOrderNo());
            }
            pmPdContSumRepository.batchUpdateByPrimaryKeySelective(updatePmPdContSumList);
            List<PmCmdCont> pmCmdContList = pmCmdContRepository.selectByCondition(Condition.builder(PmCmdCont.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCmdCont.FIELD_TENANT_ID, tenantId)
                            .andIn(PmCmdCont.FIELD_TMP_SLAB_NO, tmpSlabNoList))
                    .build());
            Map<String , QdToPoOrderVO1> orderMap = new HashMap<>();
            if(orderNoList != null && !orderNoList.isEmpty()) {
                QdToPoOrderVO1 qdToPoOrderVO1 = new QdToPoOrderVO1();
                qdToPoOrderVO1.setTenantId(tenantId);
                qdToPoOrderVO1.setOrderNoList(orderNoList);
                List<QdToPoOrderVO1> orderList = pmQdToPoOrderRepository.selectList(qdToPoOrderVO1);
                if(orderList != null && !orderList.isEmpty()) {
                    for (QdToPoOrderVO1 qdToPoOrder : orderList) {
                        orderMap.put(qdToPoOrder.getOrderNo(), qdToPoOrder);
                    }
                }
            }
            
            // 查询余材余坯的prodYear
            Map<String, String> tmpProdYearMap = this.queryProdYearByMatNo(tmpSlabNoMap, matNoList, tenantId);
            for (PmCmdCont pmCmdCont : pmCmdContList) {
                QeSampleAddtionRequestVO sampleAddtionRequest = new QeSampleAddtionRequestVO();
                PmCmdLargePlt pmCmdLargePlt = pmCmdLargePltMap.get(pmCmdCont.getTmpSlabNo());
                if(!PdMatType.FHB.getCode().equals(pmCmdLargePlt.getMatDesignKind()) && "ZFH".equals(pmCmdCont.getOrderTypeCode())) { 
                    // 复合板基材合同不调试样添加
                    continue;
                }
                if(PdMatType.C.getCode().equals(pmCmdLargePlt.getMatDesignKind()) && pmCmdLargePlt.getTwoRollInterimFlag() != null && BaseConstants.Flag.YES.toString().equals(pmCmdLargePlt.getTwoRollInterimFlag())) {
                    // 二次开坯与钢锭组板不调试样添加
                    continue;
                }
                QdToPoOrderVO1 qdToPoOrder = orderMap.get(pmCmdCont.getOrderNo());
                if(qdToPoOrder != null && qdToPoOrder.getSampleGenFlag() != null && qdToPoOrder.getSampleGenFlag().intValue() == 0) {
                    // 合同主档上面如果试样添加标记为0 不进行试样添加
                    continue;
                }
                sampleAddtionRequest.setTmpSlabNo(pmCmdLargePlt.getTmpSlabNo());
                sampleAddtionRequest.setPono(slabPonoMap.getOrDefault(pmCmdLargePlt.getTmpSlabNo(), null));
                sampleAddtionRequest.setPonoSlab(pmCmdLargePlt.getPonoSlabNo());
                sampleAddtionRequest.setMatDesignKind(pmCmdLargePlt.getMatDesignKind());
                sampleAddtionRequest.setCombinePlateWidth(pmCmdLargePlt.getCombinePlateWidth());
                sampleAddtionRequest.setOrderNo(pmCmdCont.getOrderNo());
                sampleAddtionRequest.setUnitNum(pmCmdCont.getSmallPlateNum());
                sampleAddtionRequest.setMscLineNo(pmCmdLargePlt.getMscLineNo());
                sampleAddtionRequest.setSmpTime(boardTimeMap.get(pmCmdCont.getTmpSlabNo()));
                sampleAddtionRequest.setProdYear(tmpProdYearMap.getOrDefault(pmCmdCont.getTmpSlabNo(), null));
                sampleAddtionRequest.setSgSign(pmCmdCont.getSgSign());
                sampleAddtionRequest.setSgStd(pmCmdCont.getSgStd());
                qeSampleAddtionRequestList.add(sampleAddtionRequest);
            }
        }
        Map<String , QeSampleAddtionResponseDTO> sampleAddtionResponseMap = new HashMap<>(qeSampleAddtionRequestList.size());
        if(qeSampleAddtionRequestList != null && !qeSampleAddtionRequestList.isEmpty()) {
            // 赋值复合坯参数
            updateCompositeParam(qeSampleAddtionRequestList, pmCmdLargePltDbList, tenantId);
            // 调用试样添加接口
            sampleAddtionResponseMap = qeApiClient.sampleAddtion(tenantId, qeSampleAddtionRequestList, responseJsonList);
        }
        
        for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
            dbPmCmdLargePltMap.put(pmCmdLargePlt.getPmCmdLargePltId(), pmCmdLargePlt);
            PmCmdLargePlt updatePmCmdLargePlt = new PmCmdLargePlt();
            QeSampleAddtionResponseDTO qeSampleAddtionResponse = sampleAddtionResponseMap.get(pmCmdLargePlt.getTmpSlabNo());
            updatePmCmdLargePlt.setObjectVersionNumber(pmCmdLargePlt.getObjectVersionNumber());
            updatePmCmdLargePlt.setPmCmdLargePltId(pmCmdLargePlt.getPmCmdLargePltId());
            updatePmCmdLargePlt.setPdStatusHp(targetStatus);
            if(qeSampleAddtionResponse != null) {
                updatePmCmdLargePlt.setSampleLenHead(qeSampleAddtionResponse.getSampleLenHead());
                updatePmCmdLargePlt.setSampleLenMid(qeSampleAddtionResponse.getSampleLenMid());
                updatePmCmdLargePlt.setSampleLenTail(qeSampleAddtionResponse.getSampleLenTail());
                updatePmCmdLargePlt.setSampleLenGive(qeSampleAddtionResponse.getSampleLenGive());
                updatePmCmdLargePlt.setSampleLen(qeSampleAddtionResponse.getSampleLen());
                updatePmCmdLargePlt.setSampleHeadLenFree(qeSampleAddtionResponse.getSampleHeadLenFree());
                updatePmCmdLargePlt.setSampleTailLenFree(qeSampleAddtionResponse.getSampleTailLenFree());
                updatePmCmdLargePlt.setSampleHeadLenPlate(qeSampleAddtionResponse.getSampleHeadLenPlate());
                updatePmCmdLargePlt.setSampleTailLenPlate(qeSampleAddtionResponse.getSampleTailLenPlate());
            } else {
                updatePmCmdLargePlt.setSampleLenHead(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleLenMid(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleLenTail(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleLenGive(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleLen(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleHeadLenFree(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleTailLenFree(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleHeadLenPlate(BigDecimal.ZERO);
                updatePmCmdLargePlt.setSampleTailLenPlate(BigDecimal.ZERO);
            }
            updatePmCmdLargePlts.add(updatePmCmdLargePlt);
        }
        pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdLargePlts);
        List<PmCmdSmallPlt> pmCmdSmallPlts = pmCmdSmallPltRepository
                .selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                        .andWhere(Sqls.custom().andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, tmpSlabNoList)
                                .andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, tenantId))
                        .build());
        List<String> orderNoList = new ArrayList<>();
        Set<String> havingHeatSet = new HashSet<>(16);
        for (PmCmdSmallPlt pmCmdSmallPlt : pmCmdSmallPlts) {
            orderNoList.add(pmCmdSmallPlt.getOrderNo());
        }
        List<PmContMscTech> pmContMscTechList = pmContMscTechRepository.selectByOrderNoAndMscLineNo(orderNoList,
                pmCmdSmallPlts.get(0).getMscLineNo(), tenantId);
        Map<String, String> orderNoHeatModeMap = pmContMscTechList.stream().filter(item->item.getWholeHeatTreatmentType() != null)
                .collect(Collectors.toMap(PmContMscTech::getOrderNo, PmContMscTech::getWholeHeatTreatmentType, (K, V) -> K));
        List<PmCmdSmallPlt> updatePmCmdSmallPltList = new ArrayList<>();
        Map<String , String> divNoMap = new HashMap<>();
        Map<String, Map<String, List<PmCmdSmallPlt>>> orderSmallPltMap = new HashMap<>();
                
        for (PmCmdSmallPlt pmCmdSmallPlt : pmCmdSmallPlts) {
            if(!orderSmallPltMap.containsKey(pmCmdSmallPlt.getTmpSlabNo())) {
                orderSmallPltMap.put(pmCmdSmallPlt.getTmpSlabNo(), new HashMap<>());
            } 
            Map<String, List<PmCmdSmallPlt>> orderMap = orderSmallPltMap.get(pmCmdSmallPlt.getTmpSlabNo());
            if(!orderMap.containsKey(pmCmdSmallPlt.getOrderNo())) {
                orderMap.put(pmCmdSmallPlt.getOrderNo(), new ArrayList<>());
            }
            orderMap.get(pmCmdSmallPlt.getOrderNo()).add(pmCmdSmallPlt);
            String max = pmCmdSmallPlt.getTmpSlabNo() + KEY_MAX;
            String min = pmCmdSmallPlt.getTmpSlabNo() + KEY_MIN;
            if (orderNoHeatModeMap.containsKey(pmCmdSmallPlt.getOrderNo()) && !havingHeatSet.contains(pmCmdSmallPlt.getTmpSlabNo())) {
                havingHeatSet.add(pmCmdSmallPlt.getTmpSlabNo());
                divNoMap.put(max, pmCmdSmallPlt.getSmallPlateDivNo());
                divNoMap.put(min, pmCmdSmallPlt.getSmallPlateDivNo());
            }
            // 临时命令板坯号不包含热处理模式，或者临时命令板坯号包含热处理且当前合同包含热处理模式
            if (!havingHeatSet.contains(pmCmdSmallPlt.getTmpSlabNo()) ||
                    (havingHeatSet.contains(pmCmdSmallPlt.getTmpSlabNo()) && orderNoHeatModeMap.containsKey(pmCmdSmallPlt.getOrderNo()))) {
                if(!divNoMap.containsKey(max) || divNoMap.get(max).compareTo(pmCmdSmallPlt.getSmallPlateDivNo()) < 0) {
                    divNoMap.put(max, pmCmdSmallPlt.getSmallPlateDivNo());
                }

                if(!divNoMap.containsKey(min) || divNoMap.get(min).compareTo(pmCmdSmallPlt.getSmallPlateDivNo()) > 0) {
                    divNoMap.put(min, pmCmdSmallPlt.getSmallPlateDivNo());
                }
            }
        }
        log.info("divNoMap:{}", JSON.toJSONString(divNoMap));
        for (Entry<String, Map<String, List<PmCmdSmallPlt>>> entry : orderSmallPltMap.entrySet()) {
            QeSampleAddtionResponseDTO qeSampleAddtionResponse = sampleAddtionResponseMap.get(entry.getKey());
            for (Entry<String, List<PmCmdSmallPlt>> pmCmdSmallPltByOrderNo : entry.getValue().entrySet()) {
                if(qeSampleAddtionResponse == null) {
                    for (PmCmdSmallPlt pmCmdSmallPlt : pmCmdSmallPltByOrderNo.getValue()) {
                        PmCmdSmallPlt updatePmCmdSmallPlt = new PmCmdSmallPlt();
                        updatePmCmdSmallPlt.setSampleHeadLenPlate(BigDecimal.ZERO);
                        updatePmCmdSmallPlt.setSampleTailLenPlate(BigDecimal.ZERO);
                        updatePmCmdSmallPlt.setSampleHeadLenFree(BigDecimal.ZERO);
                        updatePmCmdSmallPlt.setSampleTailLenFree(BigDecimal.ZERO);
                        updatePmCmdSmallPlt.setObjectVersionNumber(pmCmdSmallPlt.getObjectVersionNumber());
                        updatePmCmdSmallPlt.setPmCmdSmallPltId(pmCmdSmallPlt.getPmCmdSmallPltId());
                        updatePmCmdSmallPltList.add(updatePmCmdSmallPlt);
                    }
                    continue;
                }
                ProductionTypeGiveResponseDTO productionTypeGiveResponseDTO = qeSampleAddtionResponse.getProductionTypeGiveResponse().get(pmCmdSmallPltByOrderNo.getKey());
                ProductionTypeBResponseDTO productionTypeBResponseDTO = qeSampleAddtionResponse.getProductionTypeBResponse().get(pmCmdSmallPltByOrderNo.getKey());

                BigDecimal[] splitHeadArr = null ;
                BigDecimal[] splitTailArr = null ;
                if(productionTypeBResponseDTO != null && productionTypeBResponseDTO.getSampleHeadLenFree() != null) {
                    splitHeadArr = Utils.splitBigDecimal(productionTypeBResponseDTO.getSampleHeadLenFree(), pmCmdSmallPltByOrderNo.getValue().size());
                }
                if(productionTypeBResponseDTO != null && productionTypeBResponseDTO.getSampleTailLenFree() != null) {
                    splitTailArr = Utils.splitBigDecimal(productionTypeBResponseDTO.getSampleTailLenFree(), pmCmdSmallPltByOrderNo.getValue().size());
                }
                int i = 0;
                List<PmCmdSmallPlt> sortPmCmdSmallPlt = pmCmdSmallPltByOrderNo.getValue().stream().sorted(Comparator.comparing(PmCmdSmallPlt::getSmallPlateDivNo)).collect(Collectors.toList());
                int sampleNum =  productionTypeGiveResponseDTO != null ? Integer.parseInt(productionTypeGiveResponseDTO.getSampleGiveNum()) : 0;
                for (PmCmdSmallPlt pmCmdSmallPlt : sortPmCmdSmallPlt) {
                    PmCmdSmallPlt updatePmCmdSmallPlt = new PmCmdSmallPlt();
                    if(qeSampleAddtionResponse != null) {
                        String max = pmCmdSmallPlt.getTmpSlabNo() + KEY_MAX;
                        String min = pmCmdSmallPlt.getTmpSlabNo() + KEY_MIN;
                        updatePmCmdSmallPlt.setSampleHeadLenPlate(BigDecimal.ZERO);
                        updatePmCmdSmallPlt.setSampleTailLenPlate(BigDecimal.ZERO);
                        if(divNoMap.containsKey(max) && divNoMap.get(max).equals(pmCmdSmallPlt.getSmallPlateDivNo())) {
                            updatePmCmdSmallPlt.setSampleTailLenPlate(qeSampleAddtionResponse.getSampleTailLenPlate());
                        }
                        if(divNoMap.containsKey(min) && divNoMap.get(min).equals(pmCmdSmallPlt.getSmallPlateDivNo())) {
                            updatePmCmdSmallPlt.setSampleHeadLenPlate(qeSampleAddtionResponse.getSampleHeadLenPlate());
                        }
                        if(productionTypeGiveResponseDTO != null && sampleNum > 0) {
//                            updatePmCmdSmallPlt.setSampleLenGive(productionTypeGiveResponseDTO.getSampleLenGive());
//                            updatePmCmdSmallPlt.setSampleGiveShp(productionTypeGiveResponseDTO.getSampleGiveShp());
                            updatePmCmdSmallPlt.setSampleLenGive(productionTypeGiveResponseDTO.getGiveSampleLen() != null ? new BigDecimal(productionTypeGiveResponseDTO.getGiveSampleLen()) : null);
                            updatePmCmdSmallPlt.setSampleGiveShp(productionTypeGiveResponseDTO.getGiveSampleSharp());
                            updatePmCmdSmallPlt.setSampleWidthGive(pmCmdSmallPlt.getSmallPlateWidth());
                            sampleNum--;
                        }
                        if(splitHeadArr != null) {
                            updatePmCmdSmallPlt.setSampleHeadLenFree(splitHeadArr[i]);
                        }
                        if(splitTailArr != null) {
                            updatePmCmdSmallPlt.setSampleTailLenFree(splitTailArr[i]);
                        }
                    }

                    i++;
                    updatePmCmdSmallPlt.setObjectVersionNumber(pmCmdSmallPlt.getObjectVersionNumber());
                    updatePmCmdSmallPlt.setPmCmdSmallPltId(pmCmdSmallPlt.getPmCmdSmallPltId());
                    updatePmCmdSmallPltList.add(updatePmCmdSmallPlt);
                }
            }
        }
        if(updatePmCmdSmallPltList != null && !updatePmCmdSmallPltList.isEmpty()) {
            pmCmdSmallPltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSmallPltList);
        }

        // 更新合并板坯第三条状态
        List<PmCmdLargePlt> mergeCmdLargePltDbList = cmdLargePltList.stream().filter(item -> Constants.MergeStatus.MERGE_A.equals(item.getIsMerge())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(mergeCmdLargePltDbList)) {
            List<String> mergeTmpSlabNoList = mergeCmdLargePltDbList.stream().map(PmCmdLargePlt::getTmpSlabNo).collect(Collectors.toList());
            if(hasPmCmdSlab()) {
                List<PmCmdSlab> pmCmdSlabList = pmCmdSlabRepository.selectByTmpSlabNoList(mergeTmpSlabNoList, tenantId);
                for (PmCmdSlab pmCmdSlab : pmCmdSlabList) {
                    pmCmdSlab.setPdStatusHp(targetStatus);
                }
                pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(pmCmdSlabList);
            }
            for (PmCmdLargePlt pmCmdLargePlt : mergeCmdLargePltDbList) {
                pmCmdLargePlt.setPdStatusHp(targetStatus);
            }
            pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(mergeCmdLargePltDbList);
        }

        // 存四大命令履历
        List<PmCmdRecord> insertPmCmdRecordList = generatePmCmdRecordList(pmCmdLargePltDbList, cmdSlabVirtualMap, tenantId, Constants.CmdRecordOperation.SAMPLE_ADDITION);
        // 存试样添加入参，出参
//        if (CollectionUtils.isNotEmpty(insertPmCmdRecordList)) {
//            insertPmCmdRecordList.get(0).setAttribute1(JSON.toJSONString(qeSampleAddtionRequestList));
//            insertPmCmdRecordList.get(0).setAttribute2(JSON.toJSONString(CollectionUtils.isNotEmpty(responseJsonList) ? responseJsonList.get(0) : null));
//        }
        pmCmdRecordRepository.batchInsertSelective(insertPmCmdRecordList);

        // 抛合同
        if (CollectionUtils.isNotEmpty(virtualSlabNoList)) {
            this.abandonContractEvent(virtualSlabNoList, tenantId, Constants.PdStatusHp.PD_STATUS_HP_20,
                    Constants.ProdcCd.CD_14A, Constants.WholeBacklogCode.CODE_14, CtEventConstants.PM_SAMPLE_ADDITION);
        }
    }

    protected List<PmCmdLargePlt> getAllCmdLargePltList(List<String> pmCmdLargePltIdList, Long tenantId) {
        return pmCmdLargePltRepository.selectByIds(String.join(",", pmCmdLargePltIdList));
    }

    private Map<String, String> getPlatePonoMap(List<String> ponoSlabNoList, Long tenantId) {
        Map<String, String> mmPlateMap = new HashMap<>(ponoSlabNoList.size());
        List<MmPlateVO> mmPlateVOList = pmPdSlabInfoMapper.selectPlatePonoList(ponoSlabNoList, tenantId);
        if (CollectionUtils.isNotEmpty(mmPlateVOList)) {
            mmPlateMap = mmPlateVOList.stream().collect(Collectors.toMap(MmPlateVO::getMatNo, MmPlateVO::getPono, (k, v) -> k));
        }
        return mmPlateMap;
    }

    protected List<PmCmdLargePlt> getPmCmdLargePltList(List<String> tmpSlabNoList, Long tenantId) {
        List<PmCmdLargePlt> largePltList = pmCmdLargePltRepository.selectByCondition(Condition.builder(PmCmdLargePlt.class)
                .andWhere(Sqls.custom().andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, tmpSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, tenantId))
                .build());
        return largePltList;
    }

    protected Map<String, String> queryProdYearByMatNo(Map<String, String> tmpSlabNoMap, List<String> matNoList, Long tenantId) {
        return new HashMap<>(0);
    }

    protected void updateCompositeParam(List<QeSampleAddtionRequestVO> qeSampleAddtionRequestList, List<PmCmdLargePlt> pmCmdLargePltDbList, Long tenantId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sampleAdditionRollBack(Long tenantId, List<String> tmpSlapNoList) {
        if (tmpSlapNoList == null || tmpSlapNoList.isEmpty()) {
            return;
        }

//        List<PmCmdLargePlt> pmCmdLargePlts = pmCmdLargePltRepository
//                .selectByCondition(Condition.builder(PmCmdLargePlt.class)
//                        .andWhere(Sqls.custom().andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, tmpSlapNoList)
//                                .andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, tenantId))
//                        .build());
        List<PmCmdLargePlt> pmCmdLargePlts = getPmCmdLargePltList(tmpSlapNoList, tenantId);
        List<PmCmdLargePlt> updatePmCmdLargePltList = new ArrayList<>();
        List<PmCmdSmallPlt> updatePmCmdSmallPltList = new ArrayList<>();
        String targetPdStatusHp = null ;
        
        List<PmCmdCont> pmCmdContList = pmCmdContRepository.selectByCondition(Condition.builder(PmCmdCont.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdCont.FIELD_TENANT_ID, tenantId)
                        .andIn(PmCmdCont.FIELD_TMP_SLAB_NO, tmpSlapNoList))
                .build());
        Map<String , PmCmdCont> pmCmdContMap = new HashMap<>();
        for (PmCmdCont pmCmdCont : pmCmdContList) {
            pmCmdContMap.put(pmCmdCont.getOrderNo(), pmCmdCont);
        }
        Map<String ,PmCmdLargePlt> pmCmdLargePltMap = new HashMap<>();
        List<String> plateNoList = new ArrayList<>();
        for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePlts) {
            targetPdStatusHp = pdStatusHpChangeResult(pmCmdLargePlt.getPdStatusHp(), OpType.SAMPLE_ROLLBACK, pmCmdLargePlt.getTmpSlabNo());
            PmCmdLargePlt updatePmCmdLargePlt = new PmCmdLargePlt();
            updatePmCmdLargePlt.setObjectVersionNumber(pmCmdLargePlt.getObjectVersionNumber());
            updatePmCmdLargePlt.setPmCmdLargePltId(pmCmdLargePlt.getPmCmdLargePltId());
            updatePmCmdLargePlt.setPdStatusHp(targetPdStatusHp);
            pmCmdLargePltMap.put(pmCmdLargePlt.getTmpSlabNo(), pmCmdLargePlt);
            if(PdMatType.C.getCode().equals(pmCmdLargePlt.getMatDesignKind()) && pmCmdLargePlt.getTwoRollInterimFlag() != null && BaseConstants.Flag.YES.toString().equals(pmCmdLargePlt.getTwoRollInterimFlag())) {
                // 二次开坯与钢锭组板不调试样添加
                updatePmCmdLargePltList.add(updatePmCmdLargePlt);
                continue;
            }
            updatePmCmdLargePlt.setSampleLenHead(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleLenTail(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleLenMid(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleLenGive(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleLen(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleHeadLenFree(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleTailLenFree(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleHeadLenPlate(BigDecimal.ZERO);
            updatePmCmdLargePlt.setSampleTailLenPlate(BigDecimal.ZERO);
            updatePmCmdLargePltList.add(updatePmCmdLargePlt);
            plateNoList.add(pmCmdLargePlt.getPlateNo());
        }
        List<PmCmdSmallPlt> pmCmdSmallPlts = pmCmdSmallPltRepository
                .selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                        .andWhere(Sqls.custom().andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, tmpSlapNoList)
                                .andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, tenantId))
                        .build());
        for (PmCmdSmallPlt pmCmdSmallPlt : pmCmdSmallPlts) {
            PmCmdSmallPlt updatePmCmdSmallPlt = new PmCmdSmallPlt();
            PmCmdLargePlt pmCmdLargePlt = pmCmdLargePltMap.get(pmCmdSmallPlt.getTmpSlabNo());
            updatePmCmdSmallPlt.setObjectVersionNumber(pmCmdSmallPlt.getObjectVersionNumber());
            updatePmCmdSmallPlt.setPmCmdSmallPltId(pmCmdSmallPlt.getPmCmdSmallPltId());
            if(pmCmdLargePlt != null && pmCmdLargePlt.getTwoRollInterimFlag() != null && BaseConstants.Flag.YES.toString().equals(pmCmdLargePlt.getTwoRollInterimFlag())) {
                updatePmCmdSmallPltList.add(updatePmCmdSmallPlt);
                continue;
            }
            updatePmCmdSmallPlt.setSampleLenGive(BigDecimal.ZERO);
            updatePmCmdSmallPlt.setSampleHeadLenFree(BigDecimal.ZERO);
            updatePmCmdSmallPlt.setSampleTailLenFree(BigDecimal.ZERO);
            updatePmCmdSmallPlt.setSampleHeadLenPlate(BigDecimal.ZERO);
            updatePmCmdSmallPlt.setSampleTailLenPlate(BigDecimal.ZERO);
            updatePmCmdSmallPltList.add(updatePmCmdSmallPlt);
        }
        
        List<String> virtualSlabNoList = new ArrayList<>();
        Map<String, String> cmdSlabVirtualMap = new HashMap<>(16);
        if(hasPmCmdSlab()) {
            List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId)
                            .andIn(PmCmdSlab.FIELD_TMP_SLAB_NO, tmpSlapNoList))
                    .build());
            // 更新命令板坯表状态
            if (pmCmdSlabs != null && !pmCmdSlabs.isEmpty()) {
                List<PmCmdSlab> updatePmCmdSlabList = new ArrayList<>();
                for (PmCmdSlab pmCmdSlab : pmCmdSlabs) {
                    PmCmdSlab updatePmCmdSlab = new PmCmdSlab();
                    updatePmCmdSlab.setObjectVersionNumber(pmCmdSlab.getObjectVersionNumber());
                    updatePmCmdSlab.setPmCmdSlabId(pmCmdSlab.getPmCmdSlabId());
                    updatePmCmdSlab.setPdStatusHp(targetPdStatusHp);
                    updatePmCmdSlabList.add(updatePmCmdSlab);
                    virtualSlabNoList.add(pmCmdSlab.getVirtualSlabNo());
                    cmdSlabVirtualMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getVirtualSlabNo());
                }
                pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSlabList);
            }
        } else {
            virtualSlabNoList.addAll(plateNoList);
        }
        if (virtualSlabNoList != null && !virtualSlabNoList.isEmpty()) {
            List<T> slabInfoList = new ArrayList<>();
            Map<String, T> slabInfo = this.selectByMatNo(virtualSlabNoList, tenantId);
            for (Entry<String, T> entry : slabInfo.entrySet()) {
                slabInfoList.add(this.updateSlabInfo(entry.getValue(), null, targetPdStatusHp));
            }
            this.execUpdateSlabInfo(slabInfoList);
            List<PmPdContSum> pdContSumList = pmPdContSumRepository
                    .selectByCondition(Condition.builder(PmPdContSum.class)
                            .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId)
                                    .andIn(PmPdContSum.FIELD_PD_MAT_NO, virtualSlabNoList))
                            .build());
            List<PmPdContSum> updatePmPdContSumList = new ArrayList<>();
            for (PmPdContSum pmPdContSum : pdContSumList) {
                PmPdContSum updatePmPdContSum = new PmPdContSum();
                updatePmPdContSum.setPdStatus(targetPdStatusHp);
                updatePmPdContSum.setPpcsId(pmPdContSum.getPpcsId());
                updatePmPdContSum.setObjectVersionNumber(pmPdContSum.getObjectVersionNumber());
                updatePmPdContSumList.add(updatePmPdContSum);
            }
            pmPdContSumRepository.batchUpdateByPrimaryKeySelective(updatePmPdContSumList);
        }
        
        pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdLargePltList);
        pmCmdSmallPltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSmallPltList);

        // 存四大命令履历
        List<PmCmdRecord> insertPmCmdRecordList = generatePmCmdRecordList(pmCmdLargePlts, cmdSlabVirtualMap, tenantId, Constants.CmdRecordOperation.SAMPLE_ADDITION_ROLLBACK);
        pmCmdRecordRepository.batchInsertSelective(insertPmCmdRecordList);

        // todo 将临时命令板坯号，抛给质量接口，质量模块完成自己内部的试样信息删除
         this.callSampleGensRemove(tmpSlapNoList, tenantId);

        // 抛合同-试样添加取消
        if (CollectionUtils.isNotEmpty(virtualSlabNoList)) {
            this.abandonContractEvent(virtualSlabNoList, tenantId, Constants.PdStatusHp.PD_STATUS_HP_18,
                    Constants.ProdcCd.CD_14A, Constants.WholeBacklogCode.CODE_14, CtEventConstants.PM_SAMPLE_ADDITION_CANCEL);
        }
    }

    private List<PmCmdRecord> generatePmCmdRecordList(List<PmCmdLargePlt> pmCmdLargePltList, Map<String, String> cmdSlabVirtualMap,
                                                      Long tenantId, String operationName) {
        Date now = new Date();
        List<PmCmdRecord> insertPmCmdRecordList = new ArrayList<>();
        for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltList) {
            PmCmdRecord pmCmdRecord = new PmCmdRecord();
            pmCmdRecord.setOperationName(operationName);
            pmCmdRecord.setOperationId(DetailsHelper.getUserDetails().getUserId().toString());
            pmCmdRecord.setOperationTime(now);
            pmCmdRecord.setPonoSlabNo(pmCmdLargePlt.getPonoSlabNo());
            pmCmdRecord.setTmpSlabNo(pmCmdLargePlt.getTmpSlabNo());
            pmCmdRecord.setMatDesignKind(pmCmdLargePlt.getMatDesignKind());
            pmCmdRecord.setVirtualSlabNo(cmdSlabVirtualMap.get(pmCmdLargePlt.getTmpSlabNo()));
            pmCmdRecord.setSlabNo(pmCmdLargePlt.getSlabNo());
            pmCmdRecord.setPlateNo(pmCmdLargePlt.getPlateNo());
            pmCmdRecord.setTenantId(tenantId);
            insertPmCmdRecordList.add(pmCmdRecord);
        }
        return insertPmCmdRecordList;
    }

    protected void callSampleGensRemove(List<String> tmpSlapNoList, Long tenantId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void secondaryDesignRollback(Long tenantId, List<PmCmdLargePlt> pmCmdLargePltList) {
        try {
            List<String> tmpSlabNoList = new ArrayList<>();
            List<String> pmCmdLargePltIdList = new ArrayList<>();

            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltList) {
                pmCmdLargePltIdList.add(pmCmdLargePlt.getPmCmdLargePltId().toString());
            }
            List<PmCmdLargePlt> pmCmdLargePltDbList = pmCmdLargePltRepository
                    .selectByIds(String.join(",", pmCmdLargePltIdList));
            List<PmCmdLargePlt> updatePmCmdLargePltList = new ArrayList<>();
            String targetPdStatusHp = null;
            List<String> plateNoList = new ArrayList<>();
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
                if (StringUtils.isNotBlank(pmCmdLargePlt.getTmpSlabNo())) {
                    tmpSlabNoList.add(pmCmdLargePlt.getTmpSlabNo());
                }
                targetPdStatusHp = pdStatusHpChangeResult(pmCmdLargePlt.getPdStatusHp(), OpType.DESIGN_ROLLBACK, pmCmdLargePlt.getTmpSlabNo());
                PmCmdLargePlt updatePmCmdLargePlt = new PmCmdLargePlt();
                updatePmCmdLargePlt.setObjectVersionNumber(pmCmdLargePlt.getObjectVersionNumber());
                updatePmCmdLargePlt.setPmCmdLargePltId(pmCmdLargePlt.getPmCmdLargePltId());
                updatePmCmdLargePlt.setPdStatusHp(targetPdStatusHp);
                updatePmCmdLargePltList.add(updatePmCmdLargePlt);
                plateNoList.add(pmCmdLargePlt.getPlateNo());
            }
            pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdLargePltList);

            List<String> virtualSlabNoList = new ArrayList<>();
            Map<String, String> cmdSlabVirtualMap = new HashMap<>(16);
            if(hasPmCmdSlab()) {
                List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                        .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId)
                                .andIn(PmCmdSlab.FIELD_TMP_SLAB_NO, tmpSlabNoList))
                        .build());
                // 更新命令板坯表状态
                if (pmCmdSlabs != null && !pmCmdSlabs.isEmpty()) {
                    List<PmCmdSlab> updatePmCmdSlabList = new ArrayList<>();
                    for (PmCmdSlab pmCmdSlab : pmCmdSlabs) {
                        PmCmdSlab updatePmCmdSlab = new PmCmdSlab();
                        updatePmCmdSlab.setObjectVersionNumber(pmCmdSlab.getObjectVersionNumber());
                        updatePmCmdSlab.setPmCmdSlabId(pmCmdSlab.getPmCmdSlabId());
                        updatePmCmdSlab.setPdStatusHp(targetPdStatusHp);
                        updatePmCmdSlabList.add(updatePmCmdSlab);
                        virtualSlabNoList.add(pmCmdSlab.getVirtualSlabNo());
                        cmdSlabVirtualMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getVirtualSlabNo());
                    }
                    pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSlabList);
                }
            } else {
                virtualSlabNoList.addAll(plateNoList);
            }
            
            if (virtualSlabNoList != null && !virtualSlabNoList.isEmpty()) {
                List<T> slabInfoList = new ArrayList<>();
                Map<String, T> slabInfo = this.selectByMatNo(virtualSlabNoList, tenantId);
                for (Entry<String, T> entry : slabInfo.entrySet()) {
                    slabInfoList.add(this.updateSlabInfo(entry.getValue(), null, targetPdStatusHp));
                }
                this.execUpdateSlabInfo(slabInfoList);
                List<PmPdContSum> pdContSumList = pmPdContSumRepository
                        .selectByCondition(Condition.builder(PmPdContSum.class)
                                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId)
                                        .andIn(PmPdContSum.FIELD_PD_MAT_NO, virtualSlabNoList))
                                .build());
                List<PmPdContSum> updatePmPdContSumList = new ArrayList<>();
                for (PmPdContSum pmPdContSum : pdContSumList) {
                    PmPdContSum updatePmPdContSum = new PmPdContSum();
                    updatePmPdContSum.setPdStatus(targetPdStatusHp);
                    updatePmPdContSum.setPpcsId(pmPdContSum.getPpcsId());
                    updatePmPdContSum.setObjectVersionNumber(pmPdContSum.getObjectVersionNumber());
                    updatePmPdContSumList.add(updatePmPdContSum);
                }
                pmPdContSumRepository.batchUpdateByPrimaryKeySelective(updatePmPdContSumList);
            }

            // 存四大命令履历
            List<PmCmdRecord> insertPmCmdRecordList = generatePmCmdRecordList(pmCmdLargePltDbList, cmdSlabVirtualMap, tenantId, Constants.CmdRecordOperation.SECONDARY_DESIGN_ROLLBACK);
            pmCmdRecordRepository.batchInsertSelective(insertPmCmdRecordList);

            // 试样添加回退
            this.sampleAdditionRollBack(tenantId, tmpSlabNoList);
        } finally {
            remove();
        }
    }

    /**
     * 通过虚拟板坯号查询板坯信息
     * 
     * @param virtualSlabNo
     * @return
     */
    protected abstract Map<String, T> selectByMatNo(List<String> virtualSlabNo, Long tenantId);

    /**
     * 创建组板编排参数
     * 
     * @param pmCmdLarge           命令大板信息
     * @param salbInfo             板坯
     * @param axisPmProContProdTtr
     * @param pmSmallPltPoss
     * @param pmPdContSums
     * @return
     */
    protected PmProContYieldRequestDTO buildCalcRequest(PmCmdLargePlt pmCmdLargePlt, T salbInfo,
            PmProContProdTtr axisPmProContProdTtr, List<PmSmallPltPos> pmSmallPltPoss, List<PmPdContSum> pmPdContSums) {
        PmProContYieldRequestDTO pmProContYieldRequestDTO = new PmProContYieldRequestDTO();
        pmProContYieldRequestDTO.setSecondaryDesignFlag(true);
        PmProContFilterRequestDTO pmContFilterRequest = buildPmProContFilterRequestDTO(pmProContYieldRequestDTO,
                salbInfo, pmCmdLargePlt);

        pmProContYieldRequestDTO.setPmContFilterRequest(pmContFilterRequest);

        pmProContYieldRequestDTO.setSendCtEvent(false);
        pmProContYieldRequestDTO.setAxisOrderNo(axisPmProContProdTtr.getOrderNo());
        pmProContYieldRequestDTO.setVirtualSlabNo(pmCmdLargePlt.getVirtualSlabNo());
        pmProContYieldRequestDTO.setTenantId(pmCmdLargePlt.getTenantId());
        FormPlateModeStrategy formPlateModeStrategy = FormPlateModeStrategyFactory
                .matchStrategy(pmCmdLargePlt.getFormPlateMode());

        // 组板位置参数
        PmCompositeBoardDTO pmCompositeBoardDTO = formPlateModeStrategy.buildPmCompositeBoard(
                FormPlateMode.getByCode(pmCmdLargePlt.getFormPlateMode()), pmSmallPltPoss, axisPmProContProdTtr,
                pmCmdLargePlt.getMscLineNo(), pmCmdLargePlt.getTenantId());
        pmProContYieldRequestDTO.setCompositeBoard(pmCompositeBoardDTO);
        
        pmCompositeBoardDTO.setPickModeLenDir(pmCmdLargePlt.getPickModeLenDir().intValue());
        pmCompositeBoardDTO.setPickModeWidDir(pmCmdLargePlt.getPickModeWidDir().intValue());
        pmCompositeBoardDTO.setSzWidth(pmCmdLargePlt.getCombinePlateWidth());
        pmCompositeBoardDTO.setSzLength(pmCmdLargePlt.getCombinePlateLen());
        
        // 组板合同参数
        List<PmProContYieldDTO> pmProContYieldList = new ArrayList<>();
        for (PmPdContSum pmPdContSum : pmPdContSums) {
            PmProContYieldDTO pmProContYieldDTO = new PmProContYieldDTO();
            pmProContYieldDTO.setAxisFlag(pmPdContSum.getAxisFlag() == 1L);
            pmProContYieldDTO.setOrderNo(pmPdContSum.getOrderNo());
            pmProContYieldDTO.setSmallPlateLen(pmPdContSum.getSmallPlateLen());
            pmProContYieldList.add(pmProContYieldDTO);
            pmProContYieldDTO.setSkipCheckQty(true);
        }
        pmProContYieldRequestDTO.setPmProContYieldList(pmProContYieldList);
        return pmProContYieldRequestDTO;
    }

    /**
     * 获取组板请求
     * 
     * @param salbInfo
     * @param pmCmdLargePlt
     * @return
     */
    protected abstract PmProContFilterRequestDTO buildPmProContFilterRequestDTO(
            PmProContYieldRequestDTO pmProContYieldRequestDTO, T salbInfo, PmCmdLargePlt pmCmdLargePlt);

    /**
     * 收得率计算
     * 
     * @param pmCmdLargePlt
     * @param salbInfo
     * @param axisPmProContProdTtr
     * @param pmSmallPltPoss
     * @param pmPdContSums
     * @return
     */
    protected PmProContYieldResposeDTO yiledCalc(PmCmdLargePlt pmCmdLargePlt, PmProContYieldRequestDTO pmProContYield,
            PmProContProdTtr axisPmProContProdTtr) {
        if (Objects.isNull(axisPmProContProdTtr)) {
            // 读生产合同产品属性表时没有找到记录！合同号【{0}】
            throw new CommonException("pm.pm_pro_cont_prod_trl_001", pmProContYield.getAxisOrderNo());
        }

        pmProContYield.check();
        PdMatTypeStrategy pdMatTypeStrategy = PdMatTypeStrategyFactory
                .matchStrategy(pmProContYield.getPmContFilterRequest().getMatDesignKind());

        List<String> orderNoList = new ArrayList<>();
        for (PmProContYieldDTO pmProContYieldDTO : pmProContYield.getPmProContYieldList()) {
            orderNoList.add(pmProContYieldDTO.getOrderNo());
        }
        Map<String, PmProContFilterResposeDTO> filterOrderMap = pmProContRepository.orderFilterMap(orderNoList,
                pmProContYield.getTenantId(), pmProContYield.getPmContFilterRequest().getMscLineNo());

        PmProContFilterResposeDTO axisContInfo = filterOrderMap.get(pmProContYield.getAxisOrderNo());
        if (Objects.isNull(axisContInfo)) {
            // 读合同产线工艺参数表时没有找到记录！合同号【{0}】
            throw new CommonException("pm.pm_cont_msc_tech_002", pmProContYield.getAxisOrderNo());
        }

        PmContMscTech axisPmContMscTech = new PmContMscTech();
        BeanCopier.create(PmProContFilterResposeDTO.class, PmContMscTech.class, false).copy(axisContInfo,
                axisPmContMscTech, null);

        // 执行前检查
        pdMatTypeStrategy.yiledCalcBeforeCheck(pmProContYield, false);

        PmProContYieldResposeDTO pmProContYieldRespose = null;
        // 初始化校验与初始化参数
        PmCompositeSlabCalcDTO pmCompositeSlabCalc = pdMatTypeStrategy.checkAndInitParams(filterOrderMap,
                pmProContYield, axisPmProContProdTtr);
        // 记录大板粗切位置
        pdMatTypeStrategy.plateCut(filterOrderMap, pmProContYield, axisPmProContProdTtr, pmCompositeSlabCalc);
        // 计算送样长度
//        BigDecimal sampleLenHead = pmCmdLargePlt.getSampleLenHead() == null ? BigDecimal.ZERO : pmCmdLargePlt.getSampleLenHead();
//        BigDecimal sampleLenTail = pmCmdLargePlt.getSampleLenTail() == null ? BigDecimal.ZERO : pmCmdLargePlt.getSampleLenTail();
//        BigDecimal sampleLenMid = pmCmdLargePlt.getSampleLenMid() == null ? BigDecimal.ZERO : pmCmdLargePlt.getSampleLenMid();
        BigDecimal sampleLenGive = pmCmdLargePlt.getSampleLenGive() == null ? BigDecimal.ZERO : pmCmdLargePlt.getSampleLenGive();
//        BigDecimal sampleLen = sampleLenHead.add(sampleLenTail).add(sampleLenMid).add(sampleLenGive);
        pmCompositeSlabCalc.setSampleLength(pmCmdLargePlt.getSampleLen() == null ? BigDecimal.ZERO : pmCmdLargePlt.getSampleLen());
        pmCompositeSlabCalc.setSampleLength(pmCompositeSlabCalc.getSampleLength().add(sampleLenGive));
        
        // 计算RSCODE
        pdMatTypeStrategy.calcRsCodeAndBroadFlag(pmProContYield, axisPmProContProdTtr, pmCompositeSlabCalc);
        // 计算临时板坯长
//        pdMatTypeStrategy.calcLpre(pmProContYield, axisPmProContProdTtr, pmCompositeSlabCalc);
        // 计算收得率
        pmProContYieldRespose = pdMatTypeStrategy.calcYield(filterOrderMap, pmProContYield, axisPmProContProdTtr,
                axisPmContMscTech, pmCompositeSlabCalc);
        if (null == pmProContYieldRespose) {
            throw new CommonException("pm.pm_pro_cont_025");
        }
        // 规则集06校验
        executeRuleSet(pmProContYieldRespose, pmProContYield, axisPmContMscTech, axisPmProContProdTtr);

        return pmProContYieldRespose;
    }

    protected abstract PdRuleSetType buildRuleParam();

    protected void executeRuleSet(PmProContYieldResposeDTO pmProContYieldRespose,
            PmProContYieldRequestDTO pmProContYieldRequest, PmContMscTech axisPmContMscTech,
            PmProContProdTtr axisPmProContProdTtr) {
        PdRuleSetType pdRuleSetType = buildRuleParam();
        if (pdRuleSetType == null) {
            return;
        }
        RuleParamDTO ruleParam = new RuleParamDTO(pdRuleSetType);
        ruleParam.setTenantId(pmProContYieldRespose.getTenantId());
        Map<String, Object> bizData = new HashMap<>(8);
        // 材料设计种类
        bizData.put(RuleSetConstants.MAT_DESIGN_KIND,
                pmProContYieldRequest.getPmContFilterRequest().getMatDesignKind());
        // 连铸机类型
        bizData.put(RuleSetConstants.CC_TYPE, pmProContYieldRequest.getPmContFilterRequest().getCcType());
        // 产线号
        bizData.put(RuleSetConstants.MSC_LINE_NO, pmProContYieldRequest.getPmContFilterRequest().getMscLineNo());
        // 轧制方式
        bizData.put(RuleSetConstants.ROLL_MODE, axisPmContMscTech.getRollMode());
        bizData.put(RuleSetConstants.INFUR_SLAB_WID, pmProContYieldRequest.getPmContFilterRequest().getMoldWidth());
        // 板坯厚度
        bizData.put(RuleSetConstants.MOLD_THICK, pmProContYieldRequest.getPmContFilterRequest().getMoldThick());
        // 板坯宽度
        bizData.put(RuleSetConstants.MOLD_WIDTH, pmProContYieldRequest.getPmContFilterRequest().getMoldWidth());
        // 进加热炉板坯长度
        bizData.put(RuleSetConstants.INFUR_SLAB_LEN, pmProContYieldRespose.getInfurSlabLen());
        if (BaseConstants.Flag.YES.toString().equals(pmProContYieldRequest.getPmContFilterRequest().getTransFlag())) {
            // 板坯宽度
            bizData.put(RuleSetConstants.MOLD_WIDTH, pmProContYieldRespose.getInfurSlabLen());
            // 进加热炉板坯长度
            bizData.put(RuleSetConstants.INFUR_SLAB_LEN, pmProContYieldRequest.getPmContFilterRequest().getMoldWidth());
        }
        bizData.put(RuleSetConstants.NEED_SLAB_LEN, pmProContYieldRespose.getNeedSlabLen());
        // 合同属性
        bizData.put(RuleSetConstants.AXIS_PM_PRO_CONT_PROD_ATTR, axisPmProContProdTtr);
        // 工艺参数
        bizData.put(RuleSetConstants.AXIS_PM_CONT_MSC_TECH, axisPmContMscTech);
        bizData.put(RuleSetConstants.TENANT_ID, pmProContYieldRespose.getTenantId());
        if (pmProContYieldRequest.getPmPdSlab() != null) {
            bizData.put(RuleSetConstants.MAT_NO, pmProContYieldRequest.getPmPdSlab().getSlabNo());
        }
        ruleParam.setBizData(bizData);
        pmPdRuleSetService.runRuleSet(ruleParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void secondaryDesign(Long tenantId, List<PmCmdLargePlt> pmCmdLargePltList) {
        try {
            List<String> virtualSlabNoList = Lists.newArrayList();
            List<String> temSlabNoList = Lists.newArrayList();
            List<String> axisOrderNoList = Lists.newArrayList();
            List<String> pmCmdLargePltIdList = Lists.newArrayList();

            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltList) {
                pmCmdLargePltIdList.add(pmCmdLargePlt.getPmCmdLargePltId().toString());
            }
            String targetPdStatus = null;
            List<PmCmdLargePlt> pmCmdLargePltDbList = pmCmdLargePltRepository
                    .selectByIds(String.join(",", pmCmdLargePltIdList));
            Map<Long, PmCmdLargePlt> dbPmCmdLargePltMap = Maps.newHashMap();
            List<String> plateNoList = new ArrayList<>();
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
                targetPdStatus = pdStatusHpChangeResult(pmCmdLargePlt.getPdStatusHp(), OpType.DESIGN, pmCmdLargePlt.getTmpSlabNo());
//                if (!Constants.PdStatusHp.PD_STATUS_HP_20.equals(pmCmdLargePlt.getPdStatusHp())) {
//                    throw new CommonException("pm.pm_pd_secondary_design_001", pmCmdLargePlt.getPdStatusHp(),
//                            Constants.PdStatusHp.PD_STATUS_HP_20 ,pmCmdLargePlt.getTmpSlabNo());
//                }
                temSlabNoList.add(pmCmdLargePlt.getTmpSlabNo());
                dbPmCmdLargePltMap.put(pmCmdLargePlt.getPmCmdLargePltId(), pmCmdLargePlt);
                plateNoList.add(pmCmdLargePlt.getPlateNo());
            }

            List<PmSlabMerge> pmSlabMergeList = pmSlabMergeRepository.selectByMerTmpSlabNoList(temSlabNoList, tenantId);
            Map<String, List<String>> pmSlabMergeMap = pmSlabMergeList.stream().collect(Collectors.groupingBy(
                            PmSlabMerge::getTmpPonoSlabNo, Collectors.mapping(PmSlabMerge::getTmpSlabNo, Collectors.toList())));
            Map<String, PmCmdSlab> pmCmdSlabMap = Maps.newHashMap();
            Map<String, String> cmdSlabVirtualMap = new HashMap<>();
            if(hasPmCmdSlab()) {
                List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                        .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId)
                                .andIn(PmCmdSlab.FIELD_TMP_SLAB_NO, temSlabNoList))
                        .build());
                if (pmCmdSlabs != null && !pmCmdSlabs.isEmpty()) {
                    for (PmCmdSlab pmCmdSlab : pmCmdSlabs) {
                        pmCmdSlabMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab);
                        virtualSlabNoList.add(pmCmdSlab.getVirtualSlabNo());
                        cmdSlabVirtualMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getVirtualSlabNo());
                    }
                }
            } else {
                virtualSlabNoList.addAll(plateNoList);
            }

            Map<String, T> slabInfoMap = this.selectByMatNo(virtualSlabNoList, tenantId);
            Map<String, List<PmPdContSum>> contMap = Maps.newHashMap();
            Map<String, List<PmSmallPltPos>> pltPosMap = Maps.newHashMap();

            List<PmPdContSum> pmPdContSumList = this.pmPdContSumRepository.selectByPdMatNoList(tenantId,
                    virtualSlabNoList);
            List<PmSmallPltPos> pmSmallPltPosList = this.pmSmallPltPosRepository.selectPmSmallPltPos(tenantId,
                    virtualSlabNoList);
            Map<String, String> axisContMap = Maps.newHashMap();

            for (PmPdContSum pmPdContSum : pmPdContSumList) {
                if (pmPdContSum.getAxisFlag() == 1L) {
                    axisOrderNoList.add(pmPdContSum.getOrderNo());
                    axisContMap.put(pmPdContSum.getPdMatNo(), pmPdContSum.getOrderNo());
                }
                if (!contMap.containsKey(pmPdContSum.getPdMatNo())) {
                    contMap.put(pmPdContSum.getPdMatNo(), Lists.newArrayList());
                }
                contMap.get(pmPdContSum.getPdMatNo()).add(pmPdContSum);
            }

            for (PmSmallPltPos pmSmallPltPos : pmSmallPltPosList) {
                if (!pltPosMap.containsKey(pmSmallPltPos.getPdMatNo())) {
                    pltPosMap.put(pmSmallPltPos.getPdMatNo(), Lists.newArrayList());
                }
                pltPosMap.get(pmSmallPltPos.getPdMatNo()).add(pmSmallPltPos);
            }

            List<PmProContProdTtr> pmProContProdTtrList = this.pmProContProdTtrRepository
                    .selectByOrderNoList(axisOrderNoList, tenantId);
            Map<String, PmProContProdTtr> contProtrlMap = Maps.newHashMap();
            if (pmProContProdTtrList != null && !pmProContProdTtrList.isEmpty()) {
                contProtrlMap = Maps.uniqueIndex(pmProContProdTtrList, PmProContProdTtr::getOrderNo);
            }

            List<PmCmdSlab> updatePmCmdSlabList = new ArrayList<>();
            List<PmCmdLargePlt> updatePmCmdLargePltList = new ArrayList<>();
            List<PmPdContSum> updatePmPdContSumList = new ArrayList<>();
            List<T> updateSlabInfo = new ArrayList<>();

            // 前端传入数据，循环处理
            for (PmCmdLargePlt largePlt : pmCmdLargePltDbList) {
                
                String virtualSlabNo = null ;
                if(hasPmCmdSlab()) {
                    PmCmdSlab pmCmdSlab = pmCmdSlabMap.get(largePlt.getTmpSlabNo());
                    if (Objects.isNull(pmCmdSlab)) {
                        // 读命令板坯表时没有找到记录！材料设计种类【{0}】
                        throw new CommonException("pm.pm_cmd_slab_005", getMatDesignKind().getDesc());
                    }
                    virtualSlabNo = pmCmdSlab.getVirtualSlabNo();
                } else {
                    virtualSlabNo = largePlt.getPlateNo();
                }
                // 合并板坯
                if (StringUtils.isEmpty(virtualSlabNo)) {
                    PmCmdSlab oldPmCmdSlab = pmCmdSlabMap.get(largePlt.getTmpSlabNo());
                    updatePmCmdSlabList.add(updateMergePmCmdSlab(oldPmCmdSlab, pmSlabMergeMap, pmCmdSlabMap , targetPdStatus));

                    // 根据命令板坯号与产线号,更新命令大板表
                    PmCmdLargePlt oldPmCmdLargePlt = dbPmCmdLargePltMap.get(largePlt.getPmCmdLargePltId());
                    updatePmCmdLargePltList.add(updateMergePmCmdLargePlt(oldPmCmdLargePlt , targetPdStatus));

                } else {
                    // 查询命令板坯表（PM_CMD_SLAB）中所有组板状态为‘20’（质量试样添加完成），材料设计种类为‘C’（出钢材组板）的虚拟板坯号virtual_slab_no，限制制造命令号为行数据的制造命令号
                    largePlt.setVirtualSlabNo(virtualSlabNo);
                    T slabInfo = slabInfoMap.get(virtualSlabNo);
                    checkSlabInfo(slabInfo, virtualSlabNo);
    
                    String axisOrderNo = axisContMap.get(virtualSlabNo);
                    T salbInfo = slabInfoMap.get(virtualSlabNo);
                    PmProContProdTtr axisPmProContProdTtr = contProtrlMap.get(axisOrderNo);
                    List<PmPdContSum> pdContSumList = contMap.get(virtualSlabNo);
                    PmProContYieldResposeDTO pmProContYieldRespose = null ;
                    if(!PdMatType.C.getCode().equals(largePlt.getMatDesignKind())){
                        PmProContYieldRequestDTO pmProContYield = buildCalcRequest(largePlt, salbInfo, axisPmProContProdTtr,
                                pltPosMap.get(virtualSlabNo), pdContSumList);
                        pmProContYieldRespose = yiledCalc(largePlt, pmProContYield,
                                axisPmProContProdTtr);
                    } else {
                        // 非基材合同，非二次开坯，非钢锭才做二次设计
                        if(!"ZFH".equals(axisPmProContProdTtr.getOrderTypeCode()) && !BaseConstants.Flag.YES.toString().equals(largePlt.getTwoRollInterimFlag())) {
                            PmProContYieldRequestDTO pmProContYield = buildCalcRequest(largePlt, salbInfo, axisPmProContProdTtr,
                                    pltPosMap.get(virtualSlabNo), pdContSumList);
                            pmProContYieldRespose = yiledCalc(largePlt, pmProContYield,
                                    axisPmProContProdTtr);
                        }
                    }
    
                    // 根据命令板坯号与产线号，更新命令板坯表
                    if(hasPmCmdSlab()) {
                        PmCmdSlab oldPmCmdSlab = pmCmdSlabMap.get(largePlt.getTmpSlabNo());
                        updatePmCmdSlabList.add(updatePmCmdSlab(oldPmCmdSlab, pmProContYieldRespose, pmSlabMergeMap, pmCmdSlabMap , targetPdStatus));
                    }
    
                    // 根据命令板坯号与产线号,更新命令大板表
                    PmCmdLargePlt oldPmCmdLargePlt = dbPmCmdLargePltMap.get(largePlt.getPmCmdLargePltId());
                    updatePmCmdLargePltList.add(updatePmCmdLargePlt(oldPmCmdLargePlt, pmProContYieldRespose , targetPdStatus));
    
                    for (PmPdContSum pmPdContSum : pdContSumList) {
                        PmPdContSum newPmPdContSum = new PmPdContSum();
                        newPmPdContSum.setPpcsId(pmPdContSum.getPpcsId());
                        newPmPdContSum.setObjectVersionNumber(pmPdContSum.getObjectVersionNumber());
                        newPmPdContSum.setPdStatus(targetPdStatus);
                        updatePmPdContSumList.add(newPmPdContSum);
                    }

                    updateSlabInfo.add(updateSlabInfo(salbInfo, pmProContYieldRespose, targetPdStatus));
                }
            }
            
            // 更新添加试样长后的合并板坯长和重量求和
            List<PmCmdSlab> updateAllPmCmdSlabList = new ArrayList<>();
            if(hasPmCmdSlab()) {
                Map<String, PmCmdSlab> updateCmdSlabMap = updatePmCmdSlabList.stream().collect(Collectors.toMap(PmCmdSlab::getTmpSlabNo, Function.identity()));
                for (PmCmdSlab pmCmdSlab : updatePmCmdSlabList) {
                    if (Constants.MergeStatus.MERGE_A.equals(pmCmdSlab.getIsMerge())) {
                        updateAllPmCmdSlabList.add(updatePmCmdSlab(pmCmdSlab, null, pmSlabMergeMap, updateCmdSlabMap , targetPdStatus));
                    } else {
                        updateAllPmCmdSlabList.add(pmCmdSlab);
                    }
                }
            }

            if (hasPmCmdSlab() && updateAllPmCmdSlabList != null && !updateAllPmCmdSlabList.isEmpty()) {
                pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(updateAllPmCmdSlabList);
            }
            if (updatePmCmdLargePltList != null && !updatePmCmdLargePltList.isEmpty()) {
                pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdLargePltList);
            }
            if (updatePmPdContSumList != null && !updatePmPdContSumList.isEmpty()) {
                // 会有重复的数据，因为大板表在组炉会多存合并的一条
                List<PmPdContSum> deduplicatedList = updatePmPdContSumList.stream().collect(Collectors.toMap(PmPdContSum::getPpcsId, Function.identity(), (k, v) -> k)).values().stream().collect(Collectors.toList());
                pmPdContSumRepository.batchUpdateByPrimaryKeySelective(deduplicatedList);
            }

            if (updateSlabInfo != null && !updateSlabInfo.isEmpty()) {
                execUpdateSlabInfo(updateSlabInfo);
            }

            // 存四大命令履历
            List<PmCmdRecord> insertPmCmdRecordList = generatePmCmdRecordList(pmCmdLargePltDbList, cmdSlabVirtualMap, tenantId, Constants.CmdRecordOperation.SECONDARY_DESIGN);
            pmCmdRecordRepository.batchInsertSelective(insertPmCmdRecordList);

            // 抛合同-二次设计
            if (SecondaryDesignHelper.isSendCtEvent() && CollectionUtils.isNotEmpty(virtualSlabNoList)) {
                this.abandonContractEvent(virtualSlabNoList, tenantId, targetPdStatus,
                        Constants.ProdcCd.CD_14A, Constants.WholeBacklogCode.CODE_14, CtEventConstants.PM_SECONDARY_DESIGN);
            }

        } finally {
            remove();
        }
    }

    private PmCmdLargePlt updateMergePmCmdLargePlt(PmCmdLargePlt oldPmCmdLargePlt , String pdStatusHp) {
        PmCmdLargePlt upadatePmCmdLargePlt = new PmCmdLargePlt();
        upadatePmCmdLargePlt.setPdStatusHp(pdStatusHp);
        upadatePmCmdLargePlt.setObjectVersionNumber(oldPmCmdLargePlt.getObjectVersionNumber());
        upadatePmCmdLargePlt.setPmCmdLargePltId(oldPmCmdLargePlt.getPmCmdLargePltId());
        return upadatePmCmdLargePlt;
    }

    private PmCmdSlab updateMergePmCmdSlab(PmCmdSlab oldPmCmdSlab, Map<String, List<String>> pmSlabMergeMap, Map<String, PmCmdSlab> pmCmdSlabMap , String pdStatusHp) {
        // 查询合并板坯的数据
        PmCmdSlab newPmCmdSlab = new PmCmdSlab();
        if (!pmSlabMergeMap.containsKey(oldPmCmdSlab.getTmpSlabNo())) {
            throw new CommonException("pm.slab_merge_004", oldPmCmdSlab.getTmpSlabNo());
        }
        BigDecimal preCleanSlabLen = BigDecimal.ZERO;
        BigDecimal infurSlabLen = BigDecimal.ZERO;
        BigDecimal needSlabLen = BigDecimal.ZERO;
        BigDecimal preCleanSlabWt = BigDecimal.ZERO;
        BigDecimal infurSlabWt = BigDecimal.ZERO;
        BigDecimal needSlabWt = BigDecimal.ZERO;
        for (String tmpSlabNo : pmSlabMergeMap.get(oldPmCmdSlab.getTmpSlabNo())) {
            PmCmdSlab pmCmdSlab = pmCmdSlabMap.get(tmpSlabNo);
            preCleanSlabLen =  preCleanSlabLen.add(pmCmdSlab.getPreCleanSlabLen() == null ? BigDecimal.ZERO : pmCmdSlab.getPreCleanSlabLen());
            infurSlabLen =  infurSlabLen.add(pmCmdSlab.getInfurSlabLen() == null ? BigDecimal.ZERO : pmCmdSlab.getInfurSlabLen());
            needSlabLen = needSlabLen.add(pmCmdSlab.getNeedSlabLen() == null ? BigDecimal.ZERO : pmCmdSlab.getNeedSlabLen());
            preCleanSlabWt = preCleanSlabWt.add(pmCmdSlab.getPreCleanSlabWt() == null ? BigDecimal.ZERO : pmCmdSlab.getPreCleanSlabWt());
            infurSlabWt = infurSlabWt.add(pmCmdSlab.getInfurSlabWt() == null ? BigDecimal.ZERO : pmCmdSlab.getInfurSlabWt());
            needSlabWt = needSlabWt.add(pmCmdSlab.getNeedSlabWt() == null ? BigDecimal.ZERO : pmCmdSlab.getNeedSlabWt());
        }
        newPmCmdSlab.setPreCleanSlabLen(preCleanSlabLen);
        newPmCmdSlab.setInfurSlabLen(infurSlabLen);
        newPmCmdSlab.setNeedSlabLen(needSlabLen);
        newPmCmdSlab.setPreCleanSlabWt(preCleanSlabWt);
        newPmCmdSlab.setInfurSlabWt(infurSlabWt);
        newPmCmdSlab.setNeedSlabWt(needSlabWt);
        newPmCmdSlab.setPdStatusHp(pdStatusHp);
        newPmCmdSlab.setObjectVersionNumber(oldPmCmdSlab.getObjectVersionNumber());
        newPmCmdSlab.setPmCmdSlabId(oldPmCmdSlab.getPmCmdSlabId());
        newPmCmdSlab.setTmpSlabNo(oldPmCmdSlab.getTmpSlabNo());
        newPmCmdSlab.setIsMerge(oldPmCmdSlab.getIsMerge());
        return newPmCmdSlab;
    }

    protected PmCmdSlab updatePmCmdSlab(PmCmdSlab oldPmCmdSlab, PmProContYieldResposeDTO pmProContYieldRespose,
                                        Map<String, List<String>> pmSlabMergeMap, Map<String, PmCmdSlab> pmCmdSlabMap , String pdStatusHp) {
        PmCmdSlab newPmCmdSlab = new PmCmdSlab();
        if(pmProContYieldRespose != null) {
            newPmCmdSlab.setPreCleanSlabLen(pmProContYieldRespose.getPreCleanSlabLen());
            newPmCmdSlab.setPreCleanSlabMaxLen(pmProContYieldRespose.getPreCleanSlabMaxLen());
            newPmCmdSlab.setPreCleanSlabMinLen(pmProContYieldRespose.getPreCleanSlabMinLen());
            newPmCmdSlab.setPreCleanSlabWt(pmProContYieldRespose.getPreCleanSlabWt());
            newPmCmdSlab.setPreCleanSlabMaxWt(pmProContYieldRespose.getPreCleanSlabMaxWt());
            newPmCmdSlab.setPreCleanSlabMinWt(pmProContYieldRespose.getPreCleanSlabMinWt());
            newPmCmdSlab.setInfurSlabLen(pmProContYieldRespose.getInfurSlabLen());
            newPmCmdSlab.setInfurSlabMaxLen(pmProContYieldRespose.getInfurSlabMaxLen());
            newPmCmdSlab.setInfurSlabMinLen(pmProContYieldRespose.getInfurSlabMinLen());
            newPmCmdSlab.setInfurSlabWt(pmProContYieldRespose.getInfurSlabWt());
            newPmCmdSlab.setInfurSlabMaxWt(pmProContYieldRespose.getInfurSlabMaxWt());
            newPmCmdSlab.setInfurSlabMinWt(pmProContYieldRespose.getInfurSlabMinWt());
            newPmCmdSlab.setNeedSlabLen(pmProContYieldRespose.getNeedSlabLen());
            newPmCmdSlab.setNeedSlabWt(pmProContYieldRespose.getNeedSlabWt());
            if(SecondaryDesignHelper.isTwoRollFlag() && StringUtils.isNotBlank(newPmCmdSlab.getFixSlabLenFlag()) 
                    && !BaseConstants.Flag.NO.toString().equals(newPmCmdSlab.getFixSlabLenFlag())) {
                // 如果是二次开坯，为指定长，必要板坯长等于指定长
                newPmCmdSlab.setFixSlabLen(pmProContYieldRespose.getNeedSlabLen());
            }
        }
        newPmCmdSlab.setPdStatusHp(pdStatusHp);
        newPmCmdSlab.setObjectVersionNumber(oldPmCmdSlab.getObjectVersionNumber());
        newPmCmdSlab.setPmCmdSlabId(oldPmCmdSlab.getPmCmdSlabId());
        newPmCmdSlab.setTmpSlabNo(oldPmCmdSlab.getTmpSlabNo());
        newPmCmdSlab.setIsMerge(oldPmCmdSlab.getIsMerge());
        return newPmCmdSlab;
    }

    /**
     * 更新命令大板表数据
     * 
     * @param oldPmCmdLargePlt
     * @param pmProContYieldRespose
     * @return
     */
    protected PmCmdLargePlt updatePmCmdLargePlt(PmCmdLargePlt oldPmCmdLargePlt,
            PmProContYieldResposeDTO pmProContYieldRespose , String pdStatusHp) {
        PmCmdLargePlt upadatePmCmdLargePlt = new PmCmdLargePlt();
        if(pmProContYieldRespose != null) {
            upadatePmCmdLargePlt.setRollAimThick(pmProContYieldRespose.getTaim());
            upadatePmCmdLargePlt.setRollAimWidth(pmProContYieldRespose.getWaim());
            upadatePmCmdLargePlt.setRollAimLen(pmProContYieldRespose.getLaim());
            upadatePmCmdLargePlt.setRollYield(pmProContYieldRespose.getRollYield());
            upadatePmCmdLargePlt.setCommandYield(pmProContYieldRespose.getCommandYield());
            upadatePmCmdLargePlt.setNormYield(pmProContYieldRespose.getNormYield());
            upadatePmCmdLargePlt.setHeadCut(pmProContYieldRespose.getHeadCut());
            upadatePmCmdLargePlt.setTailCut(pmProContYieldRespose.getTailCut());
        }
        upadatePmCmdLargePlt.setPdStatusHp(pdStatusHp);
        upadatePmCmdLargePlt.setObjectVersionNumber(oldPmCmdLargePlt.getObjectVersionNumber());
        upadatePmCmdLargePlt.setPmCmdLargePltId(oldPmCmdLargePlt.getPmCmdLargePltId());
        return upadatePmCmdLargePlt;
    }

    /**
     * 更新板坯信息
     * 
     * @param salbInfo
     * @param pmProContYieldRespose
     * @return
     */
    protected abstract T updateSlabInfo(T salbInfo, PmProContYieldResposeDTO pmProContYieldRespose, String pdStatusHp);

    protected abstract void checkSlabInfo(T salbInfo, String virtualSlabNo);

    protected abstract void execUpdateSlabInfo(List<T> slabInfoList);

    @Override
    public void afterPropertiesSet() throws Exception {
        SecondaryDesignStrategyFactory.register(getMatDesignKind(), this);
    }

    protected abstract PdMatType getMatDesignKind();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void commandCreate(Long tenantId, List<PmCmdLargePlt> pmCmdLargePltList) {
        try {
            List<String> tmpSlabNoList = new ArrayList<>();
            List<String> virtualSlabNoList = new ArrayList<>();
            List<String> pmCmdLargePltIdList = Lists.newArrayList();
    
            List<T> slabInfoList = new ArrayList<>();
            List<PmCmdSlab> updatePmCmdSlabList = new ArrayList<>();
            List<PmCmdLargePlt> updatePmCmdLargePltList = new ArrayList<>();
            List<PmPdContSum> updatePmPdContSumList = new ArrayList<>();
    
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltList) {
                pmCmdLargePltIdList.add(pmCmdLargePlt.getPmCmdLargePltId().toString());
            }
            List<PmCmdLargePlt> pmCmdLargePltDbList = pmCmdLargePltRepository
                    .selectByIds(String.join(",", pmCmdLargePltIdList));
            Map<Long, PmCmdLargePlt> dbPmCmdLargePltMap = Maps.newHashMap();
            Map<String, PmCmdLargePlt> updatePmCmdLargePltMap = Maps.newHashMap();
            String targetPdStatusHp = null;
            List<T> slabList = new ArrayList<>();
            List<String> plateNoList = new ArrayList<>();
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
                PmCmdLargePlt updatePmCmdLargePlt = new PmCmdLargePlt();
                updatePmCmdLargePlt.setObjectVersionNumber(pmCmdLargePlt.getObjectVersionNumber());
                updatePmCmdLargePlt.setPmCmdLargePltId(pmCmdLargePlt.getPmCmdLargePltId());
                updatePmCmdLargePltMap.put(pmCmdLargePlt.getTmpSlabNo(), updatePmCmdLargePlt);
                updatePmCmdLargePlt.setFormPlateMode(pmCmdLargePlt.getFormPlateMode());
                updatePmCmdLargePltList.add(updatePmCmdLargePlt);
                targetPdStatusHp = pdStatusHpChangeResult(pmCmdLargePlt.getPdStatusHp(), OpType.COMMAND , pmCmdLargePlt.getTmpSlabNo());
                updatePmCmdLargePlt.setPdStatusHp(targetPdStatusHp);
                dbPmCmdLargePltMap.put(pmCmdLargePlt.getPmCmdLargePltId(), pmCmdLargePlt);
                tmpSlabNoList.add(pmCmdLargePlt.getTmpSlabNo());
                plateNoList.add(pmCmdLargePlt.getPlateNo());
            }
            Map<String, PmCmdSlab> pmCmdSlabMap = Maps.newHashMap();
            Map<String, String> cmdSlabVirtualMap = new HashMap<>(16);
            if(hasPmCmdSlab()) {
                List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                        .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId)
                                .andIn(PmCmdSlab.FIELD_TMP_SLAB_NO, tmpSlabNoList))
                        .build());
                if (pmCmdSlabs != null && !pmCmdSlabs.isEmpty()) {
                    for (PmCmdSlab pmCmdSlab : pmCmdSlabs) {
                        pmCmdSlabMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab);
                        virtualSlabNoList.add(pmCmdSlab.getVirtualSlabNo());
                        checkNeedSlabLen(pmCmdSlab);
                        cmdSlabVirtualMap.put(pmCmdSlab.getTmpSlabNo(), pmCmdSlab.getVirtualSlabNo());
                    }
                }
            } else {
                virtualSlabNoList.addAll(plateNoList);
            }
            // 查询合同信息
            List<PmPdContSum> pmPdContSumList = pmPdContSumRepository.selectByCondition(Condition.builder(PmPdContSum.class)
                    .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId)
                            .andIn(PmPdContSum.FIELD_PD_MAT_NO, virtualSlabNoList))
                    .build());
            Map<String, List<PmPdContSum>> pmPdContSumListMap = Maps.newHashMap();
            Map<String, String> axisFlag = Maps.newHashMap();
            for (PmPdContSum pmPdContSum : pmPdContSumList) {
                if (!pmPdContSumListMap.containsKey(pmPdContSum.getPdMatNo())) {
                    pmPdContSumListMap.put(pmPdContSum.getPdMatNo(), new ArrayList<>());
                }
                if(pmPdContSum.getAxisFlag().longValue() == 1L) {
                    axisFlag.put(pmPdContSum.getPdMatNo(), pmPdContSum.getOrderNo());
                }
                pmPdContSumListMap.get(pmPdContSum.getPdMatNo()).add(pmPdContSum);
                PmPdContSum updatePmPdContSum = new PmPdContSum();
                updatePmPdContSum.setPdStatus(targetPdStatusHp);
                updatePmPdContSum.setPpcsId(pmPdContSum.getPpcsId());
                updatePmPdContSum.setObjectVersionNumber(pmPdContSum.getObjectVersionNumber());
                updatePmPdContSumList.add(updatePmPdContSum);
            }
            Map<String, T> slabInfo = this.selectByMatNo(virtualSlabNoList, tenantId);
            for (Entry<String, T> entry : slabInfo.entrySet()) {
                slabList.add(entry.getValue());
                slabInfoList.add(this.updateSlabInfo(entry.getValue(), null, targetPdStatusHp));
            }

            // 获取余材已生成工序
           Map<String, List<String>> subBacklogCodeMap = this.getPassQualifiedPro(slabList, tenantId);

            List<String> mergeTmpSlabNoList = new ArrayList<>();
            for (PmCmdLargePlt pmCmdLargePlt : pmCmdLargePltDbList) {
                String virtualSlabNo = null ;
                String tmpSlabNo = null;
                if(hasPmCmdSlab()) {
                    PmCmdSlab pmCmdSlab = pmCmdSlabMap.get(pmCmdLargePlt.getTmpSlabNo());
                    if (Objects.isNull(pmCmdSlab)) {
                        // 读命令板坯表时没有找到记录！材料设计种类【{0}】
                        throw new CommonException("pm.pm_cmd_slab_005", getMatDesignKind().getDesc());
                    }
                    virtualSlabNo = pmCmdSlab.getVirtualSlabNo();
                    tmpSlabNo = pmCmdSlab.getTmpSlabNo();
                } else {
                    virtualSlabNo = pmCmdLargePlt.getPlateNo();
                    tmpSlabNo = pmCmdLargePlt.getTmpSlabNo();
                }
    
                if(hasPmCmdSlab()) {
                    PmCmdSlab updatePmCmdSlab = pmCmdSlabMap.get(pmCmdLargePlt.getTmpSlabNo());
                    if (Constants.MergeStatus.MERGE_A.equals(updatePmCmdSlab.getIsMerge())){
                         commandUpdateMergePmCmdSlab(updatePmCmdSlab, tenantId);
                        mergeTmpSlabNoList.add(pmCmdLargePlt.getTmpSlabNo());
                    }else {
                       dealCmdCont(updatePmCmdSlab, axisFlag.get(virtualSlabNo), pmCmdLargePlt, pmPdContSumListMap.get(tmpSlabNo),
                                updatePmCmdLargePltMap.get(tmpSlabNo) , slabInfo.get(virtualSlabNo), tenantId,
                               subBacklogCodeMap);
                    }
                    // 如果存在则需要更新
//                    updatePmCmdSlab.setObjectVersionNumber(pmCmdSlab.getObjectVersionNumber());
//                    updatePmCmdSlab.setPmCmdSlabId(pmCmdSlab.getPmCmdSlabId());
                    updatePmCmdSlab.setPdStatusHp(targetPdStatusHp);
                    updatePmCmdSlabList.add(updatePmCmdSlab);
                }else {
                    dealCmdCont(new  PmCmdSlab(), axisFlag.get(virtualSlabNo), pmCmdLargePlt, pmPdContSumListMap.get(virtualSlabNo),
                            updatePmCmdLargePltMap.get(pmCmdLargePlt.getTmpSlabNo()) , slabInfo.get(virtualSlabNo), tenantId,
                            subBacklogCodeMap);
                }
            }

            // 更新合并板坯命令参数表扫查探伤
            if (CollectionUtils.isNotEmpty(mergeTmpSlabNoList)) {
                commandUpdatePmCmdCont(mergeTmpSlabNoList, tenantId);
            }
    
    
            this.execUpdateSlabInfo(slabInfoList);
            pmPdContSumRepository.batchUpdateByPrimaryKeySelective(updatePmPdContSumList);
            pmCmdLargePltRepository.batchUpdateByPrimaryKeySelective(updatePmCmdLargePltList);
            if(hasPmCmdSlab() && updatePmCmdSlabList != null && !updatePmCmdSlabList.isEmpty()) {
                pmCmdSlabRepository.batchUpdateByPrimaryKeySelective(updatePmCmdSlabList);
            }
    
            // 出钢材更新组炉编制表
            this.updateSlabEstaPlan(tmpSlabNoList, tenantId);

            // 存四大命令履历
            List<PmCmdRecord> insertPmCmdRecordList = generatePmCmdRecordList(pmCmdLargePltDbList, cmdSlabVirtualMap, tenantId, Constants.CmdRecordOperation.COMMAND_CREATE);
            pmCmdRecordRepository.batchInsertSelective(insertPmCmdRecordList);
            
            generateHeatDest(pmCmdLargePltDbList, pmCmdSlabMap ,pmPdContSumListMap);
    
            // 抛合同-命令做成
            if (SecondaryDesignHelper.isSendCtEvent() && CollectionUtils.isNotEmpty(virtualSlabNoList)) {
                this.abandonContractEventCommand(virtualSlabNoList, slabInfo, pmPdContSumListMap, tenantId);
//                this.abandonContractEvent(virtualSlabNoList, tenantId, Constants.PdStatusHp.PD_STATUS_HP_24,
//                        Constants.ProdcCd.CD_14A, Constants.WholeBacklogCode.CODE_14, CtEventConstants.PM_COMMAND_MADE);
            }
    
            // 调用轧钢材料状态变更
            if(SecondaryDesignHelper.isCallMmMatStatusChange()) {
                callMmMatStatusModify(tenantId, slabList , tmpSlabNoList);
            }
        } finally {
            remove();
        }
    }

    protected Map<String, List<String>> getPassQualifiedPro(List<T> slabList, Long tenantId) {
        return new HashMap<>();
    }

    private void commandUpdatePmCmdCont(List<String> tmpSlabNoList, Long tenantId) {
        List<PmCmdCont> pmCmdContList = pmCmdContRepository.selectByTmpSlabNoList(tmpSlabNoList, tenantId);
        if (CollectionUtils.isEmpty(pmCmdContList)) {
            return ;
        }
        List<String> orderNoList = pmCmdContList.stream().map(PmCmdCont::getOrderNo).distinct().collect(Collectors.toList());
        // 获取QD_TO_LINEUP_RESULT_UT的ut_check_code, UT_PD_CODE
        List<QdToLineupResultUTVO> qdToLineupResultUTVOList = pmPdSlabInfoMapper.selectUtCheckCodeByOrderNo(orderNoList, tenantId);
        Map<String, List<QdToLineupResultUTVO>> qdToLineupResultUTVOMap = qdToLineupResultUTVOList.stream()
                .collect(Collectors.groupingBy(QdToLineupResultUTVO::getOrderNo));
        for (PmCmdCont pmCmdCont : pmCmdContList) {
            List<QdToLineupResultUTVO> toLineupResultUTVOList = qdToLineupResultUTVOMap.get(pmCmdCont.getOrderNo());
            String utCheckCode = CollectionUtils.isEmpty(toLineupResultUTVOList) ? null : toLineupResultUTVOList.get(0).getUtCheckCode();
            String utPdCode = CollectionUtils.isEmpty(toLineupResultUTVOList) ? null : toLineupResultUTVOList.get(0).getUtPdCode();
            pmCmdCont.setUtCheckCode(utCheckCode);
            pmCmdCont.setUtPdCode(utPdCode);
        }
        pmCmdContRepository.batchUpdateByPrimaryKeySelective(pmCmdContList);
    }

    /**
     * 生成热处理去向
     * @param pmCmdLargePltDbList
     * @param pmPdContSumList
     */
    public void generateHeatDest(List<PmCmdLargePlt> pmCmdLargePltDbList ,Map<String, PmCmdSlab> pmCmdSlabMap , Map<String, List<PmPdContSum>> pmPdContSumListMap) {
        // 默认不处理热处理去向
    }

    private void commandUpdateMergePmCmdSlab(PmCmdSlab pmCmdSlab, Long tenantId) {
//        List<PmProContProdTtr> pmProContProdTtrs = pmProContProdTtrRepository.selectByOrderNoList(Arrays.asList(pmCmdSlab.getOrderNoAxis()), tenantId);
//        if (CollectionUtils.isNotEmpty(pmProContProdTtrs)) {
//            pmCmdSlab.setSlabPreProc1(PlatePreProcUtils.secondaryCuttingProc(pmCmdSlab.getMscLineNo(), pmProContProdTtrs.get(0).getShpCode()));
//        }
        LineNoEnums lineNoEnums = LineNoEnums.getByMscLineNo(pmCmdSlab.getMscLineNo());
        if ("00".equals(lineNoEnums.getSteelPl())) {
            if ("10".equals(lineNoEnums.getRollLineNo())) {
                pmCmdSlab.setSlabPreProc1("1B1");
                pmCmdSlab.setSlabPreProc2("1B2");
            }else if ("20".equals(lineNoEnums.getRollLineNo())) {
                pmCmdSlab.setSlabPreProc1("2B1");
                pmCmdSlab.setSlabPreProc2("2B2");
            }else if ("30".equals(lineNoEnums.getRollLineNo())) {
                pmCmdSlab.setSlabPreProc1("5B1");
                pmCmdSlab.setSlabPreProc2("5B2");
            }
        } else {
            pmCmdSlab.setSlabPreProc1("5B1");
            pmCmdSlab.setSlabPreProc2("5B2");
        }
        pmCmdSlab.setSlabPreProc3(PlatePreProcUtils.rollSmallProc(Utils.mscLineNoToRoolLineNo(pmCmdSlab.getMscLineNo())));
    }

    public void checkNeedSlabLen(PmCmdSlab pmCmdSlab) {
        if (pmCmdSlab.getNeedSlabLen().compareTo(pmCmdSlab.getInfurSlabLen()) > 0
                || pmCmdSlab.getNeedSlabLen().compareTo(pmCmdSlab.getPreCleanSlabLen()) > 0) {
            // 必要板坯长度【{0}】>进加热炉板坯长度【{1}】”或“清理前板坯长度【{2}】“
            throw new CommonException("pm.pm_pd_secondary_design_002" , pmCmdSlab.getNeedSlabLen().toPlainString() , pmCmdSlab.getInfurSlabLen().toPlainString()
                    , pmCmdSlab.getPreCleanSlabLen().toPlainString());
        }
    }
    
    public abstract void abandonContractEventCommand(List<String> virtualSlabNoList ,Map<String, T> slabInfo , Map<String, List<PmPdContSum>> pmPdContSumListMap , Long tenantId);

    public abstract void callMmMatStatusModify(Long tenantId, List<T> slabInfoList , List<String> ponoSlabNoList);

    public void updateSlabEstaPlan(List<String> tmpSlabNoList, Long tenantId) {
    }

    private PmCmdSlab dealCmdCont(PmCmdSlab updatePmCmdSlab, String axisOrderNo , PmCmdLargePlt pmCmdLargePltDb, List<PmPdContSum> pmPdContSumList,
            PmCmdLargePlt pmCmdLargePlt , T info, Long tenantId, Map<String, List<String>> subBacklogCodeMap ) {
            // 更新命令参数信息 需传入的数据：临时命令板坯号tmp_slab_no、产线号msc_line_no。
            // 需进一步准备的数据：合同号order_no、材料设计类型mat_design_kind、roll_plate_dest、试样长sample_len、产线号msc_line_no，完成厚板预定通过工序生成。
            // 根据临时命令板坯号与产线号，查询命令参数表（PM_CMD_CONT）
            List<PmCmdCont> pmCmdContList = pmCmdContRepository.selectByCondition(Condition.builder(PmCmdCont.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCmdCont.FIELD_TENANT_ID, pmCmdLargePltDb.getTenantId())
                            .andEqualTo(PmCmdCont.FIELD_TMP_SLAB_NO, pmCmdLargePltDb.getTmpSlabNo())
                            .andEqualTo(PmCmdCont.FIELD_MSC_LINE_NO, pmCmdLargePltDb.getMscLineNo()))
                    .build());
            // 全部合同号
            List<String> orderNoList = pmCmdContList.stream().map(PmCmdCont::getOrderNo).collect(Collectors.toList());

            // 所有合同生产合同产品属性表
            List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository
                    .selectByCondition(Condition.builder(PmProContProdTtr.class)
                            .andWhere(Sqls.custom()
                                    .andEqualTo(PmProContProdTtr.FIELD_TENANT_ID, pmCmdLargePltDb.getTenantId())
                                    .andIn(PmProContProdTtr.FIELD_ORDER_NO, orderNoList))
                            .build());
            Map<String, PmProContProdTtr> pmProContProdTtrMap = pmProContProdTtrList.stream()
                    .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity()));
            // 所有合同产线工艺参数表
            List<PmContMscTech> pmContMscTechList = pmContMscTechRepository
                    .selectByCondition(Condition.builder(PmContMscTech.class)
                            .andWhere(Sqls.custom().andEqualTo(PmContMscTech.FIELD_TENANT_ID, pmCmdLargePltDb.getTenantId())
                                    .andEqualTo(PmContMscTech.FIELD_MSC_LINE_NO, pmCmdLargePltDb.getMscLineNo())
                                    .andIn(PmContMscTech.FIELD_ORDER_NO, orderNoList))
                            .build());
            Map<String, PmContMscTech> pmContMscTechMap = pmContMscTechList.stream()
                    .collect(Collectors.toMap(PmContMscTech::getOrderNo, Function.identity()));

            // 根据产线号与查到的合同号，读取合同处理加热工艺标准 (QD_TO_LINEUP_RESULT_HEAT)/
            // QD_TO_LINEUP_RESULT_ROLLING[质量模块]
            List<QdToLineupResultRollingVO> qdToLineupResultRollingVOList = pmPdSlabInfoMapper.selectQdRolllingList(orderNoList, pmCmdLargePltDb.getMscLineNo());
            Map<String, QdToLineupResultRollingVO> qdToLineupResultRollingMap = qdToLineupResultRollingVOList.stream().collect(Collectors.toMap(QdToLineupResultRollingVO::getOrderNo, Function.identity()));
            
            List<QdToLineupResultHeatVO> qdToLineupResultHeatList = pmPdSlabInfoMapper
                    .selectQdHeatList(orderNoList, pmCmdLargePltDb.getMscLineNo(),updatePmCmdSlab.getMoldThick());
            Map<String, QdToLineupResultHeatVO> qdToLineupResultHeatMap = new HashMap<>();
            if(qdToLineupResultHeatList != null && !qdToLineupResultHeatList.isEmpty()) {
                qdToLineupResultHeatMap = qdToLineupResultHeatList.stream()
                        .collect(Collectors.toMap(QdToLineupResultHeatVO::getOrderNo, Function.identity()));
            }

            List<QdToLineupResultHeattreatVO> qdToLineupResultHeattreatVOList = pmPdSlabInfoMapper
                    .selectReultHeatTreat(orderNoList, pmCmdLargePltDb.getMscLineNo());
            Map<String, List<QdToLineupResultHeattreatVO>> qdToLineupResultHeattreatMap = qdToLineupResultHeattreatVOList
                    .stream().collect(Collectors.groupingBy(QdToLineupResultHeattreatVO::getOrderNo));

            // 查询IS_UT，如果为1，则需要设计探伤工序
            List<QdToPoOrderVO> qdToPoOrderVOList = pmPdSlabInfoMapper.selectQdToPoOrderByOrderList(orderNoList,tenantId);
            Map<String  , QdToPoOrderVO> qdToPoOrderMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(qdToPoOrderVOList)) {
                for (QdToPoOrderVO qdToPoOrderVO : qdToPoOrderVOList) {
                    qdToPoOrderMap.put(qdToPoOrderVO.getOrderNo(), qdToPoOrderVO);
                }
            }
            // 生产跟踪代码
            // 记录轴合同号、与其对应的全程工序途径码顺序号。
            // 根据轴合同号、其对应的全程工序途径码顺序号、产线号，读取合同产线工艺参数表（PM_CONT_MSC_TECH）：
            PmContMscTech axisPmContMscTech = pmContMscTechMap.get(axisOrderNo);
            PmProContProdTtr axisPmProContProdTtr = pmProContProdTtrMap.get(axisOrderNo);
            // 取厚板板坯火焰清理区分hp_flame_clean_div，更新到命令板坯表（PM_CMD_SLAB）中。
            updatePmCmdSlab.setHpFlameCleanDiv(axisPmContMscTech.getFlameCleanDiv());
            // 此外，还需将热送区分hot_send_div更新到命令板坯表（PM_CMD_SLAB）中
            if (!Constants.MergeStatus.MERGE_B.equals(updatePmCmdSlab.getIsMerge())) {
                updatePmCmdSlab.setHotSendDiv(axisPmContMscTech.getHotSendDiv());
            }
            updatePmCmdSlabProcInfo(info , pmCmdLargePltDb, updatePmCmdSlab, axisPmContMscTech, axisPmProContProdTtr);
            
            PmCmdCont axisPmCmdCont = null;
            
            QdToLineupResultRollingVO qdToLineupResultRollingVO = qdToLineupResultRollingMap
                    .get(axisOrderNo);
            

        // 获取QD_TO_LINEUP_RESULT_UT的ut_check_code, UT_PD_CODE
        List<QdToLineupResultUTVO> qdToLineupResultUTVOList = pmPdSlabInfoMapper.selectUtCheckCodeByOrderNo(orderNoList, pmCmdLargePltDb.getTenantId());
        Map<String, List<QdToLineupResultUTVO>> qdToLineupResultUTVOMap = qdToLineupResultUTVOList.stream()
                .collect(Collectors.groupingBy(QdToLineupResultUTVO::getOrderNo));
        MmPlateVO mmPlateVO = null;
        Long mmHtmrsltNum = null;
        if(StringUtils.isNotBlank(pmCmdLargePltDb.getPlateNo())) {
            mmPlateVO = pmPdSlabInfoMapper.selectMmplate(pmCmdLargePltDb.getPlateNo());
            // 根据材料号（临时命令板坯号/临时命令板坯号前七位/000），查询厚板热处理实绩表MM_HTMRSLT中有无生产流水号（a）；
            mmHtmrsltNum = pmPdSlabInfoMapper.selectMmHtmrslt(pmCmdLargePltDb.getPlateNo());
        }
        // 查询见证状态
        List<ObtainWitnessPointDTO> witnessPointReturnList = pmQdToPoOrderRepository.selectWitnessOrderPass(orderNoList, Arrays.asList(Constants.WITNESS_POINT), tenantId);
        Map<String, String> witnessOrderMap = new HashMap<>(witnessPointReturnList.size());
        for (ObtainWitnessPointDTO witnessPointDTO : witnessPointReturnList) {
            witnessOrderMap.put(witnessPointDTO.getOrderNo(), witnessPointDTO.getWitnessPointStatus());
        }
        for (PmCmdCont pmCmdCont : pmCmdContList) {
                PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(pmCmdCont.getOrderNo());
                PmContMscTech contMscTech = pmContMscTechMap.get(pmCmdCont.getOrderNo());
                if (StringUtils.isBlank(updatePmCmdSlab.getCoolCode())) {
                    updatePmCmdSlab.setCoolCode(contMscTech.getCoolCode());
                }
                if (StringUtils.isBlank(updatePmCmdSlab.getNewTestNo())) {
                    updatePmCmdSlab.setNewTestNo(pmProContProdTtr.getNewTestNo());
                }
                List<QdToLineupResultHeattreatVO> heattreatList = qdToLineupResultHeattreatMap
                        .get(pmCmdCont.getOrderNo());
                // 更新命令参数
                updatePmCmdCont(pmCmdCont, pmProContProdTtr , contMscTech, heattreatList , qdToLineupResultRollingMap, qdToLineupResultUTVOMap.get(pmCmdCont.getOrderNo()));
                // 预定工序生成
                List<QdToLineupResultHeattreatVO> heattreats = qdToLineupResultHeattreatMap
                        .get(pmCmdCont.getOrderNo());
                generatePreProc(pmCmdCont, contMscTech, pmCmdLargePltDb, heattreats, mmPlateVO , qdToPoOrderMap, qdToLineupResultUTVOMap.get(pmCmdCont.getOrderNo()), mmHtmrsltNum, witnessOrderMap,
                        pmProContProdTtr, subBacklogCodeMap);
                if(pmCmdCont.getOrderNo().equals(axisOrderNo)) {
                    axisPmCmdCont = pmCmdCont;
                }
            }
            pmCmdContRepository.batchUpdateByPrimaryKeySelective(pmCmdContList);
            
            updatePmCmdLargePlt(pmCmdLargePlt,pmCmdLargePltDb , axisPmCmdCont, axisPmContMscTech,axisPmProContProdTtr ,
                    qdToLineupResultRollingVO, qdToLineupResultHeatMap.getOrDefault(axisOrderNo, new QdToLineupResultHeatVO()));
            return updatePmCmdSlab;
    }
    
    /**
     * 生成小板预定工序
     * @param pmCmdCont
     * @param pmContMscTech
     * @param pmCmdLargePltDb
     * @param heattreats
     * @param mmPlateVO
     * @return
     */
    private void generatePreProc(PmCmdCont pmCmdCont , PmContMscTech pmContMscTech ,PmCmdLargePlt pmCmdLargePltDb 
            , List<QdToLineupResultHeattreatVO> heattreats ,MmPlateVO mmPlateVO , Map<String  , QdToPoOrderVO> qdToPoOrderMap,
                                 List<QdToLineupResultUTVO> qdToLineupResultUTVOList,  Long mmHtmrsltNum, Map<String, String> witnessOrderMap,
                                 PmProContProdTtr pmProContProdTtr, Map<String, List<String>> subBacklogCodeMap) {
        QdToLineupResultHeattreatVO heattreat = CollectionUtils.isNotEmpty(heattreats) ? heattreats.get(0) : null;
//        // 获取QD_TO_LINEUP_RESULT_UT的ut_check_code, UT_PD_CODE
//        List<QdToLineupResultUTVO> qdToLineupResultUTVOList = pmPdSlabInfoMapper.selectUtCheckCodeByOrderNo(Arrays.asList(pmCmdCont.getOrderNo()), pmCmdLargePltDb.getTenantId());
//        String utCheckCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtCheckCode();
//        String utPdCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtPdCode();
        String utCheckCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtCheckCode();
        String utPdCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtPdCode();
//        // 根据材料号（临时命令板坯号/临时命令板坯号前七位/000），查询厚板热处理实绩表MM_HTMRSLT中有无生产流水号（a）；
//        Long mmHtmrsltNum = pmPdSlabInfoMapper.selectMmHtmrslt(pmCmdLargePltDb.getTmpSlabNo());
        QdToPoOrderVO qdToPoOrderVO = qdToPoOrderMap.get(pmCmdCont.getOrderNo());
        String isUt = qdToPoOrderVO == null ? "0" :qdToPoOrderVO.getIsUt();
        String shotFlag = qdToPoOrderVO == null ? "" : qdToPoOrderVO.getShotFlag();
        int ultDetectStd = 0;
        if (qdToPoOrderVO != null) {
            if (qdToPoOrderVO.getUltDetectStd1() != null) {
                ultDetectStd = 1;
            }
            if (qdToPoOrderVO.getUltDetectStd2() != null) {
                ultDetectStd = 2;
            }
            if (qdToPoOrderVO.getUltDetectStd3() != null) {
                ultDetectStd = 3;
            }
        }

        String process = Strings.EMPTY;
        for (int i = 0; i < pmContMscTech.getWholeBacklog().length(); i += 2) {
            String platePreProc1 = Strings.EMPTY;
            ReservationProcessGenerationDTO reservationProcessGenerationDTO = new ReservationProcessGenerationDTO();
            reservationProcessGenerationDTO.setMatDesignKind(pmCmdLargePltDb.getMatDesignKind());
            reservationProcessGenerationDTO.setMscLineNo(pmCmdLargePltDb.getMscLineNo());
            reservationProcessGenerationDTO.setSplitWholeBacklog(pmContMscTech.getWholeBacklog().substring(i , i + 2));
            reservationProcessGenerationDTO.setSlabNo(pmCmdLargePltDb.getSlabNo());
            reservationProcessGenerationDTO.setWholeBacklog(pmContMscTech.getWholeBacklog());
//           platePreProc1 =  reservationProcessGeneration(axisPmContMscTech, reservationProcessGenerationDTO,
//                   axisPmCmdCont, pmCmdLargePltDb, heattreat,
//                    isUt);

            platePreProc1 = commandPreProcessGeneration(pmContMscTech, reservationProcessGenerationDTO,
                    pmCmdLargePltDb,heattreat, mmPlateVO, utCheckCode, utPdCode, mmHtmrsltNum, isUt, shotFlag,
                    witnessOrderMap.get(pmCmdCont.getOrderNo()), ultDetectStd, pmProContProdTtr);
            if (StringUtils.isNotEmpty(platePreProc1)) {
                process = process + platePreProc1;
            }

        }
        // 4)如果为余材板坯组板，且为复合坯/叠轧坯组板（板坯号第一位为F）
        String rollLineNo = pmCmdLargePltDb.getMscLineNo().substring(2, 4);
        //        String platePreProc1 = addSplittingProcess(pmCmdLargePlt.getMatDesignKind(), rollLineNo, axisPmContMscTech.getTenantId());
        //        if (StringUtils.isNotEmpty(platePreProc1)) {
        //            process = process + platePreProc1 + "-";
        //        }

        String platePreProc3 = addSplittingProcess(pmCmdLargePltDb.getSlabNo(), rollLineNo, pmCmdLargePltDb.getTenantId());
        if (StringUtils.isNotBlank(platePreProc3)) {
            process = process + platePreProc3 + "-";
            platePreProc3 = Strings.EMPTY;
        }
        
        // 见证探伤 -如果是见证探伤，则只在形合前加一道
        String platePreProc2 = Strings.EMPTY;
        if (StringUtils.isNotEmpty(witnessOrderMap.get(pmCmdCont.getOrderNo()))) {
            ProcessGenerateStrategy processGenerateStrategy = ProcessGenerateStrategyFactory.matchProcessStrategy(PdProcessType.P1.getCode());
            platePreProc2 = processGenerateStrategy.generateCrackProcess(pmCmdLargePltDb.getPlateDtCode(), pmCmdLargePltDb.getMscLineNo().substring(2, 4),
                    utCheckCode, witnessOrderMap.get(pmCmdCont.getOrderNo()), ultDetectStd);
            if (StringUtils.isNotBlank(platePreProc2)) {
                process = process + platePreProc2 + "-";
                platePreProc2 = Strings.EMPTY;
            }
        }
        
        // 5）形合工序
        switch (rollLineNo) {
            case "10":
                platePreProc2 = "1Z1";
                break;
            case "20":
                platePreProc2 = "2Z1";
                break;
            case "30":
                platePreProc2 = "5Z1";
                break;
            default:
        }
        if (StringUtils.isNotEmpty(platePreProc2)) {
            process = process + platePreProc2 + "-";
        }

        List<String> list = Arrays.stream(process.split("-"))
                .filter(item -> StringUtils.isNotEmpty((item)) && StringUtils.isNotBlank(item))
                .collect(Collectors.toList());
        log.info("<=====生成的工序列表list:{}", JSON.toJSONString(list));

        // 余材过滤掉已经生成热处理工序
        List<String> newList = this.filterPlateProcess(subBacklogCodeMap, list, pmCmdLargePltDb);
        log.info("<=====过滤后的newList:{}", JSON.toJSONString(newList));
        int size = newList.size();
        for (int i = 1; i < size + 1; i++) {
            String fieldName1 = "platePreProc" + i;
            String platePreProc = newList.get(i - 1);
            try {
                pmCmdCont.setDynamicField(fieldName1, platePreProc);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new CommonException(e);
            }
        }
    }

    protected List<String> filterPlateProcess(Map<String, List<String>> subBacklogCodeMap, List<String> list, PmCmdLargePlt pmCmdLargePltDb) {
        return list;
    }

    /**
     * 更新大板新增表
     * @param pmCmdLargePlt
     * @param axisPmCmdCont
     * @param axisPmContMscTech
     * @param qdToLineupResultRollingVO
     */
    private void updatePmCmdLargePlt(PmCmdLargePlt pmCmdLargePlt ,PmCmdLargePlt pmCmdLargePltDb , PmCmdCont axisPmCmdCont ,PmContMscTech axisPmContMscTech,
            PmProContProdTtr axisPmProContProdTtr, QdToLineupResultRollingVO qdToLineupResultRollingVO, QdToLineupResultHeatVO resultHeatVO) {
        if(axisPmCmdCont != null) {
            pmCmdLargePlt.setPlatePreProc1(axisPmCmdCont.getPlatePreProc1());
            pmCmdLargePlt.setPlatePreProc2(axisPmCmdCont.getPlatePreProc2());
            pmCmdLargePlt.setPlatePreProc3(axisPmCmdCont.getPlatePreProc3());
            pmCmdLargePlt.setPlatePreProc4(axisPmCmdCont.getPlatePreProc4());
            pmCmdLargePlt.setPlatePreProc5(axisPmCmdCont.getPlatePreProc5());
            pmCmdLargePlt.setPlatePreProc6(axisPmCmdCont.getPlatePreProc6());
            pmCmdLargePlt.setPlatePreProc7(axisPmCmdCont.getPlatePreProc7());
            pmCmdLargePlt.setPlatePreProc8(axisPmCmdCont.getPlatePreProc8());
            pmCmdLargePlt.setPlatePreProc9(axisPmCmdCont.getPlatePreProc9());
            pmCmdLargePlt.setPlatePreProc10(axisPmCmdCont.getPlatePreProc10());
            pmCmdLargePlt.setPlatePreProc11(axisPmCmdCont.getPlatePreProc11());
            pmCmdLargePlt.setPlatePreProc12(axisPmCmdCont.getPlatePreProc12());
            pmCmdLargePlt.setPlatePreProc13(axisPmCmdCont.getPlatePreProc13());
            pmCmdLargePlt.setPlatePreProc14(axisPmCmdCont.getPlatePreProc14());
            pmCmdLargePlt.setPlatePreProc15(axisPmCmdCont.getPlatePreProc15());
            pmCmdLargePlt.setPlatePreProc16(axisPmCmdCont.getPlatePreProc16());
            pmCmdLargePlt.setPlatePreProc17(axisPmCmdCont.getPlatePreProc17());
            pmCmdLargePlt.setPlatePreProc18(axisPmCmdCont.getPlatePreProc18());
            pmCmdLargePlt.setPlatePreProc19(axisPmCmdCont.getPlatePreProc19());
            pmCmdLargePlt.setPlatePreProc20(axisPmCmdCont.getPlatePreProc20());
            pmCmdLargePlt.setPlatePreProc21(axisPmCmdCont.getPlatePreProc21());
            pmCmdLargePlt.setPlatePreProc22(axisPmCmdCont.getPlatePreProc22());
            pmCmdLargePlt.setPlatePreProc23(axisPmCmdCont.getPlatePreProc23());
            pmCmdLargePlt.setPlatePreProc24(axisPmCmdCont.getPlatePreProc24());
            pmCmdLargePlt.setPlatePreProc25(axisPmCmdCont.getPlatePreProc25());
            pmCmdLargePlt.setPlatePreProc26(axisPmCmdCont.getPlatePreProc26());
            pmCmdLargePlt.setPlatePreProc27(axisPmCmdCont.getPlatePreProc27());
            pmCmdLargePlt.setPlatePreProc28(axisPmCmdCont.getPlatePreProc28());
            pmCmdLargePlt.setPlatePreProc29(axisPmCmdCont.getPlatePreProc29());
            pmCmdLargePlt.setPlatePreProc30(axisPmCmdCont.getPlatePreProc30());
        }
        // Ⅰ当组板方式为G时, 气切可否代码取值为1；其他情况取自合同产线工艺参数表（PM_CONT_MSC_TECH）；
        // Ⅱ当组板方式为G时, CS切断可否代码取值为0；其他情况取自合同产线工艺参数表（PM_CONT_MSC_TECH）；
        // Ⅲ当组板方式为G时, DSS可否代码取值为0；其他情况取自合同产线工艺参数表（PM_CONT_MSC_TECH）；
        // Ⅳ当组板方式为A或G时, SS可否代码取值为0；其他情况取自合同产线工艺参数表（PM_CONT_MSC_TECH）；
        // Ⅴ当组板方式为G时, DS可否代码取值为0；其他情况取自合同产线工艺参数表（PM_CONT_MSC_TECH）。
        if ("G".equals(pmCmdLargePlt.getFormPlateMode())) {
            pmCmdLargePlt.setGFlag("1");
            pmCmdLargePlt.setCsFlag("0");
            pmCmdLargePlt.setDssFlag("0");
            pmCmdLargePlt.setSsFlag("0");
            pmCmdLargePlt.setDsFlag("0");
        } else if ("A".equals(pmCmdLargePlt.getFormPlateMode())) {
            pmCmdLargePlt.setSsFlag("0");
        } else {
            pmCmdLargePlt.setGFlag(axisPmContMscTech.getGFlag() != null ? axisPmContMscTech.getGFlag().toString() : null);
            pmCmdLargePlt.setCsFlag(axisPmContMscTech.getCsFlag() != null ?axisPmContMscTech.getCsFlag().toString() : null);
            pmCmdLargePlt.setDssFlag(axisPmContMscTech.getDssFlag() != null ?axisPmContMscTech.getDssFlag().toString() : null);
            pmCmdLargePlt.setSsFlag(axisPmContMscTech.getSsFlag() != null ?axisPmContMscTech.getSsFlag().toString() : null);
            pmCmdLargePlt.setDsFlag(axisPmContMscTech.getDsFlag() != null ?axisPmContMscTech.getDsFlag().toString() : null);
        }
        
        // 厚板品种代码
        pmCmdLargePlt.setProdCodeHp(axisPmProContProdTtr.getProdCodeHp());
        // 牌号
        pmCmdLargePlt.setSgSign(axisPmProContProdTtr.getSgSign());
        // 出钢记号
        pmCmdLargePlt.setStNo(pmCmdLargePltDb.getStNo());
        // 切断方式代码
        pmCmdLargePlt.setCutModeCode(axisPmContMscTech.getCutModeCode());
        // 抗拉强度最大值
        pmCmdLargePlt.setTsMax(axisPmProContProdTtr.getTsMax());
        // 抗拉强度最小值
        pmCmdLargePlt.setTsMin(axisPmProContProdTtr.getTsMin());
        // 厚板流向代码
        pmCmdLargePlt.setPlateDtCode(axisPmContMscTech.getPlateDtCode());
        // 线膨胀系数
        pmCmdLargePlt.setExpandQuot(axisPmContMscTech.getExpandQuot());
        // 产品密度
        pmCmdLargePlt.setProdDensity(axisPmProContProdTtr.getProdDensity());
        // 中间冷却模式
        pmCmdLargePlt.setMiddleCoolMode(axisPmContMscTech.getMiddleCoolMode());
        // MAX_MIDDLE_COOL_SPEED
        pmCmdLargePlt.setMaxMiddleCoolSpeed(axisPmContMscTech.getMaxMiddleCoolSpeed());
        // AD类型代码
        pmCmdLargePlt.setAdTypeCode(axisPmContMscTech.getAdTypeCode());
        // 热矫可否
        pmCmdLargePlt.setHotRectifyFlag(axisPmContMscTech.getHotRectifyFlag().toString());
        // 热矫方法代码
        pmCmdLargePlt.setHotRectifyMethodCode(axisPmContMscTech.getHotRectifyMethodCode());
        // 读取合同产线工艺参数表（PM_CONT_MSC_TECH），取plate_dt_code的第一位，作为命令大板表（PM_CMD_LARGE_PLT）中轧制大板去向roll_plate_dest的取值。
        pmCmdLargePlt.setRollPlateDest(axisPmContMscTech.getPlateDtCode().substring(0, 1));
        // 读取合同产线工艺参数表（PM_CONT_MSC_TECH），获得以下字段值，并根据合同号与临时命令板坯号更新到命令大板表（PM_CMD_LARGE_PLT）中：
        // ACC冷却开始等待时间上限
        if(qdToLineupResultRollingVO != null) {
            pmCmdLargePlt.setMaxAccWaitTime(qdToLineupResultRollingVO.getMaxAccWaitTime());
            // ACC冷却开始等待时间下限
            pmCmdLargePlt.setMinAccWaitTime(qdToLineupResultRollingVO.getMinAccWaitTime());
            // 快冷开始温度目标值
            pmCmdLargePlt.setFastBgTempAim(qdToLineupResultRollingVO.getFastBgTempAim());
            // 快冷开始温度上限
            pmCmdLargePlt.setMaxFastBgTemp(qdToLineupResultRollingVO.getMaxFastBgTemp());
            // 快冷开始温度下限
            pmCmdLargePlt.setMinFastBgTemp(qdToLineupResultRollingVO.getMinFastBgTemp());
            // 快冷速率目标值
            pmCmdLargePlt.setFastSpAim(qdToLineupResultRollingVO.getFastSpAim());
            // 快冷速率上限
            pmCmdLargePlt.setMaxFastSp(qdToLineupResultRollingVO.getMaxFastSp());
            // 快冷速率下限
            pmCmdLargePlt.setMinFastSp(qdToLineupResultRollingVO.getMinFastSp());
            // 快冷结束温度目标值
            pmCmdLargePlt.setFastEndTempAim(qdToLineupResultRollingVO.getFastEndTempAim());
            // 快冷结束温度上限
            pmCmdLargePlt.setMaxFastEndTemp(qdToLineupResultRollingVO.getMaxFastEndTemp());
            // 快冷结束温度下限
            pmCmdLargePlt.setMinFastEndTemp(qdToLineupResultRollingVO.getMinFastEndTemp());
            // 慢冷开始温度1目标值
            pmCmdLargePlt.setSlow1TBgTempAim(qdToLineupResultRollingVO.getSlow1TBgTempAim());
            // 慢冷开始温度1上限
            pmCmdLargePlt.setMaxSlow1BgTemp(qdToLineupResultRollingVO.getMaxSlow1BgTemp());
            // 慢冷开始温度1下限
            pmCmdLargePlt.setMinSlow1BgTemp(qdToLineupResultRollingVO.getMinSlow1BgTemp());
            // 慢冷速率1目标值
            pmCmdLargePlt.setSlow1SpAim(qdToLineupResultRollingVO.getSlow1SpAim());
            // 慢冷速率1上限
            pmCmdLargePlt.setMaxSlow1Sp(qdToLineupResultRollingVO.getMaxSlow1Sp());
            // 慢冷速率1下限
            pmCmdLargePlt.setMinSlow1Sp(qdToLineupResultRollingVO.getMinSlow1Sp());
            // 慢冷结束温度1目标值
            pmCmdLargePlt.setSlow1EndTempAim(qdToLineupResultRollingVO.getSlow1EndTempAim());
            // 慢冷结束温度1上限
            pmCmdLargePlt.setMaxSlow1EndTemp(qdToLineupResultRollingVO.getMaxSlow1EndTemp());
            // 慢冷开始温度2目标值
            pmCmdLargePlt.setSlow2EndTempAim(qdToLineupResultRollingVO.getSlow2EndTempAim());
            // 慢冷开始温度2上限
            pmCmdLargePlt.setMaxSlow2EndTemp(qdToLineupResultRollingVO.getMaxSlow2EndTemp());
            // 慢冷开始温度2下限
            pmCmdLargePlt.setMinSlow2EndTemp(qdToLineupResultRollingVO.getMinSlow2EndTemp());
            // 慢冷速率2目标值
            pmCmdLargePlt.setSlow2SpAim(qdToLineupResultRollingVO.getSlow2SpAim());
            // 慢冷速率2上限
            pmCmdLargePlt.setMaxSlow2Sp(qdToLineupResultRollingVO.getMaxSlow2Sp());
            // 慢冷速率2下限
            pmCmdLargePlt.setMinSlow2Sp(qdToLineupResultRollingVO.getMinSlow2Sp());
            // 慢冷结束温度2目标值
            pmCmdLargePlt.setSlow2EndTempAim(qdToLineupResultRollingVO.getSlow2EndTempAim());
            // 慢冷结束温度2上限
            pmCmdLargePlt.setMaxSlow2EndTemp(qdToLineupResultRollingVO.getMaxSlow2EndTemp());
            // 慢冷结束温度2下限
            pmCmdLargePlt.setMinSlow2EndTemp(qdToLineupResultRollingVO.getMinSlow2EndTemp());
            // ACC冷却开始温度
            pmCmdLargePlt.setAccTempStart(qdToLineupResultRollingVO.getAccTempStart());
            // ACC冷却结束温度
            pmCmdLargePlt.setAccTempEnd(qdToLineupResultRollingVO.getAccTempEnd());
            // ACC冷却速率
            pmCmdLargePlt.setAccColdV(qdToLineupResultRollingVO.getAccColdV());
            // 装炉温度
            pmCmdLargePlt.setLoadFurTemp(resultHeatVO.getLoadFurTemp());
            // 出炉温度
            pmCmdLargePlt.setHeatTemp(resultHeatVO.getHeatTemp());
            // 第一阶段厚度
            pmCmdLargePlt.setFirstThick(resultHeatVO.getFirstThick());
            // 第一阶段开始温度
            pmCmdLargePlt.setFirstBgTemp(resultHeatVO.getFirstBgTemp());
            // 第一阶段结束温度
            pmCmdLargePlt.setFirstEndTemp(resultHeatVO.getFirstEndTemp());
            // 第二阶段厚度
            pmCmdLargePlt.setScdThick(qdToLineupResultRollingVO.getScdThick());
            // 第二阶段开始温度
            pmCmdLargePlt.setScdBgTemp(qdToLineupResultRollingVO.getScdBgTemp());
            // 第二阶段结束温度
            pmCmdLargePlt.setScdEndTemp(qdToLineupResultRollingVO.getScdEndTemp());
            // 第一控轧点厚度最小值
            pmCmdLargePlt.setMinCr1Thick(qdToLineupResultRollingVO.getMinCr1Thick());
            // 第一控轧点温度目标值
            pmCmdLargePlt.setCr1TempAim(qdToLineupResultRollingVO.getCr1TempAim());
            // 第一控轧点温度最大值
            pmCmdLargePlt.setMaxCr1Temp(qdToLineupResultRollingVO.getMaxCr1Temp());
            // 第一控轧点温度最小值
            pmCmdLargePlt.setMinCr1Temp(qdToLineupResultRollingVO.getMinCr1Temp());
            // 第二控轧点厚度最小值
            pmCmdLargePlt.setMinCr2Thick(qdToLineupResultRollingVO.getMinCr2Thick());
            // 第二控轧点温度目标值
            pmCmdLargePlt.setCr2TempAim(qdToLineupResultRollingVO.getCr2TempAim());
            // 第二控轧点温度最大值
            pmCmdLargePlt.setMaxCr2Temp(qdToLineupResultRollingVO.getMaxCr2Temp());
            // 第二控轧点温度最小值
            pmCmdLargePlt.setMinCr2Temp(qdToLineupResultRollingVO.getMinCr2Temp());
        }
        // 对于所有合同号
        // ，读取合同产线工艺参数表（PM_CONT_MSC_TECH），确定下述字段取值逻辑如下，并根据合同号与临时命令板坯号更新到命令大板表中（PM_PD_PLATE_INFO）：
//        List<String> ctrlRollCodeList = pmContMscTechList.stream().map(PmContMscTech::getCtrlRollCode)
//                .collect(Collectors.toList());
//        List<String> adModeCodeList = pmContMscTechList.stream().map(PmContMscTech::getAdModeCode)
//                .collect(Collectors.toList());
//        String ultDetectMethodCode = pmContMscTechList.stream()
//                .filter(item -> Objects.nonNull(item.getUltDetectMethodCode())).collect(Collectors.toList()).get(0)
//                .getUltDetectMethodCode();
//        // trace_code生产跟踪代码
//        // finish_plan_date精整计划日期
//        adModeCodeList.add(pmCmdLargePlt.getAdModeCode());
//        ctrlRollCodeList.add(pmCmdLargePlt.getCtrlRollCode());
//        pmCmdLargePlt.setCtrlRollCode(Collections.min(ctrlRollCodeList));
//        pmCmdLargePlt.setAdModeCode(Collections.min(adModeCodeList));
//        pmCmdLargePlt.setCoolCode(updatePmCmdSlab.getCoolCode());
//        pmCmdLargePlt.setUltDetectMethodCode(ultDetectMethodCode);
        // 组板方式form_plate_mode根据不同的组板方式采用不同的取值逻辑
        // 如果为A/G型组板，取值为0；其他情况取自轴合同（合同产线工艺参数表
        if ("A".equals(pmCmdLargePlt.getFormPlateMode())) {
            pmCmdLargePlt.setSsFlag("0");
            pmCmdLargePlt.setDssFlag(axisPmContMscTech.getDssFlag() != null ? axisPmContMscTech.getDssFlag().toString():null);
            pmCmdLargePlt.setDsFlag(axisPmContMscTech.getDsFlag() != null ? axisPmContMscTech.getDsFlag().toString():null);
        } else if ("G".equals(pmCmdLargePlt.getFormPlateMode())) {
            pmCmdLargePlt.setSsFlag("0");
            pmCmdLargePlt.setDssFlag("0");
            pmCmdLargePlt.setDsFlag("0");
        } else {
            pmCmdLargePlt.setSsFlag(axisPmContMscTech.getSsFlag() != null ? axisPmContMscTech.getSsFlag().toString():null);
            pmCmdLargePlt.setDssFlag(axisPmContMscTech.getDssFlag() != null ? axisPmContMscTech.getDssFlag().toString():null);
            pmCmdLargePlt.setDsFlag(axisPmContMscTech.getDsFlag() != null ? axisPmContMscTech.getDsFlag().toString():null);
        }
    }
    
    /**
     * 更新命令参数表信息
     * @param pmCmdCont
     * @param pmProContProdTtr
     * @param contMscTech
     * @param heattreatList
     * @param qdToLineupResultHeatMap
     */
    private void updatePmCmdCont(PmCmdCont pmCmdCont , PmProContProdTtr pmProContProdTtr,PmContMscTech contMscTech, List<QdToLineupResultHeattreatVO> heattreatList,
                                 Map<String, QdToLineupResultRollingVO> qdToLineupResultRollingMap,  List<QdToLineupResultUTVO> qdToLineupResultUTVOList) {
        // 钢板形状代码
        pmCmdCont.setShpCode(pmProContProdTtr.getShpCode());

        String utCheckCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? null : qdToLineupResultUTVOList.get(0).getUtCheckCode();
        String utPdCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? null : qdToLineupResultUTVOList.get(0).getUtPdCode();
        pmCmdCont.setUtCheckCode(utCheckCode);
        pmCmdCont.setUtPdCode(utPdCode);
        // 厚板品种代码
        pmCmdCont.setProdCodeHp(pmProContProdTtr.getProdCodeHp());
        // 内部钢种
        pmCmdCont.setStNo(contMscTech.getStNo());
        // 制品记号（试验片SR）
        pmCmdCont.setProdSrMark(pmProContProdTtr.getProdSrMark());
        // 制品记号（边部形态）
        pmCmdCont.setProdSideMark(pmProContProdTtr.getProdSideMark());
        // 制品记号（抛丸涂漆）
        pmCmdCont.setProdShotMark(pmProContProdTtr.getProdShotMark());
        // 制品记号（试验片正火）
        pmCmdCont.setProdNMark(pmProContProdTtr.getProdNMark());
        // 制品记号（试验片淬火）
        pmCmdCont.setProdQMark(pmProContProdTtr.getProdQMark());
        // 制品记号（试验片回火）
        pmCmdCont.setProdTMark(pmProContProdTtr.getProdTMark());
        // 制品记号（试验片退火）
        pmCmdCont.setProdAMark(pmProContProdTtr.getProdAMark());
        // 工序记号（超声探伤）
        pmCmdCont.setBacklogUtMark(pmProContProdTtr.getBacklogUtMark());
        // 工序记号（正火）
        pmCmdCont.setBacklogNMark(pmProContProdTtr.getBacklogNMark());
        // 工序记号（淬火）
        pmCmdCont.setBacklogQMark(pmProContProdTtr.getBacklogQMark());
        // 工序记号（回火）
        pmCmdCont.setBacklogTMark(pmProContProdTtr.getBacklogTMark());
        // 工序记号（退火）
        pmCmdCont.setBacklogAMark(pmProContProdTtr.getBacklogAMark());
        // 工序记号（脱磁）
        pmCmdCont.setBacklogDemagMark(pmProContProdTtr.getBacklogDemagMark());
        // 工序记号（PT探伤）
        pmCmdCont.setBacklogPtMark(pmProContProdTtr.getBacklogPtMark());
        // 工序记号（MT探伤）
        pmCmdCont.setBacklogTMark(pmProContProdTtr.getBacklogTMark());
        // 工序记号（TMCP）
        pmCmdCont.setBacklogTmcpMark(pmProContProdTtr.getBacklogTmcpMark());
        // 订货厚度
        pmCmdCont.setOrderThick(pmProContProdTtr.getOrderThick());
        // 订货宽度
        pmCmdCont.setOrderWidth(pmProContProdTtr.getOrderWidth());
        // 订货长度
        pmCmdCont.setOrderLen(pmProContProdTtr.getOrderLen());
        // 宽度区分
        pmCmdCont.setWidthDiv(pmProContProdTtr.getWidthDiv().toString());
        // 宽度上限
        pmCmdCont.setWidthMax(pmProContProdTtr.getWidthMax());
        // 宽度下限
        pmCmdCont.setWidthMin(pmProContProdTtr.getWidthMin());
        // 长度区分
        pmCmdCont.setLenDiv(pmProContProdTtr.getLenDiv().toString());
        // 订货长度下限
        pmCmdCont.setOrderLenMin(pmProContProdTtr.getOrderMinLen());
        // 订货长度上限
        pmCmdCont.setOrderLenMax(pmProContProdTtr.getOrderMaxLen());
        // 展宽比下限
        pmCmdCont.setWidenMin(contMscTech.getWidenMin());
        // 压缩比下限
        pmCmdCont.setCompressMin(contMscTech.getCompressMin());
        // 轧制方向代码
        pmCmdCont.setRollDirectCode(contMscTech.getRollDirectCode());
        // 控轧代码
        pmCmdCont.setCtrlRollCode(contMscTech.getCtrlRollCode());
        // AD类型代码
        pmCmdCont.setAdTypeCode(contMscTech.getAdTypeCode());
        // AD控制模式代码
        pmCmdCont.setAdModeCode(contMscTech.getAdModeCode());
        // 切断方式代码
        pmCmdCont.setCutModeCode(contMscTech.getCutModeCode());
        // 探伤方式代码
        pmCmdCont.setUltDetectMethodCode(contMscTech.getUltDetectMethodCode());
        // 超声探伤代码
        pmCmdCont.setUltCode(contMscTech.getUltCode());
        // 热处理方式
        pmCmdCont.setHeatTreatMode(contMscTech.getWholeHeatTreatmentType());
        // 根据查到的合同号，读取MES合同主表，获取下表中字段并根据合同号与临时命令板坯号更新到命令参数表中（PM_CMD_CONT）
        // 合同性质代码
        pmCmdCont.setOrderTypeCode(pmProContProdTtr.getOrderTypeCode());
        // 出口标记
        pmCmdCont.setExportFlag(pmProContProdTtr.getExportFlag().toString());
        // 最终用户代码
        pmCmdCont.setFinCustCode(pmProContProdTtr.getFinCustCode());
        // 产品规范码
        pmCmdCont.setPsc(pmProContProdTtr.getPsc());
        // 产品最终用途码
        pmCmdCont.setApn(pmProContProdTtr.getApn());
        // 冶金规范码
        pmCmdCont.setMsc(pmProContProdTtr.getMsc());
        // 标准
        pmCmdCont.setSgStd(pmProContProdTtr.getSgStd());
        // 牌号（钢级）
        pmCmdCont.setSgSign(pmProContProdTtr.getSgSign());
        // 根据产线号与查到的合同号，读取合同产线工艺参数表（PM_CONT_MSC_TECH），获取下表中字段并根据合同号与临时命令板坯号更新到命令参数表中（PM_CMD_CONT）
        // 热矫可否
        QdToLineupResultRollingVO resultRollingVO = qdToLineupResultRollingMap.getOrDefault(pmCmdCont.getOrderNo(),new QdToLineupResultRollingVO());
        pmCmdCont.setHotRectifyFlag(resultRollingVO.getHotRectifyFlag());
        // 冷矫可否
        pmCmdCont.setColdRectifyFlag(resultRollingVO.getColdRectifyFlag());
        // 温矫可否
        pmCmdCont.setWarmRectifyFlag(resultRollingVO.getWarmRectifyFlag());
        // 温压可否
        pmCmdCont.setWarmPressFlag(resultRollingVO.getWarmPressFlag());
        
        // 压平可否
        // pmCmdCont.setCanPressFlag(qdToLineupResultRolling.getCanPressFlag());
        // 带温压平开始温度下限
        // pmCmdCont.setWpTempMin(new
        // BigDecimal(qdToLineupResultRolling.getWpTempMin().toString()));
        // 根据产线号与查到的合同号，读取合同产线工艺参数表（PM_CONT_MSC_TECH），获取下表中字段并根据合同号与临时命令板坯号更新到命令参数表中（PM_CMD_CONT）：

        if (CollectionUtils.isNotEmpty(heattreatList)) {
            int size = heattreatList.size();
            for (int i = 1; i < size + 1; i++) {
                String fieldName1 = "keepTempMax" + i;
                String fieldName2 = "keepTempMin" + i;
                String fieldName3 = "backfireMax" + i;
                String fieldName4 = "backfireMin" + i;
                QdToLineupResultHeattreatVO heattreat = heattreatList.get(i - 1);
                try {
                    pmCmdCont.setDynamicField(fieldName1, heattreat.getKeepWarmMax());
                    pmCmdCont.setDynamicField(fieldName2, heattreat.getKeepWarmMin());
                    pmCmdCont.setDynamicField(fieldName3, heattreat.getRednessTempMax());
                    pmCmdCont.setDynamicField(fieldName4, heattreat.getRednessTempMin());
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    log.info("QD_TO_LINEUP_RESULT_HEATTREAT表记录数,超过目标值上限！");
                }
            }
        }
    }

    private String commandPreProcessGeneration(PmContMscTech axisPmContMscTech, ReservationProcessGenerationDTO dto,
                                               PmCmdLargePlt pmCmdLargePlt, QdToLineupResultHeattreatVO heattreat,
                                               MmPlateVO mmPlateVO, String utCheckCode, String utPdCode, Long mmHtmrsltNum, String isUt,
                                               String shotFlag, String witnessStatus, int ultDetectStd,
                                               PmProContProdTtr pmProContProdTtr) {
        String processCode = "";
        ProcessGenerateStrategyDTO processDTO = new ProcessGenerateStrategyDTO();
        processDTO.setMatDesignKind(dto.getMatDesignKind());
        processDTO.setSlabNo(dto.getSlabNo());
        processDTO.setRollLineNo(dto.getMscLineNo().substring(2, 4));
        processDTO.setCoolCode(pmCmdLargePlt.getCoolCode());
        processDTO.setPlateDtCode(pmCmdLargePlt.getPlateDtCode());
        processDTO.setShpCode(pmCmdLargePlt.getShpCode());
        processDTO.setWholeBacklog(dto.getWholeBacklog());
        processDTO.setPmCmdLargePlt(pmCmdLargePlt);
        processDTO.setMmPlateVO(mmPlateVO);
        processDTO.setMmHtmrsltNum(mmHtmrsltNum);
        processDTO.setIsUt(isUt);
        processDTO.setAxisPmContMscTech(axisPmContMscTech);
        processDTO.setUtCheckCode(utCheckCode);
        processDTO.setShotFlag(shotFlag);
        processDTO.setShotHt(heattreat != null ? heattreat.getShotHt() : "0");
        processDTO.setUtPdCode(utPdCode);
        processDTO.setTenantId(axisPmContMscTech.getTenantId());
        processDTO.setWitnessStatus(witnessStatus);
        processDTO.setUltDetectStd(ultDetectStd);
        processDTO.setOrderLen(pmProContProdTtr.getOrderLen());
        ProcessGenerateStrategy processGenerateStrategy = ProcessGenerateStrategyFactory.matchProcessStrategy(dto.getSplitWholeBacklog());
        if (processGenerateStrategy != null) {
            processCode = processGenerateStrategy.getProcessCode(processDTO);
        }
        return processCode;

    }


    /**
     * 预定工序生成
     */
    private String reservationProcessGeneration(PmContMscTech axisPmContMscTech, ReservationProcessGenerationDTO dto, PmCmdCont pmCmdCont,
            PmCmdLargePlt pmCmdLargePlt,  QdToLineupResultHeattreatVO heattreat, String isUt) {
        // 若whole_backlog_code取值为P1，代表第一道轧制工序,若whole_backlog_code取值为P6，代表第一道精整工序
        String heatTreatMode = axisPmContMscTech.getHeatTreatMode();
        String platePreProc1 = "";
        String platePreProc2 = "";
        String process = "";
        // 根据材料号（临时命令板坯号），读取钢板主数据表[MM_PLATE]中的材料实际宽度mat_act_width、材料实际长度mat_act_len。
        MmPlateVO mmPlateVO = pmPdSlabInfoMapper.selectMmplate(pmCmdLargePlt.getTmpSlabNo());
        String rollLineNo = dto.getMscLineNo().substring(2, 4);
        String matDesignKind = dto.getMatDesignKind();

        // 获取QD_TO_LINEUP_RESULT_UT的ut_check_code, UT_PD_CODE
        List<QdToLineupResultUTVO> qdToLineupResultUTVOList = pmPdSlabInfoMapper.selectUtCheckCodeByOrderNo(Arrays.asList(pmCmdCont.getOrderNo()),  axisPmContMscTech.getTenantId());
        String utCheckCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtCheckCode();
        String utPdCode = CollectionUtils.isEmpty(qdToLineupResultUTVOList) ? "0" : qdToLineupResultUTVOList.get(0).getUtPdCode();

        if (dto.getSplitWholeBacklog().contains("P1")) {
            // 余材钢板组板（MAT_DESIGN_KIND为P时）不用设计本工序，余材板坯组板、出钢材组板（MAT_DESIGN_KIND为S或C时）需要设计本工序。余材板坯组板、出钢材组板的“预定工序代码1”取值决定于产线号的第三四位：
            if ("S".equals(matDesignKind) || "C".equals(matDesignKind)) {
                // 当前预定工序代码
                switch (rollLineNo) {
                case "10":
                    platePreProc1 = "1R1";
                    break;
                case "20":
                    platePreProc1 = "2R1";
                    break;
                case "30":
                    platePreProc1 = "5R1";
                    break;
                default:
                }
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            }
            // 第一道轧制工序后添加分张工序：
            // 材料设计类型为S或L且板坯号第一位为E时，根据产线号第三四位添加分张工序:
            if (("S".equals(matDesignKind) || "L".equals(matDesignKind)) ) {
                platePreProc1 = addSplittingProcess(dto.getSlabNo(), rollLineNo, axisPmContMscTech.getTenantId());
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            }
        }
        if (dto.getSplitWholeBacklog().contains("P6")) {
            // Ⅰ若缓冷代码取值为122（退火缓冷）
            // 如果产线号的第三四位为30，当前预定工序代码取值为“5A9”
            // 如果产线号的第三四位不为30，报错“产线号不为30.但源头不应该生成缓退火缓冷”
            if ("122".equals(pmCmdLargePlt.getCoolCode())) {
                if ("30".equals(rollLineNo)) {
                    platePreProc1 = "5A9";
                } else {
                    throw new CommonException("产线号不为30.但源头不应该生成缓退火缓冷");
                }
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            } else if ((Objects.nonNull(pmCmdLargePlt.getCoolCode()) && "N".equals(pmCmdLargePlt.getCoolCode())
                    && "1".equals(pmCmdLargePlt.getCoolCode().substring(0, 1))) && !"p".equals(matDesignKind)
                    && ("3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) || "2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)))) {
                // 其他情况（缓冷代码不为N/缓冷代码不为空/缓冷代码第一位不为1，不是余材钢板组板，轧制大板去向取值为3）
                if ("10".equals(rollLineNo)) {
                    platePreProc1 = "1D0";
                } else if ("20".equals(rollLineNo)) {
                    platePreProc1 = "2D0";
                } else if ("30".equals(rollLineNo)) {
                    platePreProc1 = "5D0";
                }
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            }
            // 精整火切工序，根据轧制大板去向、切割方式、组板方式决定。即“轧制大板去向取值为3，材料设计类型不为余材钢板组板或者“钢板形状代码不为空
            if ((("3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) || "2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)))
                    && !"P".equals(pmCmdLargePlt.getMatDesignKind())) || Objects.nonNull(pmCmdLargePlt.getShpCode())) {
                // Ⅰ非热处理情况下（whole_backlog以'PA'开头）：
                if (!dto.getWholeBacklog().contains("PA")) {
                    switch (rollLineNo) {
                    case "10":
                        platePreProc1 = "1G1";
                        break;
                    case "20":
                        platePreProc1 = "2G1";
                        break;
                    case "30":
                        if (Objects.nonNull(pmCmdLargePlt.getShpCode())) {
                            platePreProc1 = "5G2";
                        } else {
                            platePreProc1 = "5G1";
                        }
                        break;
                    default:
                    }
                    if (StringUtils.isNotEmpty(platePreProc1)) {
                        process = process + platePreProc1 + "-";
                        platePreProc1 = "";
                    }
                } else {
                    // Ⅱ热处理分支情况下：
                    BigDecimal rollAimLen = pmCmdLargePlt.getRollAimLen();
                    // 根据临时命令板坯号读取命令大板表中的轧制目标长度ROLL_AIM_LEN、小板块数TOT_SMALL_PLATE_NUM
//                    if ("10".equals(rollLineNo) && rollAimLen.compareTo(new BigDecimal("18000")) > 0) {
//                        platePreProc1 = "1G1";
//                    } else if ("20".equals(rollLineNo) && rollAimLen.compareTo(new BigDecimal("15000")) > 0) {
//                        platePreProc1 = "2G1";
//                    } else if ("30".equals(rollLineNo)) {
//                        if (Objects.nonNull(pmCmdLargePlt.getShpCode())) {
//                            platePreProc1 = "5G2";
//                        }
//                        if (rollAimLen.compareTo(new BigDecimal("18000")) > 0) {
//                            platePreProc1 = "5G1";
//                        }
//                    }
                    if ("10".equals(rollLineNo)) {
                        platePreProc1 = "1G1";
                    } else if ("20".equals(rollLineNo) ) {
                        platePreProc1 = "2G1";
                    } else if ("30".equals(rollLineNo)) {
                        platePreProc1 = "5G1";
                    }
                    if (StringUtils.isNotEmpty(platePreProc1)) {
                        process = process + platePreProc1 + "-";
                        platePreProc1 = "";
                    }
                }
            }
            // ③余材钢板组板（材料设计类型为P）时
            if (PdMatType.P.getCode().equals(matDesignKind)) {
                // 根据临时命令板坯号，读取命令大板表中的大板内成品小板总块数tot_small_plate_num、头部试样长sample_len_head、
                // 尾部试样长sample_len_tail、中部试样长sample_len_mid、奉送样试样长sample_len_give。
                // 根据合同号与产线号，读取tqmto41合同工艺参数表_厚板_轧机中厚板流向代码plate_dt_code的第一位，
                // 作为轧制大板去向roll_plate_dest
                // Ⅰ如果大板内成品小板总块数>1，
                if (pmCmdLargePlt.getTotSmallPlateNum() > 1) {
                    // 如果轧制大板去向不为3且产线号第三四位为30，不做处理
                    if (("3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) || "2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)))
                            || !"30".equals(pmCmdLargePlt.getMscLineNo().substring(2, 4))) {
                        switch (rollLineNo) {
                        case "10":
                            platePreProc1 = "1G1";
                            break;
                        case "20":
                            platePreProc1 = "2G1";
                            break;
                        case "30":
                            if (Objects.nonNull(pmCmdLargePlt.getShpCode())) {
                                platePreProc1 = "5G2";
                            } else {
                                platePreProc1 = "5G1";
                            }
                            break;
                        default:
                        }
                        if (StringUtils.isNotEmpty(platePreProc1)) {
                            process = process + platePreProc1 + "-";
                            platePreProc1 = "";
                        }
                    }
                } else if (pmCmdLargePlt.getTotSmallPlateNum() == 1) {
                    // 读取组板合同总量表中的小板宽度small_plate_width、小板长度small_plate_len。
                    // 如果“材料实际宽度>小板宽度”或“材料实际长度>小板长度”或“press_appoint不为0”或“头部试样长不为0”或“中部试样长不为0”或“尾部试样长不为0”或“奉送样长度不为0”：
                    if (mmPlateVO.getMatActWid().compareTo(pmCmdLargePlt.getCombinePlateWidth()) > 0
                            || mmPlateVO.getMatActLen().compareTo(pmCmdLargePlt.getCombinePlateLen()) > 0
                            || !"0".equals(pmCmdLargePlt.getPressAppoint())
                            || pmCmdLargePlt.getSampleLenHead().compareTo(BigDecimal.ZERO) != 0
                            || pmCmdLargePlt.getSampleLenTail().compareTo(BigDecimal.ZERO) != 0) {
                        // 根据材料号（临时命令板坯号/临时命令板坯号前七位/000），查询厚板热处理实绩表MM_HTMRSLT中有无生产流水号（a）；
                        Long a = pmPdSlabInfoMapper.selectMmHtmrslt(pmCmdLargePlt.getTmpSlabNo());
                        // 根据合同号与产线号，查询合同产线工艺参数表（PM_CONT_MSC_TECH）中whole_backlog含有'PA'的合同是否存在（b）
                        int b = pmPdSlabInfoMapper.selectPmContMscTech(pmCmdCont.getOrderNo(), dto.getMscLineNo());
                        // 如果“a存在”且“b存在”且“轧制大板去向为3”且“大压下指定字段press_appoint不为0”，不做处理
                        if (!(a > 0 && b > 0) || (!"3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) && !"2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)))
                                || "0".equals(pmCmdLargePlt.getPressAppoint())) {
                            switch (rollLineNo) {
                            case "10":
                                platePreProc1 = "1G2";
                                break;
                            case "20":
                                platePreProc1 = "2G2";
                                break;
                            case "30":
                                platePreProc1 = "5G2";
                                break;
                            default:
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        } else {
                            switch (rollLineNo) {
                            case "10":
                                platePreProc1 = "1G1";
                                break;
                            case "20":
                                platePreProc1 = "2G1";
                                break;
                            case "30":
                                if (Objects.nonNull(pmCmdLargePlt.getShpCode())) {
                                    platePreProc1 = "5G2";
                                } else {
                                    platePreProc1 = "5G1";
                                }
                                break;
                            default:
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                    }
                }
            }
            // ④根据临时命令板坯号与产线号，查询命令大板表中的钢板形状代码Ⅰ如果不是余材钢板组板（材料设计类型不为P）
//            if (!PdMatType.P.getCode().equals(pmCmdLargePlt.getMatDesignKind())) {
//                // 如果轧制大板去向不为3
//                if (!"3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) && !"2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1))) {
//                    List<String> ultPdCodeList = pmPdSlabInfoMapper.selectUltPdCodeList(pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                    String ultPdCode = CollectionUtils.isEmpty(ultPdCodeList) ? "" : ultPdCodeList.get(0);
//                    // 如果合同表中的探伤代码ult_pd_code为1或3
//                    if ("1".equals(ultPdCode) || "3".equals(ultPdCode)) {
//                                // 根据合同号与产线号，查询合同工艺参数表_厚板_精整(QD_TO_LINEUP_RESULT_SIZING）中的走查模式代码ult_check_code
//                        List<String> ultCheckCodeList = pmPdSlabInfoMapper.selectUltCheckCode(pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                        if (ultCheckCodeList.size() > 1) {
//                            throw new CommonException("pm.cmd_large_plt_003", pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                        }
//                        String ultCheckCode = CollectionUtils.isEmpty(ultCheckCodeList) ? "" : ultCheckCodeList.get(0);
//                        // 如果产线号的第三四位为10，
//                        switch (rollLineNo) {
//                        case "10":
//                            // ult_check_code不为2时，当前预定工序代码取值为“1U1”
//                            // ult_check_code=2时，当前预定工序代码取值为“1U4”
//                            if (!"2".equals(ultCheckCode)) {
//                                platePreProc1 = "1U1";
//                            } else {
//                                platePreProc1 = "1U4";
//                            }
//                            break;
//                        case "20":
//                            // ult_check_code不为2时，当前预定工序代码取值为“2U1”
//                            // ult_check_code=2时，当前预定工序代码取值为“2U4”
//                            if (!"2".equals(ultCheckCode)) {
//                                platePreProc1 = "2U1";
//                            } else {
//                                platePreProc1 = "2U4";
//                            }
//                            break;
//                        case "30":
//                            // 如果钢板形状代码不为空（特殊板生成离线探伤工序），当前预定工序代码取值为“5U2”
//                            // 如果钢板形状代码为空，
//                            // ult_check_code不为2时，当前预定工序代码取值为“5U1”
//                            // ult_check_code=2时，当前预定工序代码取值为“5U4”
//                            if (Objects.nonNull(pmCmdLargePlt.getShpCode())) {
//                                platePreProc1 = "5U2";
//                            } else {
//                                if (!"2".equals(ultCheckCode)) {
//                                    platePreProc1 = "5U1";
//                                } else {
//                                    platePreProc1 = "5U4";
//                                }
//                            }
//                            break;
//                        default:
//                        }
//                    }
//                    if (StringUtils.isNotEmpty(platePreProc1)) {
//                        process = process + platePreProc1 + "-";
//                        platePreProc1 = "";
//                    }
//                } else {
//                    List<String> ultPdCodeList = pmPdSlabInfoMapper.selectUltPdCodeList(pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                    String ultPdcode = CollectionUtils.isEmpty(ultPdCodeList) ? "" : ultPdCodeList.get(0);
//                    // 如果合同表中的探伤代码ult_pd_code为1或3
//                    if ("1".equals(ultPdcode) || "3".equals(ultPdcode)) {
//                        switch (rollLineNo) {
//                        case "10":
//                            platePreProc1 = "1U4";
//                            break;
//                        case "20":
//                            platePreProc1 = "2U4";
//                            break;
//                        case "30":
//                            platePreProc1 = "5U4";
//                            break;
//                        default:
//                        }
//                    }
//                    if (StringUtils.isNotEmpty(platePreProc1)) {
//                        process = process + platePreProc1 + "-";
//                        platePreProc1 = "";
//                    }
//                }
//            } else {
//                List<String> ultPdCodeList = pmPdSlabInfoMapper.selectUltPdCodeList(pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                String ultPdCode = CollectionUtils.isEmpty(ultPdCodeList) ? "" : ultPdCodeList.get(0);
//                // 如果合同表中的探伤代码ult_pd_code为1或2，没有3
//                if ("1".equals(ultPdCode) || "2".equals(ultPdCode)) {
//                    switch (rollLineNo) {
//                    case "10":
//                        platePreProc1 = "1U4";
//                        break;
//                    case "20":
//                        platePreProc1 = "2U4";
//                        break;
//                    case "30":
//                        platePreProc1 = "5U4";
//                        break;
//                    default:
//                    }
//                    if (StringUtils.isNotEmpty(platePreProc1)) {
//                        process = process + platePreProc1 + "-";
//                        platePreProc1 = "";
//                    }
//                }
//            }

            // 探伤工序
            if ("1".equals(isUt) && !(dto.getWholeBacklog().contains("PA") || dto.getWholeBacklog().contains("PB") || dto.getWholeBacklog().contains("PC"))) {
                String crackProc = this.generateCrackProcess(axisPmContMscTech.getPlateDtCode(), rollLineNo, utCheckCode);
                if (StringUtils.isNotEmpty(crackProc)) {
                    process = process + crackProc + "-";
                }
            }

            // ⑤如果有销售下的成品抛丸要求(根据轴合同号读取[质量模块]MES合同主表，shot_flag取值为1)
            String shotFlag = pmPdSlabInfoMapper.selectShotFlag(pmCmdCont.getOrderNo());
            if ("1".equals(shotFlag)) {
                switch (rollLineNo) {
                case "10":
                    platePreProc1 = "1C1";
                    break;
                case "20":
                    platePreProc1 = "2C1";
                    break;
                case "30":
                    platePreProc1 = "5C1";
                    break;
                default:
                }
            }
            if (StringUtils.isNotEmpty(platePreProc1)) {
                process = process + platePreProc1 + "-";
                platePreProc1 = "";
            }

        }
        // 若whole_backlog_code取值为PA/PB/PC（热处理
        if (dto.getSplitWholeBacklog().contains(("PA")) || dto.getSplitWholeBacklog().contains("PB")
                || dto.getSplitWholeBacklog().contains("PC")) {
            // 根据合同号、产线号，读取合同处理热处理工艺标准QD_TO_LINEUP_RESULT_HEATTREAT，记为表α
            // 根据材料号=临时命令板坯号 ，读取钢板主数据表（MM_PLATE）中的综判代码。
            // 如果厚板热处理实绩表MM_HTMRSLT中查询不到生产流水号
            // 根据材料号（临时命令板坯号/临时命令板坯号前七位/000），查询厚板热处理实绩表MM_HTMRSLT中有无生产流水号（a）；

            List<String> ultPdCodeList = pmPdSlabInfoMapper.selectUltPdCodeList(pmCmdCont.getOrderNo(), dto.getMscLineNo());
            String ultPdCode = CollectionUtils.isEmpty(ultPdCodeList) ? "" : ultPdCodeList.get(0);


            // 探伤工序
            if ("1".equals(isUt) && "1".equals(utPdCode)) {
              String crackProc = this.generateCrackProcess( axisPmContMscTech.getPlateDtCode(), rollLineNo, utCheckCode);
                if (StringUtils.isNotEmpty(crackProc)) {
                    process = process + crackProc + "-";
                }
            }

            Long a = pmPdSlabInfoMapper.selectMmHtmrslt(pmCmdLargePlt.getTmpSlabNo());
            if (a <= 0) {
                String shotHt = heattreat != null ? heattreat.getShotHt() : "";
                // （抛丸工序）如果tqmto45.shot_ht=1：
                if ("1".equals(shotHt)) {
                    if ("10".equals(rollLineNo)) {
                        platePreProc1 = "1C2";
                    } else if ("20".equals(rollLineNo)) {
                        platePreProc1 = "2C2";
                    } else if ("30".equals(rollLineNo)) {
                        platePreProc1 = "5C2";
                    }
                    if (StringUtils.isNotEmpty(platePreProc1)) {
                        process = process + platePreProc1 + "-";
                        platePreProc1 = "";
                    }
                }

                if (StringUtils.isEmpty(axisPmContMscTech.getWholeHeatTreatmentType())) {
                    throw new CommonException("pm.pm_cont_msc_tech_001", axisPmContMscTech.getOrderNo(), axisPmContMscTech.getMscLineNo());
                }
                for (int i = 0; i < axisPmContMscTech.getWholeHeatTreatmentType().length(); i++) {
                    heatTreatMode = String.valueOf(axisPmContMscTech.getWholeHeatTreatmentType().charAt(i));
                    // （热处理工序）如果tqmto45.whole_backlog_code=PA
                    if ("PA".equals(dto.getSplitWholeBacklog())) {
                        // 如果tqmto45.hot_treat_method_code=A
                        if ("A".equals(heatTreatMode)) {
                            switch (rollLineNo) {
                                case "10":
                                    platePreProc1 = "1A0";
                                    break;
                                case "20":
                                    platePreProc1 = "2A0";
                                    break;
                                case "30":
                                    platePreProc1 = "5A0";
                                    break;
                                default:
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=N
                        if ("N".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N0";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=Q
                        if ("Q".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q0";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=T
                        if ("T".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1T0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2T0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5T0";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=B（正火+回火）
                        if ("B".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N0";
                            }
                            // 再追加一道工序
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T0";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=D（淬火+回火）
                        if ("D".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q0";
                            }
                            // 再追加一道工序：
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T0";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T0";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T0";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                            if (StringUtils.isNotEmpty(platePreProc2)) {
                                process = process + platePreProc2 + "-";
                                platePreProc2 = "";
                            }
                        }
                    }
                    // 热处理工序）如果tqmto45.whole_backlog_code=PB
                    if ("PB".equals(dto.getSplitWholeBacklog())) {
                        // 如果tqmto45.hot_treat_method_code=A
                        if ("A".equals(heatTreatMode)) {
                            switch (rollLineNo) {
                                case "10":
                                    platePreProc1 = "1A1";
                                    break;
                                case "20":
                                    platePreProc1 = "2A1";
                                    break;
                                case "30":
                                    platePreProc1 = "5A1";
                                    break;
                                default:
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=N
                        if ("N".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N1";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=Q
                        if ("Q".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q1";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=T
                        if ("T".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1T1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2T1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5T1";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=B
                        if ("B".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N1";
                            }
                            // 再追加一道工序：
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T1";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                            if (StringUtils.isNotEmpty(platePreProc2)) {
                                process = process + platePreProc2 + "-";
                                platePreProc2 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=D
                        if ("D".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q1";
                            }
                            // 再追加一道工序：
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T1";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T1";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T1";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                            if (StringUtils.isNotEmpty(platePreProc2)) {
                                process = process + platePreProc2 + "-";
                                platePreProc2 = "";
                            }
                        }
                    }
                    // （热处理工序）如果tqmto45.whole_backlog_code=PC
                    if ("PC".equals(dto.getSplitWholeBacklog())) {
                        // 如果tqmto45.hot_treat_method_code=A
                        if ("A".equals(heatTreatMode)) {
                            switch (rollLineNo) {
                                case "10":
                                    platePreProc1 = "1A2";
                                    break;
                                case "20":
                                    platePreProc1 = "2A2";
                                    break;
                                case "30":
                                    platePreProc1 = "5A2";
                                    break;
                                default:
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=N
                        if ("N".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N2";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=Q
                        if ("Q".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q2";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=T
                        if ("T".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1T2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2T2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5T2";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=B
                        if ("B".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1N2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2N2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5N2";
                            }
                            // 再追加一道工序：
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T2";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc2 + "-";
                                platePreProc2 = "";
                            }
                        }
                        // 如果tqmto45.hot_treat_method_code=D
                        if ("D".equals(heatTreatMode)) {
                            if ("10".equals(rollLineNo)) {
                                platePreProc1 = "1Q2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc1 = "2Q2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc1 = "5Q2";
                            }
                            // 再追加一道工序：
                            if ("10".equals(rollLineNo)) {
                                platePreProc2 = "1T2";
                            } else if ("20".equals(rollLineNo)) {
                                platePreProc2 = "2T2";
                            } else if ("30".equals(rollLineNo)) {
                                platePreProc2 = "5T2";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc1 + "-";
                                platePreProc1 = "";
                            }
                            if (StringUtils.isNotEmpty(platePreProc1)) {
                                process = process + platePreProc2 + "-";
                                platePreProc2 = "";
                            }
                        }
                    }
                }

                // 补充工序-火切
//                if ("3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) || "2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1))) {
//                    if ("10".equals(rollLineNo)) {
//                        platePreProc1 = "1G2";
//                    } else if ("20".equals(rollLineNo)) {
//                        platePreProc1 = "2G2";
//                    } else if ("30".equals(rollLineNo)) {
//                        platePreProc1 = "5G2";
//                    }
//                    if (StringUtils.isNotEmpty(platePreProc1)) {
//                        process = process + platePreProc1 + "-";
//                        platePreProc1 = "";
//                    }
//                }

                // 添加分张工序：如果mat_design_kind=S且板坯号第一位为F（复合/叠轧板坯组板）
                platePreProc1 = addSplittingProcess(dto.getSlabNo(), rollLineNo, axisPmContMscTech.getTenantId());
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            }

            // 若是最后一道热处理大工序（1909-2188）如果“大板去向roll_plate_dest为3”或者“形状代码不为空
            if (("3".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1)) || "2".equals(axisPmContMscTech.getPlateDtCode().substring(0, 1))) || Objects.nonNull(pmCmdLargePlt.getShpCode())) {
                switch (rollLineNo) {
                case "10":
                    platePreProc1 = "1G2";
                    break;
                case "20":
                    platePreProc1 = "2G2";
                    break;
                case "30":
                    platePreProc1 = "5G2";
                    break;
                default:
                }
                if (StringUtils.isNotEmpty(platePreProc1)) {
                    process = process + platePreProc1 + "-";
                    platePreProc1 = "";
                }
            }
//            else if (!"p".equals(matDesignKind) && ("2".equals(ultPdCode) || "3".equals(ultPdCode))) {
//                // 如果不是余材钢板组板（mat_design_kind不为P）且ult_pd_code（根据轴合同号与产线号，读取合同处理精准工艺标准QD_TO_LINEUP_RESULT_SIZING）为2或3
//                switch (rollLineNo) {
//                case "10":
//                    platePreProc1 = "1U4";
//                    break;
//                case "20":
//                    platePreProc1 = "2U4";
//                    break;
//                case "30":
//                    platePreProc1 = "5U4";
//                    break;
//                default:
//                }
//                if (StringUtils.isNotEmpty(platePreProc1)) {
//                    process = process + platePreProc1 + "-";
//                    platePreProc1 = "";
//                }
//            } else if ("P".equals(matDesignKind)) {
//                // 钢板号=临时命令板坯号tmp_slab_no”，读取探伤实绩表（MM_UST_RSLT）中的UST_VALUE_LAST。检查：是否存在UST_VALUE_LAST取值为“1-FAIL”
//                boolean c = false;
//                boolean d = false;
//                String ustValueLast = pmPdSlabInfoMapper.selectMmUstRslt(pmCmdLargePlt.getTmpSlabNo());
//                if (StringUtils.isNotEmpty(ustValueLast) && "1-FAIL".equals(ustValueLast)) {
//                    // 根据原合同号（根据钢板号关联MM_PLATE，用MM_PLATE中的板坯号去MM_SLAB读取）读取合同处理精准工艺标准（QD_TO_LINEUP_RESULT_SIZING）中的ULT_CODE，记为ult_code0
//                    String orgOrderNo = pmPdSlabInfoMapper.selectOrgOrderNo(mmPlateVO.getSlabNo());
//                    // 读取合同处理精准工艺标准（QD_TO_LINEUP_RESULT_SIZING）中的ULT_CODE，记为ult_code0
//                    String ultCode0 = pmPdSlabInfoMapper.selectUltCode0(orgOrderNo);
//                    // 根据轴合同号与产线号，读取合同处理精准工艺标准（QD_TO_LINEUP_RESULT_SIZING）中的ULT_CODE，记为ult_code1;
//                    String ultCode1 = pmPdSlabInfoMapper.selectUltCode1(pmCmdCont.getOrderNo(), dto.getMscLineNo());
//                    // 当ult_code0第一位为“A”时，或ult_code0与ult_code1第一位不同时
//                    if ("A".equals(ultCode0.substring(0, 1))
//                            || !ultCode0.substring(0, 1).equals(ultCode1.substring(0, 1))) {
//                        d = true;
//                    }
//                    c = true;
//                }
//                // 当“ult_pd_code取值为2或3”且“满足条件a或条件b时”
//                if ("2".equals(ultPdCode) || "3".equals(ultPdCode)) {
//                    if (!c || d) {
//                        switch (rollLineNo) {
//                        case "10":
//                            platePreProc1 = "1U4";
//                            break;
//                        case "20":
//                            platePreProc1 = "2U4";
//                            break;
//                        case "30":
//                            platePreProc1 = "5U4";
//                            break;
//                        default:
//                        }
//                        if (StringUtils.isNotEmpty(platePreProc1)) {
//                            process = process + platePreProc1 + "-";
//                            platePreProc1 = "";
//                        }
//                    }
//                }
//            }

            // 探伤工序
            if ("1".equals(isUt)) {
                String crackProc = this.generateCrackProcess(axisPmContMscTech.getPlateDtCode(), rollLineNo, utCheckCode);
                if (StringUtils.isNotEmpty(crackProc)) {
                    process = process + crackProc + "-";
                }
            }
        }
        return process;
    }

    /**
     *
     * @param plateDtCode 厚板流向代码
     * @param rollLineNo 轧制产线号
     * @param utCheckCode 探伤扫查模式代码
     * @return
     */
    private String generateCrackProcess(String plateDtCode, String rollLineNo, String utCheckCode) {
        StringBuilder crackProcessBuilder = new StringBuilder();
        if ("10".equals(rollLineNo)) {
            crackProcessBuilder.append("1");
        } else if ("20".equals(rollLineNo)) {
            crackProcessBuilder.append("2");
        } else if ("30".equals(rollLineNo)) {
            crackProcessBuilder.append("5");
        } else {
            throw new CommonException("pm.cmd_cont_001");
        }
        if ("1".equals(plateDtCode.substring(0, 1))) {
            if ("1".equals(utCheckCode)) {
                crackProcessBuilder.append("U4");
            } else {
                crackProcessBuilder.append("U1");
            }
        } else {
            crackProcessBuilder.append("U4");
        }
        return crackProcessBuilder.toString();
    }

    protected void updatePmCmdSlabProcInfo(T info , PmCmdLargePlt pmCmdLargePltDb, PmCmdSlab updatePmCmdSlab,
            PmContMscTech axisPmContMscTech, PmProContProdTtr axisPmProContProdTtr) {
    }
    
    @Override
    public String pdStatusHpChangeResult(String currentStatus, OpType opType , String tmpSlabNo) {
        if(!SecondaryDesignHelper.isOrginStatusChange()) {
            // 如果启用原始状态不做状态校验，不修改状态
            return currentStatus;
        }
        if (OpType.SAMPLE_ADD == opType) {
            if (!Constants.PdStatusHp.PD_STATUS_HP_18.equals(currentStatus)) {
                // 当前状态为【{0}】,仅当状态为【{1}】允许执行此操作
                throw new CommonException("pm.pm_pd_secondary_design_001", currentStatus,
                        Constants.PdStatusHp.PD_STATUS_HP_18 , tmpSlabNo);
            }
            return Constants.PdStatusHp.PD_STATUS_HP_20;
        } else if (OpType.SAMPLE_ROLLBACK == opType) {
            if (!Constants.PdStatusHp.PD_STATUS_HP_20.equals(currentStatus)) {
                // 当前状态为【{0}】,仅当状态为【{1}】允许执行此操作
                throw new CommonException("pm.pm_pd_secondary_design_001", currentStatus,
                        Constants.PdStatusHp.PD_STATUS_HP_20 , tmpSlabNo);
            }
            return Constants.PdStatusHp.PD_STATUS_HP_18;
        } else if (OpType.DESIGN == opType) {
            if (!Constants.PdStatusHp.PD_STATUS_HP_20.equals(currentStatus)) {
                throw new CommonException("pm.pm_pd_secondary_design_001", currentStatus,
                        Constants.PdStatusHp.PD_STATUS_HP_20 , tmpSlabNo);
            }
            return Constants.PdStatusHp.PD_STATUS_HP_23;
        } else if (OpType.DESIGN_ROLLBACK == opType) {
            if (!Constants.PdStatusHp.PD_STATUS_HP_23.equals(currentStatus)) {
                throw new CommonException("pm.pm_pd_secondary_design_001", currentStatus,
                        Constants.PdStatusHp.PD_STATUS_HP_23 , tmpSlabNo);
            }
            return Constants.PdStatusHp.PD_STATUS_HP_20;
        } else {
            if (!Constants.PdStatusHp.PD_STATUS_HP_23.equals(currentStatus)) {
                throw new CommonException("pm.pm_pd_secondary_design_001", currentStatus,
                        Constants.PdStatusHp.PD_STATUS_HP_23 , tmpSlabNo);
            }
            return Constants.PdStatusHp.PD_STATUS_HP_24;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void  abandonContractEvent(List<String> virtualSlabNoList, Long tenantId, String pdMatStatus, String prodcCd,
                                      String wholeBacklogCode, String eventCode){
    }

    /**
     * 添加分张工序
     * @param slabNo
     * @return
     */
    public String addSplittingProcess(String slabNo  , String rollLineNo, Long tenantId) {
        return null;
    }
}
