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

import com.google.common.collect.Lists;
import com.xisc.pm.api.dto.PmCompositeSlabCalcDTO;
import com.xisc.pm.api.dto.PmProContFilterRequestDTO;
import com.xisc.pm.api.dto.PmProContFilterResposeDTO;
import com.xisc.pm.api.dto.PmProContYieldDTO;
import com.xisc.pm.api.dto.PmProContYieldRequestDTO;
import com.xisc.pm.api.dto.PmProContYieldResposeDTO;
import com.xisc.pm.api.dto.RuleParamDTO;
import com.xisc.pm.app.service.PmCompositeSlabService;
import com.xisc.pm.app.service.PmPdSlabInfoService;
import com.xisc.pm.app.service.PmPdSlabService;
import com.xisc.pm.app.service.PmRuleCodeService;
import com.xisc.pm.app.service.strategy.PdMatTypeStrategyFactory;
import com.xisc.pm.domain.entity.MmSlab;
import com.xisc.pm.domain.entity.PmCompositeSlab;
import com.xisc.pm.domain.entity.PmCompositeSlabList;
import com.xisc.pm.domain.entity.PmContMscTech;
import com.xisc.pm.domain.entity.PmPdContSum;
import com.xisc.pm.domain.entity.PmPdSlab;
import com.xisc.pm.domain.entity.PmPdSlabInfo;
import com.xisc.pm.domain.entity.PmProCont;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSlabSpecBt;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.repository.MmSlabRepository;
import com.xisc.pm.domain.repository.PmCompositeSlabListRepository;
import com.xisc.pm.domain.repository.PmCompositeSlabRepository;
import com.xisc.pm.domain.repository.PmPdSlabInfoRepository;
import com.xisc.pm.domain.repository.PmPdSlabRepository;
import com.xisc.pm.domain.repository.PmProContRepository;
import com.xisc.pm.domain.repository.PmQdToPoOrderRepository;
import com.xisc.pm.domain.vo.CtMainVO;
import com.xisc.pm.domain.vo.MmPlateVO;
import com.xisc.pm.domain.vo.QdToPoOrderVO1;
import com.xisc.pm.domain.vo.WmMatPileVo;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.constant.Constants.PdStatusHp;
import com.xisc.pm.infra.constant.PmPlateConstants;
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.util.Utils;
import io.choerodon.core.exception.CommonException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hzero.boot.platform.code.builder.CodeRuleBuilder;
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.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 复合板组板
 * 
 * @author jun.zeng
 *
 */
@Component
public class CompositSlabPdMatTypeStratrgy extends DefaultPdMatTypeStrategy<PmPdSlab> {

    @Autowired
    private PmPdSlabInfoRepository pmPdSlabInfoRepository;

    @Autowired
    private PmPdSlabInfoService pmPdSlabInfoService;

    @Autowired
    private PmPdSlabRepository pmPdSlabRepository;

    @Autowired
    private PmPdSlabService pmPdSlabService;

    @Autowired
    private PmCompositeSlabListRepository pmCompositeSlabListRepository;

    @Autowired
    private PmCompositeSlabRepository pmCompositeSlabRepository;
    
    @Autowired
    private PmCompositeSlabService pmCompositeSlabService;

    @Autowired
    private MmSlabRepository mmSlabRepository;

    @Autowired
    private CodeRuleBuilder codeRuleBuilder;

    @Autowired
    private PmProContRepository pmProContRepository;

    @Autowired
    private PmQdToPoOrderRepository pmQdToPoOrderRepository;
    
    @Autowired
    private PmRuleCodeService pmRuleCodeService;

    @Autowired
    private LovAdapter lovAdapter;

    @Override
    public void afterPropertiesSet() throws Exception {
        PdMatTypeStrategyFactory.register(PdMatType.FHB, this);
    }

