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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xisc.pm.api.dto.BoardContractItemDTO;
import com.xisc.pm.api.dto.BoardLayoutItemDTO;
import com.xisc.pm.api.dto.ObtainWitnessPointDTO;
import com.xisc.pm.api.dto.PmCompositeSlabCalcDTO;
import com.xisc.pm.api.dto.PmPdCcSlabLengthDTO;
import com.xisc.pm.api.dto.PmPdCcSlabLineDTO;
import com.xisc.pm.api.dto.PmPdCcSlabOrderDTO;
import com.xisc.pm.api.dto.PmPdCcSlabReqDetailDTO;
import com.xisc.pm.api.dto.PmPdCcSlabReqParamDTO;
import com.xisc.pm.api.dto.PmPdCcSlabResDTO;
import com.xisc.pm.api.dto.PmPdCcSlabResDetailDTO;
import com.xisc.pm.api.dto.PmPdCcSlabThickDTO;
import com.xisc.pm.api.dto.PmPdCcSlabWidthDTO;
import com.xisc.pm.api.dto.PmPdMidSplitRequestDTO;
import com.xisc.pm.api.dto.PmPdRecDTO;
import com.xisc.pm.api.dto.PmProContFilterRequestDTO;
import com.xisc.pm.api.dto.PmProContFilterResposeDTO;
import com.xisc.pm.api.dto.PmProContYieldCopyRequestDTO;
import com.xisc.pm.api.dto.PmProContYieldDTO;
import com.xisc.pm.api.dto.PmProContYieldRequestDTO;
import com.xisc.pm.api.dto.PmProContYieldResposeDTO;
import com.xisc.pm.api.dto.ctevent.ProContBoardEndDTO;
import com.xisc.pm.api.dto.ctevent.ProContConsumeDTO;
import com.xisc.pm.app.service.PmPdCcSlabService;
import com.xisc.pm.app.service.PmPdRecService;
import com.xisc.pm.app.service.PmPdSlabService;
import com.xisc.pm.app.service.strategy.PdMatTypeStrategyFactory;
import com.xisc.pm.app.service.strategy.pdmattype.PdMatTypeStrategy;
import com.xisc.pm.domain.entity.PmContMscTech;
import com.xisc.pm.domain.entity.PmPdBlockPos;
import com.xisc.pm.domain.entity.PmPdCcSlab;
import com.xisc.pm.domain.entity.PmPdContSum;
import com.xisc.pm.domain.entity.PmPdPlateCut;
import com.xisc.pm.domain.entity.PmPdSlab;
import com.xisc.pm.domain.entity.PmProCont;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSlabLenConfig;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.repository.PmContMscTechRepository;
import com.xisc.pm.domain.repository.PmCtMainRepository;
import com.xisc.pm.domain.repository.PmPdBlockPosRepository;
import com.xisc.pm.domain.repository.PmPdCcSlabRepository;
import com.xisc.pm.domain.repository.PmPdContSumRepository;
import com.xisc.pm.domain.repository.PmPdPlateCutRepository;
import com.xisc.pm.domain.repository.PmPdPlateInfoRepository;
import com.xisc.pm.domain.repository.PmPdSlabInfoRepository;
import com.xisc.pm.domain.repository.PmPdSlabRepository;
import com.xisc.pm.domain.repository.PmProContProdTtrRepository;
import com.xisc.pm.domain.repository.PmProContRepository;
import com.xisc.pm.domain.repository.PmQdToPoOrderRepository;
import com.xisc.pm.domain.repository.PmSlabLenConfigRepository;
import com.xisc.pm.domain.repository.PmSmallPltPosRepository;
import com.xisc.pm.domain.vo.CtMainVO;
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.Constants.AutoManualFlag;
import com.xisc.pm.infra.constant.Constants.PdStatusHp;
import com.xisc.pm.infra.constant.CtEventConstants;
import com.xisc.pm.infra.enums.PdEventType;
import com.xisc.pm.infra.enums.PdMatType;
import com.xisc.pm.infra.enums.PdProdFlag;
import com.xisc.pm.infra.mapper.PmSlabPoolInMapper;
import com.xisc.pm.infra.util.BeanUtils;
import io.choerodon.core.domain.Page;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
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.boot.platform.lov.adapter.LovAdapter;
import org.hzero.boot.platform.lov.dto.LovValueDTO;
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.time.ZoneId;
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.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 组板连铸板坯表(PmPdCcSlab)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-31 16:36:58
 */
@Service
public class PmPdCcSlabServiceImpl implements PmPdCcSlabService {

    private PmPdCcSlabRepository pmPdCcSlabRepository;

    private PmContMscTechRepository pmContMscTechRepository;

    private PmSlabLenConfigRepository pmSlabLenConfigRepository;

    private PmProContProdTtrRepository pmProContProdTtrRepository;

    private PmPdContSumRepository pmPdContSumRepository;

    private LovAdapter lovAdapter;

    private PmPdSlabInfoRepository pmPdSlabInfoRepository;

    private PmPdPlateInfoRepository pmPdPlateInfoRepository;
    
    @Autowired
    private PmPdPlateCutRepository pmPdPlateCutRepository;

    @Autowired
    private PmSmallPltPosRepository pmSmallPltPosRepository;
    
    @Autowired
    private PmPdBlockPosRepository pmPdBlockPosRepository;
    
    @Autowired
    private PmPdSlabRepository pmPdSlabRepository;
    
    @Autowired
    private CodeRuleBuilder codeRuleBuilder;
    
    @Autowired
    private PmProContRepository pmProContRepository;
    
    @Autowired
    private PmPdRecService pmPdRecService;
    
    @Autowired
    private PmSlabPoolInMapper pmSlabPoolInMapper;

    @Autowired
    private PmPdSlabService pmPdSlabService;
    
    @Autowired
    private PmCtMainRepository pmCtMainRepository;
    
    @Autowired
    private EventClient eventClient;

    @Autowired
    private PmQdToPoOrderRepository pmQdToPoOrderRepository;


    @Autowired
    private QdOrderClient qdOrderClient;

    public PmPdCcSlabServiceImpl(PmPdCcSlabRepository pmPdCcSlabRepository,
                                 PmContMscTechRepository pmContMscTechRepository, PmSlabLenConfigRepository pmSlabLenConfigRepository,
                                 PmProContProdTtrRepository pmProContProdTtrRepository, PmPdContSumRepository pmPdContSumRepository,
                                 LovAdapter lovAdapter, PmPdSlabInfoRepository pmPdSlabInfoRepository, PmPdPlateInfoRepository pmPdPlateInfoRepository) {
        this.pmPdCcSlabRepository = pmPdCcSlabRepository;
        this.pmContMscTechRepository = pmContMscTechRepository;
        this.pmSlabLenConfigRepository = pmSlabLenConfigRepository;
        this.pmProContProdTtrRepository = pmProContProdTtrRepository;
        this.pmPdContSumRepository = pmPdContSumRepository;
        this.lovAdapter = lovAdapter;
        this.pmPdSlabInfoRepository = pmPdSlabInfoRepository;
        this.pmPdPlateInfoRepository = pmPdPlateInfoRepository;
    }

