package com.xisc.pm.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.xisc.boot.common.feign.pojo.MtUserInfo;
import com.xisc.boot.common.sys.UserClient;
import com.xisc.pm.api.dto.PmOrderOverDTO;
import com.xisc.pm.api.dto.PmPdCcSlabStoveParamDTO;
import com.xisc.pm.api.dto.PmPdCcSlabStoveResDTO;
import com.xisc.pm.api.dto.PmSlabPoolInDTO;
import com.xisc.pm.api.dto.PmSlabPoolInFurnaceDTO;
import com.xisc.pm.api.dto.PmSlabPoolInNoReqDTO;
import com.xisc.pm.api.dto.PmSlabPoolInOrderDTO;
import com.xisc.pm.api.dto.PmSlabPoolInPreDTO;
import com.xisc.pm.api.dto.PmSlabPoolInPreLineDTO;
import com.xisc.pm.api.dto.PmSlabPoolInReqParamDTO;
import com.xisc.pm.api.dto.PmSlabPoolInResDTO;
import com.xisc.pm.api.dto.PreOptimalChargingDTO;
import com.xisc.pm.api.dto.ctevent.PmMaterialCommandDTO;
import com.xisc.pm.api.dto.ctevent.PmSlabApplyMakeDTO;
import com.xisc.pm.app.service.PmSlabEstaPlanService;
import com.xisc.pm.app.service.PmSlabPoolInService;
import com.xisc.pm.app.service.comparator.PmSlabPoolInDTOComparator;
import com.xisc.pm.app.service.strategy.SecondaryDesignStrategyFactory;
import com.xisc.pm.domain.entity.PmCmdCont;
import com.xisc.pm.domain.entity.PmCmdLargePlt;
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.PmPdCcSlab;
import com.xisc.pm.domain.entity.PmPdContSum;
import com.xisc.pm.domain.entity.PmPnsort;
import com.xisc.pm.domain.entity.PmPonoWtInfo;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSlabEstaPlan;
import com.xisc.pm.domain.entity.PmSlabMerge;
import com.xisc.pm.domain.entity.PmSlabPoolIn;
import com.xisc.pm.domain.entity.PmSlabPoolInHis;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.entity.PmWmWwBt;
import com.xisc.pm.domain.repository.PmCmdContRepository;
import com.xisc.pm.domain.repository.PmCmdLargePltRepository;
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.PmPdCcSlabRepository;
import com.xisc.pm.domain.repository.PmPdContSumRepository;
import com.xisc.pm.domain.repository.PmPnsortRepository;
import com.xisc.pm.domain.repository.PmPonoWtInfoRepository;
import com.xisc.pm.domain.repository.PmProContProdTtrRepository;
import com.xisc.pm.domain.repository.PmSlabEstaPlanRepository;
import com.xisc.pm.domain.repository.PmSlabMergeRepository;
import com.xisc.pm.domain.repository.PmSlabPoolInHisRepository;
import com.xisc.pm.domain.repository.PmSlabPoolInRepository;
import com.xisc.pm.domain.repository.PmSmallPltPosRepository;
import com.xisc.pm.domain.repository.PmWmWwBtRepository;
import com.xisc.pm.domain.vo.CtMainVO;
import com.xisc.pm.domain.vo.OrderNoRangeVO;
import com.xisc.pm.domain.vo.QdToLineupResultSizingVO;
import com.xisc.pm.domain.vo.QdToPoOrderVO;
import com.xisc.pm.domain.vo.QeTjBetterToWorseVO;
import com.xisc.pm.infra.client.EventClient;
import com.xisc.pm.infra.client.QdOrderClient;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.constant.CtEventConstants;
import com.xisc.pm.infra.constant.PmPlateConstants;
import com.xisc.pm.infra.enums.PdMatType;
import com.xisc.pm.infra.mapper.PmSlabPoolInMapper;
import com.xisc.pm.infra.util.BeanUtils;
import com.xisc.pm.infra.util.DateUtils;
import com.xisc.pm.infra.util.Utils;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.hzero.boot.platform.code.builder.CodeRuleBuilder;
import org.hzero.boot.platform.code.constant.CodeConstants;
import org.hzero.core.base.AopProxy;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 组炉收池表(PmSlabPoolIn)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-08-07 17:11:27
 */
@Service
@Slf4j
public class PmSlabPoolInServiceImpl implements AopProxy<PmSlabPoolInService>, PmSlabPoolInService {

    @Autowired
    private PmSlabPoolInRepository pmSlabPoolInRepository;

    @Autowired
    private PmPdCcSlabRepository pmPdCcSlabRepository;

    @Autowired
    private PmContMscTechRepository pmContMscTechRepository;

    @Autowired
    private PmProContProdTtrRepository pmProContProdTtrRepository;

    @Autowired
    private PmSlabPoolInMapper pmSlabPoolInMapper;

    @Autowired
    private PmPdContSumRepository pmPdContSumRepository;

    @Autowired
    private PmSlabEstaPlanRepository pmSlabEstaPlanRepository;

    @Autowired
    private PmPonoWtInfoRepository pmPonoWtInfoRepository;

    @Autowired
    private CodeRuleBuilder codeRuleBuilder;

    @Autowired
    private PmSmallPltPosRepository pmSmallPltPosRepository;

    @Autowired
    private PmCmdSlabRepository pmCmdSlabRepository;

    @Autowired
    private PmCmdLargePltRepository pmCmdLargePltRepository;

    @Autowired
    private PmCmdContRepository pmCmdContRepository;

    @Autowired
    private PmCmdSmallPltRepository pmCmdSmallPltRepository;

    @Autowired
    private PmSlabPoolInHisRepository pmSlabPoolInHisRepository;

    @Autowired
    private PmSlabMergeRepository pmSlabMergeRepository;

    @Autowired
    private PmWmWwBtRepository pmWmWwBtRepository;

    @Autowired
    private PmPnsortRepository pmPnsortRepository;

    @Autowired
    private EventClient eventClient;
    
    @Autowired
    private QdOrderClient qdOrderClient;

    @Autowired
    private PmSlabEstaPlanService pmSlabEstaPlanService;

    @Autowired
    private UserClient userClient;

    private static final int EIGHT = 8;