    @Override
    public void contFilterInitParam(PmProContFilterRequestDTO pmProContFilterRequest) {
        pmProContFilterRequest.setSgSign(null);
        if (pmProContFilterRequest.getPlateId() == null) {
            // 请选择要组板的坯号！
            throw new CommonException("pm.pm_composite_list_001");
        }
        PmCompositeSlabList pmCompositeSlabList = pmCompositeSlabListRepository
                .selectByPrimaryKey(pmProContFilterRequest.getPlateId());
        PmCompositeSlab pmCompositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(pmCompositeSlabList.getSlabId());
        // 通过基材合同，查询关联的成品合同
        String qfhQueryFlag = BaseConstants.Flag.YES.toString();
        if(StringUtils.isBlank(pmCompositeSlabList.getCompMatNo())) {
            qfhQueryFlag = BaseConstants.Flag.NO.toString();
        }
        // 获取合同性质对应类型
        List<String> lovHavingComList = lovAdapter.queryLovValue(Constants.LovCode.COMPOSITE_CONTRACT_INQUIRY001,
                pmProContFilterRequest.getTenantId()).stream().map(LovValueDTO::getValue).collect(Collectors.toList());
        List<String> lovNotHavingComList = lovAdapter.queryLovValue(Constants.LovCode.COMPOSITE_CONTRACT_INQUIRY002,
                pmProContFilterRequest.getTenantId()).stream().map(LovValueDTO::getValue).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(lovHavingComList)) {
            throw new CommonException("pm.pm_composite_list_010", Constants.LovCode.COMPOSITE_CONTRACT_INQUIRY001);
        }
        if (CollectionUtils.isEmpty(lovNotHavingComList)) {
            throw new CommonException("pm.pm_composite_list_010",Constants.LovCode.COMPOSITE_CONTRACT_INQUIRY002);
        }
        List<String> lovNotHavingComEList = lovAdapter.queryLovValue(Constants.LovCode.COMPOSITE_CONTRACT_INQUIRY003,
                pmProContFilterRequest.getTenantId()).stream().map(LovValueDTO::getValue).collect(Collectors.toList());
        List<String> orderNoList = pmQdToPoOrderRepository.selectFhbOrderNoByBaseOrderNo(
                pmProContFilterRequest.getTenantId(), pmCompositeSlabList.getBaseOrderNo(), pmCompositeSlab.getSlabType() , qfhQueryFlag,
                lovHavingComList, lovNotHavingComList, lovNotHavingComEList);