    @Override
    public PmPdCcSlabResDTO selectList(PmPdCcSlabReqParamDTO dto, Long tenantId) {
        // 根据条件查询
        Condition.Builder builder = Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_STEEL_LATEST_DATE, dto.getSteelLatestDateFrom(), true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_STEEL_LATEST_DATE, dto.getSteelLatestDateTo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_HOT_CHARGE_FLAG, dto.getHotChargeFlag(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_ST_NO, dto.getStNo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_THICK, dto.getPreCleanSlabThick(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_AXIS_ORDER_THICK, dto.getOrderThickFrom(),true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_AXIS_ORDER_THICK, dto.getOrderThickTo(),true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_CC_TYPE, dto.getCcType(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PD_STATUS_HP, Constants.PdStatusHp.PD_STATUS_HP_12))
                .andWhere(Sqls.custom().andLikeRight(PmPdCcSlab.FIELD_MSC_LINE_NO, dto.getMscLineNo(), true));
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByCondition(builder.build());
        // 如果为空则返回
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            return null;
        }

        // 按照长度
        List<PmSlabLenConfig> pmSlabLenConfigs = new ArrayList<>();
        // 如果为Y,说明勾选了长度，获取板坯长度配置表
        if (dto.getIsLength().equals(BaseConstants.FlagChar.YES)) {
            pmSlabLenConfigs = pmSlabLenConfigRepository.selectByCondition(Condition.builder(PmSlabLenConfig.class)
                    .andWhere(Sqls.custom().andEqualTo(PmSlabLenConfig.FIELD_TENANT_ID, tenantId))
                    .andWhere(Sqls.custom().andEqualTo(PmSlabLenConfig.FIELD_VALID_FLAG, Constants.ValidFlag.ONE))
                    .orderBy(PmSlabLenConfig.FIELD_SLAB_MIN_LEN).build());
        }

        // 定义返回DTO
        PmPdCcSlabResDTO resDTO = new PmPdCcSlabResDTO();
        // 赋值是否勾选长度标识
        resDTO.setIsLength(dto.getIsLength());
        // 获取钢种数据集合
        Optional<PmPdCcSlab> first = pmPdCcSlabList.stream().filter(item -> StringUtils.isEmpty(item.getStNo()) || StringUtils.isBlank(item.getStNo())).findFirst();
        if (first.isPresent()) {
            throw new CommonException("pm.pd_cc_slab_007", first.get().getVirtualSlabNo());
        }

        List<String> stNoList = pmPdCcSlabList.stream().sorted(Comparator.comparing(PmPdCcSlab::getStNo))
                .map(PmPdCcSlab::getStNo).distinct().collect(Collectors.toList());
        resDTO.setStNoList(stNoList);

        List<PmPdCcSlabThickDTO> slabThickList = new ArrayList<>();
        // 按照厚度和宽度分组
        Map<BigDecimal, Map<BigDecimal, List<PmPdCcSlab>>> groupMap = pmPdCcSlabList.stream().collect(Collectors
                .groupingBy(PmPdCcSlab::getPreCleanSlabThick, Collectors.groupingBy(PmPdCcSlab::getPreCleanSlabWidth)));
        for (Map.Entry<BigDecimal, Map<BigDecimal, List<PmPdCcSlab>>> entry : groupMap.entrySet()) {

            PmPdCcSlabThickDTO slabThickDTO = new PmPdCcSlabThickDTO();
            slabThickList.add(slabThickDTO);
            // 设置板厚值
            slabThickDTO.setSlabThick(entry.getKey());

            // 按照宽度
            List<PmPdCcSlabWidthDTO> slabWidthList = new ArrayList<>();
            for (Map.Entry<BigDecimal, List<PmPdCcSlab>> witdhEntry : entry.getValue().entrySet()) {
                List<PmPdCcSlab> slabWithList = witdhEntry.getValue();
                PmPdCcSlabWidthDTO slabWidthDTO = new PmPdCcSlabWidthDTO();
                // 设置板宽值
                slabWidthDTO.setSlabWidth(witdhEntry.getKey());
                // 将板宽DTO添加到列表中
                slabWidthList.add(slabWidthDTO);
                // 判断是否按照长度
                if (dto.getIsLength().equals(BaseConstants.FlagChar.YES)) {
                    // 按照长度
                    List<PmPdCcSlabLengthDTO> slabLengthList = new ArrayList<>();
                    Map<String, List<PmPdCcSlab>> stNoWtMap = slabWithList.stream()
                            .collect(Collectors.groupingBy(PmPdCcSlab::getStNo));
                    // 遍历配置的长度范围
                    for (PmSlabLenConfig pmSlabLenConfig : pmSlabLenConfigs) {
                        Map<String, BigDecimal> totalWtMap = new HashMap<>(16);
                        PmPdCcSlabLengthDTO pmPdCcSlabLengthDTO = new PmPdCcSlabLengthDTO();
                        // 设置长度范围
                        pmPdCcSlabLengthDTO.setSlabLengthFrom(pmSlabLenConfig.getSlabMinLen());
                        pmPdCcSlabLengthDTO.setSlabLengthTo(pmSlabLenConfig.getSlabMaxLen());
                        pmPdCcSlabLengthDTO.setSlabTotalWtMap(totalWtMap);
                        // 将长度DTO添加到列表
                        slabLengthList.add(pmPdCcSlabLengthDTO);
                        // 按照钢种分组
                        for (Map.Entry<String, List<PmPdCcSlab>> stNoEntry : stNoWtMap.entrySet()) {
                            List<PmPdCcSlab> slabOrderList = stNoEntry.getValue();
                            BigDecimal reduce = slabOrderList.stream().filter(slabOrder -> slabOrder
                                    .getPreCleanSlabLen().compareTo(pmSlabLenConfig.getSlabMinLen()) >= 0
                                    && slabOrder.getPreCleanSlabLen().compareTo(pmSlabLenConfig.getSlabMaxLen()) <= 0)
                                    .map(PmPdCcSlab::getPreCleanSlabWt).filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            totalWtMap.put(stNoEntry.getKey(), reduce);
                        }
                    }
                    // 设置长度列表到板宽DTO
                    slabWidthDTO.setSlabLengthList(slabLengthList);

                } else {
                    Map<String, BigDecimal> slabTotalWtMap = new HashMap<>(16);
                    // 按照钢种分组
                    Map<String, List<PmPdCcSlab>> stNoWtMap = slabWithList.stream()
                            .collect(Collectors.groupingBy(PmPdCcSlab::getStNo));
                    // 遍历钢种分组计算总重量
                    for (Map.Entry<String, List<PmPdCcSlab>> stNoEntry : stNoWtMap.entrySet()) {
                        String stNo = stNoEntry.getKey();
                        // 计算钢种的板坯总重量
                        BigDecimal slabTotalWt = stNoEntry.getValue().stream().map(PmPdCcSlab::getPreCleanSlabWt)
                                .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        // 将总重量存入Map
                        slabTotalWtMap.put(stNo, slabTotalWt);
                    }
                    // 设置总重量Map到板宽DTO
                    slabWidthDTO.setSlabTotalWtMap(slabTotalWtMap);
                }
            }
            // 按照宽度排序
            List<PmPdCcSlabWidthDTO> sortSlabWidthList = slabWidthList.stream()
                    .sorted(Comparator.comparing(PmPdCcSlabWidthDTO::getSlabWidth)).collect(Collectors.toList());
            slabThickDTO.setSlabWidthList(sortSlabWidthList);
        }
        // 按照长度排序
        List<PmPdCcSlabThickDTO> sortSlabThickList = slabThickList.stream()
                .sorted(Comparator.comparing(PmPdCcSlabThickDTO::getSlabThick)).collect(Collectors.toList());
        // 设置厚度列表到结果DTO
        resDTO.setThickList(sortSlabThickList);

        // 获取不同产线的板坯总重量
        Map<String, BigDecimal> mscLineWtMap = new HashMap<>(pmPdCcSlabList.size());
        // 遍历产线分组计算总重量
        Map<String, List<PmPdCcSlab>> mscLineMap = pmPdCcSlabList.stream()
                .collect(Collectors.groupingBy(PmPdCcSlab::getMscLineNo));
        for (Map.Entry<String, List<PmPdCcSlab>> entry : mscLineMap.entrySet()) {
            BigDecimal totalWt = entry.getValue().stream().map(PmPdCcSlab::getPreCleanSlabWt).filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 将总重量存入Map
            mscLineWtMap.put(entry.getKey(), totalWt);
        }
        // 设置产线总重量Map到结果DTO
        resDTO.setMscLineWtMap(mscLineWtMap);
        // 不同热处理模式的板坯总重量
        Map<String, BigDecimal> heatWtMap = new HashMap<>(16);
        // 获取所有合同号
        List<String> orderList = pmPdCcSlabList.stream().map(PmPdCcSlab::getOrderNoAxis).distinct().collect(Collectors.toList());
        List<String> mscLineList = pmPdCcSlabList.stream().map(PmPdCcSlab::getMscLineNo).distinct().collect(Collectors.toList());

        // 根据热处理条件查询数据
        List<PmContMscTech> pmContMscTeches =  pmContMscTechRepository.selectByOrderNoAndMscLineNo(orderList, mscLineList, tenantId);
        // 处理查询结果，计算总重量
        if (CollectionUtils.isNotEmpty(pmContMscTeches)) {
            // 热处理模式值集翻译
            List<LovValueDTO> treatMethodLovList = lovAdapter.queryLovValue(Constants.LovCode.HOT_TREAT_METHOD_CODE, tenantId);
            Map<String, String> treatMethodMap = new HashMap<>(treatMethodLovList.size());
            if (CollectionUtils.isNotEmpty(treatMethodLovList)) {
                treatMethodMap = treatMethodLovList.stream()
                        .collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
            }
            Map<String, String> contMscTechMap = pmContMscTeches.stream().collect(Collectors
                    .toMap(item -> item.getOrderNo() + item.getMscLineNo(), item -> Optional.ofNullable(item.getHeatTreatMode()).orElse(" "), (k,v)->k));
            for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
                String headMode = contMscTechMap.getOrDefault(pmPdCcSlab.getOrderNoAxis() + pmPdCcSlab.getMscLineNo(), "");
                if (StringUtils.isNotEmpty(headMode)) {
                    BigDecimal slabWt = pmPdCcSlab.getPreCleanSlabWt() == null ? BigDecimal.ZERO : pmPdCcSlab.getPreCleanSlabWt();
                    BigDecimal wtTotal = heatWtMap.getOrDefault(treatMethodMap.getOrDefault(headMode,headMode), BigDecimal.ZERO).add(slabWt);
                    heatWtMap.put(treatMethodMap.getOrDefault(headMode,headMode), wtTotal);
                }
            }
            // 设置热处理总重量Map到结果DTO
            resDTO.setHeatWtMap(heatWtMap);
        }