    @Override
    public List<PmPdCcSlabStoveResDTO> listStoveForui(PmPdCcSlabStoveParamDTO dto, Long tenantId) {
        // 校验内部钢种号
        if (StringUtils.isEmpty(dto.getOutSgNo())) {
            throw new CommonException("pm.slab_pool_in_001");
        }
        // 构建查询条件
        List<String> outSgNoList = new ArrayList<>();
        outSgNoList.add(dto.getOutSgNo());
        Map<String, List<QeTjBetterToWorseVO>> pmHtolStaticMap = new HashMap<>(16);
        // 勾选了含可以优充次材料，根据内部钢种号和生效标记查询基表获取次内部钢种
        if (dto.getIsContain().equals(BaseConstants.FlagChar.YES)) {
            // 【内部钢种以优充次维护（QE_TJ_BETTER_TO_WORSE）】 ，其中内部钢种与【QE_TJ_BETTER_TO_WORSE】中的优内部钢种（BETTER_ST_NO）关联
            List<QeTjBetterToWorseVO> qeTjBetterToWorseList =  pmSlabPoolInMapper.queryQeTjBetterToWorse(dto.getOutSgNo(), tenantId);

            // 匹配到则获取次内部钢种，参与查询
            if (CollectionUtils.isNotEmpty(qeTjBetterToWorseList)) {
                pmHtolStaticMap = qeTjBetterToWorseList.stream().collect(Collectors.groupingBy(QeTjBetterToWorseVO::getWorseStNo));
                outSgNoList.addAll(qeTjBetterToWorseList.stream().map(QeTjBetterToWorseVO::getWorseStNo).collect(Collectors.toList()));
            }
        }
        log.info("<=====获取到的钢种号为:{}=====>",outSgNoList);

        // 执行查询
        List<PmPdCcSlabStoveResDTO> resultList = pmPdCcSlabRepository.selectStoveList(dto, tenantId, outSgNoList);
        log.info("<=====材料收池获取到数据size=:{}=====>",resultList);
        // 为空，则返回
        if (CollectionUtils.isEmpty(resultList)) {
            return Collections.emptyList();
        }
        for (PmPdCcSlabStoveResDTO resDTO : resultList) {
            // 赋值次内部钢种的以优充次顺序码 便于排序
            if (!pmHtolStaticMap.isEmpty() && pmHtolStaticMap.containsKey(resDTO.getOutSgNo())) {
                Optional<QeTjBetterToWorseVO> max = pmHtolStaticMap.get(resDTO.getOutSgNo()).stream().min(Comparator.comparing(QeTjBetterToWorseVO::getBetterToWorseSeq));
                if (max.isPresent()) {
                    resDTO.setBetterToWorseSeq(max.get().getBetterToWorseSeq());
                }
            }
        }


        // 获取差欠总重量（SUM_LACK_WT）和差欠总件数（SUM_LACK_NUM）
        Set<OrderNoRangeVO> orderNoRangeSet = new HashSet<>(resultList.size());
        resultList.forEach(resDTO -> {
            // 截取轴合同号前8位字符，令起始合同号等于轴合同号前8位拼接“00”、终止合同号等于轴合同号前8位拼接“99，获取位于合同号区间的数据
            if (resDTO.getOrderNo().length() < EIGHT) {
                throw new CommonException("pm.slab_pool_in_002");
            }
            String orderNoFrom = resDTO.getOrderNo().substring(0, 8).concat("00");
            String orderNoTo = resDTO.getOrderNo().substring(0, 8).concat("99");
            OrderNoRangeVO orderNoRangeVO = new OrderNoRangeVO();
            orderNoRangeVO.setOrderNoFrom(orderNoFrom);
            orderNoRangeVO.setOrderNoTo(orderNoTo);
            orderNoRangeSet.add(orderNoRangeVO);
        });

        // e)	根据合同号关联查询【合同跟踪主表（CT_MAIN）】信息，以合同号关联，取合同号落于起始、终止合同号区间的合同欠重量（ORD_REM_WGT）、
        // 合同欠件数（ORD_REM_NUM）；
        List<CtMainVO> ctMainList = pmSlabPoolInMapper.selectRemByCtMain(tenantId, new ArrayList<>(orderNoRangeSet));
        if (CollectionUtils.isNotEmpty(ctMainList)) {
            Map<String, List<CtMainVO>> ctMainMap = ctMainList.stream().collect(Collectors.groupingBy(item -> item.getOrderNo().substring(0, 8)));
            for (PmPdCcSlabStoveResDTO resDTO : resultList) {
                if (ctMainMap.containsKey(resDTO.getOrderNo().substring(0, 8))) {
                    List<CtMainVO> mainList = ctMainMap.get(resDTO.getOrderNo().substring(0, 8));
                    BigDecimal numAdd = mainList.stream().map(CtMainVO::getOrdRemNum).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal wtAdd = mainList.stream().map(CtMainVO::getOrdRemWgt).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                    resDTO.setSumLackNum(numAdd);
                    resDTO.setSumLackWt(wtAdd);
                }
            }
        }

        // 排序
        //  若用户勾选了“含可以优充次材料”单选框，则先显示优钢种信息，再按以优充次顺序码（BETTER_TO_WORSE_SEQ）升序显示次钢种信息
        List<PmPdCcSlabStoveResDTO> betterResultList = resultList.stream().filter(resDTO -> dto.getOutSgNo().equals(resDTO.getOutSgNo()))
                .sorted(Comparator.comparing(PmPdCcSlabStoveResDTO::getOutSgNo)).collect(Collectors.toList());
        List<PmPdCcSlabStoveResDTO> worseResultList = resultList.stream().filter(resDTO -> !dto.getOutSgNo().equals(resDTO.getOutSgNo()))
                .sorted(Comparator.comparing(PmPdCcSlabStoveResDTO::getBetterToWorseSeq,
                        Comparator.nullsLast(Long::compareTo))).collect(Collectors.toList());
        List<PmPdCcSlabStoveResDTO> finalList = new ArrayList<>();
        finalList.addAll(betterResultList);
        finalList.addAll(worseResultList);
        return finalList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void collectPool(Long tenantId, List<String> virtualSlabNoList) {
        // a)	根据前端传入的虚拟板坯号查询【组板连铸板坯表（PM_PD_CC_SLAB）
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByCondition(Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmPdCcSlab.FIELD_VIRTUAL_SLAB_NO, virtualSlabNoList))
                .build());
        // 如果为空，则返回
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            return;
        }

        // c)	如果厚板组板状态不等于“12”（组板完成），则报错（右下角弹窗报错）：PM.FURNACE.CASTING.001,程序结束
        pmPdCcSlabList.forEach(pmPdCcSlab -> {
            if (!Constants.PdStatusHp.PD_STATUS_HP_12.equals(pmPdCcSlab.getPdStatusHp())) {
                throw new CommonException("pm.furnace.casting.001");
            }
        });
        // 获取合同号和产线集合
        List<String> orderNoAxisList = pmPdCcSlabList.stream().map(PmPdCcSlab::getOrderNoAxis).collect(Collectors.toList());
        List<String> mscLineNoList = pmPdCcSlabList.stream().map(PmPdCcSlab::getMscLineNo).collect(Collectors.toList());
        Map<String, String> pmPdCcSlabMap = pmPdCcSlabList.stream().collect(Collectors.toMap(PmPdCcSlab::getVirtualSlabNo, PmPdCcSlab::getCcType));
        // b)	根据轴合同号查询【合同产线工艺参数表（PM_CONT_MSC_TECH）】
        List<PmContMscTech> pmContMscTechList = pmContMscTechRepository.selectByCondition(Condition.builder(PmContMscTech.class)
                .andWhere(Sqls.custom().andEqualTo(PmContMscTech.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmContMscTech.FIELD_ORDER_NO, orderNoAxisList))
                .andWhere(Sqls.custom().andIn(PmContMscTech.FIELD_MSC_LINE_NO, mscLineNoList))
                .build());
        Map<String, PmContMscTech> pmContMscTechMap = new HashMap<>(pmContMscTechList.size());
        if (CollectionUtils.isNotEmpty(pmContMscTechList)) {
            pmContMscTechMap = pmContMscTechList.stream().collect(Collectors.toMap(pmContMscTech -> Strings.concat(pmContMscTech.getOrderNo(), pmContMscTech.getMscLineNo()), Function.identity(), (v1, v2) -> v1));
        }
        //  c)	根据轴合同号查询【生产合同产品属性表（PM_PRO_CONT_PROD_ATTR）
        List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository.selectByCondition(Condition.builder(PmProContProdTtr.class)
                .andWhere(Sqls.custom().andEqualTo(PmProContProdTtr.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmProContProdTtr.FIELD_ORDER_NO, orderNoAxisList))
                .build());
        Map<String, PmProContProdTtr> pmProContProdTtrMap = new HashMap<>(pmProContProdTtrList.size());
        if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
            pmProContProdTtrMap = pmProContProdTtrList.stream().collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (v1, v2) -> v1));
        }


        // 查询查来的结果值、组炉责任者ID（USER_ID）以及编制状态（ESTA_STATUS）插入到【组炉收池表（PM_SLAB_POOL_IN）】
        List<PmSlabPoolIn> pmSlabPoolInList = new ArrayList<>(pmPdCcSlabList.size());
        for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
            PmSlabPoolIn pmSlabPoolIn = new PmSlabPoolIn();
            pmSlabPoolIn.setVirtualSlabNo(pmPdCcSlab.getVirtualSlabNo());
            pmSlabPoolIn.setMainBacklogCode("00".equals(pmPdCcSlab.getMscLineNo().substring(0, 2)) ?
                    Constants.MainBacklogCode.CODE_A : Constants.MainBacklogCode.CODE_C);
            pmSlabPoolIn.setMscLineNo(pmPdCcSlab.getMscLineNo());
            pmSlabPoolIn.setUserId(DetailsHelper.getUserDetails().getUserId().toString());
            pmSlabPoolIn.setNomSlabThick(pmPdCcSlab.getPreCleanSlabThick());
            pmSlabPoolIn.setNomSlabWidth(pmPdCcSlab.getPreCleanSlabWidth());
            pmSlabPoolIn.setNomSlabLen(pmPdCcSlab.getPreCleanSlabLen());
            pmSlabPoolIn.setSlabMaxNomLen(pmPdCcSlab.getPreCleanSlabMaxLen());
            pmSlabPoolIn.setSlabMinNomLen(pmPdCcSlab.getPreCleanSlabMinLen());
            pmSlabPoolIn.setCcType(pmPdCcSlab.getCcType());
            pmSlabPoolIn.setNomSlabWt(pmPdCcSlab.getPreCleanSlabWt());
            pmSlabPoolIn.setSlabMaxNomWt(pmPdCcSlab.getPreCleanSlabMaxWt());
            pmSlabPoolIn.setSlabMinNomWt(pmPdCcSlab.getPreCleanSlabMinWt());
            pmSlabPoolIn.setSlabPlaceCode(pmPdCcSlab.getSlabPlaceCode());
            pmSlabPoolIn.setNomRollWidth(pmPdCcSlab.getRollAimWidth());
            pmSlabPoolIn.setNomRollThick(pmPdCcSlab.getRollAimThick());
            pmSlabPoolIn.setUrgOrderFlag(pmPdCcSlab.getUrgOrderFlag());
            pmSlabPoolIn.setIgMatDesignKind(pmPdCcSlab.getIgMatDesignKind());
            pmSlabPoolIn.setIngotType(pmPdCcSlab.getIngotType());
            pmSlabPoolIn.setOrderNo(pmPdCcSlab.getOrderNoAxis());
            pmSlabPoolIn.setStNo(pmPdCcSlab.getStNo());
            pmSlabPoolIn.setSteelPlanDate(pmPdCcSlab.getSteelPlanDate());
            pmSlabPoolIn.setEstaStatus(Constants.EstaStatus.STATUS_0);
            pmSlabPoolIn.setNomHotSendFlag(pmPdCcSlab.getHotSendFlag());
            pmSlabPoolIn.setOrderHotChargeFlag(pmPdCcSlab.getHotChargeFlag() == null ? null : pmPdCcSlab.getHotChargeFlag().toString());
            pmSlabPoolIn.setTenantId(tenantId);
            // 获取合同产线表数据赋值
            if (!pmContMscTechMap.isEmpty() && pmContMscTechMap.containsKey(Strings.concat(pmPdCcSlab.getOrderNoAxis(), pmPdCcSlab.getMscLineNo()))) {
                PmContMscTech pmContMscTech = pmContMscTechMap.get(Strings.concat(pmPdCcSlab.getOrderNoAxis(), pmPdCcSlab.getMscLineNo()));
                pmSlabPoolIn.setWholeBacklogCode(pmContMscTech.getWholeBacklogCode());
                pmSlabPoolIn.setSlabDest(pmContMscTech.getSlabDest());
                pmSlabPoolIn.setWholeBacklog(Constants.WholeBacklog.CODE_14);
                pmSlabPoolIn.setRfPath(pmContMscTech.getRfPath());
            }
            // 获取合同属性表数据赋值
            if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(pmPdCcSlab.getOrderNoAxis())) {
                PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(pmPdCcSlab.getOrderNoAxis());
                pmSlabPoolIn.setOrderTypeCode(pmProContProdTtr.getOrderTypeCode());
                pmSlabPoolIn.setSgSign(pmProContProdTtr.getSgSign());
                pmSlabPoolIn.setSgCode(pmProContProdTtr.getSgCode());
                pmSlabPoolIn.setDelivyDate(pmProContProdTtr.getDelivyDate());
                pmSlabPoolIn.setConsignCustCname(pmProContProdTtr.getConsignCustCname());
                pmSlabPoolIn.setDelivyPlaceName(pmProContProdTtr.getDelivyPlaceName());
            }
            pmSlabPoolInList.add(pmSlabPoolIn);
        }
        // 插入组炉收池表
        pmSlabPoolInRepository.batchInsertSelective(pmSlabPoolInList);

        // 虚拟板坯号更新【组板连铸板坯表（PM_PD_CC_SLAB）】中的厚板组板状态（PD_STATUS_HP）为15
        pmPdCcSlabList.forEach(pmPdCcSlab -> pmPdCcSlab.setPdStatusHp(Constants.PdStatusHp.PD_STATUS_HP_15));
        pmPdCcSlabRepository.batchUpdateByPrimaryKey(pmPdCcSlabList);

        // f)	将以下字段作为入参，调用合同跟踪模块“组炉组浇收池事件”接口，向合同跟踪抛帐：
        List<PmSmallPltPos> pmSmallPltPosList = pmSmallPltPosRepository.selectByCondition(Condition.builder(PmSmallPltPos.class)
                .andWhere(Sqls.custom().andIn(PmSmallPltPos.FIELD_PD_MAT_NO, virtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmSmallPltPos.FIELD_TENANT_ID, tenantId))
                .build());
        Map<String, List<PmSmallPltPos>> pmSmallPltPosMap = new HashMap<>(pmSmallPltPosList.size());
        if (CollectionUtils.isNotEmpty(pmSmallPltPosList)) {
            pmSmallPltPosMap = pmSmallPltPosList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getPdMatNo));
        }
        List<PmSlabApplyMakeDTO> resList = new ArrayList<>();
        for (String virtualSlabNo : virtualSlabNoList) {
            // 虚拟板坯号信息
            PmSlabApplyMakeDTO applyMakeDTO = new PmSlabApplyMakeDTO();
            applyMakeDTO.setMatNo(virtualSlabNo);
            if (pmPdCcSlabMap.containsKey(virtualSlabNo)) {
                // 钢锭连铸
                applyMakeDTO.setPpFlag(0);
/*                if (Constants.CcType.TYPE_5.equals(pmPdCcSlabMap.get(virtualSlabNo))) {
                    applyMakeDTO.setPpFlag(8);
                } else {
                    applyMakeDTO.setPpFlag(0);
                }*/
            } else {
                throw new CommonException("pm.pd_cc_slab_006",virtualSlabNo);
            }
            applyMakeDTO.setOrdFlag("1");
            applyMakeDTO.setPdMatStatus("15");
            applyMakeDTO.setProcCd("14A");
            applyMakeDTO.setWholeBacklogCode("14");
            resList.add(applyMakeDTO);
            // 大板信息
            PmSlabApplyMakeDTO applyMakeDTO1 = new PmSlabApplyMakeDTO();
            applyMakeDTO1.setMatNo(virtualSlabNo);
            applyMakeDTO1.setPpFlag(1);
            applyMakeDTO.setOrdFlag("1");
            applyMakeDTO1.setPdMatStatus("15");
            applyMakeDTO1.setProcCd("14A");
            applyMakeDTO1.setWholeBacklogCode("14");
            resList.add(applyMakeDTO1);
            // 子板信息
            if (!pmSmallPltPosMap.containsKey(virtualSlabNo)) {
                throw new CommonException("pm.small_plt_pos", virtualSlabNo);
            }
            List<PmSmallPltPos> pmSmallPltPos = pmSmallPltPosMap.get(virtualSlabNo);
            for (PmSmallPltPos pmSmallPltPo : pmSmallPltPos) {
                PmSlabApplyMakeDTO makeDTO = new PmSlabApplyMakeDTO();
                makeDTO.setMoMatNo(pmSmallPltPo.getPdMatNo());
                makeDTO.setMatNo(pmSmallPltPo.getPdMatNo() + pmSmallPltPo.getSmallPlateDivNo());
                makeDTO.setPpFlag(2);
                makeDTO.setOrdFlag("1");
                makeDTO.setPdMatStatus("15");
                makeDTO.setProcCd("14A");
                makeDTO.setWholeBacklogCode("14");
                resList.add(makeDTO);
            }
        }
        log.info("<=====调用组炉组浇收池事件，入参为{}=====>", JSON.toJSONString(resList));
        eventClient.sendEventWithOutResponse(tenantId, CtEventConstants.EVENT_PM_SLAB_APPLY_MAKE, resList);
    }

    @Override
    public List<PmSlabPoolInResDTO> listFurnaceForui(PmSlabPoolInReqParamDTO dto, Long tenantId) {
        // 校验内部钢种号是否为空
        if (StringUtils.isEmpty(dto.getNomStNo())) {
            throw new CommonException("pm.slab_pool_in_001");
        }
        List<String> stNoList = new ArrayList<>();
        stNoList.add(dto.getNomStNo());
        Map<String, List<QeTjBetterToWorseVO>> pmHtolStaticMap = new HashMap<>(16);
        // 勾选了含可以优充次材料，根据内部钢种号和生效标记查询获取次内部钢种
        if (dto.getIsContain().equals(BaseConstants.FlagChar.YES)) {
            // 查询【内部钢种以优充次维护（QE_TJ_BETTER_TO_WORSE）】 ，其中内部钢种与【QE_TJ_BETTER_TO_WORSE】中的优内部钢种（BETTER_ST_NO）关联
            List<QeTjBetterToWorseVO> qeTjBetterToWorseList =  pmSlabPoolInMapper.queryQeTjBetterToWorse(dto.getNomStNo(), tenantId);

            // 匹配到则获取次内部钢种，参与查询
            if (CollectionUtils.isNotEmpty(qeTjBetterToWorseList)) {
                pmHtolStaticMap = qeTjBetterToWorseList.stream().collect(Collectors.groupingBy(QeTjBetterToWorseVO::getWorseStNo));
                stNoList.addAll(qeTjBetterToWorseList.stream().map(QeTjBetterToWorseVO::getWorseStNo).collect(Collectors.toList()));
            }
        }
        // 组炉收池表查询
        List<PmSlabPoolIn> pmSlabPoolInList = pmSlabPoolInRepository.selectByCondition(Condition.builder(PmSlabPoolIn.class)
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_ESTA_STATUS, Constants.EstaStatus.STATUS_0))
                .andWhere(Sqls.custom().andIn(PmSlabPoolIn.FIELD_ST_NO, stNoList))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_MAIN_BACKLOG_CODE, dto.getMainBacklogCode(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_NOM_SLAB_THICK, dto.getNomSlabThick(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_NOM_SLAB_WIDTH, dto.getNomSlabWidth(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_NOM_HOT_SEND_FLAG, dto.getNomHotSendFlag(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_ORDER_HOT_CHARGE_FLAG, dto.getOrderHotChargeFlag(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_USER_ID, dto.getUserId(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmSlabPoolIn.FIELD_STEEL_PLAN_DATE, dto.getSteelPlanDateFrom(),true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmSlabPoolIn.FIELD_STEEL_PLAN_DATE, dto.getSteelPlanDateTo(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_INGOT_TYPE, dto.getIngotType(), true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_SLAB_DEST, dto.getSlabDest(),true))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_CC_TYPE, dto.getCcType(),true))
                .build());
        // 为空，则返回
        if (CollectionUtils.isEmpty(pmSlabPoolInList)) {
            return Collections.emptyList();
        }
        // 获取轴合同号
        List<String> orderNoList = pmSlabPoolInList.stream().map(PmSlabPoolIn::getOrderNo).distinct().collect(Collectors.toList());

        // 铸坯类型选择“板坯连铸”
        List<PmSlabPoolInResDTO> resultList = new ArrayList<>();
        if (Constants.CcType.TYPE_1.equals(dto.getCcType()) || Constants.CcType.TYPE_5.equals(dto.getCcType())) {
            // b)	根据虚拟板坯号（VIRTUAL_SLAB_NO）查询【组板连铸板坯表（PM_PD_CC_SLAB）】信息
            List<String> virtualSlabNoList = pmSlabPoolInList.stream().map(PmSlabPoolIn::getVirtualSlabNo).distinct()
                    .collect(Collectors.toList());
            List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByVirtualSlabList(virtualSlabNoList, tenantId);
            Map<String, PmPdCcSlab> pmPdCcSlabMap = new HashMap<>(pmPdCcSlabList.size());
            if (CollectionUtils.isNotEmpty(pmPdCcSlabList)) {
                pmPdCcSlabMap = pmPdCcSlabList.stream().collect(Collectors.toMap(PmPdCcSlab::getVirtualSlabNo, Function.identity(), (k, v) -> k));
            }

            // 查询并搜索合同属性表
            List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository.selectByCondition(Condition.builder(PmProContProdTtr.class)
                    .andWhere(Sqls.custom().andIn(PmProContProdTtr.FIELD_ORDER_NO, orderNoList))
                    .andWhere(Sqls.custom().andEqualTo(PmProContProdTtr.FIELD_TENANT_ID, tenantId))
                    .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmProContProdTtr.FIELD_HULL_SECTION_NO, dto.getHullSectionNoFrom(), true))
                    .andWhere(Sqls.custom().andLessThanOrEqualTo(PmProContProdTtr.FIELD_HULL_SECTION_NO, dto.getHullSectionNoTo(), true))
                    .build());
            // 为空，则返回
            if (CollectionUtils.isEmpty(pmProContProdTtrList)) {
                throw new CommonException("pm.pd_cc_slab_002",String.join(",", orderNoList), "生产合同产品属性表");
            }
            Map<String, PmProContProdTtr> pmProContProdTtrMap = pmProContProdTtrList.stream()
                    .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (k, v) -> k));

            Long twoRollInterimFlag = 1L;
            for (PmSlabPoolIn pmSlabPoolIn : pmSlabPoolInList) {
                PmSlabPoolInResDTO result = new PmSlabPoolInResDTO();
                // 赋值
                transToDto(pmSlabPoolIn, result);

                // 赋值次内部钢种的以优充次顺序码 便于后面区分优钢种，次钢种排序
                if (pmHtolStaticMap.containsKey(result.getNomStNo())) {
                    Optional<QeTjBetterToWorseVO> max = pmHtolStaticMap.get(result.getNomStNo()).stream()
                            .min(Comparator.comparing(QeTjBetterToWorseVO::getBetterToWorseSeq));
                    if (max.isPresent()) {
                        result.setBetterToWorseSeq(max.get().getBetterToWorseSeq());
                    }
                }

                // 从合同属性表获取数据赋值
                if (pmProContProdTtrMap.containsKey(pmSlabPoolIn.getOrderNo())) {
                    PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(pmSlabPoolIn.getOrderNo());
                    result.setHullSectionNo(pmProContProdTtr.getHullSectionNo());
                    result.setGiveSampleFlag(pmProContProdTtr.getGiveSampleCode());
                    result.setSectionManage(pmProContProdTtr.getSectionManage());
                    result.setConsignCustCname(pmProContProdTtr.getConsignCustCname());
                }

                // 从连铸板坯表获取数据赋值
                if (!pmPdCcSlabMap.isEmpty() && pmPdCcSlabMap.containsKey(pmSlabPoolIn.getVirtualSlabNo())) {
                    PmPdCcSlab pmPdCcSlab = pmPdCcSlabMap.get(pmSlabPoolIn.getVirtualSlabNo());
                    result.setOuMemo4("" + pmPdCcSlab.getTwoRollInterimFlag());
                    result.setFixSlabLenFlag("" + pmPdCcSlab.getFixSlabLenFlag());
                    result.setUltCode(pmPdCcSlab.getUltCode());
                    result.setOrderQThick(pmPdCcSlab.getAxisOrderThick());
                    result.setOrderQWidth(pmPdCcSlab.getAxisOrderWidth());
                    // 是否是二次开坯
                    result.setMidFlag((twoRollInterimFlag.equals(pmPdCcSlab.getTwoRollInterimFlag()) && !"A".equals(pmPdCcSlab.getIgMatDesignKind())) ?
                            1L : 0L);
                }
                result.setCcType(dto.getCcType());
                resultList.add(result);
            }

        } else if (Constants.CcType.TYPE_2.equals(dto.getCcType()) || Constants.CcType.TYPE_4.equals(dto.getCcType())) {
            // 轴合同号（ORDER_NO）、船体分段号（HULL_SECTION_NO）作为入参调用质量模块“组炉编制”接口（MES合同主档表QD_TO_PO_ORDER）
            List<QdToPoOrderVO> poOrderVOList = pmSlabPoolInMapper.selectListByQdToPoOrder(orderNoList, dto.getHullSectionNoFrom()
                    , dto.getHullSectionNoTo(), tenantId);
            Map<String, QdToPoOrderVO> poOrderMap = new HashMap<>(poOrderVOList.size());
            if (CollectionUtils.isNotEmpty(poOrderVOList)) {
                poOrderMap = poOrderVOList.stream().collect(Collectors.toMap(QdToPoOrderVO::getOrderNo, Function.identity(), (k, v) -> k));
            }

            // 轴合同号（ORDER_NO）作为入参，调用质量模块“组炉编制”接口（合同处理精整工艺标准QD_TO_LINEUP_RESULT_SIZING
            List<QdToLineupResultSizingVO> resultSizingList = pmSlabPoolInMapper.selectByQdToLineupResultSizing(orderNoList, tenantId);
            Map<String, String> resultSizingMap = new HashMap<>(resultSizingList.size());
            if (CollectionUtils.isNotEmpty(resultSizingList)) {
                resultSizingMap = resultSizingList.stream().collect(Collectors
                        .toMap(QdToLineupResultSizingVO::getOrderNo, QdToLineupResultSizingVO::getUltCode, (k, v) -> k));
            }
            for (PmSlabPoolIn pmSlabPoolIn : pmSlabPoolInList) {
                PmSlabPoolInResDTO result = new PmSlabPoolInResDTO();
                // 赋值
                transToDto(pmSlabPoolIn, result);

                // 赋值次内部钢种的以优充次顺序码 便于排序
                if (pmHtolStaticMap.containsKey(result.getNomStNo())) {
                    Optional<QeTjBetterToWorseVO> max = pmHtolStaticMap.get(result.getNomStNo()).stream()
                            .min(Comparator.comparing(QeTjBetterToWorseVO::getBetterToWorseSeq));
                    if (max.isPresent()) {
                        result.setBetterToWorseSeq(max.get().getBetterToWorseSeq());
                    }
                }

                // 从查询返回的数据赋值
                if (!poOrderMap.isEmpty() && poOrderMap.containsKey(pmSlabPoolIn.getOrderNo())) {
                    QdToPoOrderVO poOrderVO = poOrderMap.get(pmSlabPoolIn.getOrderNo());
                    result.setGiveSampleFlag(poOrderVO.getGiveSampleFlag());
                    result.setOrderQThick(poOrderVO.getOrderThick());
                    result.setOrderQWidth(poOrderVO.getOrderWidth());
                    result.setSectionManage(poOrderVO.getSectionManage());
                    result.setConsignCustCname(poOrderVO.getConsignCustCname());
                }

                if (!resultSizingMap.isEmpty() && resultSizingMap.containsKey(resultSizingMap.get(pmSlabPoolIn.getOrderNo()))) {
                    result.setUltCode(resultSizingMap.get(pmSlabPoolIn.getOrderNo()));
                }
                result.setCcType(dto.getCcType());
                resultList.add(result);
            }
        }
        // 排序
        List<PmSlabPoolInResDTO> finalList = new ArrayList<>();
        // a)	校验优钢种虚拟板坯的板坯位置代码（SLAB_PLACE_CODE）
        if (dto.getIsContain().equals(BaseConstants.FlagChar.YES)) {
            // 获取优钢种
            List<PmSlabPoolInResDTO> betterResultList = resultList.stream().filter(resDTO -> dto.getNomStNo().equals(resDTO.getNomStNo()))
                    .sorted(Comparator.comparing(PmSlabPoolInResDTO::getNomStNo)).collect(Collectors.toList());
            resultList.removeAll(betterResultList);
            // 获取次钢种
            List<PmSlabPoolInResDTO> worResultList = resultList.stream()
                    .sorted(Comparator.comparing(PmSlabPoolInResDTO::getBetterToWorseSeq, Comparator.nullsLast(Long::compareTo)))
                    .collect(Collectors.toList());
            // 优钢种板坯位置代码集合
            Set<String> betterResultSet = betterResultList.stream().map(PmSlabPoolInResDTO::getSlabPlaceCode).collect(Collectors.toSet());

            // i.	若存在板坯位置代码的值等于“X”或同时存在板坯位置代码等于“T”和”B”，则将次钢种虚拟板坯的位置平均排在显示结果的头部和尾部
            boolean isContainX = betterResultList.stream().anyMatch(item -> "X".equals(item.getSlabPlaceCode()));
            boolean isContainTAndB = betterResultSet.contains("T") && betterResultSet.contains("B");

            // ii.	若只存在板坯位置代码等于“T”，不存在等于“X”和”B”的情况，则将所有次钢种虚拟板坯的位置排在显示结果的头部；
            boolean isContainT = betterResultList.stream().anyMatch(item -> "T".equals(item.getSlabPlaceCode()));
            boolean isContainXAndB = betterResultSet.contains("X") && betterResultSet.contains("B");


            // iii.	若只存在板坯位置代码等于“B”，不存在等于“X”和”T”的情况，则将所有次钢种虚拟板坯的位置排在显示结果的尾部
            boolean isContainB = betterResultList.stream().anyMatch(item -> "B".equals(item.getSlabPlaceCode()));
            boolean isContainXAndT = betterResultSet.contains("X") && betterResultSet.contains("T");

            // b)	剩余优钢种虚拟板坯按照组炉规则的方式排列；
            if (isContainX || isContainTAndB) {
                // 次钢种排一半头，一半尾
                int size = worResultList.size() / 2 + worResultList.size() % 2;
                for (int i = 0; i < size; i++) {
                    finalList.add(worResultList.get(i));
                }
                // 优钢种-优钢种虚拟板坯按照组炉规则的方式排列；
                finalList.addAll(this.sortByPdPnsort(betterResultList, dto.getId(), tenantId));
                // 次钢种
                for (int i = size; i < worResultList.size(); i++) {
                    finalList.add(worResultList.get(i));
                }

            } else if (isContainT && !isContainXAndB) {
                // 次钢种显示在头
                for (int i = 0; i < worResultList.size(); i++) {
                    finalList.add(worResultList.get(i));
                }
                // 优钢种-优钢种虚拟板坯按照组炉规则的方式排列
                finalList.addAll(this.sortByPdPnsort(betterResultList, dto.getId(), tenantId));
            } else   if (isContainB && !isContainXAndT) {
                // 优钢种-优钢种虚拟板坯按照组炉规则的方式排列
                finalList.addAll(this.sortByPdPnsort(betterResultList, dto.getId(), tenantId));
                // 次钢种显示在尾
                for (int i = 0; i < worResultList.size(); i++) {
                    finalList.add(worResultList.get(i));
                }
            } else {
                // 优钢种-优钢种虚拟板坯按照组炉规则的方式排列
                finalList.addAll(this.sortByPdPnsort(betterResultList, dto.getId(), tenantId));
                // 则将所有次钢种虚拟板坯的位置排在显示结果的尾部
                for (int i = 0; i < worResultList.size(); i++) {
                    finalList.add(worResultList.get(i));
                }
            }
        } else {
            // 优钢种-优钢种虚拟板坯按照组炉规则的方式排列
            finalList.addAll(this.sortByPdPnsort(resultList, dto.getId(), tenantId));
        }
        return finalList;
    }

    public List<PmSlabPoolInResDTO> sortByPdPnsort(List<PmSlabPoolInResDTO> poolList, Long id, Long tenantId) {
        // 根据主键id查询组炉规则配置的记录
        List<PmPnsort> pmPnsortList = pmPnsortRepository.selectByCondition(Condition.builder(PmPnsort.class)
                .andWhere(Sqls.custom().andEqualTo(PmPnsort.FIELD_ID, id))
                .andWhere(Sqls.custom().andEqualTo(PmPnsort.FIELD_TENANT_ID, tenantId))
                .build());
        // 未获取到则报错
        if (CollectionUtils.isEmpty(pmPnsortList)) {
            throw new CommonException("pm.pnsort_003", id);
        }
        // 排序
        PmSlabPoolInDTOComparator comparator = new PmSlabPoolInDTOComparator();
        comparator.setPmPnsort(pmPnsortList.get(0));
        List<PmSlabPoolInResDTO> sortPoolList = poolList.stream().sorted(comparator).collect(Collectors.toList());
        return sortPoolList;
    }

    public void transToDto(PmSlabPoolIn pmSlabPoolIn, PmSlabPoolInResDTO result) {
        result.setId(pmSlabPoolIn.getSlabPoolInId());
        result.setVirtualSlabNo(pmSlabPoolIn.getVirtualSlabNo());
        result.setNomSlabLen(pmSlabPoolIn.getNomSlabLen());
        result.setMainBacklogCode(pmSlabPoolIn.getMainBacklogCode());
        result.setWholeBacklogCode(pmSlabPoolIn.getWholeBacklogCode());
        result.setNomSlabWt(pmSlabPoolIn.getNomSlabWt());
        result.setNomSlabThick(pmSlabPoolIn.getNomSlabThick());
        result.setNomSlabWidth(pmSlabPoolIn.getNomSlabWidth());
        result.setNomStNo(pmSlabPoolIn.getStNo());
        result.setOrderNo(pmSlabPoolIn.getOrderNo());
        result.setDelivyDate(pmSlabPoolIn.getDelivyDate());
        result.setMscLineNo(pmSlabPoolIn.getMscLineNo());
        result.setSgSign(pmSlabPoolIn.getSgSign());
        result.setOrderHotChargeFlag(pmSlabPoolIn.getOrderHotChargeFlag());
        result.setNomHotSendFlag(pmSlabPoolIn.getNomHotSendFlag());
        result.setRfPath(pmSlabPoolIn.getRfPath());
        result.setSlabPlaceCode(pmSlabPoolIn.getSlabPlaceCode());
        result.setUrgOrderFlag(pmSlabPoolIn.getUrgOrderFlag());
        result.setIsChargFurnace(BaseConstants.FlagChar.NO);
        result.setDelivyPlaceName(pmSlabPoolIn.getDelivyPlaceName());
        result.setConsignCustCname(pmSlabPoolIn.getConsignCustCname());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void returnPool(Long tenantId, List<PmSlabPoolInOrderDTO> dtoList) {
        // 校验为空
        if (CollectionUtils.isEmpty(dtoList)) {
            throw new CommonException("pm.slab_pool_in");
        }
        List<String> virtualSlabNoList = new ArrayList<>(dtoList.size());
        List<String> orderNoList = new ArrayList<>(dtoList.size());
        Map<String, PmSlabPoolInOrderDTO> virtualSlabMap = new HashMap<>(dtoList.size());
        for (PmSlabPoolInOrderDTO dto : dtoList) {
            virtualSlabNoList.add(dto.getVirtualSlabNo());
            orderNoList.add(dto.getOrderNo());
            virtualSlabMap.put(dto.getVirtualSlabNo(), dto);
        }

        // c)	根据虚拟板坯号（VIRTUAL_SLAB_NO）删除【组炉收池表（PM_SLAB_POOL_IN）】中该虚拟板坯的记录
        List<PmSlabPoolIn> pmSlabPoolInList = pmSlabPoolInRepository.selectByVirtualSlabNoList(virtualSlabNoList, tenantId);
        // 备份到组炉收池历史表
        if (CollectionUtils.isEmpty(pmSlabPoolInList)) {
            throw new CommonException("pm.slab_pool_in_006",virtualSlabNoList);
        }
        Map<String, PmSlabPoolIn> poolMap = pmSlabPoolInList.stream().collect(Collectors.toMap(PmSlabPoolIn::getVirtualSlabNo, Function.identity()));
        List<PmSlabPoolInHis> pmSlabPoolInHisList = new ArrayList<>(pmSlabPoolInList.size());
        for (PmSlabPoolIn pmSlabPoolIn : pmSlabPoolInList) {
            PmSlabPoolInHis pmSlabPoolInHis = new PmSlabPoolInHis();
            BeanUtils.copy(pmSlabPoolIn, pmSlabPoolInHis);
            pmSlabPoolInHisList.add(pmSlabPoolInHis);

        }
        // 定义事件入参
        List<PmSlabApplyMakeDTO> resList = new ArrayList<>();
        // 定义事件入参-外卖坯
        List<PmSlabApplyMakeDTO> takeOutResList = new ArrayList<>();

        // a)	根据虚拟板坯号（VIRTUAL_SLAB_NO）更新【组板连铸板坯表（PM_PD_CC_SLAB）】中厚板组板状态（PD_STATUS_HP）的值为‘12
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByVirtualSlabList(virtualSlabNoList, tenantId);
        if (CollectionUtils.isNotEmpty(pmPdCcSlabList)) {
            // 更新连铸板坯的厚板组板状态
            pmPdCcSlabList.forEach(pmPdCcSlab -> pmPdCcSlab.setPdStatusHp(Constants.PdStatusHp.PD_STATUS_HP_12));
            pmPdCcSlabRepository.batchUpdateByPrimaryKey(pmPdCcSlabList);

            // 获取组板小板位置表
            List<String> slabVirtualNoList = pmPdCcSlabList.stream().map(PmPdCcSlab::getVirtualSlabNo).collect(Collectors.toList());
            List<PmSmallPltPos> pmSmallPltPosList = pmSmallPltPosRepository.selectByPdMatNoList(slabVirtualNoList,tenantId);
            Map<String, List<PmSmallPltPos>> pmSmallPltPosMap = new HashMap<>(pmSmallPltPosList.size());
            if (CollectionUtils.isNotEmpty(pmSmallPltPosList)) {
                pmSmallPltPosMap = pmSmallPltPosList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getPdMatNo));
            }
            for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
                // 虚拟板坯号信息
                PmSlabApplyMakeDTO makeDTO = new PmSlabApplyMakeDTO();
                makeDTO.setMatNo(pmPdCcSlab.getVirtualSlabNo());
                /*if (Constants.CcType.TYPE_5.equals(pmPdCcSlab.getCcType())) {
                    makeDTO.setPpFlag(8);
                } else {
                    makeDTO.setPpFlag(0);
                }*/
                makeDTO.setPpFlag(0);
//                makeDTO.setOrdFlag("1");
                makeDTO.setPdMatStatus("12");
                makeDTO.setProcCd("14A");
                makeDTO.setWholeBacklogCode("14");
                resList.add(makeDTO);

                // 大板信息
                PmSlabApplyMakeDTO applyMakeDTO1 = new PmSlabApplyMakeDTO();
                applyMakeDTO1.setMatNo(pmPdCcSlab.getVirtualSlabNo());
                applyMakeDTO1.setPpFlag(1);
//                applyMakeDTO1.setOrdFlag("1");
                applyMakeDTO1.setPdMatStatus("12");
                applyMakeDTO1.setProcCd("14A");
                applyMakeDTO1.setWholeBacklogCode("14");
                resList.add(applyMakeDTO1);

                // 子板信息
                if (!pmSmallPltPosMap.containsKey(pmPdCcSlab.getVirtualSlabNo())) {
                    throw new CommonException("pm.small_plt_pos", pmPdCcSlab.getVirtualSlabNo());
                }
                List<PmSmallPltPos> pmSmallPltPos = pmSmallPltPosMap.get(pmPdCcSlab.getVirtualSlabNo());
                for (PmSmallPltPos pmSmallPltPo : pmSmallPltPos) {
                    PmSlabApplyMakeDTO applyMakeDTO = new PmSlabApplyMakeDTO();
                    applyMakeDTO.setMoMatNo(pmSmallPltPo.getPdMatNo());
                    applyMakeDTO.setMatNo(pmSmallPltPo.getPdMatNo() + pmSmallPltPo.getSmallPlateDivNo());
                    applyMakeDTO.setPpFlag(2);
//                    applyMakeDTO.setOrdFlag("1");
                    applyMakeDTO.setPdMatStatus("12");
                    applyMakeDTO.setProcCd("14A");
                    applyMakeDTO.setWholeBacklogCode("14");
                    resList.add(applyMakeDTO);
                }

                // 获取剩余的外供板坯
                virtualSlabNoList.removeAll(slabVirtualNoList);
            }
        }
        pmSlabPoolInRepository.batchDeleteByPrimaryKey(pmSlabPoolInList);
        pmSlabPoolInHisRepository.batchInsertSelective(pmSlabPoolInHisList);
        String eventCode = "";
        List<PmOrderOverDTO> resOverOverList = new ArrayList<>();
        // 说明当前板坯为外供板坯或备坯
        if (virtualSlabNoList.size() > 0) {
            // 是否有超投数量
            List<CtMainVO> ctMainVOList = pmSlabPoolInRepository.selectCtMainByOrderNoList(orderNoList, tenantId);
            Map<String, CtMainVO> ctMainVOMap = new HashMap<>(ctMainVOList.size());
            if (CollectionUtils.isNotEmpty(ctMainVOList)) {
                ctMainVOMap = ctMainVOList.stream().collect(Collectors.toMap(CtMainVO::getOrderNo, Function.identity()));
            }
            Map<String, BigDecimal> orderDevoMap = new HashMap<>(virtualSlabNoList.size());

            // 将以下字段作为入参，调用合同跟踪模块“组炉组浇退池事件”接口，向合同跟踪抛帐：
            for (String virtualSlabNo : virtualSlabNoList) {
                if (poolMap.containsKey(virtualSlabNo)) {
                    PmSlabPoolIn pmSlabPoolIn = poolMap.get(virtualSlabNo);
                    PmSlabApplyMakeDTO makeDTO = new PmSlabApplyMakeDTO();
                    makeDTO.setMatNo(pmSlabPoolIn.getVirtualSlabNo());
                    if (Constants.OrderTypeCode.QBP.equals(pmSlabPoolIn.getOrderTypeCode())) {
                        makeDTO.setPpFlag(3);
                        eventCode = CtEventConstants.EVENT_PM_TAKE_OUT_SLAB_APPLY_CANCEL;
                    } else if (Constants.OrderTypeCode.YZA.equals(pmSlabPoolIn.getOrderTypeCode())) {
                        makeDTO.setPpFlag(4);
                        eventCode = CtEventConstants.EVENT_PM_PREPARATION_SLAB_APPLY_CANCEL;
                    } else {
                        throw new CommonException("pm.slab_pool_in_005", virtualSlabNo, pmSlabPoolIn.getOrderTypeCode());
                    }
//                    makeDTO.setOrdFlag("1");
                    makeDTO.setPdMatStatus(null);
                    makeDTO.setProcCd("14A");
                    makeDTO.setWholeBacklogCode("14");
                    makeDTO.setEnableFlag("0");
                    takeOutResList.add(makeDTO);
                } else {
                    throw new CommonException("pm.slab_pool_in_006", virtualSlabNo);
                }

                // 超投退池
                PmSlabPoolInOrderDTO pmSlabPoolInOrderDTO = virtualSlabMap.get(virtualSlabNo);
                CtMainVO ctMainVO = ctMainVOMap.get(pmSlabPoolInOrderDTO.getOrderNo());
                if (Objects.nonNull(ctMainVO) && ctMainVO.getOverDevoNumTotal() != null &&
                        ctMainVO.getOverDevoNumTotal().compareTo(BigDecimal.ZERO) > 0) {
                    if (orderDevoMap.getOrDefault(pmSlabPoolInOrderDTO.getOrderNo(), BigDecimal.ZERO).compareTo(ctMainVO.getOverDevoNumTotal()) >= 0) {
                        continue;
                    }
                    if (!orderDevoMap.containsKey(pmSlabPoolInOrderDTO.getOrderNo())) {
                        orderDevoMap.put(pmSlabPoolInOrderDTO.getOrderNo(), BigDecimal.ZERO);
                    }
                    orderDevoMap.put(pmSlabPoolInOrderDTO.getOrderNo(), orderDevoMap.get(pmSlabPoolInOrderDTO.getOrderNo()).add(BigDecimal.ONE));

                    PmOrderOverDTO pmOrderOverDTO = new PmOrderOverDTO();
                    pmOrderOverDTO.setOrderNo(ctMainVO.getOrderNo());
                    pmOrderOverDTO.setContractNum(ctMainVO.getOrderNo().substring(0, 8));
                    pmOrderOverDTO.setNum(BigDecimal.ONE);
                    pmOrderOverDTO.setWgt(pmSlabPoolInOrderDTO.getNomSlabWt());
                    resOverOverList.add(pmOrderOverDTO);
                }
            }
        }
        try{
            if (CollectionUtils.isNotEmpty(resList)) {
                log.info("<=====调用组炉组浇退池事件，入参为{}=====>", JSON.toJSONString(resList));
                eventClient.addEvent(CtEventConstants.EVENT_PM_SLAB_APPLY_CANCEL, resList);
            }
            if (CollectionUtils.isNotEmpty(takeOutResList)) {
                log.info("<=====调用外卖坯/备坯合同退池事件，入参为{}=====>", JSON.toJSONString(takeOutResList));
                eventClient.addEvent(eventCode, takeOutResList);
            }
            if (CollectionUtils.isNotEmpty(resOverOverList)) {
                log.info("<=====调用外卖坯/备坯合同超投退池事件，入参为{}=====>", JSON.toJSONString(resOverOverList));
                eventClient.addEvent(CtEventConstants.PM_OUT_SLAB_CONTRACT_BOARD_OVER_CANCEL, resOverOverList);
            }
            eventClient.sendEvent(tenantId);
        }finally {
            eventClient.remove();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void preGroup(Long tenantId, PmSlabPoolInPreDTO dto) {
        // 校验入参是否有值
        if (CollectionUtils.isEmpty(dto.getFurnaceList())) {
            throw new CommonException("pm.slab_pool_in_004");
        }

        // 所有虚拟板坯号集合
        List<String> virtualSlabNoList = new ArrayList<>();
        // 获取所有的虚拟板坯号 ,以M开头，但是第二位不是字母的才是合并板坯
        virtualSlabNoList.addAll(dto.getFurnaceList().stream().flatMap(furnace -> furnace.getLineList().stream())
                .map(PmSlabPoolInPreLineDTO::getVirtualSlabNo).map(item -> Utils.isMergeSlab(item) ? item.substring(1, item.length()) : item)
                .collect(Collectors.toList()));
        // 获取合并板坯的另外一个虚拟板坯号
        virtualSlabNoList.addAll(dto.getFurnaceList().stream().flatMap(furnace -> furnace.getLineList().stream())
                .map(PmSlabPoolInPreLineDTO::getMergeVirtualSlabNo).filter(StringUtils::isNotEmpty).collect(Collectors.toList()));
        // 去除无委坯的
        virtualSlabNoList.removeAll(virtualSlabNoList.stream().filter(item -> Utils.isMergeSlab(item) || item.startsWith("W"))
              .collect(Collectors.toList()));

        // 获取次钢种的虚拟板坯号
        List<String> worVirtualSlabNoList = dto.getFurnaceList().stream().flatMap(furnace -> furnace.getLineList().stream())
                .filter(line -> Objects.nonNull(line.getBetterToWorseSeq()))
                .map(item -> Utils.isMergeSlab(item.getVirtualSlabNo()) ? item.getVirtualSlabNo().substring(1, item.getVirtualSlabNo().length())
                        : item.getVirtualSlabNo()).collect(Collectors.toList());
        worVirtualSlabNoList.addAll( dto.getFurnaceList().stream().flatMap(furnace -> furnace.getLineList().stream())
                .filter(line -> Objects.nonNull(line.getMergeBetterToWorseSeq()))
                .map(PmSlabPoolInPreLineDTO::getMergeVirtualSlabNo).collect(Collectors.toList()));

        // 获取优钢种,只会有一个优钢种
        String betterStNo = "";
        Optional<String> betterStNoOptional = dto.getFurnaceList().stream().flatMap(furnace -> furnace.getLineList().stream())
                .filter(line -> Objects.isNull(line.getBetterToWorseSeq())).map(PmSlabPoolInPreLineDTO::getNomStNo).findFirst();
        if (betterStNoOptional.isPresent()) {
            betterStNo = betterStNoOptional.get();
        }
        Set<PreOptimalChargingDTO> chargingDTOList = new HashSet<>(16);
        Map<String, List<String>> pmPdContSumMap = new HashMap<>(16);
        List<PreOptimalChargingDTO> resultChargeList = new ArrayList<>(16);
        if (CollectionUtils.isNotEmpty(worVirtualSlabNoList)) {
            List<PmPdContSum> pmPdContSumList = pmPdContSumRepository.selectByCondition(Condition.builder(PmPdContSum.class)
                    .andWhere(Sqls.custom().andIn(PmPdContSum.FIELD_PD_MAT_NO, worVirtualSlabNoList))
                    .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId))
                    .build());
            if (CollectionUtils.isNotEmpty(pmPdContSumList)) {
                // 按照材料号分组取合同号集合
                pmPdContSumMap = pmPdContSumList.stream().collect(Collectors.groupingBy(PmPdContSum::getPdMatNo,
                        Collectors.mapping(PmPdContSum::getOrderNo, Collectors.toList())));
                // 组装入参，调用质量校验接口
                for (PmPdContSum pmPdContSum : pmPdContSumList) {
                    PreOptimalChargingDTO chargeDto = new PreOptimalChargingDTO();
                    chargeDto.setOrderNo(pmPdContSum.getOrderNo());
                    chargeDto.setStNo(betterStNo);
                    chargingDTOList.add(chargeDto);
                }
            } else {
                throw new CommonException("pm.pd_cc_slab_001",String.join(",",worVirtualSlabNoList) , "【组板合同总量表（PM_PD_CONT_SUM）】");
            }
        }
        // 调用质量模块“组炉编制”接口进行化学成分校验，返回验证结果
        if (CollectionUtils.isNotEmpty(chargingDTOList)) {
            resultChargeList = qdOrderClient.preOptimalChargingApi(tenantId, new ArrayList<>(chargingDTOList));
            if (CollectionUtils.isEmpty(resultChargeList)) {
                throw new CommonException("pm.pd_cc_slab_008");
            }
        }

        // 查询组炉收池表数据
        List<PmSlabPoolIn> pmSlabPoolInList = pmSlabPoolInRepository.selectByVirtualSlabNoList(virtualSlabNoList,tenantId);
        Map<String, PmSlabPoolIn> pmSlabPoolInMap = new HashMap<>(pmSlabPoolInList.size());
        if (CollectionUtils.isNotEmpty(pmSlabPoolInList)) {
            pmSlabPoolInMap = pmSlabPoolInList.stream().collect(Collectors.toMap(PmSlabPoolIn::getVirtualSlabNo, Function.identity(), (k, v) -> k));
        }

        String userId = DetailsHelper.getUserDetails().getUserId().toString();
        LocalDate now = LocalDate.now();
        List<PmSlabEstaPlan> pmSlabEstaPlanList = new ArrayList<>();
        List<PmSlabMerge> pmSlabMergeList = new ArrayList<>();
        List<PmPonoWtInfo> pmPonoWtInfoList = new ArrayList<>();
        Long slabSeqFlow = 1L;
        String precCastLotNo = Strings.EMPTY;
        List<PmSlabApplyMakeDTO> resList = new ArrayList<>();
        for (int i = 0; i < dto.getFurnaceList().size(); i++) {
            PmSlabPoolInFurnaceDTO furnace = dto.getFurnaceList().get(i);
            // c)	若同一炉中同时包含优钢种与次钢种，需要验证优钢种与次钢种的化学成分是否匹配
            checkWorserAndBetter(furnace, pmPdContSumMap, resultChargeList, betterStNo);
            // 定义预定制造命令号
            String precPono = "";
            for (int j = 0; j < furnace.getLineList().size(); j++) {
                PmSlabPoolInPreLineDTO line = furnace.getLineList().get(j);

                // i.	判断是否为浇次内第一块组炉板坯，若是第一块组炉板坯，获取预定CAST_LOT号（PREC_CAST_LOT_NO）
                if (i == 0 && j == 0) {
                    precCastLotNo = generatePreCastLot(tenantId, line);
                }
                if (j == 0) {
                    // ii.	判读是否是炉内第一块组炉板坯，若是炉内第一块组炉板坯，生成生成预定制造命令号（PREC_PONO）
                    precPono = generatePrecPono(tenantId, line, now);
                }

                // v.	每预组炉完一块板坯，往【组炉编制表（PM_SLAB_ESTA_PLAN）】新增一行记录
                PmSlabEstaPlan pmSlabEstaPlan = new PmSlabEstaPlan();
                pmSlabEstaPlan.setVirtualSlabNo(line.getVirtualSlabNo());
                pmSlabEstaPlan.setUserId(userId);
                pmSlabEstaPlan.setYearId((long) now.getYear());
                pmSlabEstaPlan.setTenantId(tenantId);
                pmSlabEstaPlan.setMatSeqNo(0L);
                pmSlabEstaPlan.setPrecCastLotNo(precCastLotNo);
                pmSlabEstaPlan.setPrecPono(precPono);
                pmSlabEstaPlan.setSlabSeqHeat(j + 1L);
                pmSlabEstaPlan.setCastLotDivNo(i + 1L);
                pmSlabEstaPlan.setCsPrecPlanStatus(Constants.CsPrecPlanStatus.STATUS_01);
                pmSlabEstaPlan.setSlabSeqFlow(slabSeqFlow++);
                pmSlabEstaPlan.setCcNum(dto.getCcNum().longValue());
                pmSlabEstaPlan.setLslabDesignFlag("0");
                pmSlabEstaPlan.setPlanType(dto.getIgnotType());
                if (line.getVirtualSlabNo().startsWith("W")) {
                    // 则从【无委充炉】接口获取对应板坯信息
                    pmSlabEstaPlan.setOrderNo(line.getOrderNo());
                    pmSlabEstaPlan.setStNo(line.getNomStNo());
                    pmSlabEstaPlan.setSteelAppDate(line.getSteelAppDate());
                    pmSlabEstaPlan.setMainBacklogCode(line.getMainBacklogCode());
                    pmSlabEstaPlan.setWholeBacklogCode(line.getWholeBacklogCode());
                    pmSlabEstaPlan.setCcType(line.getCcType());
                    pmSlabEstaPlan.setMoldWid(line.getMoldWid());
                    pmSlabEstaPlan.setMoldThick(line.getMoldThick());
                    pmSlabEstaPlan.setAppType(line.getAppType());
                    pmSlabEstaPlan.setSlabThick(line.getNomSlabThick());
                    pmSlabEstaPlan.setSlabWidth(line.getNomSlabWidth());
                    pmSlabEstaPlan.setSlabLen(line.getNomSlabLen());
                    pmSlabEstaPlan.setSlabWt(line.getNomSlabWt());
                    pmSlabEstaPlan.setActHotChargeFlag(line.getOrderHotChargeFlag());
                    pmSlabEstaPlan.setBilletType(line.getBilletType());
                    pmSlabEstaPlan.setDescription(line.getDescription());
                    // 预定制造命令号 + 连铸机类型 + 炉内板坯顺序号
                    if (StringUtils.isNotEmpty(precCastLotNo)) {
                        pmSlabEstaPlan.setTmpSlabNo(precPono + line.getCcType() + "1" + String.format("%03d", pmSlabEstaPlan.getSlabSeqHeat()));
                    }

                    // 组装抛合同事件参数
                    PmSlabApplyMakeDTO applyMakeDTO = new PmSlabApplyMakeDTO();
                    applyMakeDTO.setMatNo(line.getVirtualSlabNo());
                    applyMakeDTO.setPpFlag(0);
                    applyMakeDTO.setOrdFlag("2");
                    applyMakeDTO.setPdMatStatus("16");
                    applyMakeDTO.setProcCd("14A");
                    applyMakeDTO.setWholeBacklogCode("14");
                    resList.add(applyMakeDTO);
                }  else {
                    boolean flag = false;
                    // 若是合并板坯
                    String virtualSlabNo = line.getVirtualSlabNo();
                    if (Utils.isMergeSlab(line.getVirtualSlabNo())) {
                        flag = true;
                        virtualSlabNo = line.getVirtualSlabNo().substring(1, line.getVirtualSlabNo().length());
                    }
                    // 虚拟板坯号从【组炉收池表（PM_SLAB_POOL_IN）】查出
                    PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.getOrDefault(virtualSlabNo, null);
                    if (Objects.isNull(pmSlabPoolIn)) {
                        throw new CommonException("pm.slab_pool_in_006", virtualSlabNo);
                    }
                    pmSlabEstaPlan.setOrderNo(pmSlabPoolIn.getOrderNo());
                    pmSlabEstaPlan.setStNo(pmSlabPoolIn.getStNo());
                    pmSlabEstaPlan.setSteelAppDate(pmSlabPoolIn.getSteelPlanDate());
                    pmSlabEstaPlan.setWholeBacklogCode(pmSlabPoolIn.getWholeBacklogCode());
                    pmSlabEstaPlan.setMainBacklogCode(pmSlabPoolIn.getMainBacklogCode());
                    pmSlabEstaPlan.setRollAppDate(pmSlabPoolIn.getRollPlanDate());
                    pmSlabEstaPlan.setCcType(pmSlabPoolIn.getCcType());
                    pmSlabEstaPlan.setMoldWid(pmSlabPoolIn.getNomSlabWidth());
                    pmSlabEstaPlan.setMoldThick(pmSlabPoolIn.getNomSlabThick());
                    if ("20".equals(pmSlabPoolIn.getSlabDest())) {
                        pmSlabEstaPlan.setAppType("4");
                    } else {
                        Long type = Long.parseLong(pmSlabPoolIn.getOrderHotChargeFlag()) + 1;
                        pmSlabEstaPlan.setAppType(type.toString());
                    }
                    pmSlabEstaPlan.setSlabThick(pmSlabPoolIn.getNomSlabThick());
                    pmSlabEstaPlan.setSlabWidth(pmSlabPoolIn.getNomSlabWidth());
                    if (flag) {
                        // 若是合并板坯，则取两块板坯长度、板坯重量之和
                        pmSlabEstaPlan.setSlabLen(line.getNomSlabLen());
                        pmSlabEstaPlan.setSlabWt(line.getNomSlabWt());
                    } else {
                        pmSlabEstaPlan.setSlabLen(pmSlabPoolIn.getNomSlabLen());
                        pmSlabEstaPlan.setSlabWt(pmSlabPoolIn.getNomSlabWt());
                    }
                    pmSlabEstaPlan.setActHotChargeFlag(pmSlabPoolIn.getOrderHotChargeFlag());
                    if (Constants.MainBacklogCode.CODE_A.equals(pmSlabPoolIn.getMainBacklogCode())) {
                        pmSlabEstaPlan.setBilletType(Constants.BilletType.TYPE_1);
                    } else if (Constants.MainBacklogCode.CODE_C.equals(pmSlabPoolIn.getMainBacklogCode())) {
                        pmSlabEstaPlan.setBilletType(Constants.BilletType.TYPE_5);
                    }

                    // 预定制造命令号 + 连铸机类型 + 炉内板坯顺序号
                    if (StringUtils.isNotEmpty(precCastLotNo)) {
                        pmSlabEstaPlan.setTmpSlabNo(precPono + pmSlabPoolIn.getCcType() + "1" + String.format("%03d", pmSlabEstaPlan.getSlabSeqHeat()));
                    }

                    // 如果是合并板坯，则根据合并板坯的虚拟板坯号，往【组炉板坯合并表（PM_SLAB_MERGE）】中新增两条记录：
                    if (flag) {
                        pmSlabMergeList.addAll(buildMergeSlab(pmSlabEstaPlan, line, precPono, tenantId));
                    }
                }
                if (BigDecimal.ZERO.compareTo(pmSlabEstaPlan.getSlabWt()) == 0) {
                    throw new CommonException("pm.slab_esta_plan_018", Utils.isMergeSlab(pmSlabEstaPlan.getVirtualSlabNo()) ?
                            pmSlabEstaPlan.getVirtualSlabNo().substring(1, pmSlabEstaPlan.getVirtualSlabNo().length()) :
                            pmSlabEstaPlan.getVirtualSlabNo());
                }
                pmSlabEstaPlanList.add(pmSlabEstaPlan);
            }
            //vi.	每组满一炉，往【炉重信息表（PM_PONO_WT_INFO）】中新增一行记录，
            PmPonoWtInfo pmPonoWtInfo = new PmPonoWtInfo();
            pmPonoWtInfo.setMainBacklogCode(furnace.getLineList().get(0).getMainBacklogCode());
            pmPonoWtInfo.setStNo(furnace.getLineList().get(0).getNomStNo());
            pmPonoWtInfo.setCcType(furnace.getLineList().get(0).getCcType());
            pmPonoWtInfo.setActAimInitWt(furnace.getActualAimInitWt());
            pmPonoWtInfo.setActPonoWt(furnace.getActualWt());
            pmPonoWtInfo.setPonoWtPlus(dto.getPonoWtPlus());
            pmPonoWtInfo.setPonoWtMinus(dto.getPonoWtMinus());
            pmPonoWtInfo.setPrecCastLotNo(precCastLotNo);
            pmPonoWtInfo.setPrecPono(precPono);
            pmPonoWtInfo.setUserId(userId);
            pmPonoWtInfo.setPonoYield(furnace.getActualWt().divide(furnace.getActualAimInitWt(), 4, BigDecimal.ROUND_HALF_UP));
            pmPonoWtInfo.setTenantId(tenantId);
            pmPonoWtInfoList.add(pmPonoWtInfo);
        }
        
        // v.	每预组炉完一块板坯，往【组炉编制表（PM_SLAB_ESTA_PLAN）】新增一行记录
        pmSlabEstaPlanRepository.batchInsertSelective(pmSlabEstaPlanList);

        // 合并板坯往组炉板坯合并表（PM_SLAB_MERGE）新增
        pmSlabMergeRepository.batchInsertSelective(pmSlabMergeList);

        // vi.	每组满一炉，往【炉重信息表（PM_PONO_WT_INFO）】中新增一行记录
        pmPonoWtInfoRepository.batchInsertSelective(pmPonoWtInfoList);

        // 组炉收池表（PM_SLAB_POOL_IN）】中对应虚拟板坯的编制状态（ESTA_STATUS）设为‘1’，表示这些板坯已完成编制，并在前端提示“预组炉成功”
        pmSlabPoolInList.forEach(pmSlabPoolIn -> pmSlabPoolIn.setEstaStatus(Constants.EstaStatus.STATUS_1));
        pmSlabPoolInRepository.batchUpdateByPrimaryKey(pmSlabPoolInList);

        // viii根据虚拟板坯号（VIRTUAL_SLAB_NO）更新【组板连铸板坯表（PM_PD_CC_SLAB）】中厚板组板状态（PD_STATUS_HP）为“16“状态，
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByVirtualSlabList(virtualSlabNoList, tenantId);
        Map<String, String> pmPdCcSlabMap = new HashMap<>(pmPdCcSlabList.size());
        if (CollectionUtils.isNotEmpty(pmPdCcSlabList)) {
            pmPdCcSlabMap = pmPdCcSlabList.stream().collect(Collectors.toMap(PmPdCcSlab::getVirtualSlabNo, PmPdCcSlab::getCcType));
            pmPdCcSlabList.forEach(pmPdCcSlab -> pmPdCcSlab.setPdStatusHp(Constants.PdStatusHp.PD_STATUS_HP_16));
            pmPdCcSlabRepository.batchUpdateByPrimaryKey(pmPdCcSlabList);
        }

        // x.	将以下字段作为入参，调用合同跟踪“组炉组浇完成事件”接口，向合同跟踪抛帐：
        List<PmSmallPltPos> pmSmallPltPosList = pmSmallPltPosRepository.selectByPdMatNoList(virtualSlabNoList, tenantId);
        Map<String, List<PmSmallPltPos>> pmSmallPltPosMap = new HashMap<>(pmSmallPltPosList.size());
        if (CollectionUtils.isNotEmpty(pmSmallPltPosList)) {
            pmSmallPltPosMap = pmSmallPltPosList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getPdMatNo));
        }
        resList.addAll(abandoningContract(virtualSlabNoList, pmPdCcSlabMap,pmSmallPltPosMap, pmSlabPoolInMap,
                "16", "14A", "14"));

        // xi.	待预组炉结束之后，调用【临时命令信息生成接口】生成临时命令信息；
        List<PmMaterialCommandDTO> resCommandList = self().tempCommandGeneratInterface(pmSlabEstaPlanList, tenantId);
        try{
            List<PmSlabApplyMakeDTO> wResList = resList.stream().filter(item -> item.getMatNo().startsWith("W")).collect(Collectors.toList());
            // 无委充炉事件
            if (CollectionUtils.isNotEmpty(wResList)) {
                log.info("<=====调用无委充炉事件，入参为{}=====>", JSON.toJSONString(wResList));
                eventClient.addEvent(CtEventConstants.PM_NO_COMMISSION_CHARGING_FURNACE, wResList);
            }
            log.info("<=====调用组炉组浇完成事件，入参为{}=====>", JSON.toJSONString(resList));
            eventClient.addEvent(CtEventConstants.EVENT_PM_SLAB_APPLY_CONFIRM, resList);

            if (CollectionUtils.isNotEmpty(resCommandList)) {
                log.info("<=====调用材料命令已生成事件，入参为{}=====>", JSON.toJSONString(resCommandList));
                eventClient.addEvent(CtEventConstants.EVENT_PM_MATERIAL_COMMAND_GENERATED, resCommandList);
            }
            eventClient.sendEvent(tenantId);
        }finally {
            eventClient.remove();
        }
    }

    private  List<PmSlabMerge>  buildMergeSlab(PmSlabEstaPlan pmSlabEstaPlan, PmSlabPoolInPreLineDTO line, String precPono, Long tenantId) {
        List<PmSlabMerge> pmSlabMergeList = new ArrayList<>();
        PmSlabMerge pmSlabMerge = new PmSlabMerge();
        pmSlabMerge.setMergeSlabNo(line.getVirtualSlabNo());
        pmSlabMerge.setVirtualSlabNo(line.getVirtualSlabNo().substring(1, line.getVirtualSlabNo().length()));
        pmSlabMerge.setTmpSlabNo(precPono+pmSlabEstaPlan.getCcType() + "1" + String.format("A%02d", pmSlabEstaPlan.getSlabSeqHeat()));
        pmSlabMerge.setTmpPonoSlabNo(pmSlabEstaPlan.getTmpSlabNo());
        pmSlabMerge.setTenantId(tenantId);

        PmSlabMerge slabMerge = new PmSlabMerge();
        slabMerge.setMergeSlabNo(line.getVirtualSlabNo());
        slabMerge.setVirtualSlabNo(line.getMergeVirtualSlabNo());
        slabMerge.setTmpSlabNo(precPono+pmSlabEstaPlan.getCcType() + "1" + String.format("B%02d", pmSlabEstaPlan.getSlabSeqHeat()));
        slabMerge.setTmpPonoSlabNo(pmSlabEstaPlan.getTmpSlabNo());
        slabMerge.setTenantId(tenantId);

        pmSlabMergeList.add(pmSlabMerge);
        pmSlabMergeList.add(slabMerge);

        return pmSlabMergeList;
    }

    private void checkWorserAndBetter(PmSlabPoolInFurnaceDTO furnace, Map<String, List<String>> pmPdContSumMap, List<PreOptimalChargingDTO> resultChargeList,
                                      String betterStNo) {
        boolean betterFlag = furnace.getLineList().stream()
                .anyMatch(item -> Objects.isNull(item.getBetterToWorseSeq()) || Objects.isNull(item.getMergeBetterToWorseSeq()));
        boolean worseFlag = furnace.getLineList()
                .stream().anyMatch(item -> Objects.nonNull(item.getBetterToWorseSeq()) || Objects.nonNull(item.getMergeBetterToWorseSeq()));
        if (betterFlag && worseFlag) {
            // 获取次钢种虚拟板坯号
            List<String> virtualList = furnace.getLineList().stream().filter(item -> Objects.nonNull(item.getBetterToWorseSeq()))
                    .map(item->Utils.isMergeSlab(item.getVirtualSlabNo()) ? item.getVirtualSlabNo().substring(1, item.getVirtualSlabNo().length()) : item.getVirtualSlabNo())
                    .collect(Collectors.toList());
            virtualList.addAll(furnace.getLineList().stream().filter(item -> Objects.nonNull(item.getMergeBetterToWorseSeq()))
                    .map(PmSlabPoolInPreLineDTO::getMergeVirtualSlabNo).collect(Collectors.toList()));
            // 校验
            for (String virtualSlabNo : virtualList) {
                // 判断该板坯上所挂合同
                if (pmPdContSumMap.containsKey(virtualSlabNo)) {
                    List<String> pdOrderNoList = pmPdContSumMap.get(virtualSlabNo);
                    List<PreOptimalChargingDTO> filterChargeList = resultChargeList.stream()
                            .filter(item-> pdOrderNoList.contains(item.getOrderNo())).filter(item->"不合格".equals(item.getResult()))
                            .collect(Collectors.toList());
                    // iii.	若存在次钢种虚拟板坯化学成分不匹配，则报错（右下角提示）：PM.FURNACE.CASTING.013，程序结束
                    if (CollectionUtils.isNotEmpty(filterChargeList)) {
                        String orderList = filterChargeList.stream().map(PreOptimalChargingDTO::getOrderNo).collect(Collectors.joining(","));
                        throw new CommonException("pm.furnace_casting_013",virtualSlabNo, orderList, betterStNo);
                    }
                } else {
                    throw new CommonException("pm.pd_cont_sum",virtualSlabNo);
                }
            }
        }
    }

    private List<PmSlabApplyMakeDTO> abandoningContract(List<String> virtualSlabNoList,  Map<String, String> pmPdCcSlabMap,
                                                        Map<String, List<PmSmallPltPos>> pmSmallPltPosMap,
                                                        Map<String, PmSlabPoolIn> pmSlabPoolInMap,
                                                        String pdMatStatus, String procCd, String wholeBacklogCode) {
        List<PmSlabApplyMakeDTO> resList = new ArrayList<>();
        for (String virtualSlabNo : virtualSlabNoList) {
            if (pmPdCcSlabMap.containsKey(virtualSlabNo)) {
                PmSlabApplyMakeDTO applyMakeDTO = new PmSlabApplyMakeDTO();
                applyMakeDTO.setMatNo(virtualSlabNo);
/*                if (Constants.CcType.TYPE_5.equals(pmPdCcSlabMap.get(virtualSlabNo))) {
                    applyMakeDTO.setPpFlag(8);
                } else {
                    applyMakeDTO.setPpFlag(0);
                }*/
                applyMakeDTO.setPpFlag(0);
                applyMakeDTO.setOrdFlag("1");
                applyMakeDTO.setPdMatStatus(pdMatStatus);
                applyMakeDTO.setProcCd(procCd);
                applyMakeDTO.setWholeBacklogCode(wholeBacklogCode);
                resList.add(applyMakeDTO);

                // 大板信息
                PmSlabApplyMakeDTO applyMakeDTO1 = new PmSlabApplyMakeDTO();
                applyMakeDTO1.setMatNo(virtualSlabNo);
                applyMakeDTO1.setPpFlag(1);
                applyMakeDTO1.setOrdFlag("1");
                applyMakeDTO1.setPdMatStatus(pdMatStatus);
                applyMakeDTO1.setProcCd(procCd);
                applyMakeDTO1.setWholeBacklogCode(wholeBacklogCode);
                resList.add(applyMakeDTO1);
                // 子板信息
                if (!pmSmallPltPosMap.containsKey(virtualSlabNo)) {
                    throw new CommonException("pm.small_plt_pos", virtualSlabNo);
                }
                List<PmSmallPltPos> pmSmallPltPos = pmSmallPltPosMap.get(virtualSlabNo);
                for (PmSmallPltPos pmSmallPltPo : pmSmallPltPos) {
                    PmSlabApplyMakeDTO makeDTO = new PmSlabApplyMakeDTO();
                    makeDTO.setMoMatNo(pmSmallPltPo.getPdMatNo());
                    makeDTO.setMatNo(pmSmallPltPo.getPdMatNo() + pmSmallPltPo.getSmallPlateDivNo());
                    makeDTO.setPpFlag(2);
                    applyMakeDTO.setOrdFlag("1");
                    makeDTO.setPdMatStatus(pdMatStatus);
                    makeDTO.setProcCd(procCd);
                    makeDTO.setWholeBacklogCode(wholeBacklogCode);
                    resList.add(makeDTO);
                }

            } else {
                // 外卖坯
                PmSlabApplyMakeDTO applyMakeDTO = new PmSlabApplyMakeDTO();
                if (pmSlabPoolInMap.containsKey(virtualSlabNo)) {
                    PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(virtualSlabNo);
                    applyMakeDTO.setMatNo(virtualSlabNo);
                    if (Constants.OrderTypeCode.QBP.equals(pmSlabPoolIn.getOrderTypeCode())) {
                        applyMakeDTO.setPpFlag(3);
                    } else if (Constants.OrderTypeCode.YZA.equals(pmSlabPoolIn.getOrderTypeCode())) {
                        applyMakeDTO.setPpFlag(4);
                    } else {
                        throw new CommonException("pm.slab_pool_in_005",virtualSlabNo, pmSlabPoolIn.getOrderTypeCode() );
                    }
                    applyMakeDTO.setOrdFlag("1");
                    applyMakeDTO.setPdMatStatus(null);
                    applyMakeDTO.setProcCd(procCd);
                    applyMakeDTO.setWholeBacklogCode(wholeBacklogCode);
                    resList.add(applyMakeDTO);
                } else {
                    throw new CommonException("pm.slab_pool_in_006", virtualSlabNo);
                }
            }
        }
        return resList;
    }

    private String generatePrecPono(Long tenantId, PmSlabPoolInPreLineDTO line, LocalDate now) {
        String precPono = "";
        Map<String, String> ponoParamsMap = new HashMap<>(4);
        ponoParamsMap.put("wholeBackCode", Constants.MainBacklogCode.CODE_C.equals(line.getMainBacklogCode())
                ? "W" : "Y");
        ponoParamsMap.put("yearLastNum", String.format("%1d", now.getYear() % 10));
        if (Constants.CcType.TYPE_1.equals(line.getCcType())) {
            precPono = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_PONO,
                    CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, ponoParamsMap);
        } else if (Constants.CcType.TYPE_2.equals(line.getCcType())) {
            precPono = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_PONO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_2_LEVEL_CODE, ponoParamsMap);
        } else if (Constants.CcType.TYPE_4.equals(line.getCcType())) {
            precPono = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_PONO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_4_LEVEL_CODE, ponoParamsMap);
        } else if (Constants.CcType.TYPE_5.equals(line.getCcType())) {
            precPono = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_PONO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_5_LEVEL_CODE, ponoParamsMap);
        }
        return precPono;
    }

    private String generatePreCastLot(Long tenantId, PmSlabPoolInPreLineDTO line) {
        String precCastLotNo = "";
        Map<String, String> paramsMap = new HashMap<>(4);
        paramsMap.put("wholeBackCode", Constants.MainBacklogCode.CODE_C.equals(line.getMainBacklogCode()) ?
                "W" : "Y");
        if (Constants.CcType.TYPE_1.equals(line.getCcType())) {
            precCastLotNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_CAST_LOT_NO,
                    CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, paramsMap);
        } else if (Constants.CcType.TYPE_2.equals(line.getCcType())) {
            precCastLotNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_CAST_LOT_NO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_2_LEVEL_CODE, paramsMap);
        } else if (Constants.CcType.TYPE_4.equals(line.getCcType())) {
            precCastLotNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_CAST_LOT_NO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_4_LEVEL_CODE, paramsMap);
        } else if (Constants.CcType.TYPE_5.equals(line.getCcType())) {
            precCastLotNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.PREC_CAST_LOT_NO,
                    CodeConstants.CodeRuleLevelCode.CUSTOM, Constants.CodeRule.TYPE_5_LEVEL_CODE, paramsMap);
        } else {
            throw new CommonException("pm.slab_esta_plan_006", line.getCcType());
        }
        return precCastLotNo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public   List<PmMaterialCommandDTO> tempCommandGeneratInterface(List<PmSlabEstaPlan> pmSlabEstaPlanList, Long tenantId) {
        // 根据预定CAST_LOT号和预定制造命令号（PREC_PONO）分组
        Map<String, Map<String, List<PmSlabEstaPlan>>> slabEstaPlanMap = pmSlabEstaPlanList.stream()
                .collect(Collectors.groupingBy(PmSlabEstaPlan::getPrecCastLotNo, Collectors.groupingBy(PmSlabEstaPlan::getPrecPono)));

        // 3.查询板坯去向不为外供板坯和备坯、且轴合同号不为空的信息（外供板坯、备坯和无委坯不需要进行二次设计），获取虚拟板坯号（VIRTUAL_SLAB_NO）
        boolean isDelivery  = pmSlabEstaPlanList.stream().anyMatch(esta -> Constants.CcType.TYPE_2.equals(esta.getCcType()) ||
                Constants.CcType.TYPE_4.equals(esta.getCcType()));
        if (isDelivery) {
            // 修改连铸预定计划状态为临时命令生成
            pmSlabEstaPlanList.forEach(item->item.setCsPrecPlanStatus(Constants.CsPrecPlanStatus.STATUS_02));
            pmSlabEstaPlanRepository.batchUpdateByPrimaryKey(pmSlabEstaPlanList);
            return Collections.emptyList();
        }
        List<String> virtualSlabNoList = pmSlabEstaPlanList.stream().filter(esta -> StringUtils.isNotEmpty(esta.getOrderNo()))
                .filter(item->!Utils.isMergeSlab(item.getVirtualSlabNo())).map(PmSlabEstaPlan::getVirtualSlabNo).collect(Collectors.toList());
        // 获取合并板坯的虚拟板坯信息
        List<String> mergeSlabNoList = pmSlabEstaPlanList.stream().filter(esta -> StringUtils.isNotEmpty(esta.getOrderNo()))
                .filter(item -> Utils.isMergeSlab(item.getVirtualSlabNo())).map(PmSlabEstaPlan::getVirtualSlabNo).collect(Collectors.toList());
        Map<String, List<PmSlabMerge>> pmSlabMergeMap = new HashMap<>(mergeSlabNoList.size());
        if (CollectionUtils.isNotEmpty(mergeSlabNoList)) {
            List<PmSlabMerge> pmSlabMergeList =  pmSlabMergeRepository.selectByMergeSlabNoList(mergeSlabNoList, tenantId);
            if (CollectionUtils.isNotEmpty(pmSlabMergeList)) {
                // 根据合并板坯号分组
                pmSlabMergeMap = pmSlabMergeList.stream().collect(Collectors.groupingBy(PmSlabMerge::getMergeSlabNo));
                List<String> slabNoList = pmSlabMergeList.stream().map(PmSlabMerge::getVirtualSlabNo).collect(Collectors.toList());
                virtualSlabNoList.addAll(slabNoList);
            }
        }

        // 查询连铸板坯表数据
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByVirtualSlabList(virtualSlabNoList, tenantId);
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            throw new CommonException("pm.slab_esta_plan_004",virtualSlabNoList);
        }

        // 查询组炉收池表数据
        List<PmSlabPoolIn> pmSlabPoolInList = pmSlabPoolInRepository.selectByVirtualSlabNoList(virtualSlabNoList, tenantId);
        Map<String, PmSlabPoolIn> pmSlabPoolInMap = new HashMap<>(pmSlabPoolInList.size());
        if (CollectionUtils.isNotEmpty(pmSlabPoolInList)) {
            pmSlabPoolInMap = pmSlabPoolInList.stream().collect(Collectors.toMap(PmSlabPoolIn::getVirtualSlabNo, Function.identity(), (k, v) -> k));
        }

        // 产线、轴合同号集合
        List<String> mscLineNoList = pmSlabPoolInList.stream().map(PmSlabPoolIn::getMscLineNo).distinct().collect(Collectors.toList());
        List<String> orderNoList = pmSlabPoolInList.stream().map(PmSlabPoolIn::getOrderNo).distinct().collect(Collectors.toList());

        Map<String, PmPdCcSlab> pdCcSlabMap = new HashMap<>(pmPdCcSlabList.size());
        Map<String, PmProContProdTtr> pmProContProdTtrMap = new HashMap<>(pmPdCcSlabList.size());
        if (CollectionUtils.isNotEmpty(pmPdCcSlabList)) {
            pdCcSlabMap = pmPdCcSlabList.stream().collect(Collectors.toMap(PmPdCcSlab::getVirtualSlabNo, Function.identity()));
        }

        // 组板合同总量表数据查询
        List<PmPdContSum> pmPdContSumList = pmPdContSumRepository.selectByPdMatNoList(tenantId, virtualSlabNoList);
        Map<String, List<PmPdContSum>> pmPdContSumMap = new HashMap<>(pmSlabPoolInList.size());
        if (CollectionUtils.isNotEmpty(pmPdContSumList)) {
            pmPdContSumMap = pmPdContSumList.stream().collect(Collectors.groupingBy(PmPdContSum::getPdMatNo));
        }
        orderNoList.addAll(pmPdContSumList.stream().map(PmPdContSum::getOrderNo).distinct().collect(Collectors.toList()));

        // 生产合同产品属性数据查询
        List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository.selectByOrderNoList(orderNoList, tenantId);
        if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
            pmProContProdTtrMap = pmProContProdTtrList.stream().collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (k, v) -> k));
        }

        // 合同产线工艺参数表数据查询
        List<PmContMscTech> pmContMscTecheList = pmContMscTechRepository.selectByOrderNoAndMscLineNo(orderNoList, mscLineNoList, tenantId);
        Map<String, PmContMscTech> pmContMscTecheMap = new HashMap<>(pmContMscTecheList.size());
        if (CollectionUtils.isNotEmpty(pmContMscTecheList)) {
            pmContMscTecheMap = pmContMscTecheList.stream()
                    .collect(Collectors.toMap(teche -> Strings.concat(teche.getOrderNo(), teche.getMscLineNo()),
                            Function.identity(), (k, v) -> k));
        }

        // 组板小板位置表数据查询
        List<PmSmallPltPos> pmSmallPltPoList = pmSmallPltPosRepository.selectByPdMatNoList(virtualSlabNoList, tenantId);
        Map<String, List<PmSmallPltPos>> pmSmallPltPoMap = new HashMap<>(pmSmallPltPoList.size());
        if (CollectionUtils.isNotEmpty(pmSmallPltPoList)) {
            pmSmallPltPoMap = pmSmallPltPoList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getPdMatNo));
        }

        // 定义四大命令集合
        List<PmCmdSlab> pmCmdSlabList = new ArrayList<>();
        List<PmCmdLargePlt> pmCmdLargePltList = new ArrayList<>();
        List<PmCmdCont> pmCmdContList = new ArrayList<>();
        List<PmCmdSmallPlt> pmCmdSmallPltList = new ArrayList<>();
        List<PmPdCcSlab> updatePdCcSlabList = new ArrayList<>();
        for (Map.Entry<String, Map<String, List<PmSlabEstaPlan>>> entry : slabEstaPlanMap.entrySet()) {
            for (Map.Entry<String, List<PmSlabEstaPlan>> precEntry : entry.getValue().entrySet()) {
                for (PmSlabEstaPlan slabEstaPlan : precEntry.getValue()) {
                    // 无委板坯不进行二次设计
                    if (slabEstaPlan.getVirtualSlabNo().startsWith("W")) {
                        continue;
                    }
                    PmPdCcSlab pmPdCcSlab = null;
                    String pdStatusHp = Constants.PdStatusHp.PD_STATUS_HP_18;
                    if (Utils.isMergeSlab(slabEstaPlan.getVirtualSlabNo())) {
                        // i.	根据虚拟板坯号查询【组炉板坯合并表（PM_SLAB_MERGE）】，
                        if (!pmSlabMergeMap.containsKey(slabEstaPlan.getVirtualSlabNo())) {
                            throw new CommonException("pm.slab_merge_003",slabEstaPlan.getVirtualSlabNo());
                        }
                        List<PmSlabMerge> slabMergeList = pmSlabMergeMap.get(slabEstaPlan.getVirtualSlabNo());

                        for (PmSlabMerge slabMerge : slabMergeList) {
                            // 无委板坯不进行二次设计
                            if (slabMerge.getVirtualSlabNo().startsWith("W")) {
                                continue;
                            }
                            // 更新连铸板坯表的数据
                            pmPdCcSlab = pdCcSlabMap.get(slabMerge.getVirtualSlabNo());
                            if (Constants.CcType.TYPE_5.equals(pmPdCcSlab.getCcType())) {
                                pdStatusHp = Constants.PdStatusHp.PD_STATUS_HP_23;
                            }
                            pmPdCcSlab.setPdStatusHp(pdStatusHp);
                            pmPdCcSlab.setTmpSlabNo(slabMerge.getTmpSlabNo());
                            pmPdCcSlab.setPrecPono(slabEstaPlan.getPrecPono());
                            pmPdCcSlab.setPrecCastLotNo(slabEstaPlan.getPrecCastLotNo());
                            updatePdCcSlabList.add(pmPdCcSlab);

                            // 4.	初始化【命令板坯表（PM_CMD_SLAB）】
                            PmCmdSlab pmCmdSlab = new PmCmdSlab();
                            pmCmdSlab.setTenantId(tenantId);
                            pmCmdSlab.setTmpSlabNo(slabMerge.getTmpSlabNo());
                            pmCmdSlab.setSlabNo(slabMerge.getMergeSlabNo());
                            pmCmdSlab.setVirtualSlabNo(slabMerge.getVirtualSlabNo());
                            pmCmdSlab.setSlabHtFlag(slabEstaPlan.getSlabSeqHeat().equals(0L) ? "1" : "0");
                            pmCmdSlab.setPono(slabEstaPlan.getPrecPono());
                            pmCmdSlab.setIsMerge(Constants.MergeStatus.MERGE_B);
                            pmCmdSlab.setBigPlateNum(1L);
                            pmCmdSlab.setShortSlabNumInLong(1L);
                            if (slabMerge.getTmpSlabNo().contains("A")) {
                                pmCmdSlab.setSlabDivNo(1L);
                            } else {
                                pmCmdSlab.setSlabDivNo(2L);
                            }
                            if ( pmSlabPoolInMap.containsKey(slabMerge.getVirtualSlabNo())) {
                                PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(slabMerge.getVirtualSlabNo());
                                pmCmdSlab.setOrderNoAxis(pmSlabPoolIn.getOrderNo());
                                pmCmdSlab.setHotChargeFlag(pmSlabPoolIn.getOrderHotChargeFlag());
                                pmCmdSlab.setHotSendDiv(pmSlabPoolIn.getNomHotSendFlag());
                                pmCmdSlab.setMscLineNo(pmSlabPoolIn.getMscLineNo());
                            }
                            pmCmdSlab.setHotSendDiv("C");
                            buildPmCmdSlab(pmCmdSlab, pmPdCcSlab, pdStatusHp);
                            pmCmdSlabList.add(pmCmdSlab);
                            // 合并板坯-第三块
                            if (slabMerge.getTmpSlabNo().contains("A")) {
                                PmCmdSlab mergePmCmdSlab = new PmCmdSlab();
                                BeanUtils.copy(pmCmdSlab, mergePmCmdSlab);
                                mergePmCmdSlab.setTmpSlabNo(slabMerge.getTmpPonoSlabNo());
                                mergePmCmdSlab.setVirtualSlabNo(null);
                                mergePmCmdSlab.setPdStatusHp(Constants.PdStatusHp.PD_STATUS_HP_20);
                                mergePmCmdSlab.setIsMerge(Constants.MergeStatus.MERGE_A);
                                mergePmCmdSlab.setSlabDivNo(1L);
                                mergePmCmdSlab.setHotSendDiv("C");
                                mergePmCmdSlab.setBigPlateNum(2L);
                                mergePmCmdSlab.setShortSlabNumInLong(2L);
                                pmCmdSlabList.add(mergePmCmdSlab);
                            }

                            // 6.	初始化【命令参数表（PM_CMD_CONT）】
                            String rollMode = "";
                            Long axisFlag = 1L;
                            if (pmPdContSumMap.containsKey(slabMerge.getVirtualSlabNo())) {
                                List<PmPdContSum> pdContSumList = pmPdContSumMap.get(slabMerge.getVirtualSlabNo());
                                for (PmPdContSum pmPdContSum : pdContSumList) {
                                    PmCmdCont pmCmdCont = new PmCmdCont();
                                    pmCmdCont.setTenantId(tenantId);
                                    pmCmdCont.setTmpSlabNo(slabMerge.getTmpSlabNo());
                                    pmCmdCont.setSlabNo(slabMerge.getMergeSlabNo());
                                    pmCmdCont.setMatDesignKind(pmPdCcSlab.getMatDesignKind());
                                    buildPmPdContSum(pmCmdCont, pmPdContSum, pmSlabPoolInMap, pmProContProdTtrMap,
                                            pmContMscTecheMap, slabEstaPlan, slabMerge.getVirtualSlabNo());
                                    if (axisFlag.equals(pmCmdCont.getAxisFlag())) {
                                        rollMode = pmCmdCont.getRollMode();
                                    }
                                    pmCmdContList.add(pmCmdCont);
                                    if (slabMerge.getTmpSlabNo().contains("A")) {
                                        PmCmdCont mergePmCmdCont = new PmCmdCont();
                                        BeanUtils.copy(pmCmdCont, mergePmCmdCont);
                                        mergePmCmdCont.setTmpSlabNo(slabMerge.getTmpPonoSlabNo());
                                        pmCmdContList.add(mergePmCmdCont);
                                    }
                                }
                            } else {
                                throw new CommonException("pm.slab_esta_plan_008",slabMerge.getVirtualSlabNo());
                            }

                            // 5.	初始化【命令大板表（PM_CMD_LARGE_PLT）】
                            PmCmdLargePlt pmCmdLargePlt = new PmCmdLargePlt();
                            pmCmdLargePlt.setTenantId(tenantId);
                            pmCmdLargePltList.add(pmCmdLargePlt);
                            pmCmdLargePlt.setTmpSlabNo(slabMerge.getTmpSlabNo());
                            pmCmdLargePlt.setSlabNo(slabMerge.getMergeSlabNo());
                            pmCmdLargePlt.setIsMerge(Constants.MergeStatus.MERGE_B);
                            pmCmdLargePlt.setRollMode(rollMode);
                            if (slabMerge.getTmpSlabNo().contains("A")) {
                                pmCmdLargePlt.setSlabDivNo(1L);
                            } else {
                                pmCmdLargePlt.setSlabDivNo(2L);
                            }
                            // 组装数据
                            buildPmCmdLargePlt(pmCmdLargePlt, pmPdCcSlab, pmProContProdTtrMap, pmPdContSumMap,
                                    slabMerge.getVirtualSlabNo(), pmSmallPltPoMap, pdStatusHp, slabEstaPlan);
                            if (pmSlabPoolInMap.containsKey(slabMerge.getVirtualSlabNo())) {
                                PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(slabMerge.getVirtualSlabNo());
                                if (pmContMscTecheMap.containsKey(Strings.concat(pmSlabPoolIn.getOrderNo(), pmSlabPoolIn.getMscLineNo()))) {
                                    PmContMscTech pmContMscTech = pmContMscTecheMap.get(Strings.concat(pmSlabPoolIn.getOrderNo(),
                                            pmSlabPoolIn.getMscLineNo()));
                                    pmCmdLargePlt.setPlateDtCode(pmContMscTech.getPlateDtCode());
                                }
                            }

                            if (slabMerge.getTmpSlabNo().contains("A")) {
                                PmCmdLargePlt mergePmCmdLargePlt = new PmCmdLargePlt();
                                BeanUtils.copy(pmCmdLargePlt, mergePmCmdLargePlt);
                                mergePmCmdLargePlt.setTmpSlabNo(slabMerge.getTmpPonoSlabNo());
                                mergePmCmdLargePlt.setPdStatusHp(Constants.PdStatusHp.PD_STATUS_HP_20);
                                mergePmCmdLargePlt.setIsMerge(Constants.MergeStatus.MERGE_A);
                                mergePmCmdLargePlt.setSlabDivNo(1L);
                                pmCmdLargePltList.add(mergePmCmdLargePlt);
                            }

                            // 7.	初始化【命令小板表（PM_CMD_SMALL_PLT）】
                            if (!pmSmallPltPoMap.isEmpty() && pmSmallPltPoMap.containsKey(slabMerge.getVirtualSlabNo())) {
                                for (PmSmallPltPos pmSmallPltPos : pmSmallPltPoMap.get(slabMerge.getVirtualSlabNo())) {
                                    PmCmdSmallPlt pmCmdSmallPlt = new PmCmdSmallPlt();
                                    pmCmdSmallPlt.setTenantId(tenantId);
                                    pmCmdSmallPlt.setTmpSlabNo(slabMerge.getTmpSlabNo());
                                    pmCmdSmallPlt.setSlabNo(slabMerge.getMergeSlabNo());
                                    if ( pmSlabPoolInMap.containsKey(slabMerge.getVirtualSlabNo())) {
                                        PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(slabMerge.getVirtualSlabNo());
                                        pmCmdSmallPlt.setMscLineNo(pmSlabPoolIn.getMscLineNo());
                                    }
                                    buildPmCmdSmallPlt(pmCmdSmallPlt, pmSmallPltPos);
                                    pmCmdSmallPltList.add(pmCmdSmallPlt);
                                    if (slabMerge.getTmpSlabNo().contains("A")) {
                                        PmCmdSmallPlt mergePmCmdSmallPlt = new PmCmdSmallPlt();
                                        BeanUtils.copy(pmCmdSmallPlt, mergePmCmdSmallPlt);
                                        mergePmCmdSmallPlt.setTmpSlabNo(slabMerge.getTmpPonoSlabNo());
                                        pmCmdSmallPltList.add(mergePmCmdSmallPlt);
                                    }
                                }
                            }
                        }
                    } else {
                        // 更新连铸板坯表的数据
                        pmPdCcSlab = pdCcSlabMap.get(slabEstaPlan.getVirtualSlabNo());
                        if (Constants.CcType.TYPE_5.equals(pmPdCcSlab.getCcType())) {
                            pdStatusHp = Constants.PdStatusHp.PD_STATUS_HP_23;
                        }

                        pmPdCcSlab.setPdStatusHp(pdStatusHp);
                        pmPdCcSlab.setTmpSlabNo(slabEstaPlan.getTmpSlabNo());
                        pmPdCcSlab.setPrecPono(slabEstaPlan.getPrecPono());
                        pmPdCcSlab.setPrecCastLotNo(slabEstaPlan.getPrecCastLotNo());
                        updatePdCcSlabList.add(pmPdCcSlab);


                        // 4.	初始化【命令板坯表（PM_CMD_SLAB）】
                        PmCmdSlab pmCmdSlab = new PmCmdSlab();
                        pmCmdSlab.setTenantId(tenantId);
                        pmCmdSlab.setVirtualSlabNo(slabEstaPlan.getVirtualSlabNo());
                        pmCmdSlab.setOrderNoAxis(slabEstaPlan.getOrderNo());
                        pmCmdSlab.setTmpSlabNo(slabEstaPlan.getTmpSlabNo());
                        pmCmdSlab.setSlabHtFlag(slabEstaPlan.getSlabSeqHeat().equals(0L) ? "1" : "0");
                        pmCmdSlab.setPono(slabEstaPlan.getPrecPono());
                        pmCmdSlab.setSlabNo(null);
                        pmCmdSlab.setIsMerge(Constants.MergeStatus.MERGE_N);
                        pmCmdSlab.setBigPlateNum(1L);
                        pmCmdSlab.setShortSlabNumInLong(1L);
                        pmCmdSlab.setSlabDivNo(1L);

                        if (!pmSlabPoolInMap.isEmpty() && pmSlabPoolInMap.containsKey(slabEstaPlan.getVirtualSlabNo())) {
                            PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(slabEstaPlan.getVirtualSlabNo());
                            pmCmdSlab.setHotChargeFlag(pmSlabPoolIn.getOrderHotChargeFlag());
                            pmCmdSlab.setHotSendDiv(pmSlabPoolIn.getNomHotSendFlag());
                            pmCmdSlab.setMscLineNo(pmSlabPoolIn.getMscLineNo());
                        }
                        buildPmCmdSlab(pmCmdSlab, pmPdCcSlab, pdStatusHp);
                        pmCmdSlabList.add(pmCmdSlab);

                        // 6.	初始化【命令参数表（PM_CMD_CONT）】
                        String rollMode = "";
                        Long axisFlag = 1L;
                        if (!pmPdContSumMap.isEmpty() && pmPdContSumMap.containsKey(slabEstaPlan.getVirtualSlabNo())) {
                            List<PmPdContSum> pdContSumList = pmPdContSumMap.get(slabEstaPlan.getVirtualSlabNo());
                            for (PmPdContSum pmPdContSum : pdContSumList) {
                                PmCmdCont pmCmdCont = new PmCmdCont();
                                pmCmdCont.setTenantId(tenantId);
                                pmCmdCont.setTmpSlabNo(slabEstaPlan.getTmpSlabNo());
                                pmCmdCont.setMatDesignKind(pmPdCcSlab.getMatDesignKind());
                                buildPmPdContSum(pmCmdCont, pmPdContSum, pmSlabPoolInMap, pmProContProdTtrMap,
                                        pmContMscTecheMap, slabEstaPlan, slabEstaPlan.getVirtualSlabNo());
                                if (axisFlag.equals(pmCmdCont.getAxisFlag())) {
                                    rollMode = pmCmdCont.getRollMode();
                                }
                                pmCmdContList.add(pmCmdCont);
                            }
                        } else {
                            throw new CommonException("pm.slab_esta_plan_008", slabEstaPlan.getVirtualSlabNo());
                        }

                        // 5.	初始化【命令大板表（PM_CMD_LARGE_PLT）】
                        PmCmdLargePlt pmCmdLargePlt = new PmCmdLargePlt();
                        pmCmdLargePlt.setTenantId(tenantId);
                        pmCmdLargePlt.setTmpSlabNo(slabEstaPlan.getTmpSlabNo());
                        pmCmdLargePlt.setIsMerge(Constants.MergeStatus.MERGE_N);
                        pmCmdLargePlt.setSlabDivNo(1L);
                        pmCmdLargePlt.setRollMode(rollMode);
                        pmCmdLargePltList.add(pmCmdLargePlt);
                        PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(slabEstaPlan.getVirtualSlabNo());
                        if (pmContMscTecheMap.containsKey(Strings.concat(pmSlabPoolIn.getOrderNo(), pmSlabPoolIn.getMscLineNo()))) {
                            PmContMscTech pmContMscTech = pmContMscTecheMap.get(Strings.concat(pmSlabPoolIn.getOrderNo(),
                                    pmSlabPoolIn.getMscLineNo()));
                            pmCmdLargePlt.setPlateDtCode(pmContMscTech.getPlateDtCode());
                        }
                        buildPmCmdLargePlt(pmCmdLargePlt, pmPdCcSlab, pmProContProdTtrMap, pmPdContSumMap,
                                slabEstaPlan.getVirtualSlabNo(), pmSmallPltPoMap, pdStatusHp, slabEstaPlan);

                        // 7.	初始化【命令小板表（PM_CMD_SMALL_PLT）】
                        if (!pmSmallPltPoMap.isEmpty() && pmSmallPltPoMap.containsKey(slabEstaPlan.getVirtualSlabNo())) {
                            for (PmSmallPltPos pmSmallPltPos : pmSmallPltPoMap.get(slabEstaPlan.getVirtualSlabNo())) {
                                PmCmdSmallPlt pmCmdSmallPlt = new PmCmdSmallPlt();
                                pmCmdSmallPlt.setTenantId(tenantId);
                                pmCmdSmallPlt.setTmpSlabNo(slabEstaPlan.getTmpSlabNo());
                                pmCmdSmallPlt.setMscLineNo(pmSlabPoolIn.getMscLineNo());
                                buildPmCmdSmallPlt(pmCmdSmallPlt, pmSmallPltPos);
                                pmCmdSmallPltList.add(pmCmdSmallPlt);
                            }
                        }
                    }
                }
            }
        }
        // 修改连铸预定计划状态为临时命令生成
        pmSlabEstaPlanList.forEach(item->item.setCsPrecPlanStatus(Constants.CsPrecPlanStatus.STATUS_02));

        pmCmdSlabRepository.batchInsertSelective(pmCmdSlabList);
        pmCmdLargePltRepository.batchInsertSelective(pmCmdLargePltList);
        pmCmdContRepository.batchInsertSelective(pmCmdContList);
        pmCmdSmallPltRepository.batchInsertSelective(pmCmdSmallPltList);
        pmPdCcSlabRepository.batchUpdateByPrimaryKey(updatePdCcSlabList);
        pmSlabEstaPlanRepository.batchUpdateByPrimaryKey(pmSlabEstaPlanList);

        // f)	将以下字段作为入参，调用合同跟踪模块“组炉组浇收池事件”接口，向合同跟踪抛帐：
        List<PmMaterialCommandDTO> resList = TempcommandAbandonOrder(pdCcSlabMap, pmPdCcSlabList, pmSmallPltPoMap, "18", "14A", "14");
        return resList;
    }

    private List<PmMaterialCommandDTO> TempcommandAbandonOrder( Map<String, PmPdCcSlab> pdCcSlabMap, List<PmPdCcSlab> pmPdCcSlabList,
                                                                Map<String, List<PmSmallPltPos>> pmSmallPltPoMap,
                                                                String pdMatStatus, String procCd, String wholeBacklogCode ) {
        List<PmMaterialCommandDTO> resList = new ArrayList<>();
        for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
            // 虚拟板坯号信息
            PmMaterialCommandDTO materialCommandDTO = new PmMaterialCommandDTO();
            materialCommandDTO.setMatNo(pmPdCcSlab.getVirtualSlabNo());
            if (pdCcSlabMap.containsKey(pmPdCcSlab.getVirtualSlabNo())) {
                // 钢锭连铸
                /*if (Constants.CcType.TYPE_5.equals(pdCcSlabMap.get(pmPdCcSlab.getVirtualSlabNo()).getCcType())) {
                    materialCommandDTO.setPpFlag(8);
                } else {
                    materialCommandDTO.setPpFlag(0);
                }*/
                materialCommandDTO.setPpFlag(0);
            } else {
                throw new CommonException("pm.pd_cc_slab_006",pmPdCcSlab.getVirtualSlabNo());
            }
            materialCommandDTO.setOrdFlag("1");
            materialCommandDTO.setPdMatStatus(pdMatStatus);
            materialCommandDTO.setProcCd(procCd);
            materialCommandDTO.setWholeBacklogCode(wholeBacklogCode);
            resList.add(materialCommandDTO);
            // 大板信息
            PmMaterialCommandDTO commandDTO = new PmMaterialCommandDTO();
            commandDTO.setMatNo(pmPdCcSlab.getVirtualSlabNo());
            commandDTO.setPpFlag(1);
            commandDTO.setOrdFlag("1");
            commandDTO.setPdMatStatus(pdMatStatus);
            commandDTO.setProcCd(procCd);
            commandDTO.setWholeBacklogCode(wholeBacklogCode);
            resList.add(commandDTO);
            // 子板信息
            if (!pmSmallPltPoMap.containsKey(pmPdCcSlab.getVirtualSlabNo())) {
                throw new CommonException("pm.small_plt_pos", pmPdCcSlab.getVirtualSlabNo());
            }
            List<PmSmallPltPos> pmSmallPltPos = pmSmallPltPoMap.get(pmPdCcSlab.getVirtualSlabNo());
            for (PmSmallPltPos pmSmallPltPo : pmSmallPltPos) {
                PmMaterialCommandDTO makeDTO = new PmMaterialCommandDTO();
                makeDTO.setMoMatNo(pmSmallPltPo.getPdMatNo());
                makeDTO.setMatNo(pmSmallPltPo.getPdMatNo() + pmSmallPltPo.getSmallPlateDivNo());
                makeDTO.setPpFlag(2);
                makeDTO.setOrdFlag("1");
                makeDTO.setPdMatStatus(pdMatStatus);
                makeDTO.setProcCd(procCd);
                makeDTO.setWholeBacklogCode(wholeBacklogCode);
                resList.add(makeDTO);
            }
        }
        return resList;
    }

    private void buildPmCmdSmallPlt(PmCmdSmallPlt pmCmdSmallPlt, PmSmallPltPos pmSmallPltPos) {
        pmCmdSmallPlt.setSmallPlateDivNo(pmSmallPltPos.getSmallPlateDivNo());
        pmCmdSmallPlt.setOrderNo(pmSmallPltPos.getOrderNo());
        pmCmdSmallPlt.setSlabNo(pmSmallPltPos.getSlabNo());
        pmCmdSmallPlt.setPlateNo(pmSmallPltPos.getPlateNo());
        pmCmdSmallPlt.setPickModeLenDir(pmSmallPltPos.getPickModeLenDir());
        pmCmdSmallPlt.setPickModeWidDir(pmSmallPltPos.getPickModeWidDir());
        pmCmdSmallPlt.setOrderThick(pmSmallPltPos.getOrderThick());
        pmCmdSmallPlt.setOrderWidth(pmSmallPltPos.getOrderWidth());
        pmCmdSmallPlt.setOrderLen(pmSmallPltPos.getOrderLen());
        pmCmdSmallPlt.setOrderLenMax(pmSmallPltPos.getOrderLenMax());
        pmCmdSmallPlt.setOrderLenMin(pmSmallPltPos.getOrderLenMin());
        pmCmdSmallPlt.setSmallPlateThick(pmSmallPltPos.getSmallPlateThick());
        pmCmdSmallPlt.setSmallPlateWidth(pmSmallPltPos.getSmallPlateWidth());
        pmCmdSmallPlt.setSmallPlateLen(pmSmallPltPos.getSmallPlateLen());

        pmCmdSmallPlt.setSampleHeadLenFree(BigDecimal.ZERO);
        pmCmdSmallPlt.setSampleTailLenFree(BigDecimal.ZERO);
        pmCmdSmallPlt.setSampleHeadLenPlate(BigDecimal.ZERO);
        pmCmdSmallPlt.setSampleTailLenPlate(BigDecimal.ZERO);
        pmCmdSmallPlt.setSampleLenGive(BigDecimal.ZERO);
    }

    private void buildPmPdContSum(PmCmdCont pmCmdCont, PmPdContSum pmPdContSum, Map<String, PmSlabPoolIn> pmSlabPoolInMap,
                                  Map<String, PmProContProdTtr> pmProContProdTtrMap,  Map<String, PmContMscTech> pmContMscTecheMap,
                                  PmSlabEstaPlan slabEstaPlan, String virtualSlabNo) {
        pmCmdCont.setOrderNo(pmPdContSum.getOrderNo());
        pmCmdCont.setSmallPlateThick(pmPdContSum.getSmallPlateThick());
        pmCmdCont.setSmallPlateWidth(pmPdContSum.getSmallPlateWidth());
        pmCmdCont.setSmallPlateLen(pmPdContSum.getSmallPlateLen());
        pmCmdCont.setAxisFlag(pmPdContSum.getAxisFlag());

        // 据合同号和产线号多表关联查询【生产合同产品属性表（PM_PRO_CONT_PROD_ATTR）】和【合同产线工艺参数表（PM_CONT_MSC_TECH）】，
        // 【生产合同产品属性表】和【合同产线工艺参数表】以合同号关联，
        if (pmSlabPoolInMap.containsKey(virtualSlabNo)) {
            PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInMap.get(virtualSlabNo);
            if (!pmContMscTecheMap.isEmpty() && pmContMscTecheMap.containsKey(Strings.concat(pmSlabPoolIn.getOrderNo(),
                    pmSlabPoolIn.getMscLineNo()))) {
                PmContMscTech pmContMscTech = pmContMscTecheMap.get(Strings.concat(pmSlabPoolIn.getOrderNo(),
                        pmSlabPoolIn.getMscLineNo()));
                pmCmdCont.setWholeBacklogNo(null);
                pmCmdCont.setWholeBacklog(pmContMscTech.getWholeBacklog());
                pmCmdCont.setStNo(pmContMscTech.getStNo());
                pmCmdCont.setWidenMin(pmContMscTech.getWidenMin());
                pmCmdCont.setCompressMin(pmContMscTech.getCompressMin());
                pmCmdCont.setRollDirectCode(pmContMscTech.getRollDirectCode());
                pmCmdCont.setCtrlRollCode(pmContMscTech.getCtrlRollCode());
                pmCmdCont.setAdTypeCode(pmContMscTech.getAdTypeCode());
                pmCmdCont.setAdModeCode(pmContMscTech.getAdModeCode());
                pmCmdCont.setHotRectifyFlag(pmContMscTech.getHotRectifyFlag() == null ?
                        null : pmContMscTech.getHotRectifyFlag().toString());
                pmCmdCont.setHeadCut(pmContMscTech.getHeadCut());
                pmCmdCont.setCutModeCode(pmContMscTech.getCutModeCode());
                pmCmdCont.setGFlag(pmContMscTech.getGFlag() == null ?
                        null : pmContMscTech.getGFlag().toString());
                pmCmdCont.setCsFlag(pmContMscTech.getCsFlag()== null ?
                        null : pmContMscTech.getCsFlag().toString());
                pmCmdCont.setDssFlag(pmContMscTech.getDssFlag()== null ?
                        null : pmContMscTech.getDssFlag().toString());
                pmCmdCont.setSsFlag(pmContMscTech.getSsFlag()== null ?
                        null : pmContMscTech.getSsFlag().toString());
                pmCmdCont.setDsFlag(pmContMscTech.getDsFlag()== null ?
                        null : pmContMscTech.getDsFlag().toString());
                pmCmdCont.setHeatTreatMode(pmContMscTech.getWholeHeatTreatmentType());
                pmCmdCont.setUltDetectMethodCode(pmContMscTech.getUltDetectMethodCode());
                pmCmdCont.setUltCode(pmContMscTech.getUltCode());
                pmCmdCont.setMscLineNo(pmContMscTech.getMscLineNo());
                pmCmdCont.setRollMode(pmContMscTech.getRollMode());
            }
        }
        if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(slabEstaPlan.getOrderNo())) {
            PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(slabEstaPlan.getOrderNo());
            pmCmdCont.setTwoRollInterimFlag("" + pmProContProdTtr.getTwoRollFlag());
            pmCmdCont.setOrderTypeCode(pmProContProdTtr.getOrderTypeCode());
            pmCmdCont.setExportFlag(pmProContProdTtr.getExportFlag() == null ?
                    null : pmProContProdTtr.getExportFlag().toString());
            pmCmdCont.setFinCustCode(pmProContProdTtr.getFinCustCode());
            pmCmdCont.setPsc(pmProContProdTtr.getPsc());
            pmCmdCont.setApn(pmProContProdTtr.getApn());
            pmCmdCont.setMsc(pmProContProdTtr.getMsc());
            pmCmdCont.setProdCodeHp(pmProContProdTtr.getProdCodeHp());
            pmCmdCont.setSgStd(pmProContProdTtr.getSgStd());
            pmCmdCont.setSgSign(pmProContProdTtr.getSgSign());
            pmCmdCont.setShpCode(pmProContProdTtr.getShpCode());
            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());
            pmCmdCont.setBacklogPtMark(pmProContProdTtr.getBacklogPtMark());
            pmCmdCont.setBacklogMtMark(pmProContProdTtr.getBacklogMtMark());
            pmCmdCont.setBacklogTmcpMark(pmProContProdTtr.getBacklogTmcpMark());
            pmCmdCont.setUnitWtMax(pmProContProdTtr.getOrderUnitMaxWt());
            pmCmdCont.setUnitWtMin(pmProContProdTtr.getOrderUnitMinWt());
            pmCmdCont.setUnitWtAim(pmProContProdTtr.getOrderUnitAimWt());
            pmCmdCont.setOrderThick(pmProContProdTtr.getOrderThick());
            pmCmdCont.setOrderWidth(pmProContProdTtr.getOrderWidth());
            pmCmdCont.setOrderLen(pmProContProdTtr.getOrderLen());
            pmCmdCont.setWidthDiv(pmProContProdTtr.getWidthDiv() == null ?
                    null : pmProContProdTtr.getWidthDiv().toString());
            pmCmdCont.setWidthMax(pmProContProdTtr.getWidthMax());
            pmCmdCont.setWidthMin(pmProContProdTtr.getWidthMin());
            pmCmdCont.setLenDiv(pmProContProdTtr.getLenDiv() == null ?
                    null : pmProContProdTtr.getLenDiv().toString());
            pmCmdCont.setOrderLenMin(pmProContProdTtr.getOrderMinLen());
            pmCmdCont.setOrderLenMax(pmProContProdTtr.getOrderMaxLen());
            pmCmdCont.setUrgOrderFlag(pmProContProdTtr.getUrgOrderFlag() == null ?
                    null : pmProContProdTtr.getUrgOrderFlag().toString());
            pmCmdCont.setTrimCode(null);
        }
    }

    private void buildPmCmdLargePlt(PmCmdLargePlt pmCmdLargePlt, PmPdCcSlab pmPdCcSlab,   Map<String, PmProContProdTtr>
            pmProContProdTtrMap, Map<String, List<PmPdContSum>> pmPdContSumMap, String virtualSlabNo,
                                    Map<String, List<PmSmallPltPos>> pmSmallPltPoMap, String pdStatusHp, PmSlabEstaPlan slabEstaPlan) {
        pmCmdLargePlt.setPdBacklogSeq(pmPdCcSlab.getOuBacklogSeq());
        pmCmdLargePlt.setPdBacklogCode(pmPdCcSlab.getOuBacklogCode());
        pmCmdLargePlt.setPdStatusHp(pdStatusHp);
        pmCmdLargePlt.setFormPlateMode(pmPdCcSlab.getFormPlateMode());
        pmCmdLargePlt.setPickModeLenDir(pmPdCcSlab.getPickModeLenDir());
        pmCmdLargePlt.setPickModeWidDir(pmPdCcSlab.getPickModeWidDir());
        pmCmdLargePlt.setFurType(pmPdCcSlab.getFurType());
        pmCmdLargePlt.setAutoManualFlag(pmPdCcSlab.getAutoManualFlag());
        pmCmdLargePlt.setOrderRemainDiv(pmPdCcSlab.getOrderRemainDiv());
        pmCmdLargePlt.setMatDesignKind(pmPdCcSlab.getMatDesignKind());
        pmCmdLargePlt.setOrderNumInPlate(pmPdCcSlab.getOrderNumInPlate());
        pmCmdLargePlt.setTotSmallPlateNum(pmPdCcSlab.getTotSmallPlateNum());
        pmCmdLargePlt.setProdCodeHp(pmPdCcSlab.getProdCodeHp());
        pmCmdLargePlt.setAdTypeCode(pmPdCcSlab.getAdTypeCode());
        pmCmdLargePlt.setUltCode(pmPdCcSlab.getUltCode());
        pmCmdLargePlt.setCoolCode(pmPdCcSlab.getCoolCode());
        pmCmdLargePlt.setCtrlRollCode(pmPdCcSlab.getCtrlRollCode());
        pmCmdLargePlt.setWithSideFlag(pmPdCcSlab.getWithSideFlag());
        pmCmdLargePlt.setCutModeCode(pmPdCcSlab.getCutModeCode());
        pmCmdLargePlt.setHeadCut(pmPdCcSlab.getHeadCut());
        pmCmdLargePlt.setTailCut(pmPdCcSlab.getTailCut());
        pmCmdLargePlt.setSgSign(pmPdCcSlab.getSgSign());
        pmCmdLargePlt.setStNo(pmPdCcSlab.getStNo());
        pmCmdLargePlt.setRollAimThick(pmPdCcSlab.getRollAimThick());
        pmCmdLargePlt.setRollAimWidth(pmPdCcSlab.getRollAimWidth());
        pmCmdLargePlt.setRollAimLen(pmPdCcSlab.getRollAimLen());
        pmCmdLargePlt.setRollThickTolMax(pmPdCcSlab.getRollThickTolMax());
        pmCmdLargePlt.setRollThickTolMin(pmPdCcSlab.getRollThickTolMin());
        pmCmdLargePlt.setOrder1Thick(pmPdCcSlab.getAxisOrderThick());
        pmCmdLargePlt.setCombinePlateWidth(pmPdCcSlab.getCombinePlateWidth());
        pmCmdLargePlt.setCombinePlateLen(pmPdCcSlab.getCombinePlateLen());
        pmCmdLargePlt.setRollWtHp(pmPdCcSlab.getRollWtHp());
        pmCmdLargePlt.setNormYield(pmPdCcSlab.getNormYield());
        pmCmdLargePlt.setCommandYield(pmPdCcSlab.getCommandYield());
        pmCmdLargePlt.setRollYield(pmPdCcSlab.getRollYield());
        pmCmdLargePlt.setEdgerUseFlag(pmPdCcSlab.getEdgerUseFlag());
        pmCmdLargePlt.setBroadMasUseFlag(pmPdCcSlab.getBroadMasUseFlag());
        pmCmdLargePlt.setFormMasUseFlag(pmPdCcSlab.getFormMasUseFlag());
        pmCmdLargePlt.setRollDirectCode(pmPdCcSlab.getRollDirectCode());
        pmCmdLargePlt.setSampleLenHead(pmPdCcSlab.getSampleLenHead());
        pmCmdLargePlt.setSampleLenTail(pmPdCcSlab.getSampleLenTail());
        pmCmdLargePlt.setSampleLenMid(pmPdCcSlab.getSampleLenMid());
        pmCmdLargePlt.setRsCode(pmPdCcSlab.getRsCode());
        pmCmdLargePlt.setBroadFlag(pmPdCcSlab.getBroadFlag());
        pmCmdLargePlt.setTwoRollInterimFlag(pmPdCcSlab.getTwoRollInterimFlag() == null ?
                null : pmPdCcSlab.getTwoRollInterimFlag().toString());
        pmCmdLargePlt.setTaperRollThick1(pmPdCcSlab.getTaperRollThick1());
        pmCmdLargePlt.setTaperRollThickMax1(pmPdCcSlab.getTaperRollThickMax1());
        pmCmdLargePlt.setTaperRollThickMin1(pmPdCcSlab.getTaperRollThickMin1());
        pmCmdLargePlt.setTaperRollThick2(pmPdCcSlab.getTaperRollThick2());
        pmCmdLargePlt.setTaperRollThickMax2(pmPdCcSlab.getTaperRollThickMax2());
        pmCmdLargePlt.setTaperRollThickMin2(pmPdCcSlab.getTaperRollThickMin2());
        pmCmdLargePlt.setTaperRollThick3(pmPdCcSlab.getTaperRollThick3());
        pmCmdLargePlt.setTaperRollThickMax3(pmPdCcSlab.getTaperRollThickMax3());
        pmCmdLargePlt.setTaperRollThickMin3(pmPdCcSlab.getTaperRollThickMin3());
        pmCmdLargePlt.setTaperRollWidth(pmPdCcSlab.getTaperRollWidth());
        pmCmdLargePlt.setTaperRollLen1(pmPdCcSlab.getTaperRollLen1());
        pmCmdLargePlt.setTaperRollLen2(pmPdCcSlab.getTaperRollLen2());
        pmCmdLargePlt.setTaperRollLen3(pmPdCcSlab.getTaperRollLen3());
        pmCmdLargePlt.setTaperRollLen4(pmPdCcSlab.getTaperRollLen4());
        pmCmdLargePlt.setTaperRollLen5(pmPdCcSlab.getTaperRollLen5());
        pmCmdLargePlt.setGFlag(pmPdCcSlab.getGFlag());
        pmCmdLargePlt.setCsFlag(pmPdCcSlab.getCsFlag());
        pmCmdLargePlt.setDssFlag(pmPdCcSlab.getDssFlag());
        pmCmdLargePlt.setDsFlag(pmCmdLargePlt.getDsFlag());
        pmCmdLargePlt.setSsFlag(pmPdCcSlab.getSsFlag());
        pmCmdLargePlt.setFormPlateTime(pmPdCcSlab.getCreationDate());
        pmCmdLargePlt.setProdDensity(pmPdCcSlab.getProdDensity());
        pmCmdLargePlt.setMscLineNo(pmPdCcSlab.getMscLineNo());
        pmCmdLargePlt.setMatDesignKind(pmPdCcSlab.getMatDesignKind());
        pmCmdLargePlt.setIngotType(pmPdCcSlab.getIngotType());

        if (pmProContProdTtrMap.containsKey(pmPdCcSlab.getOrderNoAxis())) {
            pmCmdLargePlt.setSampleLenGive(pmProContProdTtrMap.get(pmPdCcSlab.getOrderNoAxis()).getSampleLenGive());
        }

        if (pmSmallPltPoMap.containsKey(virtualSlabNo)) {
            Optional<PmSmallPltPos> max = pmSmallPltPoMap.get(virtualSlabNo).stream()
                    .max(Comparator.comparing(PmSmallPltPos::getSmallPlateDivNo));
            if (!max.isPresent()) {
                throw new CommonException("pm.pd_cc_slab_001", "虚拟板坯号", "组板小板位置表");
            }
            int index = Utils.findIndex(PmPlateConstants.SMALL_PLATE_SPLIT_NO, max.get().getSmallPlateDivNo());
            // 二次开坯不需要余母板号
            if (index != -1) {
                pmCmdLargePlt.setOtherPlateNo1(PmPlateConstants.SMALL_PLATE_SPLIT_NO[++index]);
                pmCmdLargePlt.setOtherPlateNo2(PmPlateConstants.SMALL_PLATE_SPLIT_NO[++index]);
                pmCmdLargePlt.setOtherPlateNo3(PmPlateConstants.SMALL_PLATE_SPLIT_NO[++index]);
                pmCmdLargePlt.setOtherPlateNo4(PmPlateConstants.SMALL_PLATE_SPLIT_NO[++index]);
            }
        }

        // b)	计算最大轧制厚度（MAX_ROLL_THICK）和最小轧制厚度（MIN_ROLL_THICK）
        // i.是特殊形状板，即钢板形状代码（SHP_CODE）的值不为空,
        // 取特殊形状板轧制厚度1（TAPER_ROLL_THICK_MAX_1）、特殊形状板轧制厚度2（TAPER_ROLL_THICK_MAX_2）、
        // 特殊形状板轧制厚度3（TAPER_ROLL_THICK_MAX_3）三者中的最大值,最小值
        if (StringUtils.isNotEmpty(pmPdCcSlab.getShpCode())) {
            BigDecimal maxValue = pmPdCcSlab.getTaperRollThickMax1() != null ?
                    pmPdCcSlab.getTaperRollThickMax1() : BigDecimal.ZERO;
            BigDecimal minValue = maxValue;
            if (pmPdCcSlab.getTaperRollThickMax1() != null && pmPdCcSlab.getTaperRollThickMax2() != null) {
                maxValue = pmPdCcSlab.getTaperRollThickMax1().compareTo(pmPdCcSlab.getTaperRollThickMax2()) > 0 ?
                        pmPdCcSlab.getTaperRollThickMax1() : pmPdCcSlab.getTaperRollThickMax2();
                minValue = pmPdCcSlab.getTaperRollThickMax1().compareTo(pmPdCcSlab.getTaperRollThickMax2()) < 0 ?
                        pmPdCcSlab.getTaperRollThickMax1() : pmPdCcSlab.getTaperRollThickMax2();
            }
            if (pmPdCcSlab.getTaperRollThickMax3() != null) {
                maxValue = maxValue.compareTo(pmPdCcSlab.getTaperRollThickMax3()) > 0 ?
                        maxValue : pmPdCcSlab.getTaperRollThickMax3();
                minValue = minValue.compareTo(pmPdCcSlab.getTaperRollThickMax3()) < 0 ?
                        minValue : pmPdCcSlab.getTaperRollThickMax3();
            }
            pmCmdLargePlt.setMaxRollThick(maxValue);
            pmCmdLargePlt.setMinRollThick(minValue);
        } else {
            // ii.	如果是普通板型，即钢板形状代码（SHP_CODE）的值为空
            if (!pmPdContSumMap.isEmpty() && pmPdContSumMap.containsKey(virtualSlabNo)) {
                List<PmPdContSum> pdContSumList = pmPdContSumMap.get(virtualSlabNo);
                // 1.	板坯只包含一个合同的情况：
                if (pdContSumList.size() == 1) {
                    String orderNo = pdContSumList.get(0).getOrderNo();
                    if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(orderNo)) {
                        PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(orderNo);
                        pmCmdLargePlt.setMaxRollThick(pmProContProdTtr.getOrderThick().add(pmProContProdTtr.getThickTolMax()));
                        pmCmdLargePlt.setMinRollThick(pmProContProdTtr.getOrderThick().add(pmProContProdTtr.getThickTolMin()));
                    }
                } else {
                    // 2.	板坯包含多个合同的情况：取交集
                    PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(pdContSumList.get(0).getOrderNo());
                    BigDecimal maxRollThick = pmProContProdTtr.getOrderThick().add(pmProContProdTtr.getThickTolMax());
                    BigDecimal mixRollThick = pmProContProdTtr.getOrderThick().add(pmProContProdTtr.getThickTolMin());
                    for (int i = 1; i < pdContSumList.size(); i++) {
                        if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(pdContSumList.get(i).getOrderNo())) {
                            PmProContProdTtr proContProdTtr = pmProContProdTtrMap.get(pdContSumList.get(i).getOrderNo());
                            BigDecimal maxThick = proContProdTtr.getOrderThick().add(proContProdTtr.getThickTolMax());
                            BigDecimal minThick = proContProdTtr.getOrderThick().add(proContProdTtr.getThickTolMin());
                            maxRollThick = maxThick.compareTo(maxRollThick) < 0 ? maxThick : maxRollThick;
                            mixRollThick = minThick.compareTo(mixRollThick) > 0 ? minThick : mixRollThick;
                        }
                    }
                    pmCmdLargePlt.setMaxRollThick(maxRollThick);
                    pmCmdLargePlt.setMinRollThick(mixRollThick);
                }
            }
        }

        pmCmdLargePlt.setSampleLenHead(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleLenMid(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleLenTail(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleLenGive(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleLen(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleHeadLenFree(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleTailLenFree(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleHeadLenPlate(BigDecimal.ZERO);
        pmCmdLargePlt.setSampleTailLenPlate(BigDecimal.ZERO);
    }

    private void buildPmCmdSlab(PmCmdSlab pmCmdSlab, PmPdCcSlab pmPdCcSlab, String pdStatusHp) {
        pmCmdSlab.setPdBacklogCode(pmPdCcSlab.getOuBacklogCode());
        pmCmdSlab.setPdBacklogSeq(pmPdCcSlab.getOuBacklogSeq());
        pmCmdSlab.setPdStatusHp(pdStatusHp);
        pmCmdSlab.setOrderNumInPlate(pmPdCcSlab.getOrderNumInPlate());
        pmCmdSlab.setOrderRemainDiv(pmPdCcSlab.getOrderRemainDiv());
        pmCmdSlab.setMatDesignKind(pmPdCcSlab.getMatDesignKind());
        pmCmdSlab.setProdCodeHp(pmPdCcSlab.getProdCodeHp());
        pmCmdSlab.setSgSign(pmPdCcSlab.getSgSign());
        pmCmdSlab.setStNo(pmPdCcSlab.getStNo());
        pmCmdSlab.setPreCleanSlabThick(pmPdCcSlab.getPreCleanSlabThick());
        pmCmdSlab.setPreCleanSlabWidth(pmPdCcSlab.getPreCleanSlabWidth());
        pmCmdSlab.setPreCleanSlabLen(pmPdCcSlab.getPreCleanSlabLen());
        pmCmdSlab.setPreCleanSlabMaxLen(pmPdCcSlab.getPreCleanSlabMaxLen());
        pmCmdSlab.setPreCleanSlabMinLen(pmPdCcSlab.getPreCleanSlabMinLen());
        pmCmdSlab.setPreCleanSlabWt(pmPdCcSlab.getPreCleanSlabWt());
        pmCmdSlab.setPreCleanSlabMaxWt(pmPdCcSlab.getPreCleanSlabMaxWt());
        pmCmdSlab.setPreCleanSlabMinWt(pmPdCcSlab.getPreCleanSlabMinWt());
        pmCmdSlab.setMoldThick(pmPdCcSlab.getMoldThick());
        pmCmdSlab.setMoldWid(pmPdCcSlab.getMoldWid());
        pmCmdSlab.setInfurSlabThick(pmPdCcSlab.getInfurSlabThick());
        pmCmdSlab.setInfurSlabWid(pmPdCcSlab.getInfurSlabWid());
        pmCmdSlab.setInfurSlabLen(pmPdCcSlab.getInfurSlabLen());
        pmCmdSlab.setInfurSlabMaxLen(pmPdCcSlab.getInfurSlabMaxLen());
        pmCmdSlab.setInfurSlabMinLen(pmPdCcSlab.getInfurSlabMinLen());
        pmCmdSlab.setInfurSlabWt(pmPdCcSlab.getInfurSlabWt());
        pmCmdSlab.setInfurSlabMaxWt(pmPdCcSlab.getInfurSlabMaxWt());
        pmCmdSlab.setInfurSlabMinWt(pmPdCcSlab.getInfurSlabMinWt());
        pmCmdSlab.setNeedSlabLen(pmPdCcSlab.getNeedSlabLen());
        pmCmdSlab.setNeedSlabWt(pmPdCcSlab.getNeedSlabWt());
        pmCmdSlab.setFixSlabLenFlag(pmPdCcSlab.getFixSlabLenFlag() == null ? null : pmPdCcSlab.getFixSlabLenFlag().toString());
        pmCmdSlab.setFixSlabLen(pmPdCcSlab.getFixSlabLen());
        pmCmdSlab.setSlabPlaceCode(pmPdCcSlab.getSlabPlaceCode());
        pmCmdSlab.setHpFlameCleanDiv(pmPdCcSlab.getHpFlameCleanDiv());
        pmCmdSlab.setSlabFinishCode(pmPdCcSlab.getSlabFinishCode());
        pmCmdSlab.setSlabCleanWtLossRateSt(pmPdCcSlab.getSlabCleanWtLossRateSt());
        pmCmdSlab.setSlabCleanWtLossRateFr(pmPdCcSlab.getSlabCleanWtLossRateFr());
        pmCmdSlab.setCoolCode(pmPdCcSlab.getCoolCode());
        pmCmdSlab.setFurType(pmPdCcSlab.getFurType());
        pmCmdSlab.setFormPlateTime(pmPdCcSlab.getCreationDate());
        pmCmdSlab.setShpCode(pmPdCcSlab.getShpCode());
    }

    @Override
    public List<PmSlabPoolInResDTO> noCommitFurnace(Long tenantId, PmSlabPoolInNoReqDTO dto) {
        List<PmSlabPoolIn> pmSlabPoolInList = pmSlabPoolInRepository.selectByCondition(Condition.builder(PmSlabPoolIn.class)
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_SLAB_POOL_IN_ID, dto.getId()))
                .andWhere(Sqls.custom().andEqualTo(PmSlabPoolIn.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmSlabPoolInList)) {
           throw new CommonException("pm.slab_pool_in_007", dto.getId());
        }
        PmSlabPoolIn pmSlabPoolIn = pmSlabPoolInList.get(0);

        // 非钢锭组炉校验无委坯长度
        if (!Constants.CcType.TYPE_5.equals(pmSlabPoolIn.getCcType())) {
            // 无委校验长度
            List<PmWmWwBt> pmWmWwBtList = pmWmWwBtRepository.selectByCondition(Condition.builder(PmWmWwBt.class)
                    .andWhere(Sqls.custom().andEqualTo(PmWmWwBt.FIELD_MSC_LINE_NO, pmSlabPoolIn.getMscLineNo()))
                    .andWhere(Sqls.custom().andEqualTo(PmWmWwBt.FIELD_CC_TYPE, pmSlabPoolIn.getCcType()))
                    .andWhere(Sqls.custom().andEqualTo(PmWmWwBt.FIELD_TENANT_ID, tenantId))
                    .andWhere(Sqls.custom().andLessThanOrEqualTo(PmWmWwBt.FIELD_SLAB_WIDTH_FROM, pmSlabPoolIn.getNomSlabWidth()))
                    .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmWmWwBt.FIELD_SLAB_WIDTH_TO, pmSlabPoolIn.getNomSlabWidth()))
                    .andWhere(Sqls.custom().andLessThanOrEqualTo(PmWmWwBt.FIELD_SLAB_THICK_FROM, pmSlabPoolIn.getNomSlabThick()))
                    .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmWmWwBt.FIELD_SLAB_THICK_TO, pmSlabPoolIn.getNomSlabThick()))
                    .build());
            if (CollectionUtils.isEmpty(pmWmWwBtList)) {
                throw new CommonException("pm.wm_ww_bt_007", pmSlabPoolIn.getMscLineNo(),pmSlabPoolIn.getCcType(),
                        pmSlabPoolIn.getNomSlabThick(),pmSlabPoolIn.getNomSlabWidth());
            }
            if (pmWmWwBtList.get(0).getFillSlabLenMin() == null || pmWmWwBtList.get(0).getFillSlabLenMax() == null) {
                throw new CommonException("pm.wm_ww_bt_011", pmSlabPoolIn.getMscLineNo(),pmSlabPoolIn.getCcType(),
                        pmSlabPoolIn.getNomSlabThick(),pmSlabPoolIn.getNomSlabWidth());
            }
            // 2.	验证无委坯长度（WW_LEN），若用户输入的无委坯长度不在无委充当板坯长度上下限之内
            if (dto.getSlabLen().compareTo(pmWmWwBtList.get(0).getFillSlabLenMin()) < 0
                    || dto.getSlabLen().compareTo(pmWmWwBtList.get(0).getFillSlabLenMax()) > 0) {
                throw new CommonException("pm.wm_ww_bt_008", dto.getSlabLen(), pmWmWwBtList.get(0).getFillSlabLenMin(),
                        pmWmWwBtList.get(0).getFillSlabLenMax());
            }
        }
        List<PmSlabPoolInResDTO> resultList = new ArrayList<>();
        // 编码规则生成无委坯虚拟板坯号
        List<String> virtualSlabNoList = codeRuleBuilder.batchGenerateCode(dto.getNum().intValue(), tenantId, Constants.CodeRule.W_VIRTUAL_SLAB_NO,
                CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, null);
        for (int i = 0; i < dto.getNum(); i++) {
            PmSlabPoolInResDTO pmSlabPoolInResDTO = new PmSlabPoolInResDTO();
            pmSlabPoolInResDTO.setMainBacklogCode(pmSlabPoolIn.getMainBacklogCode());
            pmSlabPoolInResDTO.setWholeBacklogCode(pmSlabPoolIn.getWholeBacklogCode());
            if ("20".equals(pmSlabPoolIn.getSlabDest())) {
                pmSlabPoolInResDTO.setAppType("4");
            } else {
                Long type = Long.parseLong(pmSlabPoolIn.getOrderHotChargeFlag()) + 1;
                pmSlabPoolInResDTO.setAppType(type.toString());
            }
            pmSlabPoolInResDTO.setSteelAppDate(pmSlabPoolIn.getSteelPlanDate());
            pmSlabPoolInResDTO.setMoldWid(pmSlabPoolIn.getNomSlabWidth());
            pmSlabPoolInResDTO.setMoldThick(pmSlabPoolIn.getNomSlabThick());
            if (Constants.MainBacklogCode.CODE_A.equals(pmSlabPoolIn.getMainBacklogCode())) {
                pmSlabPoolInResDTO.setBilletType(Constants.BilletType.TYPE_1);
            } else if (Constants.MainBacklogCode.CODE_C.equals(pmSlabPoolIn.getMainBacklogCode())) {
                pmSlabPoolInResDTO.setBilletType(Constants.BilletType.TYPE_5);
            }
            pmSlabPoolInResDTO.setCcType(pmSlabPoolIn.getCcType());
            pmSlabPoolInResDTO.setNomSlabThick(pmSlabPoolIn.getNomSlabThick());
            pmSlabPoolInResDTO.setNomSlabWidth(pmSlabPoolIn.getNomSlabWidth());
            pmSlabPoolInResDTO.setNomStNo(pmSlabPoolIn.getStNo());
            pmSlabPoolInResDTO.setVirtualSlabNo(Strings.concat("W", virtualSlabNoList.get(i)));
            pmSlabPoolInResDTO.setNomSlabLen((dto.getSlabLen() == null || dto.getSlabLen().compareTo(BigDecimal.ZERO) == 0) ?
                    pmSlabPoolIn.getNomSlabLen() : dto.getSlabLen());
            pmSlabPoolInResDTO.setNomSlabWt(dto.getSlabWt());
            pmSlabPoolInResDTO.setOrderNo(null);
            pmSlabPoolInResDTO.setIsChargFurnace(BaseConstants.FlagChar.YES);
            pmSlabPoolInResDTO.setDescription(dto.getDescription());
            resultList.add(pmSlabPoolInResDTO);
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void furnaceComplete(Long tenantId, PmSlabPoolInDTO dto) {
        Long userId = DetailsHelper.getUserDetails().getUserId();
        Date now = new Date();
        // 1.	根据组炉责任者（USER_ID）查询【组炉编制表（PM_SLAB_ESTA_PLAN）】中连铸预定计划状态值为“02”,创建时间为当天的，最新一浇信息，获取预定CAST_LOT号
        List<PmSlabEstaPlan> pmSlabEstaPlanList = pmSlabEstaPlanRepository.selectByCondition(Condition.builder(PmSlabEstaPlan.class)
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_CS_PREC_PLAN_STATUS, Constants.CsPrecPlanStatus.STATUS_02))
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_USER_ID, userId))
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_MAIN_BACKLOG_CODE, dto.getMainBacklogCode()))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmSlabEstaPlan.FIELD_CREATION_DATE, DateUtils.firstDate(now)))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmSlabEstaPlan.FIELD_CREATION_DATE, DateUtils.lastedDate(now)))
                .orderByDesc(PmSlabEstaPlan.FIELD_CREATION_DATE)
                .build());
        Map<Long, MtUserInfo> mtUserInfoMap = userClient.userInfoBatchGet(tenantId, Collections.singletonList(userId));
        if (CollectionUtils.isEmpty(pmSlabEstaPlanList)) {
            String loginName = "";
            if (mtUserInfoMap.containsKey(userId)) {
                loginName = mtUserInfoMap.get(userId).getLoginName();
            }
            throw new CommonException("pm.slab_esta_plan_003", loginName);
        }
        // 获取最新的那一浇次的数据
        String precCastLotNo = pmSlabEstaPlanList.get(0).getPrecCastLotNo();
        List<PmSlabEstaPlan> lastSlabEstaPlanList = pmSlabEstaPlanList.stream().filter(item ->
                precCastLotNo.equals(item.getPrecCastLotNo())).collect(Collectors.toList());
        // 执行组炉完成操作
        self().excuteSecondaryDesign(lastSlabEstaPlanList, tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void excuteSecondaryDesign(List<PmSlabEstaPlan> pmSlabEstaPlanList, Long tenantId) {
        List<String> tmpSlabNoList = new ArrayList<>();

        // 过滤备坯，外卖坯，无委坯
        List<PmSlabEstaPlan> slabEstaPlanList = pmSlabEstaPlanList.stream().filter(item -> Constants.CcType.TYPE_1.equals(item.getCcType()) ||
                Constants.CcType.TYPE_5.equals(item.getCcType())).filter(item -> StringUtils.isNotEmpty(item.getOrderNo())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(slabEstaPlanList)) {
            throw new CommonException("pm.slab_esta_plan_017");
        }

        tmpSlabNoList.addAll(slabEstaPlanList.stream().map(PmSlabEstaPlan::getTmpSlabNo).collect(Collectors.toList()));
        // 获取合并板坯的虚拟板坯信息
        List<PmSlabMerge> pmSlabMergeList = new ArrayList<>();
        List<String> mergeSlabNoList = slabEstaPlanList.stream().filter(item -> Utils.isMergeSlab(item.getVirtualSlabNo()))
                .map(PmSlabEstaPlan::getVirtualSlabNo).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(mergeSlabNoList)) {
            pmSlabMergeList = pmSlabMergeRepository.selectByMergeSlabNoList(mergeSlabNoList, tenantId);
            if (CollectionUtils.isNotEmpty(pmSlabMergeList)) {
                tmpSlabNoList.addAll(pmSlabMergeList.stream().map(PmSlabMerge::getTmpSlabNo).collect(Collectors.toList()));
                tmpSlabNoList.addAll(pmSlabMergeList.stream().map(PmSlabMerge::getTmpPonoSlabNo).collect(Collectors.toList()));
            }
        }

        // 查询命令大板表
        List<PmCmdLargePlt> pmCmdLargePltList = pmCmdLargePltRepository.selectByTmpSlabNoList(tmpSlabNoList, tenantId);
        if (CollectionUtils.isEmpty(pmCmdLargePltList)) {
            throw new CommonException("pm.cmd_large_plt_001", tmpSlabNoList);
        }

        // 按照炉号分组 调用试样添加
        Map<String, List<PmSlabEstaPlan>> estaPlanMap = slabEstaPlanList.stream().collect(Collectors.groupingBy(PmSlabEstaPlan::getPrecPono));
        for (Map.Entry<String, List<PmSlabEstaPlan>> entry : estaPlanMap.entrySet()) {
            List<String> ponoTmpSlabNoList = entry.getValue().stream().map(PmSlabEstaPlan::getTmpSlabNo).collect(Collectors.toList());
            // 合并的临时命令板坯号
            List<String> merVirtualSlabNoList = entry.getValue().stream().filter(item -> Utils.isMergeSlab(item.getVirtualSlabNo()))
                    .map(PmSlabEstaPlan::getVirtualSlabNo).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(merVirtualSlabNoList)) {
                ponoTmpSlabNoList.addAll(pmSlabMergeList.stream().filter(item->merVirtualSlabNoList.contains(item.getMergeSlabNo()))
                        .map(PmSlabMerge::getTmpSlabNo).collect(Collectors.toList()));
                ponoTmpSlabNoList.addAll(pmSlabMergeList.stream().filter(item->merVirtualSlabNoList.contains(item.getMergeSlabNo()))
                        .map(PmSlabMerge::getTmpPonoSlabNo).collect(Collectors.toList()));
            }
            List<PmCmdLargePlt> cmdPltLargePltList = pmCmdLargePltList.stream().filter(item -> ponoTmpSlabNoList.contains(item.getTmpSlabNo())).collect(Collectors.toList());

            String ccType = entry.getValue().get(0).getCcType();
            if ( Constants.CcType.TYPE_1.equals(ccType)) {
                // 出钢材-调用试样添加方法
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.C).sampleAddition(tenantId, cmdPltLargePltList);
            }
        }

        // 根据连铸机类型分组进行二次设计，命令做成
        Map<String, List<PmSlabEstaPlan>> ccTypeEstaMap = slabEstaPlanList.stream().collect(Collectors.groupingBy(PmSlabEstaPlan::getCcType));
        for (Map.Entry<String, List<PmSlabEstaPlan>> entry : ccTypeEstaMap.entrySet()) {
            List<String> ponoTmpSlabNoList = entry.getValue().stream().map(PmSlabEstaPlan::getTmpSlabNo).collect(Collectors.toList());
            // 合并的临时命令板坯号
            List<String> merVirtualSlabNoList = entry.getValue().stream().filter(item -> Utils.isMergeSlab(item.getVirtualSlabNo()))
                    .map(PmSlabEstaPlan::getVirtualSlabNo).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(merVirtualSlabNoList)) {
                ponoTmpSlabNoList.addAll(pmSlabMergeList.stream().filter(item->merVirtualSlabNoList.contains(item.getMergeSlabNo()))
                        .map(PmSlabMerge::getTmpSlabNo).collect(Collectors.toList()));
                ponoTmpSlabNoList.addAll(pmSlabMergeList.stream().filter(item->merVirtualSlabNoList.contains(item.getMergeSlabNo()))
                        .map(PmSlabMerge::getTmpPonoSlabNo).collect(Collectors.toList()));
            }
            List<PmCmdLargePlt> cmdPltLargePltList = pmCmdLargePltList.stream().filter(item -> ponoTmpSlabNoList.contains(item.getTmpSlabNo())).collect(Collectors.toList());
            if ( Constants.CcType.TYPE_1.equals(entry.getKey())) {
                // 二次设计
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.C).secondaryDesign(tenantId, cmdPltLargePltList);
                // 命令做成
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.C).commandCreate(tenantId, cmdPltLargePltList);
            } else if (Constants.CcType.TYPE_5.equals(entry.getKey())) {
                // 命令做成
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.A).commandCreate(tenantId, cmdPltLargePltList);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void commandCommit(Long tenantId) {
        // 执行组炉完成之后进行命令确认，命令提交
        Long userId = DetailsHelper.getUserDetails().getUserId();
        Date now = new Date();
        // 1.	根据组炉责任者（USER_ID）查询【组炉编制表（PM_SLAB_ESTA_PLAN）】中连铸预定计划状态值为“03”，时间为当天的信息，获取预定CAST_LOT号
        List<PmSlabEstaPlan> pmSlabEstaPlanList = pmSlabEstaPlanRepository.selectByCondition(Condition.builder(PmSlabEstaPlan.class)
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_TENANT_ID, tenantId))
//                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_CS_PREC_PLAN_STATUS, Constants.CsPrecPlanStatus.STATUS_03))
                .andWhere(Sqls.custom().andEqualTo(PmSlabEstaPlan.FIELD_USER_ID, userId))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmSlabEstaPlan.FIELD_CREATION_DATE, DateUtils.firstDate(now)))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmSlabEstaPlan.FIELD_CREATION_DATE, DateUtils.lastedDate(now)))
                .orderByDesc(PmSlabEstaPlan.FIELD_LAST_UPDATE_DATE)
                .build());
        if (CollectionUtils.isEmpty(pmSlabEstaPlanList)) {
            throw new CommonException("pm.slab_esta_plan_012", userId);
        }

        // 板坯，钢锭先组炉完成，状态变03; 外卖坯，备坯不需要组炉完成，状态02
        List<PmSlabEstaPlan> filterPmSlabEstaPlanList = pmSlabEstaPlanList.stream().filter(item ->
                ((Constants.CcType.TYPE_1.equals(item.getCcType()) || Constants.CcType.TYPE_5.equals(item.getCcType())) &&
                        Constants.CsPrecPlanStatus.STATUS_03.equals(item.getCsPrecPlanStatus())) ||
                        ((Constants.CcType.TYPE_2.equals(item.getCcType()) || Constants.CcType.TYPE_4.equals(item.getCcType())) &&
                                Constants.CsPrecPlanStatus.STATUS_02.equals(item.getCsPrecPlanStatus()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(filterPmSlabEstaPlanList)) {
            throw new CommonException("pm.slab_esta_plan_012", userId);
        }
        // 获取最新的那一浇次的数据
        String precCastLotNo = filterPmSlabEstaPlanList.get(0).getPrecCastLotNo();
//        List<String> precCastLotNoList = filterPmSlabEstaPlanList.stream().map(PmSlabEstaPlan::getPrecCastLotNo).distinct().collect(Collectors.toList());

        // 执行命令提交操作
        pmSlabEstaPlanService.commit(Arrays.asList(precCastLotNo), tenantId);

    }

    /**
     * 获取小板分割号
     * @param trimCode
     * @param index
     * @return
     */
    public String getSmallPlateDivNo(String trimCode , int index) {
        if ("0".equals(trimCode)) {
            return PmPlateConstants.SMALL_PLATE_SPLIT_NO[0];
        } else {
            return PmPlateConstants.SMALL_PLATE_SPLIT_NO[index];
        }
    }
}