        if (orderNoList == null || orderNoList.isEmpty()) {
            // 基材合同[”+基材合同号 + “]未维护对应的成品合同信息
            throw new CommonException("pm.pm_composite_list_004", pmCompositeSlabList.getBaseOrderNo());
        } else {
            // 查询成品合同时，校验校验每个成品合同的PD_LACK_QTY+PD_OVER_DEVO_QTY>0,才展示
            List<String> lastOrderNoList = new ArrayList<>();
            List<PmProCont> pmProContList = pmProContRepository.selectByOrderList(orderNoList, pmProContFilterRequest.getTenantId());
            pmProContList.forEach(pmProCont -> {
                if (pmProCont.getPdLackQty().add(pmProCont.getPdOverDevoQty()).compareTo(BigDecimal.ZERO) > 0) {
                    lastOrderNoList.add(pmProCont.getOrderNo());
                }
            });

            pmProContFilterRequest.setOrderNoList(lastOrderNoList);
            pmProContFilterRequest.setMscLineNo(pmCompositeSlab.getMscLineNo());
        }
    }

    @Override
    public boolean contFilterRuleSetCheck(PmProContFilterRequestDTO pmProContFilterRequest,
            PmProContFilterResposeDTO pmProContFilterResposeDTO, List<PmSlabSpecBt> pmSlabSpecBts,
            Map<String, CtMainVO> cmCtMainMap) {
        // 复合板基材合同与成品合同事先维护好了，无需校验规则集
        return true;
    }

    @Override
    public RuleParamDTO contSelectionCheckRuleSet() {
        return null;
    }

    @Override
    public RuleParamDTO contSelectionRuleSet() {
        return null;
    }

    @Override
    public RuleParamDTO pdResultCheckRuleSet() {
        return null;
    }
    
    @Override
    public String getSmallPlateDivNo(String plateNo, String trimCode, int index) {
        return PmPlateConstants.SMALL_PLATE_SPLIT_NO[index];
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PmPdSlab generateResult(PmProContYieldRequestDTO pmProContYield,
            Map<String, PmProContFilterResposeDTO> filterOrderMap, PmCompositeSlabCalcDTO pmCompositeSlabCalc,
            PmProContYieldResposeDTO pmProContYieldRespose, PmContMscTech axisPmContMscTech,
            PmProContProdTtr axisPmProContProdTtr) {
        PmCompositeSlabList pmCompositeSlabList = pmCompositeSlabListRepository
                .selectByPrimaryKey(pmProContYield.getPmContFilterRequest().getPlateId());
        PmCompositeSlab pmCompositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(pmCompositeSlabList.getSlabId());
        // 查询是否生成复合批的板坯记录
        PmPdSlabInfo pmPdSlabInfo = pmPdSlabInfoRepository.selectBySlabNo(pmCompositeSlab.getSlabNo(),
                pmProContYield.getTenantId());

        MmSlab mmSlab = mmSlabRepository.selectBySlabNo(pmCompositeSlab.getSlabNo(), pmProContYield.getTenantId());
        if (mmSlab == null) {
            throw new CommonException("pm.pm_composite_list_005", pmCompositeSlab.getSlabNo());
        }

        WmMatPileVo wmMatPileVo = pmWmMatPileRepository.selectWmMatPileByMatNo(pmCompositeSlab.getSlabNo(),
                pmCompositeSlab.getTenantId());
        if (wmMatPileVo == null) {
            throw new CommonException("pm.pm_pd_slab_info_007", pmCompositeSlab.getSlabNo());
        }

        mmSlab.setStockCode(wmMatPileVo.getStockCode());
        if (pmPdSlabInfo == null) {
            // 生成复合坯的板坯信息表
            pmPdSlabInfo = pmPdSlabInfoService.createFhbSlabInfo(mmSlab, pmCompositeSlab, pmCompositeSlabList, true);
        }
        
        // 生成基材的板坯信息表
        PmPdSlabInfo basePmPdSlabInfo = pmPdSlabInfoService.createFhbSlabInfo(mmSlab, pmCompositeSlab,
                pmCompositeSlabList, false);

        MmPlateVO mmPlateVO = mmPlateRepository.selectByPrimary(pmCompositeSlabList.getBaseMatId());
        if (mmPlateVO == null) {
            throw new CommonException("pm.pm_composite_list_007", pmCompositeSlabList.getBaseMatNo());
        }

        List<PmPdSlab> pdSlabs = pmPdSlabRepository.selectListBySlabNo(pmCompositeSlab.getSlabNo(),
                pmCompositeSlab.getTenantId());

        // 组装基础对象
        PmPdSlab pmpdSlab = pmPdSlabService.buildPmPdSlab(pmProContYield, axisPmContMscTech, axisPmProContProdTtr,
                filterOrderMap);
        // 填充计算结构
        pmPdSlabService.buildPmPdSlab(pmpdSlab, pmProContYield, pmProContYieldRespose, pmCompositeSlabCalc);
        pmpdSlab.setSlabPlaceCode(pmPdSlabInfo.getSlabPlaceCode());
        fillPmPdSlab(mmPlateVO.getPono(), pmProContYield.getTenantId(), pmpdSlab, basePmPdSlabInfo.getSlabNo());
        pmpdSlab.setSlabType(pmPdSlabInfo.getSlabType());
        pmpdSlab.setStNo(axisPmContMscTech.getStNo());
        updateFhbPmPdSlab(pmpdSlab, pmCompositeSlabList);

        this.pmPdSlabRepository.insertSelective(pmpdSlab);

        // 校验组合板重量必须小于基材重量
        List<QdToPoOrderVO1> qdOrderList = pmQdToPoOrderRepository.selectQdOrderList(Collections.singletonList(pmProContYield.getAxisOrderNo()),
                pmProContYield.getTenantId());
        BigDecimal combineWt =  (Utils.getBigDecimalValue(qdOrderList.get(0).getOrderThick()).subtract(Utils.getBigDecimalValue(qdOrderList.get(0).getStainlessThk())))
                .multiply(pmpdSlab.getCombinePlateWidth()).multiply(pmpdSlab.getCombinePlateLen()).multiply(BigDecimal.valueOf(7.85));
        // 基材重量
        BigDecimal baseMatWt = pmCompositeSlabList.getBaseMatThick().multiply(pmCompositeSlabList.getBaseMatWidth())
                .multiply(pmCompositeSlabList.getBaseMatLength()).multiply(BigDecimal.valueOf(7.85));
        if (combineWt.compareTo(baseMatWt) >= 0) {
            throw new CommonException("pm.composite_slab_list_004", combineWt.divide(BigDecimal.valueOf(1000000000),2, RoundingMode.HALF_UP),
                    baseMatWt.divide(BigDecimal.valueOf(1000000000), 2, RoundingMode.HALF_UP));
        }

        // 更新设置虚拟板坯号
        pmProContYield.setVirtualSlabNo(pmpdSlab.getVirtualSlabNo());
        pmProContYieldRespose.setVirtualSlabNo(pmpdSlab.getVirtualSlabNo());

        if (pdSlabs == null || pdSlabs.isEmpty()) {
            if (pmCompositeSlabList.getLayerNo() == 1L) {
                // 如果当前基材是第一层基材，创建复合坯组板板坯表
                // 组装基础对象
                PmPdSlab fhbPmpdSlab = pmPdSlabService.buildPmPdSlab(pmProContYield, axisPmContMscTech,
                        axisPmProContProdTtr, filterOrderMap);
                // 填充计算结构
                pmPdSlabService.buildPmPdSlab(fhbPmpdSlab, pmProContYield, pmProContYieldRespose, pmCompositeSlabCalc);
                fhbPmpdSlab.setSlabPlaceCode(pmPdSlabInfo.getSlabPlaceCode());
                fhbPmpdSlab.setSlabType(pmPdSlabInfo.getSlabType());
                fhbPmpdSlab.setStNo(axisPmContMscTech.getStNo());

                fillPmPdSlab(pmCompositeSlab.getPono(), pmProContYield.getTenantId(), fhbPmpdSlab, pmPdSlabInfo.getSlabNo());

                updateFhbPmPdSlab(fhbPmpdSlab, pmCompositeSlab);
                
                this.pmPdSlabRepository.insertSelective(fhbPmpdSlab);
            }
        }
        pmCompositeSlabService.summaryFhbPmPdSlabInfo(pmCompositeSlab.getSlabNo(), pmProContYield.getTenantId());
        int baseCount = pmCompositeSlabListRepository.selectCountByCondition(Condition.builder(PmCompositeSlabList.class).andWhere(Sqls.custom()
                .andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, pmCompositeSlab.getTenantId()).andEqualTo(PmCompositeSlabList.FIELD_SLAB_ID, pmCompositeSlab.getSlabId())).build());
        int slabCount = pmPdSlabInfoRepository.selectCountByCondition(Condition.builder(PmPdSlabInfo.class).andWhere(Sqls.custom()
                .andEqualTo(PmPdSlab.FIELD_TENANT_ID, pmCompositeSlab.getTenantId()).andEqualTo(PmPdSlabInfo.FIELD_COMPOSITE_SLAB_NO, pmCompositeSlab.getSlabNo())).build());
        if(baseCount > 0 && slabCount > 0 && baseCount == slabCount) {
            // 当全部组板完成时修改状态
            PmCompositeSlab updatePmCompositeSlab = new PmCompositeSlab();
            updatePmCompositeSlab.setSlabId(pmCompositeSlab.getSlabId());
            updatePmCompositeSlab.setObjectVersionNumber(pmCompositeSlab.getObjectVersionNumber());
            updatePmCompositeSlab.setStatusCode(PdStatusHp.PD_STATUS_HP_56);
            pmCompositeSlabRepository.updateByPrimaryKeySelective(updatePmCompositeSlab);
        }
        return pmpdSlab;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCmd(PmPdSlab matParam, List<PmPdContSum> pmPdContSums, List<PmSmallPltPos> pmSmallPltPoss,
            String mscLineNo) {
        // 组板，执行时不生成命令表数据,单坯组板确认时生成命令表
    }

    @Override
    public PmCompositeSlabCalcDTO checkAndInitParams(Map<String, PmProContFilterResposeDTO> filterOrderMap,
            PmProContYieldRequestDTO pmProContYield, PmProContProdTtr axisPmProContProdTtr) {
        PmProContFilterResposeDTO pmProContFilterResposeDTO = filterOrderMap.get(pmProContYield.getAxisOrderNo());
        pmProContYield.getPmContFilterRequest().setRollDirectCode(pmProContFilterResposeDTO.getRollDirectCode());
        return super.checkAndInitParams(filterOrderMap, pmProContYield, axisPmProContProdTtr);
    }

    @Override
    public void yiledCalcBeforeCheck(PmProContYieldRequestDTO pmProContYield, boolean isExec) {
        if (pmProContYield.getPmContFilterRequest().getPlateId() == null) {
            // 请选择要组板的坯号！
            throw new CommonException("pm.pm_composite_list_001");
        }
        PmCompositeSlabList pmCompositeSlabList = pmCompositeSlabListRepository
                .selectByPrimaryKey(pmProContYield.getPmContFilterRequest().getPlateId());
        PmCompositeSlab pmCompositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(pmCompositeSlabList.getSlabId());
        PmPdSlabInfo pmPdSlabInfo = pmPdSlabInfoRepository.selectBySlabNo(pmCompositeSlabList.getBaseMatNo(),
                pmProContYield.getTenantId());
        if (isExec && pmPdSlabInfo != null) {
            // “ 复合坯[”+ 复合坯号 + “]的基材[“ + 基材号 + “] 已组板确认，如需重新组板，请先解散！”
            throw new CommonException("pm.pm_composite_list_002", pmCompositeSlab.getSlabNo(),
                    pmCompositeSlabList.getBaseMatNo());
        }
        if (StringUtils.isBlank(pmProContYield.getPmContFilterRequest().getFormPlateMode())) {
            // 请选择组板类型
            throw new CommonException("pm.pm_composite_list_003");
        }
        if (pmProContYield.getPmProContYieldList() == null || pmProContYield.getPmProContYieldList().isEmpty()) {
            throw new CommonException("pm.pm_composite_list_004", pmProContYield.getAxisOrderNo());
        }
        if(!pmProContYield.isSecondaryDesignFlag()) {
            List<String> orderNoList = Lists.newArrayList();
            for (PmProContYieldDTO pmProContYieldDTO : pmProContYield.getPmProContYieldList()) {
                orderNoList.add(pmProContYieldDTO.getOrderNo());
            }
            if(orderNoList != null && !orderNoList.isEmpty()) {
                List<PmProCont> pmProConts = pmProContRepository.selectByOrderList(orderNoList, pmProContYield.getTenantId());
                for (PmProCont pmProCont : pmProConts) {
                    BigDecimal pdQty = pmProCont.getPdLackQty() == null ? BigDecimal.ZERO : pmProCont.getPdLackQty();
                    BigDecimal pdOverDevoQty = pmProCont.getPdOverDevoQty() == null ? BigDecimal.ZERO : pmProCont.getPdOverDevoQty();
                    pdQty = pdQty.add(pdOverDevoQty);
                    if(pmProContYield.getCompositeBoard().getOrderSpCount() != null 
                            && pmProContYield.getCompositeBoard().getOrderSpCount().containsKey(pmProCont.getOrderNo())) {
                        BigDecimal orderSpCount = pmProContYield.getCompositeBoard().getOrderSpCount().get(pmProCont.getOrderNo());
                        if(orderSpCount.compareTo(pdQty) > 0) {
                            throw new CommonException("pm.pm_pro_cont_041");
                        }
                    }
                }

                // 校验成品合同是否收池
                List<PmProContProdTtr> pmProContProdTtrList = pmProContProdTtrRepository.selectByOrderNoList(orderNoList, pmProContYield.getTenantId());
                if (CollectionUtils.isEmpty(pmProContProdTtrList)) {
                    throw new CommonException("pm.composite_order_rel_006", orderNoList);
                }
                if (pmProContProdTtrList.size() < orderNoList.size()) {
                    List<String> contOrderNoList = pmProContProdTtrList.stream().map(PmProContProdTtr::getOrderNo).collect(Collectors.toList());
                    orderNoList.forEach(orderNo->{
                        if (!contOrderNoList.contains(orderNo)) {
                            throw new CommonException("pm.composite_order_rel_006", orderNo);
                        }
                    });
                    throw new CommonException("pm.composite_order_rel_006", orderNoList);
                }
                // 校验成品合同产线号是否包含基材合同产线号
                List<PmContMscTech> pmContMscTechList = pmContMscTechRepository.selectByOrderNoAndMscLineNo(orderNoList, pmCompositeSlab.getMscLineNo(), pmProContYield.getTenantId());
                if (CollectionUtils.isEmpty(pmContMscTechList)) {
                    throw new CommonException("pm.composite_order_rel_005", orderNoList, pmCompositeSlab.getMscLineNo());
                }
                if (pmContMscTechList.size() < orderNoList.size()) {
                    List<String> contOrderNoList = pmContMscTechList.stream().map(PmContMscTech::getOrderNo).collect(Collectors.toList());
                    orderNoList.forEach(orderNo->{
                        if (!contOrderNoList.contains(orderNo)) {
                            throw new CommonException("pm.composite_order_rel_005", orderNo, pmCompositeSlab.getMscLineNo());
                        }
                    });
                }
            }
        }
        // 设置默认值
        pmProContYield.getPmContFilterRequest().setMoldThick(pmCompositeSlab.getActThick());
        pmProContYield.getPmContFilterRequest().setMoldWidth(pmCompositeSlab.getActWidth());
        pmProContYield.getPmContFilterRequest().setMscLineNo(pmCompositeSlab.getMscLineNo());
        pmProContYield.getPmContFilterRequest().setRollDirectCode(pmCompositeSlab.getRollType());
        pmProContYield.getCompositeBoard().getOrderSpCount();
    }

    @Override
    public void plateCut(Map<String, PmProContFilterResposeDTO> filterOrderMap, PmProContYieldRequestDTO pmProContYield,
            PmProContProdTtr axisPmProContProdTtr, PmCompositeSlabCalcDTO compositeSlabCalcDTO) {
        // 定义每块小板终点位置
        BigDecimal endPos = BigDecimal.ZERO;
        if (compositeSlabCalcDTO.getMLen() != null && !compositeSlabCalcDTO.getMLen().isEmpty()) {
            for (int i = 0; i < compositeSlabCalcDTO.getMLen().size(); i++) {
                BigDecimal mLen = compositeSlabCalcDTO.getMLen().get(i);
                endPos = endPos.add(mLen);
                // 添加分段累计和
                compositeSlabCalcDTO.getSum().add(endPos);
            }
        }
    }

    @Override
    public void calcLpre(PmProContYieldRequestDTO pmProContYield, PmProContProdTtr axisPmProContProdTtr,
            PmCompositeSlabCalcDTO pmCompositeSlabCalc) {
        // 复合板不需要计算临时板坯长
    }

    @Override
    public void calc(PmProContYieldRequestDTO pmProContYield, PmProContProdTtr axisPmProContProdTtr,
            PmCompositeSlabCalcDTO pmCompositeSlabCalc, Map<String, PmProContProdTtr> pmProContProdTtrs,
            PmProContYieldResposeDTO yieldRespose) {
        // 复合板的轧制目标宽度，复合坯上的轧制目标宽度
        PmCompositeSlabList pmCompositeSlabList = pmCompositeSlabListRepository
                .selectByPrimaryKey(pmProContYield.getPmContFilterRequest().getPlateId());
        PmCompositeSlab pmCompositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(pmCompositeSlabList.getSlabId());
        yieldRespose.setWaim(pmCompositeSlab.getRollAimWidth());
        if(yieldRespose.getCombinePlateWidth().compareTo(yieldRespose.getWaim()) >= 0) {
            throw new CommonException("pm.pm_composite_list_008" , yieldRespose.getCombinePlateWidth().toPlainString() , yieldRespose.getWaim().toPlainString());
        }
        
        // 密度（克/cm^3）
        pmProContYield.getPmContFilterRequest().setFixSlabLenFlag(0L);
        pmProContYield.getPmContFilterRequest().setFixSlabLen(BigDecimal.ZERO);
        pmProContYield.getPmContFilterRequest().setSampleLenGice(BigDecimal.ZERO);
        // 碳板密度根据基材上的第一个合同号读取质量的qd_to_po_order表字段PROD_DENSITY值。
        BigDecimal prodDensity = axisPmProContProdTtr.getProdDensity();
        // 厚板轧制重量roll_wt_hp = 轧制目标厚度(mm) * 轧制目标宽度(mm) * 轧制目标长度(mm) * 密度
        // 转化为吨
        yieldRespose.setRollWtHp(yieldRespose.getTaim().multiply(yieldRespose.getWaim())
                .multiply(yieldRespose.getLaim()).multiply(prodDensity)
                .divide(BigDecimal.valueOf(1000L * 1000L * 1000L), PmPlateConstants.WT_SCALE, RoundingMode.HALF_UP));
        
        QdToPoOrderVO1 qdToPoOrderVO1 = pmQdToPoOrderRepository.selectByOrderNo(axisPmProContProdTtr.getOrderNo(), pmProContYield.getTenantId());
        // 不锈钢密度: 据基材上的第一个合同号读取质量的qd_to_po_order表字段COMP_BOARD_DENSITY值
        BigDecimal compBoardDensity = qdToPoOrderVO1.getCompBoardDensity() == null ? BigDecimal.ZERO : qdToPoOrderVO1.getCompBoardDensity();
        // 不锈钢厚度：据基材上的第一个合同号读取质量的qd_to_po_order表字段STAINLESS_THK值。
        BigDecimal stainlessThk = qdToPoOrderVO1.getStainlessThk() == null ? BigDecimal.ZERO : qdToPoOrderVO1.getStainlessThk();
        // 不锈钢重量 = 不锈钢厚度 * 组合板宽度 * 组合板长度 * 不锈钢密度
        BigDecimal stainlessWt = stainlessThk.multiply(yieldRespose.getCombinePlateWidth()).multiply(yieldRespose.getCombinePlateLen()).multiply(compBoardDensity);
        // 碳板重量 = （成品合同订货厚度- 不锈钢厚度）* 组合板宽度 * 组合板长度 * 碳板密度
        BigDecimal baseMatThick = axisPmProContProdTtr.getOrderThick().subtract(stainlessThk);
        BigDecimal baseMatWt = baseMatThick.multiply(yieldRespose.getCombinePlateWidth()).multiply(yieldRespose.getCombinePlateLen()).multiply(prodDensity);
        BigDecimal sumWt = baseMatWt.add(stainlessWt);
        // 厚板轧制重量 = 碳板重量 + 不锈钢重量
        yieldRespose.setRollWtHp(sumWt.divide(BigDecimal.valueOf(1000L * 1000L * 1000L), PmPlateConstants.WT_SCALE, RoundingMode.HALF_UP));
    }

    /**
     * 更新复合板基础信息-复合板基材计算数据处理
     * 
     * @param pmPdSlab
     * @param pmCompositeSlabList

     */
    private void updateFhbPmPdSlab(PmPdSlab pmPdSlab, PmCompositeSlabList pmCompositeSlabList) {
        pmPdSlab.setPreCleanSlabThick(pmCompositeSlabList.getBaseMatThick());
        pmPdSlab.setPreCleanSlabWidth(pmCompositeSlabList.getBaseMatWidth());
        pmPdSlab.setInfurSlabThick(pmCompositeSlabList.getBaseMatThick());
        pmPdSlab.setInfurSlabWid(pmCompositeSlabList.getBaseMatWidth());
        pmPdSlab.setPreCleanSlabLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setPreCleanSlabWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setInfurSlabLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setInfurSlabWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setPreCleanSlabMaxLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setPreCleanSlabMinLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setPreCleanSlabMaxWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setPreCleanSlabMinWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setInfurSlabMaxLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setInfurSlabMinLen(pmCompositeSlabList.getBaseMatLength());
        pmPdSlab.setInfurSlabMaxWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setInfurSlabMinWt(pmCompositeSlabList.getBaseMatWt());
        pmPdSlab.setMatDesignKind(PdMatType.S.getCode());
        pmPdSlab.setIngotType(" ");
        pmPdSlab.setTwoRollInterimFlag(BaseConstants.Flag.NO.longValue());
    }

    /**
     * 更新复合板基础信息-复合板计算数据处理
     * 
     * @param pmPdSlab
     * @param pmCompositeSlab
     */
    private void updateFhbPmPdSlab(PmPdSlab pmPdSlab, PmCompositeSlab pmCompositeSlab) {
        pmPdSlab.setPreCleanSlabThick(pmCompositeSlab.getActThick());
        pmPdSlab.setPreCleanSlabWidth(pmCompositeSlab.getActWidth());
        pmPdSlab.setInfurSlabThick(pmCompositeSlab.getActThick());
        pmPdSlab.setInfurSlabWid(pmCompositeSlab.getActWidth());
        pmPdSlab.setPreCleanSlabLen(pmCompositeSlab.getActLength());
        pmPdSlab.setPreCleanSlabWt(pmCompositeSlab.getActWt());
        pmPdSlab.setInfurSlabLen(pmCompositeSlab.getActLength());
        pmPdSlab.setInfurSlabWt(pmCompositeSlab.getActWt());
        pmPdSlab.setPreCleanSlabMaxLen(pmCompositeSlab.getActLength());
        pmPdSlab.setPreCleanSlabMinLen(pmCompositeSlab.getActLength());
        pmPdSlab.setPreCleanSlabMaxWt(pmCompositeSlab.getActWt());
        pmPdSlab.setPreCleanSlabMinWt(pmCompositeSlab.getActWt());
        pmPdSlab.setInfurSlabMaxLen(pmCompositeSlab.getActLength());
        pmPdSlab.setInfurSlabMinLen(pmCompositeSlab.getActLength());
        pmPdSlab.setInfurSlabMaxWt(pmCompositeSlab.getActWt());
        pmPdSlab.setInfurSlabMinWt(pmCompositeSlab.getActWt());
        pmPdSlab.setRollAimThick(pmCompositeSlab.getRollAimThick());
        pmPdSlab.setRollAimWidth(pmCompositeSlab.getRollAimWidth());
        pmPdSlab.setMatDesignKind(PdMatType.S.getCode());
        pmPdSlab.setIngotType(" ");
        pmPdSlab.setTwoRollInterimFlag(BaseConstants.Flag.NO.longValue());
    }

    /**
     * 生成虚拟板坯号与其他信息
     * 
     * @param pono
     * @param tenantId
     * @param pmPdSlab
     * @param slabNo
     */
    private void fillPmPdSlab(String pono, Long tenantId, PmPdSlab pmPdSlab, String slabNo) {
        Map<String, String> paramsMap = new HashMap<String, String>();
//        paramsMap.put("poNo", pono);
//        String virtualSlabNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.SPLIT_VIRTUAL_SLAB_NO,
//                CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, paramsMap);
        String virtualSlabNo = pmRuleCodeService.generateCode(tenantId,
                Constants.CodeRule.SPLIT_VIRTUAL_SLAB_NO, pono + "S", 4);
        
        pmPdSlab.setVirtualSlabNo(virtualSlabNo);
        pmPdSlab.setSlabNo(slabNo);
        pmPdSlab.setPono(pono);
        pmPdSlab.setPdStatusHp(PdStatusHp.PD_STATUS_HP_18);
    }

    @Override
    public boolean needPlateCut() {
        // 复合板基材组板时，不需要生成粗切位置，复合板粗切位置确定需要多层板合并之后确定。
        return false;
    }

    @Override
    protected String getSlabNo(PmProContYieldRequestDTO pmProContYield) {
        PmCompositeSlabList pmCompositeSlabList = pmCompositeSlabListRepository
                .selectByPrimaryKey(pmProContYield.getPmContFilterRequest().getPlateId());
        return pmCompositeSlabList.getBaseMatNo();
    }

    @Override
    public String pdProgram() {return Constants.PdProgram.FHB_PD_PROGRAM;}

    @Override
    protected PdEventType pdDeleteEventType() {
        return PdEventType.HP11;
    }

    @Override
    protected PdEventType pdFinshedEventType() {
        return PdEventType.HP10;
    }
    
    @Override
    protected Long ctEventBoardPpFlag(PmPdSlab t, PmProContYieldRequestDTO pmProContYield) {
        if("K".equals(t.getSlabType())) {
            return PdProdFlag.STOCK_ROLL_PLATE.getCode();
        }
        return PdProdFlag.COMPOSITE_PLATE.getCode();
    }
    
    @Override
    public void ctEventRec(PmPdSlab t, List<PmSmallPltPos> pmSmallPltPoss,
            Map<String, PmProContFilterResposeDTO> filterOrderMap, PmProContYieldRequestDTO pmProContYield,
            PmCompositeSlabCalcDTO pmCompositeSlabCalc, PmProContYieldResposeDTO pmProContYieldRespose) {
        // 复合板组板不抛合同跟踪组板完成事件
    }
}