        // 取涂漆板坯的总重量
        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, orderList))
                        .andWhere(Sqls.custom().andEqualTo(PmProContProdTtr.FIELD_NEED_LECQUERING, "1")).build());
        // 处理查询结果，计算总重量
        if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
            List<String> trOrderList = pmProContProdTtrList.stream().map(PmProContProdTtr::getOrderNo)
                    .collect(Collectors.toList());
            BigDecimal reduce = pmPdCcSlabList.stream().filter(line -> trOrderList.contains(line.getOrderNoAxis()))
                    .map(PmPdCcSlab::getPreCleanSlabWt).filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 设置涂漆板坯总重量到结果DTO
            resDTO.setNeedLecqueringWt(reduce);
        }
        return resDTO;
    }

    @Override
    public List<PmPdCcSlabLineDTO> listSlabForui(PmPdCcSlabReqParamDTO dto, Long tenantId) {
        // 查询条件
        Condition.Builder builder = Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_STEEL_LATEST_DATE, dto.getSteelLatestDateFrom(), true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_STEEL_LATEST_DATE, dto.getSteelLatestDateTo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_HOT_CHARGE_FLAG, dto.getHotChargeFlag(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_ST_NO, dto.getStNo()))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_THICK, dto.getPreCleanSlabThick(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_AXIS_ORDER_THICK, dto.getOrderThickFrom(),true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_AXIS_ORDER_THICK, dto.getOrderThickTo(),true))
                .andWhere(Sqls.custom().andLikeRight(PmPdCcSlab.FIELD_MSC_LINE_NO, dto.getMscLineNo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_CC_TYPE, dto.getCcType(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PD_STATUS_HP, Constants.PdStatusHp.PD_STATUS_HP_12))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_THICK, dto.getSlabThick(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_WIDTH, dto.getSlabWidth(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_MIN_LEN, dto.getSlabLengthFrom(), true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_PRE_CLEAN_SLAB_MAX_LEN, dto.getSlabLengthTo(), true));
        // 执行查询
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByCondition(builder.build());
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            return Collections.emptyList();
        }
        // 查询合同属性表信息
        List<String> orderList = pmPdCcSlabList.stream().map(PmPdCcSlab::getOrderNoAxis).collect(Collectors.toList());
        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, orderList)).build());
        // 根据合同号转map
        Map<String, PmProContProdTtr> trOrderMap = new HashMap<>(pmProContProdTtrList.size());
        if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
            trOrderMap = pmProContProdTtrList.stream()
                    .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (v1, v2) -> v1));
        }
        // 组装参数
        List<PmPdCcSlabLineDTO> resultList = new ArrayList<>();
        for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
            // 从实体中提取信息并设置到DTO
            PmPdCcSlabLineDTO pmPdCcSlabLineDTO = new PmPdCcSlabLineDTO();
            pmPdCcSlabLineDTO.setVirtualSlabNo(pmPdCcSlab.getVirtualSlabNo());
            pmPdCcSlabLineDTO.setSteelLatestDate(pmPdCcSlab.getSteelLatestDate());
            pmPdCcSlabLineDTO.setPreCleanSlabWt(pmPdCcSlab.getPreCleanSlabWt());
            pmPdCcSlabLineDTO.setStNo(pmPdCcSlab.getStNo());
            pmPdCcSlabLineDTO.setPreCleanSlabThick(pmPdCcSlab.getPreCleanSlabThick());
            pmPdCcSlabLineDTO.setPreCleanSlabWidth(pmPdCcSlab.getPreCleanSlabWidth());
            pmPdCcSlabLineDTO.setPreCleanSlabLen(pmPdCcSlab.getPreCleanSlabLen());
            pmPdCcSlabLineDTO.setSteelPlanDate(pmPdCcSlab.getSteelPlanDate());
            pmPdCcSlabLineDTO.setUrgOrderFlag(pmPdCcSlab.getUrgOrderFlag());
            pmPdCcSlabLineDTO.setPdStatusHp(pmPdCcSlab.getPdStatusHp());
            pmPdCcSlabLineDTO.setRollAimThick(pmPdCcSlab.getRollAimThick());
            pmPdCcSlabLineDTO.setRollAimWidth(pmPdCcSlab.getRollAimWidth());
            pmPdCcSlabLineDTO.setOrderNo(pmPdCcSlab.getOrderNoAxis());
            pmPdCcSlabLineDTO.setCreationDate(pmPdCcSlab.getCreationDate());
            if (!trOrderMap.isEmpty() && trOrderMap.containsKey(pmPdCcSlab.getOrderNoAxis())) {
                pmPdCcSlabLineDTO.setDelivyDate(trOrderMap.get(pmPdCcSlab.getOrderNoAxis()).getDelivyDate());
                pmPdCcSlabLineDTO
                        .setConsignCustCname(trOrderMap.get(pmPdCcSlab.getOrderNoAxis()).getConsignCustCname());
            }
            resultList.add(pmPdCcSlabLineDTO);
        }
        return resultList;
    }

    @Override
    public List<PmPdCcSlabOrderDTO> listOrderForui(String slabNo, Long tenantId) {
        // 根据钢板编号和租户ID查询汇总信息
        List<PmPdContSum> pmPdContSumList = pmPdContSumRepository.selectByCondition(Condition.builder(PmPdContSum.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_PD_MAT_NO, slabNo)).build());
        // 如果没有找到汇总信息，直接返回空列表
        if (CollectionUtils.isEmpty(pmPdContSumList)) {
            return Collections.emptyList();
        }
        // 从汇总信息中提取订单号列表，并去除重复值
        List<String> orderList = pmPdContSumList.stream().map(PmPdContSum::getOrderNo).distinct()
                .collect(Collectors.toList());
        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, orderList)).build());
        // 创建一个列表来存储最终的订单DTO
        List<PmPdCcSlabOrderDTO> resultList = new ArrayList<>();
        // 组装数据
        for (PmProContProdTtr pmProContProdTtr : pmProContProdTtrList) {
            PmPdCcSlabOrderDTO pmPdCcSlabOrderDTO = new PmPdCcSlabOrderDTO();
            pmPdCcSlabOrderDTO.setOrderNo(pmProContProdTtr.getOrderNo());
            pmPdCcSlabOrderDTO.setOrderNoErp(pmProContProdTtr.getOrderNoErp());
            pmPdCcSlabOrderDTO.setConsignCustCname(pmProContProdTtr.getConsignCustCname());
            pmPdCcSlabOrderDTO.setOrderThick(pmProContProdTtr.getOrderThick());
            pmPdCcSlabOrderDTO.setOrderWidth(pmProContProdTtr.getOrderWidth());
            pmPdCcSlabOrderDTO.setDelivyDate(pmProContProdTtr.getDelivyDate());
            pmPdCcSlabOrderDTO.setFinCustCode(pmProContProdTtr.getFinCustCode());
            pmPdCcSlabOrderDTO.setSgCode(pmProContProdTtr.getSgCode());
            pmPdCcSlabOrderDTO.setDelivyPlaceName(pmProContProdTtr.getDelivyPlaceName());
            pmPdCcSlabOrderDTO.setHullSectionNo(pmProContProdTtr.getHullSectionNo());
            pmPdCcSlabOrderDTO.setSectionManage(pmProContProdTtr.getSectionManage());
            pmPdCcSlabOrderDTO.setNeedLecquering(pmProContProdTtr.getNeedLecquering());
            pmPdCcSlabOrderDTO.setGiveSampleCode(pmProContProdTtr.getGiveSampleCode());
            pmPdCcSlabOrderDTO.setSampleLenGive(pmProContProdTtr.getSampleLenGive());
            resultList.add(pmPdCcSlabOrderDTO);
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PmPdCcSlab createPmPdCcSlab(PmProContYieldRequestDTO pmProContYield,
            Map<String, PmProContFilterResposeDTO> filterOrderMap, PmCompositeSlabCalcDTO pmCompositeSlabCalc,
            PmProContYieldResposeDTO pmProContYieldRespose, PmContMscTech axisPmContMscTech, PmProContProdTtr axisPmProContProdTtr) {
        // 生产虚拟板坯表
        PmPdCcSlab pmPdCcSlab = buildPmPdCcSlab(pmProContYield, axisPmContMscTech, axisPmProContProdTtr,
                filterOrderMap);
        buildPmPdCcSlab(pmPdCcSlab, pmProContYield, pmProContYieldRespose, pmCompositeSlabCalc);

        // 调用质量见证点状态接口，获取见证点
        List<ObtainWitnessPointDTO> witnessPointList = pmQdToPoOrderRepository.selectWitnessOrderPass(Arrays.asList(pmPdCcSlab.getOrderNoAxis()), Arrays.asList(Constants.WITNESS_POINT),
                pmProContYield.getTenantId());
        pmPdCcSlab.setWitnessPointStatus(CollectionUtils.isNotEmpty(witnessPointList) ? witnessPointList.get(0).getWitnessPointStatus() : null);
        this.pmPdCcSlabRepository.insertSelective(pmPdCcSlab);
        return pmPdCcSlab;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyPmPdCcSlab(PmProContYieldCopyRequestDTO pmProContYieldCopy) {
        
        List<PmPdContSum> pmPdContSumHiss = this.pmPdContSumRepository.selectByPdMatNo(pmProContYieldCopy.getTenantId() , pmProContYieldCopy.getVirtualSlabNo());
        // 检验合同欠件数
        Map<String , Long> sumNeedQty = new HashMap<>(pmPdContSumHiss.size());
        for (PmPdContSum pmPdContSum : pmPdContSumHiss) {
            if(!Constants.PdStatusHp.PD_STATUS_HP_12.equals(pmPdContSum.getPdStatus())) {
                throw new CommonException("pm.pm_pro_cont_051", pmProContYieldCopy.getVirtualSlabNo() , pmPdContSum.getPdStatus());
            }
                   }
        List<PmProCont> pmProConts = this.pmProContRepository.queryByOrderNoList(Lists.newArrayList(sumNeedQty.keySet()), pmProContYieldCopy.getTenantId());
        PmProContFilterRequestDTO pmProContFilterRequest = new PmProContFilterRequestDTO();
        pmProContFilterRequest.setTenantId(pmProContYieldCopy.getTenantId());
        pmProContFilterRequest.setOrderNoList(Lists.newArrayList(sumNeedQty.keySet()));
        List<CtMainVO> ctMainVOs = this.pmCtMainRepository.selectCanPdByOrderStatus(pmProContFilterRequest);
        Map<String , CtMainVO> ctMainMap = Maps.uniqueIndex(ctMainVOs, CtMainVO::getOrderNo);
        for (PmProCont pmProCont : pmProConts) {
            CtMainVO ctMainVO = ctMainMap.get(pmProCont.getOrderNo());
            BigDecimal qty = BigDecimal.valueOf(sumNeedQty.get(pmProCont.getOrderNo()));
            if(ctMainVO.getStockNum().compareTo(qty) < 0) {
                throw new CommonException("pm.pm_pro_cont_045", pmProCont.getOrderNo() , ctMainVO.getStockNum().toPlainString(), qty.toPlainString() );
            }
        }
        Map<String, BigDecimal> orderUnitAimWtMap = pmProContProdTtrRepository.selectByOrderNoList(Lists.newArrayList(sumNeedQty.keySet()), pmProContYieldCopy.getTenantId())
                .stream().collect(Collectors.toMap(PmProContProdTtr::getOrderNo, PmProContProdTtr::getOrderUnitAimWt));

        List<PmPdPlateCut> pmPdPlateCutHiss = this.pmPdPlateCutRepository.selectByPdMatNo(pmProContYieldCopy.getTenantId() , pmProContYieldCopy.getVirtualSlabNo());
        List<PmPdBlockPos> pmPdBlockPosHiss = this.pmPdBlockPosRepository.selectByPdMatNo(pmProContYieldCopy.getTenantId() , pmProContYieldCopy.getVirtualSlabNo());
        List<PmSmallPltPos> pmSmallPltPosHiss = this.pmSmallPltPosRepository.selectByPdMatNo(pmProContYieldCopy.getTenantId() , pmProContYieldCopy.getVirtualSlabNo());
        PmPdCcSlab pmPdCcSlab = this.pmPdCcSlabRepository.selectByPdMatNo(pmProContYieldCopy.getTenantId() , pmProContYieldCopy.getVirtualSlabNo());
        
        List<String> slabNos = codeRuleBuilder.generateCode(pmProContYieldCopy.getCopyNum() , pmProContYieldCopy.getTenantId(), Constants.CodeRule.VIRTUAL_SLAB_NO,
                CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, new HashMap<>(1));
        List<PmPdCcSlab> pmPdCcSlabs = new ArrayList<>(pmProContYieldCopy.getCopyNum());
        
        List<PmPdPlateCut> pmPdPlateCuts = new ArrayList<>(pmProContYieldCopy.getCopyNum() * pmPdPlateCutHiss.size());
        List<PmPdBlockPos> pmPdBlockPoss = new ArrayList<>(pmProContYieldCopy.getCopyNum() * pmPdBlockPosHiss.size());
        List<PmPdContSum> pmPdContSums = new ArrayList<>(pmProContYieldCopy.getCopyNum() * pmPdContSumHiss.size());
        List<PmSmallPltPos> pmSmallPltPoss = new ArrayList<>(pmProContYieldCopy.getCopyNum() * pmSmallPltPosHiss.size());

        //调用合同跟踪 准备
        List<ProContBoardEndDTO> boardEndEventList = new ArrayList<>();

        for (String virtualSlabNo : slabNos) {
            PmPdCcSlab temp = BeanUtils.copy(pmPdCcSlab, PmPdCcSlab.class);
            temp.setObjectVersionNumber(0L);
            temp.setVirtualSlabId(null);
            temp.setVirtualSlabNo(virtualSlabNo);
            pmPdCcSlabs.add(temp);

            //  合同跟踪 虚拟板坯维度
            boardEndEventList.add(new ProContBoardEndDTO(temp.getOrderNoAxis())
                    .setMatNo(temp.getVirtualSlabNo())
                    .setLen(temp.getNeedSlabLen())
                    .setMoMatNo(null)
                    .setMscLineNo(temp.getMscLineNo())
                    .setPdMatStatus(PdStatusHp.PD_STATUS_HP_12)
                    .setPpFlag(PdProdFlag.VIRTUAL_SLAB.getCode())
                    .setThk(temp.getMoldThick())
                    .setWid(temp.getMoldWid())
                    .setWgt(temp.getNeedSlabWt())
                    .setWholeBacklogCode(Constants.WholeBacklogCode.CODE_14)
                    .setStNo(temp.getStNo())
                    .setSgSign(temp.getSgSign()));

            //  合同跟踪 大板维度
            boardEndEventList.add(new ProContBoardEndDTO(temp.getOrderNoAxis())
                    .setMatNo(temp.getVirtualSlabNo())
                    .setLen(temp.getRollAimLen())
                    .setMoMatNo(null)
                    .setMscLineNo(temp.getMscLineNo())
                    .setPdMatStatus(PdStatusHp.PD_STATUS_HP_12)
                    .setPpFlag(PdProdFlag.VIRTUAL_COMPOSITE_SLAB.getCode())
                    .setThk(temp.getRollAimThick())
                    .setWid(temp.getRollAimWidth())
                    .setWgt(temp.getRollWtHp())
                    .setWholeBacklogCode(Constants.WholeBacklogCode.CODE_14)
                    .setStNo(temp.getStNo())
                    .setSgSign(temp.getSgSign()));

            for (PmSmallPltPos value : pmSmallPltPosHiss) {
                PmSmallPltPos pmSmallPltPosTemp = BeanUtils.copy(value, PmSmallPltPos.class);
                pmSmallPltPosTemp.setObjectVersionNumber(0L);
                pmSmallPltPosTemp.setPsppId(null);
                pmSmallPltPosTemp.setPdMatNo(virtualSlabNo);
                pmSmallPltPoss.add(pmSmallPltPosTemp);

                //  合同跟踪 小板维度
                boardEndEventList
                        .add(new ProContBoardEndDTO(pmSmallPltPosTemp.getOrderNo())
                                .setMatNo(temp.getVirtualSlabNo()+pmSmallPltPosTemp.getSmallPlateDivNo())
                                .setLen(pmSmallPltPosTemp.getOrderLen())
                                .setMoMatNo(pmSmallPltPosTemp.getPdMatNo())
                                .setMscLineNo(temp.getMscLineNo())
                                .setPdMatStatus(PdStatusHp.PD_STATUS_HP_12)
                                .setPpFlag(PdProdFlag.VIRTUAL_SUB_SLAB.getCode())
                                .setThk(pmSmallPltPosTemp.getOrderThick())
                                .setWid(pmSmallPltPosTemp.getOrderWidth())
                                .setWgt(orderUnitAimWtMap.get(pmSmallPltPosTemp.getOrderNo()))
                                .setWholeBacklogCode(Constants.WholeBacklogCode.CODE_14)
                                .setStNo(temp.getStNo())
                                .setSgSign(temp.getSgSign()));
            }
            
            for (PmPdBlockPos value : pmPdBlockPosHiss) {
                PmPdBlockPos pmPdBlockPosTemp = BeanUtils.copy(value, PmPdBlockPos.class);
                pmPdBlockPosTemp.setObjectVersionNumber(0L);
                pmPdBlockPosTemp.setPdBlockPosId(null);
                pmPdBlockPosTemp.setPdMatNo(virtualSlabNo);
                pmPdBlockPoss.add(pmPdBlockPosTemp);
            }
            List<PmPdRecDTO> pmPdRecs = new ArrayList<>();
            for (PmPdContSum contSum : pmPdContSumHiss) {
                PmPdContSum contSumTemp = BeanUtils.copy(contSum, PmPdContSum.class);
                contSumTemp.setObjectVersionNumber(0L);
                contSumTemp.setPpcsId(null);
                contSumTemp.setPdMatNo(virtualSlabNo);
                pmPdContSums.add(contSumTemp);
                
                PmPdRecDTO pmPdRecDTO = new PmPdRecDTO();
                pmPdRecDTO.setOrderNo(contSum.getOrderNo());
                pmPdRecDTO.setMscLineNo(pmPdCcSlab.getMscLineNo());
                pmPdRecDTO.setKeyvalue1Desc(PmPdRecDTO.DESC_VIRTUAL_SLAB_NO);
                pmPdRecDTO.setKeyvalue1(virtualSlabNo);
                pmPdRecDTO.setMatNo(virtualSlabNo);
                pmPdRecDTO.setQty(contSum.getOrderPlateNum());
                pmPdRecs.add(pmPdRecDTO);
            }
            
            for (PmPdPlateCut pmPdPlateCut : pmPdPlateCutHiss) {
                PmPdPlateCut pmPdPlateCutTemp = BeanUtils.copy(pmPdPlateCut, PmPdPlateCut.class);
                pmPdPlateCutTemp.setObjectVersionNumber(0L);
                pmPdPlateCutTemp.setCutId(null);
                pmPdPlateCutTemp.setPdMatNo(virtualSlabNo);
                pmPdPlateCuts.add(pmPdPlateCutTemp);
            }
            pmPdRecService.createEvent(pmPdCcSlab.getTenantId(), pmPdRecs 
                    , PdEventType.HP16, Constants.SYSTEM_PD_CODE, Constants.PdProgram.CC_SLAB_COPY_PD_PROGRAM);
        }

        this.pmPdCcSlabRepository.batchInsertSelective(pmPdCcSlabs);
        this.pmPdPlateCutRepository.batchInsertSelective(pmPdPlateCuts);
        this.pmPdBlockPosRepository.batchInsertSelective(pmPdBlockPoss);
        this.pmPdContSumRepository.batchInsertSelective(pmPdContSums);
        this.pmSmallPltPosRepository.batchInsertSelective(pmSmallPltPoss);

        //调用合同跟踪
        try {
            eventClient.addEvent(CtEventConstants.EVENT_PM_BOARD_END, boardEndEventList);
            eventClient.sendEvent(pmPdCcSlab.getTenantId());
        } finally {
            eventClient.remove();
        }
        
    }
    
    /**
     * 基于计算结果填充板坯表信息
     * 
     * @param pmPdCcSlab
     * @param pmProContYieldRespose
     * @param pmCompositeSlabCalc
     */
    private void buildPmPdCcSlab(PmPdCcSlab pmPdCcSlab, PmProContYieldRequestDTO pmProContYield,
            PmProContYieldResposeDTO pmProContYieldRespose, PmCompositeSlabCalcDTO pmCompositeSlabCalc) {
        pmPdCcSlab.setVirtualSlabNo(pmProContYieldRespose.getVirtualSlabNo());
        pmPdCcSlab.setTenantId(pmProContYield.getTenantId());
        // 清理器板坯宽厚 = 进加热炉板坯宽厚 = 结晶器宽厚
        pmPdCcSlab.setPreCleanSlabThick(pmProContYield.getPmContFilterRequest().getMoldThick());
        pmPdCcSlab.setPreCleanSlabWidth(pmProContYield.getPmContFilterRequest().getMoldWidth());
        pmPdCcSlab.setInfurSlabThick(pmProContYield.getPmContFilterRequest().getMoldThick());
        pmPdCcSlab.setInfurSlabWid(pmProContYield.getPmContFilterRequest().getMoldWidth());

        pmPdCcSlab.setPreCleanSlabLen(pmProContYieldRespose.getPreCleanSlabLen());
        pmPdCcSlab.setPreCleanSlabWt(pmProContYieldRespose.getPreCleanSlabWt());
        pmPdCcSlab.setInfurSlabLen(pmProContYieldRespose.getInfurSlabLen());
        pmPdCcSlab.setInfurSlabWt(pmProContYieldRespose.getInfurSlabWt());
        pmPdCcSlab.setPreCleanSlabMaxLen(pmProContYieldRespose.getPreCleanSlabMaxLen());
        pmPdCcSlab.setPreCleanSlabMinLen(pmProContYieldRespose.getPreCleanSlabMinLen());
        pmPdCcSlab.setPreCleanSlabMaxWt(pmProContYieldRespose.getPreCleanSlabMaxWt());
        pmPdCcSlab.setPreCleanSlabMinWt(pmProContYieldRespose.getPreCleanSlabMinWt());
        pmPdCcSlab.setInfurSlabMaxLen(pmProContYieldRespose.getInfurSlabMaxLen());
        pmPdCcSlab.setInfurSlabMinLen(pmProContYieldRespose.getInfurSlabMinLen());
        pmPdCcSlab.setInfurSlabMaxWt(pmProContYieldRespose.getInfurSlabMaxWt());
        pmPdCcSlab.setInfurSlabMinWt(pmProContYieldRespose.getInfurSlabMinWt());
        pmPdCcSlab.setNeedSlabLen(pmProContYieldRespose.getNeedSlabLen());
        // 清理前板坯重量 ＝ 进加热炉板坯重量 = 必要板坯重量
        pmPdCcSlab.setNeedSlabWt(pmProContYieldRespose.getNeedSlabWt());
        pmPdCcSlab.setCommandYield(pmProContYieldRespose.getCommandYield());
        pmPdCcSlab.setRollYield(pmProContYieldRespose.getRollYield());

        pmPdCcSlab.setNormYield(pmProContYieldRespose.getNormYield());

        pmPdCcSlab.setRollWtHp(pmProContYieldRespose.getRollWtHp());
        pmPdCcSlab.setPickModeLenDir(pmProContYield.getCompositeBoard().getPickModeLenDir().longValue());
        pmPdCcSlab.setPickModeWidDir(pmProContYield.getCompositeBoard().getPickModeWidDir().longValue());
        pmPdCcSlab.setTotSmallPlateNum(pmProContYield.getCompositeBoard().getSpCount().longValue());
        pmPdCcSlab.setCombinePlateLen(pmProContYieldRespose.getCombinePlateLen());
        pmPdCcSlab.setCombinePlateWidth(pmProContYieldRespose.getCombinePlateWidth());
        pmPdCcSlab.setSampleLenHead(pmCompositeSlabCalc.getSampleLenHead());
        pmPdCcSlab.setSampleLenMid(pmCompositeSlabCalc.getSampleLenMid());
        pmPdCcSlab.setSampleLenTail(pmCompositeSlabCalc.getSampleLenTail());
        pmPdCcSlab.setOrderNumInPlate(pmProContYield.getCompositeBoard().getOrderCount().longValue());

        pmPdCcSlab.setRollThickTolMax(pmProContYieldRespose.getRollThickTolMax());
        pmPdCcSlab.setRollThickTolMin(pmProContYieldRespose.getRollThickTolMin());
        pmPdCcSlab.setHeadCut(pmProContYieldRespose.getHeadCut());
        pmPdCcSlab.setTailCut(pmProContYieldRespose.getTailCut());
        pmPdCcSlab.setRollAimLen(pmProContYieldRespose.getLaim());
        pmPdCcSlab.setRollAimThick(pmProContYieldRespose.getTaim());
        pmPdCcSlab.setRollAimWidth(pmProContYieldRespose.getWaim());
        pmPdCcSlab.setBroadMasUseFlag(pmProContYieldRespose.getBroadMasUseFlag());
        pmPdCcSlab.setEdgerUseFlag(pmProContYieldRespose.getEdgerUseFlag());
        pmPdCcSlab.setFormMasUseFlag(pmProContYieldRespose.getFormMasUseFlag());
        pmPdCcSlab.setBroadFlag(pmCompositeSlabCalc.getBroadFlag());
        pmPdCcSlab.setRsCode(pmCompositeSlabCalc.getRsCode().toString());
    }

    /**
     * 组装基本信息
     * 
     * @param pmProContYield
     * @param axisPmContMscTech
     * @param axisPmProContProdTtr
     * @param filterOrderMap
     * @return
     */
    private PmPdCcSlab buildPmPdCcSlab(PmProContYieldRequestDTO pmProContYield, PmContMscTech axisPmContMscTech,
            PmProContProdTtr axisPmProContProdTtr, Map<String, PmProContFilterResposeDTO> filterOrderMap) {
        PmPdCcSlab pmPdCcSlab = new PmPdCcSlab();
        pmPdCcSlab.setMatDesignKind(pmProContYield.getPmContFilterRequest().getMatDesignKind());
        pmPdCcSlab.setPdStatusHp(PdStatusHp.PD_STATUS_HP_12);
        pmPdCcSlab.setPdResp(DetailsHelper.getUserDetails().getUserId().toString());
        pmPdCcSlab.setFurType(pmProContYield.getPmContFilterRequest().getFurType());
        pmPdCcSlab.setAutoManualFlag(AutoManualFlag.AUTO_MANUA_FLAG_M);
        if (pmProContYield.getPmContFilterRequest().getFixSlabLenFlag() != null) {
            pmPdCcSlab.setFixSlabLenFlag(pmProContYield.getPmContFilterRequest().getFixSlabLenFlag());
            if (pmProContYield.getPmContFilterRequest().getFixSlabLenFlag().intValue() == 1) {
                // 指定长
                pmPdCcSlab.setFixSlabLen(pmProContYield.getPmContFilterRequest().getFixSlabLen());
            } else if(pmProContYield.getPmContFilterRequest().getFixSlabLenFlag().intValue() == 2){
                // 奉送样
                pmPdCcSlab.setFixSlabLen(pmProContYield.getPmContFilterRequest().getSampleLenGice());
            } else {
                // 不指定长
                pmPdCcSlab.setFixSlabLen(BigDecimal.ZERO);
            }
        }
        pmPdCcSlab.setMoldThick(pmProContYield.getPmContFilterRequest().getMoldThick());
        pmPdCcSlab.setMoldWid(pmProContYield.getPmContFilterRequest().getMoldWidth());
        pmPdCcSlab.setSlabCleanWtLossRateSt(BigDecimal.ZERO);
        pmPdCcSlab.setSlabCleanWtLossRateFr(BigDecimal.ZERO);
        
        pmPdCcSlab.setTwoRollInterimFlag(Long.valueOf(BaseConstants.Flag.NO));
        pmPdCcSlab.setRfPath(axisPmContMscTech.getRfPath());
        pmPdCcSlab.setCcType(pmProContYield.getPmContFilterRequest().getCcType());
        pmPdCcSlab.setOrderRemainDiv(BaseConstants.Flag.YES.toString());
        pmPdCcSlab.setCanDelFlag(BaseConstants.Flag.YES.toString());
        pmPdCcSlab.setMscLineNo(pmProContYield.getPmContFilterRequest().getMscLineNo());
        pmPdCcSlab.setHpFlameCleanDiv(axisPmContMscTech.getFlameCleanDiv());
        pmPdCcSlab.setSlabFinishCode(axisPmContMscTech.getSlabFinishCode());
        pmPdCcSlab.setProdDensity(axisPmProContProdTtr.getProdDensity());
        pmPdCcSlab.setTransFlag(pmProContYield.getPmContFilterRequest().getTransFlag());
        pmPdCcSlab.setSgSign(axisPmProContProdTtr.getSgSign());
        Date steelPlanDate = null;
        Date steelLatestDate = null;
        Set<String> ultCode = new TreeSet<>();
        String hotSendDiv = "H";
        Long hotChargeFlag = 0L;
        Long macroSmpFlag = 1L;
        for (PmProContYieldDTO order : pmProContYield.getPmProContYieldList()) {
            PmProContFilterResposeDTO resposeDTO = filterOrderMap.get(order.getOrderNo());
            // 对PM_PD_CC_SLAB，遍历所有合同及其产线，取PM_CONT_MSC_TECH 的SLAB_PLACE_CODE，若出现X或出现B和T，则落X；否则若仅出现B或T，则落对应的值，否则落0.
            if ("X".equals(resposeDTO.getSlabPlaceCode())) {
                pmPdCcSlab.setSlabPlaceCode("X");
            }
            if(resposeDTO.getHotChargeFlag() != null) {
                hotChargeFlag = resposeDTO.getHotChargeFlag();
            }
            //  存在一个合同macro_smp_flag != 0或者合同热送区分为C,则落C;否则H
            if("C".equals(resposeDTO.getHotSendDiv()) || macroSmpFlag.equals(resposeDTO.getMacroSmpFlag())) {
                hotSendDiv = "C";
            }
            if (StringUtils.isNotBlank(pmPdCcSlab.getSlabPlaceCode())) {
                if(!resposeDTO.getSlabPlaceCode().equals(pmPdCcSlab.getSlabPlaceCode())){
                    pmPdCcSlab.setSlabPlaceCode("X");
                }
            } else {
                pmPdCcSlab.setSlabPlaceCode(resposeDTO.getSlabPlaceCode());
            }
            if (StringUtils.isBlank(pmPdCcSlab.getUrgOrderFlag()) && resposeDTO.getUrgOrderFlag() != null) {
                pmPdCcSlab.setUrgOrderFlag(resposeDTO.getUrgOrderFlag().toString());
            }
            if (steelPlanDate == null || (resposeDTO.getSteelPlanDate() != null && steelPlanDate.after(resposeDTO.getSteelPlanDate()))) {
                steelPlanDate = resposeDTO.getSteelPlanDate();
            }
            if (steelLatestDate == null || (resposeDTO.getSteelLatestDate() != null && steelLatestDate.after(resposeDTO.getSteelLatestDate()))) {
                steelLatestDate = resposeDTO.getSteelLatestDate();
            }
            if (StringUtils.isNotBlank(resposeDTO.getErpUtSpec1())) {
               ultCode.add(resposeDTO.getErpUtSpec1());
            }
            if (StringUtils.isNotBlank(resposeDTO.getErpUtSpec2())) {
                ultCode.add(resposeDTO.getErpUtSpec2());
            }
            if (StringUtils.isNotBlank(resposeDTO.getErpUtSpec3())) {
                ultCode.add(resposeDTO.getErpUtSpec3());
            }
            if (StringUtils.isBlank(pmPdCcSlab.getCoolCode()) && StringUtils.isNotBlank(resposeDTO.getCoolCode())) {
                pmPdCcSlab.setCoolCode(resposeDTO.getCoolCode());
            }
            if (StringUtils.isBlank(pmPdCcSlab.getUltDetectMethodCode())
                    && StringUtils.isNotBlank(resposeDTO.getUltDetectMethodCode())) {
                pmPdCcSlab.setUltDetectMethodCode(resposeDTO.getUltDetectMethodCode());
            }
        }
        if(ultCode != null && !ultCode.isEmpty()) {
            pmPdCcSlab.setUltCode(String.join("@", ultCode));
        }

        if (steelPlanDate == null) {
            // 获取当前时间往前推15天
            LocalDate now = LocalDate.now().minusDays(15);
            steelPlanDate = Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant());
        }
        pmPdCcSlab.setSteelPlanDate(steelPlanDate);
        pmPdCcSlab.setSteelLatestDate(steelLatestDate);

        pmPdCcSlab.setTmpSlabNo("");
        pmPdCcSlab.setPrecPono("");
        pmPdCcSlab.setPrecCastLotNo("");
        pmPdCcSlab.setSgDecideTime(null);
        pmPdCcSlab.setManualOm("");
        pmPdCcSlab.setHpOmTime(null);
        pmPdCcSlab.setHotSendFlag(hotSendDiv);
        pmPdCcSlab.setHotChargeFlag(hotChargeFlag);
        pmPdCcSlab.setSteelGroup("");
        pmPdCcSlab.setSlabPlaceCode("");
        pmPdCcSlab.setIgMatDesignKind("");
        pmPdCcSlab.setIngotType("");
        pmPdCcSlab.setShpCode(""); 

        pmPdCcSlab.setAdTypeCode(axisPmContMscTech.getAdTypeCode());
        pmPdCcSlab.setAdModeCode(axisPmContMscTech.getAdModeCode());
        pmPdCcSlab.setCheckMethodCode(axisPmProContProdTtr.getCheckMethodCode());
        pmPdCcSlab.setCtrlRollCode(axisPmContMscTech.getCtrlRollCode());
        pmPdCcSlab.setWithSideFlag(axisPmProContProdTtr.getProdSideMark());
        pmPdCcSlab.setCutModeCode(axisPmContMscTech.getCutModeCode());
        pmPdCcSlab.setGFlag(axisPmContMscTech.getGFlag() == null ? "" : axisPmContMscTech.getGFlag().toString());
        pmPdCcSlab.setCsFlag(axisPmContMscTech.getCsFlag() == null ? "" : axisPmContMscTech.getCsFlag().toString());
        pmPdCcSlab.setDssFlag(axisPmContMscTech.getDssFlag() == null ? "" : axisPmContMscTech.getDssFlag().toString());
        pmPdCcSlab.setSsFlag(axisPmContMscTech.getSsFlag() == null ? "" : axisPmContMscTech.getSsFlag().toString());
        pmPdCcSlab.setDsFlag(axisPmContMscTech.getDsFlag() == null ? "" : axisPmContMscTech.getDsFlag().toString());
        pmPdCcSlab.setProdCodeHp(axisPmProContProdTtr.getProdCodeHp());
        pmPdCcSlab.setAxisOrderThick(axisPmProContProdTtr.getOrderThick());
        pmPdCcSlab.setAxisOrderWidth(axisPmProContProdTtr.getOrderWidth());
        pmPdCcSlab.setOrderNoAxis(axisPmProContProdTtr.getOrderNo());
        pmPdCcSlab.setFormPlateMode(pmProContYield.getPmContFilterRequest().getFormPlateMode());

        pmPdCcSlab.setRollDirectCode(axisPmContMscTech.getRollDirectCode());

        setStNo(pmProContYield, pmPdCcSlab);

        return pmPdCcSlab;
    }

    /**
     * 
     * 
     * @param pmProContYield
     * @param pmPdCcSlab
     */
    private void setStNo(PmProContYieldRequestDTO pmProContYield, PmPdCcSlab pmPdCcSlab) {
        pmPdCcSlab.setStNo(pmProContYield.getPmContFilterRequest().getStNo());
        pmPdCcSlab.setOutSgNo(pmProContYield.getPmContFilterRequest().getStNo());
    }

    @Override
    public Page<PmPdCcSlab> detaillist(PageRequest pageRequest, PmPdCcSlabReqDetailDTO dto, Long tenantId) {
        Condition build = Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_ST_NO, dto.getStNo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_PD_STATUS_HP, dto.getPdStatus(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_VIRTUAL_SLAB_NO, dto.getVirtualSlabNo(), true))
                .andWhere(Sqls.custom().andIn(PmPdCcSlab.FIELD_PD_RESP, dto.getPdResp(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_MOLD_THICK, dto.getMoldThick(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_MOLD_WID, dto.getMoldWidth(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_MSC_LINE_NO, dto.getMscLineNo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_AUTO_MANUAL_FLAG, dto.getAutoManualFlag(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmPdCcSlab.FIELD_CREATION_DATE, dto.getCreateDateFrom(), true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmPdCcSlab.FIELD_CREATION_DATE, dto.getCreateDateTo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_TENANT_ID, tenantId))
                .build();
        Page<PmPdCcSlab> page = PageHelper.doPageAndSort(pageRequest, () -> pmPdCcSlabRepository.selectByCondition(build));
        page.getContent().forEach(item->item.setInvertedMark(item.getVirtualSlabNo().startsWith("D") ? "D" : null));
        return page;
    }
    
    @Override
    public List<PmPdCcSlabResDetailDTO> recordCheckGroupByVirtualSlabNo(List<String> virtualSlabNoList, Long tenantId) {
        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByCondition(Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_VIRTUAL_SLAB_NO, virtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            throw new CommonException("pm.pd_cc_slab_001", virtualSlabNoList, "组板连铸板坯表");
        }
        Map<String, String> formPlateModeMap = new HashMap<>();
        for (PmPdCcSlab pmPdCcSlab : pmPdCcSlabList) {
            if(pmPdCcSlab.getTwoRollInterimFlag() != null && pmPdCcSlab.getTwoRollInterimFlag() == 1L) {
                List<PmPdSlab> pdSlabs = pmPdSlabRepository.selectListBySlabNo(pmPdCcSlab.getVirtualSlabNo(), tenantId);
                if(pdSlabs != null && !pdSlabs.isEmpty()) {
                    virtualSlabNoList.remove(pmPdCcSlab.getVirtualSlabNo());
                    for (PmPdSlab pmPdSlab : pdSlabs) {
                        virtualSlabNoList.add(pmPdSlab.getVirtualSlabNo());
                        formPlateModeMap.put(pmPdSlab.getVirtualSlabNo(), pmPdSlab.getFormPlateMode());
                    }
                }
            } else {
                formPlateModeMap.put(pmPdCcSlab.getVirtualSlabNo(), pmPdCcSlab.getFormPlateMode());
            }
        }
        PmPdCcSlabResDetailDTO pmPdCcSlabResDetail = recordCheck(pmPdCcSlabList , virtualSlabNoList, tenantId);
        List<PmPdCcSlabResDetailDTO> pmPdCcSlabResDetailList = new ArrayList<>();
        Map<String, List<BoardContractItemDTO>> contractMap =  pmPdCcSlabResDetail.getContractItemDTOList().stream().collect(Collectors.groupingBy(BoardContractItemDTO::getVirtualSlabNo));
        Map<String, List<BoardLayoutItemDTO>> boardLayoutItemDTOMap =  pmPdCcSlabResDetail.getLayoutItemDTOList().stream().collect(Collectors.groupingBy(BoardLayoutItemDTO::getVirtualSlabNo));
        for (Entry<String, List<BoardContractItemDTO>> entry : contractMap.entrySet()) {
            PmPdCcSlabResDetailDTO pmPdCcSlabResDetailDTO = new PmPdCcSlabResDetailDTO();
            pmPdCcSlabResDetailDTO.setVirtualSlabNo(entry.getKey());
            pmPdCcSlabResDetailDTO.setFormPlateMode(formPlateModeMap.get(entry.getKey()));
            pmPdCcSlabResDetailDTO.setContractItemDTOList(contractMap.get(entry.getKey()).stream().sorted(Comparator.comparing(BoardContractItemDTO::getOrderSeqNo)).collect(Collectors.toList()));
            pmPdCcSlabResDetailDTO.setLayoutItemDTOList(boardLayoutItemDTOMap.get(entry.getKey()).stream().sorted(Comparator.comparing(BoardLayoutItemDTO::getOrderSeqNo)).collect(Collectors.toList()));
            pmPdCcSlabResDetailList.add(pmPdCcSlabResDetailDTO);
        }
        return pmPdCcSlabResDetailList;
    }

    @Override
    public PmPdCcSlabResDetailDTO recordCheck(List<PmPdCcSlab> pmPdCcSlabList , List<String> virtualSlabNoList, Long tenantId) {
        if (CollectionUtils.isEmpty(virtualSlabNoList)) {
            return null;
        }
        List<String> mscLineNoList = pmPdCcSlabList.stream().map(PmPdCcSlab::getMscLineNo).distinct().collect(Collectors.toList());
        Map<String, PmPdCcSlab> pmPdCcSlabMap = pmPdCcSlabList.stream().collect(Collectors.toMap(PmPdCcSlab::getVirtualSlabNo, Function.identity()));

        List<PmPdContSum> pdContSumList = pmPdContSumRepository.selectByPdMatNoList(tenantId, virtualSlabNoList);
        if (CollectionUtils.isEmpty(pdContSumList)) {
            throw new CommonException("pm.pd_cc_slab_001", virtualSlabNoList, "组板合同总量表");
        }
        List<String> orderNoList = pdContSumList.stream().map(PmPdContSum::getOrderNo).distinct().collect(Collectors.toList());

        List<PmProCont> pmProContList = pmProContRepository.selectByOrderList(orderNoList, tenantId);
        if (CollectionUtils.isEmpty(pdContSumList)) {
            throw new CommonException("pm.pd_cc_slab_002", orderNoList, "生产合同主表");
        }
        Map<String, PmProCont> proContMap = pmProContList.stream()
                .collect(Collectors.toMap(PmProCont::getOrderNo, Function.identity()));

        List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository.selectByOrderNoList(orderNoList, tenantId);
        if (CollectionUtils.isEmpty(pmProContProdTtrList)) {
            throw new CommonException("pm.pd_cc_slab_002", orderNoList, "生产合同产品属性表");
        }
        Map<String, PmProContProdTtr> proContProdTtrMap = pmProContProdTtrList.stream()
                .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity()));

        List<PmContMscTech> pmContMscTecheList = pmContMscTechRepository.selectByOrderNoAndMscLineNo(orderNoList, mscLineNoList, tenantId);
        if (CollectionUtils.isEmpty(pmContMscTecheList)) {
            throw new CommonException("pm.pd_cc_slab_002", orderNoList,  "合同产线工艺参数表");
        }
        Map<String, PmContMscTech> contMscTecherMap = pmContMscTecheList.stream()
                .collect(Collectors.toMap(item-> Strings.concat(item.getOrderNo(), item.getMscLineNo()), Function.identity()));

        List<PmPdBlockPos> pmPdBlockPosList = pmPdBlockPosRepository.selectByPdMatNoList(virtualSlabNoList, tenantId);
        if (CollectionUtils.isEmpty(pmPdBlockPosList)) {
            throw new CommonException("pm.pd_cc_slab_001", virtualSlabNoList, "组合子板位置表");
        }


        PmPdCcSlabResDetailDTO result = new PmPdCcSlabResDetailDTO();
        List<BoardContractItemDTO> contractItemDTOList = new ArrayList<>(pmPdCcSlabList.size());
        List<BoardLayoutItemDTO> layoutItemDTOList = new ArrayList<>(pmPdCcSlabList.size());
        for (PmPdContSum pmPdContSum : pdContSumList) {
            BoardContractItemDTO contractItemDTO = new BoardContractItemDTO();
                contractItemDTOList.add(contractItemDTO);
                contractItemDTO.setVirtualSlabNo(pmPdContSum.getPdMatNo());
                contractItemDTO.setOrderSeqNo(pmPdContSum.getOrderSeqNo().longValue());
                contractItemDTO.setOrderNo(pmPdContSum.getOrderNo());
                contractItemDTO.setSmallPlateThick(pmPdContSum.getSmallPlateThick());
                contractItemDTO.setSmallPlateWidth(pmPdContSum.getSmallPlateWidth());
                contractItemDTO.setSmallPlateLen(pmPdContSum.getSmallPlateLen());

                if (proContMap.containsKey(pmPdContSum.getOrderNo())) {
                    PmProCont pmProCont = proContMap.get(pmPdContSum.getOrderNo());
                    contractItemDTO.setPdLackQty(pmProCont.getPdLackQty());
                    contractItemDTO.setPdOverDevoQty(pmProCont.getPdOverDevoQty());
                    contractItemDTO.setPdOverDevoCause(pmProCont.getPdOverDevoCause());
                }

                if (proContProdTtrMap.containsKey(pmPdContSum.getOrderNo())) {
                    PmProContProdTtr ttr = proContProdTtrMap.get(pmPdContSum.getOrderNo());
                    contractItemDTO.setSgSign(ttr.getSgSign());
                    contractItemDTO.setOrderThick(ttr.getOrderThick());
                    contractItemDTO.setOrderWidth(ttr.getOrderWidth());
                    contractItemDTO.setWidthDiv(ttr.getWidthDiv());
                    contractItemDTO.setOrderLen(ttr.getOrderLen());
                    contractItemDTO.setOrderMinLen(ttr.getOrderMinLen());
                    contractItemDTO.setOrderMaxLen(ttr.getOrderMaxLen());
                    contractItemDTO.setLenDiv(ttr.getLenDiv());
                    contractItemDTO.setOrderTypeCode(ttr.getOrderTypeCode());
                    contractItemDTO.setDelivyPlaceName(ttr.getDelivyPlaceName());
                    contractItemDTO.setConsignCustCname(ttr.getConsignCustCname());
                }

                if (pmPdCcSlabMap.containsKey(pmPdContSum.getPdMatNo())) {
                    String mscLineNo = pmPdCcSlabMap.get(pmPdContSum.getPdMatNo()).getMscLineNo();
                    if (contMscTecherMap.containsKey( Strings.concat(pmPdContSum.getOrderNo(), mscLineNo))) {
                        PmContMscTech pmContMscTech = contMscTecherMap.get(Strings.concat(pmPdContSum.getOrderNo(), mscLineNo));
                        contractItemDTO.setStNo(pmContMscTech.getStNo());
                    }
                }
        }
        for (PmPdBlockPos pmPdBlockPos : pmPdBlockPosList) {
            BoardLayoutItemDTO layoutItemDTO = new BoardLayoutItemDTO();
            layoutItemDTO.setOrderNo(pmPdBlockPos.getOrderNo());
            layoutItemDTO.setOrderSeqNo(pmPdBlockPos.getOrderSeqNo());
            layoutItemDTO.setOrderBlockNo(pmPdBlockPos.getOrderBlockNo());
            layoutItemDTO.setBlockPlateNum(pmPdBlockPos.getBlockPlateNum());
            layoutItemDTO.setVirtualSlabNo(pmPdBlockPos.getPdMatNo());
            if (pmPdCcSlabMap.containsKey(pmPdBlockPos.getPdMatNo())) {
                layoutItemDTO.setOrderNoAxis(pmPdCcSlabMap.get(pmPdBlockPos.getPdMatNo()).getOrderNoAxis());
            }
            layoutItemDTOList.add(layoutItemDTO);
        }
        result.setContractItemDTOList(contractItemDTOList);
        result.setLayoutItemDTOList(layoutItemDTOList);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disband(Long tenantId, List<String> virtualSlabNoList) {
        if (CollectionUtils.isEmpty(virtualSlabNoList)) {
            throw new CommonException("pm.pd_cc_slab_003");
        }

        Long userId = DetailsHelper.getUserDetails().getUserId();

        List<PmPdCcSlab> pmPdCcSlabList = pmPdCcSlabRepository.selectByCondition(Condition.builder(PmPdCcSlab.class)
                .andWhere(Sqls.custom().andIn(PmPdCcSlab.FIELD_VIRTUAL_SLAB_NO, virtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmPdCcSlab.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            throw new CommonException("pm.pd_cc_slab_001", virtualSlabNoList, "组板连铸板坯表");
        }
        final Map<String , String> mscLineNoMap = new HashMap<>();
        pmPdCcSlabList.forEach(item->{
            // 若PD_STATUS大于12且不等于52
           if (item.getPdStatusHp().compareTo(Constants.PdStatusHp.PD_STATUS_HP_12) > 0
                   && !item.getPdStatusHp().equals(Constants.PdStatusHp.PD_STATUS_HP_52)) {
               throw new CommonException("pm.pd_cc_slab_004", item.getVirtualSlabNo(), item.getPdStatusHp());
           }

           // 若PD_STATUS等于52且PD_RESP不等于系统操作者
            if (item.getPdStatusHp().equals(Constants.PdStatusHp.PD_STATUS_HP_52) &&
                   ! userId.toString().equals(item.getPdResp())) {
                throw new CommonException("pm.pd_cc_slab_005", item.getVirtualSlabNo());
            }
            mscLineNoMap.put(item.getVirtualSlabNo(), item.getMscLineNo());

        });


        List<PmPdCcSlab> pdCcSlabList = pmPdCcSlabList.stream().filter(item -> item.getTwoRollInterimFlag() == 1L).collect(Collectors.toList());
        for (PmPdCcSlab pmPdCcSlab : pdCcSlabList) {
            PmPdMidSplitRequestDTO splitInfoRequest = new PmPdMidSplitRequestDTO();
            splitInfoRequest.setTenantId(tenantId);
            splitInfoRequest.setVirtualSlabNo(pmPdCcSlab.getVirtualSlabNo());
            splitInfoRequest.setMscLineNo(pmPdCcSlab.getMscLineNo());
            splitInfoRequest.setRomoveAll(true);
            pmPdSlabService.removeMidSplit(splitInfoRequest);
        }

        pmPdCcSlabList.removeAll(pdCcSlabList);
        if (CollectionUtils.isEmpty(pmPdCcSlabList)) {
            return ;
        }
        List<String> notTwoRollVirtualSlabNoList = pmPdCcSlabList.stream().map(PmPdCcSlab::getVirtualSlabNo).collect(Collectors.toList());


        List<PmSmallPltPos> pmSmallPltPosList = pmSmallPltPosRepository.selectByCondition(Condition.builder(PmSmallPltPos.class)
                .andWhere(Sqls.custom().andIn(PmSmallPltPos.FIELD_PD_MAT_NO, notTwoRollVirtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmSmallPltPos.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmSmallPltPosList)) {
            throw new CommonException("pm.pd_cc_slab_001", notTwoRollVirtualSlabNoList, "组板小板位置表");
        }

        // 4.	根据虚拟板坯号，删除PM_PD_CC_SLAB、PM_PD_BLOCK_POS、PM_PD_CONT_SUM、PM_SMALL_PLT_POS的所有记录
        List<PmPdContSum> pdContSumList = pmPdContSumRepository.selectByCondition(Condition.builder(PmPdContSum.class)
                .andWhere(Sqls.custom().andIn(PmPdContSum.FIELD_PD_MAT_NO, notTwoRollVirtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pdContSumList)) {
            throw new CommonException("pm.pd_cc_slab_001", notTwoRollVirtualSlabNoList, "组板合同总量表");
        }

        List<PmPdBlockPos> pmPdBlockPosList = pmPdBlockPosRepository.selectByCondition(Condition.builder(PmPdBlockPos.class)
                .andWhere(Sqls.custom().andIn(PmPdBlockPos.FIELD_PD_MAT_NO, notTwoRollVirtualSlabNoList))
                .andWhere(Sqls.custom().andEqualTo(PmPdBlockPos.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmPdBlockPosList)) {
            throw new CommonException("pm.pd_cc_slab_001", notTwoRollVirtualSlabNoList, "组合子板位置表");
        }

        // 删除大板粗切
        List<PmPdPlateCut> pmPdPlateCutList = pmPdPlateCutRepository.selectByPdMatNoList(virtualSlabNoList, tenantId);

        // 根据虚拟板坯号，从组板合同总量表调用组板履历函数，抛组板履历事件
        Map<String , List<PmPdContSum>> contSumMap = pdContSumList.stream().collect(Collectors.groupingBy(PmPdContSum::getPdMatNo));
        PdMatTypeStrategy pdMatTypeStrategy = PdMatTypeStrategyFactory.matchStrategy(PdMatType.C);
        for (Entry<String, List<PmPdContSum>> entry : contSumMap.entrySet()) {
            pdMatTypeStrategy.pdDeleteEvent(entry.getValue(), entry.getKey()
                    , mscLineNoMap.get(entry.getKey()), Constants.PdProgram.CC_SLAB_DETAIL_DELETE_PROGRAM, tenantId);
        }

        pmPdCcSlabRepository.batchDeleteByPrimaryKey(pmPdCcSlabList);
        pmPdContSumRepository.batchDeleteByPrimaryKey(pdContSumList);
        pmSmallPltPosRepository.batchDeleteByPrimaryKey(pmSmallPltPosList);
        pmPdBlockPosRepository.batchDeleteByPrimaryKey(pmPdBlockPosList);
        pmPdPlateCutRepository.batchDeleteByPrimaryKey(pmPdPlateCutList);

        // 将事件标识、材料号（虚拟板坯号拼接小板分割号）、是否有效、产品标记（板坯1）抛合同跟踪组板解散事件
        Map<String ,List<PmSmallPltPos>> pmSmallPltPosListMap = pmSmallPltPosList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getPdMatNo));
        try {
            for (Entry<String, List<PmSmallPltPos>> entry : pmSmallPltPosListMap.entrySet()) {
                List<ProContConsumeDTO> proContConsumeDTOs = new ArrayList<>();
                proContConsumeDTOs.add(new ProContConsumeDTO(entry.getKey(), PdProdFlag.VIRTUAL_SLAB.getCode(), BaseConstants.Flag.NO.longValue()));
                proContConsumeDTOs.add(new ProContConsumeDTO(entry.getKey(), PdProdFlag.VIRTUAL_COMPOSITE_SLAB.getCode(), BaseConstants.Flag.NO.longValue()));
                for (PmSmallPltPos pmSmallPltPos : entry.getValue()) {
                    proContConsumeDTOs.add(new ProContConsumeDTO(pmSmallPltPos.getPdMatNo() + pmSmallPltPos.getSmallPlateDivNo(), PdProdFlag.VIRTUAL_SUB_SLAB.getCode(), BaseConstants.Flag.NO.longValue()));
                }
                eventClient.addEvent(CtEventConstants.EVENT_PM_CONTRACT_BOARD_CONSUME, proContConsumeDTOs);
            }
            eventClient.sendEvent(tenantId);
        } finally {
            eventClient.remove();
        }
    }
}
