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

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xisc.boot.common.feign.pojo.MtUserInfo;
import com.xisc.boot.common.sys.UserClient;
import com.xisc.pm.api.dto.PmCompositeSlaParamDTO;
import com.xisc.pm.api.dto.PmCompositeSlabCopyDTO;
import com.xisc.pm.api.dto.PmCompositeSlabCopyIdDTO;
import com.xisc.pm.api.dto.PmCompositeSlabDTO;
import com.xisc.pm.api.dto.PmCompositeSlabListCtDTO;
import com.xisc.pm.api.dto.PmCompositeSlabListDTO;
import com.xisc.pm.api.dto.PmCompositeSlabListResDTO;
import com.xisc.pm.api.dto.PmCompositeSlabPdDTO;
import com.xisc.pm.api.dto.PmCompositeSlabReqDTO;
import com.xisc.pm.api.dto.PmCompositeSlabResDTO;
import com.xisc.pm.api.dto.PmCompositeSlabResLineDTO;
import com.xisc.pm.api.dto.PmPdBlockPosDTO;
import com.xisc.pm.api.dto.PmSmallPltPosDTO;
import com.xisc.pm.app.service.PmCmdLargePltService;
import com.xisc.pm.app.service.PmCmdSlabService;
import com.xisc.pm.app.service.PmCompositeSlabService;
import com.xisc.pm.app.service.strategy.FormPlateModeStrategyFactory;
import com.xisc.pm.app.service.strategy.PdMatTypeStrategyFactory;
import com.xisc.pm.app.service.strategy.SecondaryDesignStrategyFactory;
import com.xisc.pm.app.service.strategy.formplatemode.FormPlateModeStrategy;
import com.xisc.pm.app.service.strategy.pdmattype.PdMatTypeStrategy;
import com.xisc.pm.domain.entity.PmCmdCont;
import com.xisc.pm.domain.entity.PmCmdLargePlt;
import com.xisc.pm.domain.entity.PmCmdSlab;
import com.xisc.pm.domain.entity.PmCmdSmallPlt;
import com.xisc.pm.domain.entity.PmCompositeSlab;
import com.xisc.pm.domain.entity.PmCompositeSlabDiv;
import com.xisc.pm.domain.entity.PmCompositeSlabList;
import com.xisc.pm.domain.entity.PmPdBlockPos;
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.PmPdSlabInfo;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.repository.PmCmdContRepository;
import com.xisc.pm.domain.repository.PmCmdLargePltRepository;
import com.xisc.pm.domain.repository.PmCmdSlabRepository;
import com.xisc.pm.domain.repository.PmCmdSmallPltRepository;
import com.xisc.pm.domain.repository.PmCompositeOrderRelRepository;
import com.xisc.pm.domain.repository.PmCompositeSlabDivRepository;
import com.xisc.pm.domain.repository.PmCompositeSlabListRepository;
import com.xisc.pm.domain.repository.PmCompositeSlabRepository;
import com.xisc.pm.domain.repository.PmContMscTechRepository;
import com.xisc.pm.domain.repository.PmPdBlockPosRepository;
import com.xisc.pm.domain.repository.PmPdContSumRepository;
import com.xisc.pm.domain.repository.PmPdPlateCutRepository;
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.PmSmallPltPosRepository;
import com.xisc.pm.domain.vo.CtDetVO;
import com.xisc.pm.domain.vo.EventFeignVO;
import com.xisc.pm.domain.vo.MatStatusModifyVO;
import com.xisc.pm.domain.vo.MmPlateVO;
import com.xisc.pm.domain.vo.MmSlabVO;
import com.xisc.pm.domain.vo.PmCmdVO;
import com.xisc.pm.domain.vo.QdToPoOrderVO;
import com.xisc.pm.domain.vo.WmStockInfoVO;
import com.xisc.pm.infra.client.EventClient;
import com.xisc.pm.infra.client.MmEventClient;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.constant.Constants.PdStatusHp;
import com.xisc.pm.infra.constant.CtEventConstants;
import com.xisc.pm.infra.constant.PmPlateConstants;
import com.xisc.pm.infra.enums.CutPositionType;
import com.xisc.pm.infra.enums.CutType;
import com.xisc.pm.infra.enums.FormPlateMode;
import com.xisc.pm.infra.enums.PdMatType;
import com.xisc.pm.infra.mapper.PmCompositeSlabMapper;
import com.xisc.pm.infra.util.BeanUtils;
import com.xisc.pm.infra.util.PageUtils;
import com.xisc.pm.infra.util.Utils;
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 io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
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.AopProxy;
import org.hzero.core.base.BaseConstants;
import org.hzero.core.redis.RedisHelper;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 复合/叠轧坯基本信息表(PmCompositeSlab)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-08-01 15:46:27
 */
@Slf4j
@Service
public class PmCompositeSlabServiceImpl implements PmCompositeSlabService, AopProxy<PmCompositeSlabService> {

    private PmCompositeSlabRepository pmCompositeSlabRepository;

    private PmCompositeSlabListRepository pmCompositeSlabListRepository;

    private PmProContProdTtrRepository pmProContProdTtrRepository;

    private CodeRuleBuilder codeRuleBuilder;

    private UserClient userClient;
    
    @Autowired
    private RedisHelper redisHelper;

    @Autowired
    private PmPdContSumRepository pmPdContSumRepository;

    @Autowired
    private PmPdBlockPosRepository pmPdBlockPosRepository;

    private PmSmallPltPosRepository pmSmallPltPosRepository;
    
    @Autowired
    protected PmPdPlateCutRepository pmPdPlateCutRepository;
    
    @Autowired
    private PmPdSlabRepository pmPdSlabRepository;
    
    @Autowired
    private PmPdSlabInfoRepository pmPdSlabInfoRepository;
    
    @Autowired
    private PmCmdSlabService pmCmdSlabService;
    
    @Autowired
    private PmCmdLargePltRepository pmCmdLargePltRepository;
    
    @Autowired
    private PmCmdLargePltService pmCmdLargePltService;

    @Autowired
    private LovAdapter lovAdapter;
    
    @Autowired
    private PmCompositeSlabDivRepository pmCompositeSlabDivRepository;

    @Autowired
    private PmCompositeSlabMapper pmCompositeSlabMapper;

    @Autowired
    private EventClient eventClient;

    @Autowired
    private PmCmdSmallPltRepository pmCmdSmallPltRepository;

    @Autowired
    private PmCmdContRepository pmCmdContRepository;

    @Autowired
    private MmEventClient mmEventClient;

    @Autowired
    private PmCmdSlabRepository pmCmdSlabRepository;

    @Autowired
    private PmCompositeOrderRelRepository pmCompositeOrderRelRepository;

    @Autowired
    private PmContMscTechRepository pmContMscTechRepository;

    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    
    public PmCompositeSlabServiceImpl(PmCompositeSlabRepository pmCompositeSlabRepository,
                                      PmCompositeSlabListRepository pmCompositeSlabListRepository,
                                      PmProContProdTtrRepository pmProContProdTtrRepository, CodeRuleBuilder codeRuleBuilder,
                                      UserClient userClient, PmSmallPltPosRepository pmSmallPltPosRepository) {
        this.pmCompositeSlabRepository = pmCompositeSlabRepository;
        this.pmCompositeSlabListRepository = pmCompositeSlabListRepository;
        this.pmProContProdTtrRepository = pmProContProdTtrRepository;
        this.codeRuleBuilder = codeRuleBuilder;
        this.userClient = userClient;
        this.pmSmallPltPosRepository = pmSmallPltPosRepository;
    }

    @Override
    public Page<PmCompositeSlabResDTO> selectList(PageRequest pageRequest, PmCompositeSlabReqDTO dto, Long tenantId) {

        // 1.根据条件查询获取pm_composite_slab表主键id
        List<PmCompositeSlab> pmCompositeSlabs = pmCompositeSlabRepository.selectSlabIds(dto, tenantId);
        // 如果为空，则返回
        if (CollectionUtils.isEmpty(pmCompositeSlabs)) {
            return new Page<>();
        }
        List<Long> slabIdList = pmCompositeSlabs.stream().map(PmCompositeSlab::getSlabId).distinct().collect(Collectors.toList());
        // 根据返参主键id查询复合/叠轧坯基本信息表获取数据
        List<PmCompositeSlab> pmCompositeSlabList = pmCompositeSlabRepository.selectByCondition(Condition.builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlab.FIELD_SLAB_ID, slabIdList))
                .build());
        // 如果为空，则返回
        if (CollectionUtils.isEmpty(pmCompositeSlabList)) {
            return new Page<>();
        }

        // 查询用户账号信息
        List<Long> userIdList = pmCompositeSlabList.stream().map(PmCompositeSlab::getCreatedBy).distinct().collect(Collectors.toList());
        userIdList.addAll(pmCompositeSlabList.stream().map(PmCompositeSlab::getLastUpdatedBy).distinct().collect(Collectors.toList()));
        Map<Long, MtUserInfo> userInfoMap = userClient.userInfoBatchGet(tenantId, userIdList);

        // 查询目的库区所属产线号
        List<Long> stockIdList = pmCompositeSlabList.stream().map(PmCompositeSlab::getDestStockId).distinct().collect(Collectors.toList());
        List<WmStockInfoVO> wmStockInfoVOList = pmCompositeSlabMapper.getStockLineById(stockIdList, tenantId, DetailsHelper.getUserDetails().getUserId());
        Map<Long, String> collewmStockInfoVOMap = new HashMap<>(wmStockInfoVOList.size());
        if (CollectionUtils.isNotEmpty(wmStockInfoVOList)) {
            collewmStockInfoVOMap = wmStockInfoVOList.stream().collect(Collectors.toMap(WmStockInfoVO::getStockId, WmStockInfoVO::getStockLine));
        }

        // 定义返回的list集合
        List<PmCompositeSlabResDTO> resultList = new ArrayList<>();

        // 查询明细表数据
        List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlabList.FIELD_SLAB_ID, slabIdList))
                .build());

        // 将明细表根据头表主键分组Map
        if (CollectionUtils.isNotEmpty(pmCompositeSlabLists)) {
            // 按照关联的主键id分组
            Map<Long, List<PmCompositeSlabList>> pmCompositeSlabListMap = pmCompositeSlabLists.stream().collect(Collectors.groupingBy(PmCompositeSlabList::getSlabId));

            // 遍历查询到的数据
            for (PmCompositeSlab pmCompositeSlab : pmCompositeSlabList) {
                // 定义返回DTO
                PmCompositeSlabResDTO slabResDTO = new PmCompositeSlabResDTO();
                // 赋值
                slabResDTO.setSlabId(pmCompositeSlab.getSlabId());
                slabResDTO.setSlabNo(pmCompositeSlab.getSlabNo());
                slabResDTO.setStatus(pmCompositeSlab.getStatusCode());
                slabResDTO.setStockCodeId(pmCompositeSlab.getDestStockId());
                slabResDTO.setStockLine(collewmStockInfoVOMap.getOrDefault(pmCompositeSlab.getDestStockId(), null));
                slabResDTO.setStockCode(pmCompositeSlab.getDestStockCode());
                slabResDTO.setSlabType(pmCompositeSlab.getSlabType());
                slabResDTO.setCreatedBy(pmCompositeSlab.getCreatedBy());
                if (userInfoMap.containsKey(pmCompositeSlab.getCreatedBy())) {
                    MtUserInfo mtUserInfo =  userInfoMap.get(pmCompositeSlab.getCreatedBy());
                    slabResDTO.setCreatedByName(Strings.concat(mtUserInfo.getLoginName(), mtUserInfo.getRealName()));
                }
                slabResDTO.setLastUpdatedBy(pmCompositeSlab.getLastUpdatedBy());
                if (userInfoMap.containsKey(pmCompositeSlab.getLastUpdatedBy())) {
                    MtUserInfo mtUserInfo =  userInfoMap.get(pmCompositeSlab.getLastUpdatedBy());
                    slabResDTO.setLastUpdatedByName(Strings.concat(mtUserInfo.getLoginName(), mtUserInfo.getRealName()));
                }
                slabResDTO.setCreationDate(pmCompositeSlab.getCreationDate());
                slabResDTO.setLastUpdateDate(pmCompositeSlab.getLastUpdateDate());
                slabResDTO.setMscLineNo(pmCompositeSlab.getMscLineNo());
                slabResDTO.setFactoryCode(pmCompositeSlab.getFactoryCode());
                slabResDTO.setFactoryName(pmCompositeSlab.getFactoryName());

                // 判断明细表是否存在该主键id
                if (!pmCompositeSlabListMap.isEmpty() && pmCompositeSlabListMap.containsKey(pmCompositeSlab.getSlabId())) {
                    List<PmCompositeSlabList> compositeSlabListList = pmCompositeSlabListMap.get(pmCompositeSlab.getSlabId()).stream().sorted(Comparator.comparing(PmCompositeSlabList::getLayerNo)).collect(Collectors.toList());
                    List<String> baseOrderNoList = new ArrayList<>(compositeSlabListList.size());
                    // 赋值合同号
                    for (PmCompositeSlabList compositeSlabList : compositeSlabListList) {
                        baseOrderNoList.add(compositeSlabList.getBaseOrderNo());
                    }
                    slabResDTO.setBaseOrderNoList(baseOrderNoList);
                    resultList.add(slabResDTO);
                }
            }
        }
        // 分页
        return PageUtils.convertListToPage(resultList, pageRequest);

    }

    @Override
    public List<PmCompositeSlabResLineDTO> queryLineList(Long id, Long tenantId) {
        // 根据的表ID列表查询行数据
        List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId)).andWhere(Sqls.custom()
                        .andEqualTo(PmCompositeSlabList.FIELD_SLAB_ID, id)).build());
        if (CollectionUtils.isEmpty(pmCompositeSlabLists)) {
            return Collections.emptyList();
        }
        // 获取所有不重复的合同号列表
        List<String> orderNoList = pmCompositeSlabLists.stream().map(PmCompositeSlabList::getBaseOrderNo).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, orderNoList)).build());

        // 准备存储合同属性表数据的Map，以合同号为键
        Map<String, PmProContProdTtr> pmProContProdTtrMap = new HashMap<>(pmCompositeSlabLists.size());

        // 准备存储最终结果的列表
        List<PmCompositeSlabResLineDTO> resultList = new ArrayList<>();

        // 如果查询到合同属性表信息
        if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
            // 将合同属性表信息按合同号存储到Map中
            pmProContProdTtrMap = pmProContProdTtrList.stream()
                    .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (v1, v2) -> v1));
        }

        // 遍历行数据列表
        for (PmCompositeSlabList line : pmCompositeSlabLists) {
            PmCompositeSlabResLineDTO lineDTO = new PmCompositeSlabResLineDTO();
            lineDTO.setLayerNo(line.getLayerNo());
            lineDTO.setOrderNo(line.getBaseOrderNo());
            // 如果存在合同信息，并且合同属性Map中包含当前合同号对应的订单信息
            if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(line.getBaseOrderNo())) {
                PmProContProdTtr pmProContProdTtr = pmProContProdTtrMap.get(line.getBaseOrderNo());
                lineDTO.setOrderThick(pmProContProdTtr.getOrderThick());
                lineDTO.setOrderWidth(pmProContProdTtr.getOrderWidth());
                lineDTO.setOrderLength(pmProContProdTtr.getOrderLen());
                lineDTO.setSgSign(pmProContProdTtr.getSgSign());
                lineDTO.setOrderCustCname(pmProContProdTtr.getOrderCustCname());
                lineDTO.setConsignCustCname(pmProContProdTtr.getConsignCustCname());
            }
            // 将行数据DTO添加到列表
            resultList.add(lineDTO);
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, PmCompositeSlabDTO dto) {
        // 1.校验
        if (CollectionUtils.isNotEmpty(dto.getLineList())) {
            // 2.查询出来合同数和未编计划数
            List<String> orderNoList = dto.getLineList().stream().map(PmCompositeSlabListDTO::getBaseOrderNo).distinct().collect(Collectors.toList());
            List<PmProContProdTtr> pmProContProdTtrList = pmCompositeSlabListRepository.queryOrderAttrByOrderNo(orderNoList, tenantId);
            Map<String, PmProContProdTtr> orderQtyMap = new HashMap<>(pmProContProdTtrList.size());
            if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
                orderQtyMap = pmProContProdTtrList.stream().collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity(), (v1, v2) -> v1));
            }
            Map<String, List<PmCompositeSlabListDTO>> lineMap = dto.getLineList().stream().collect(Collectors.groupingBy(PmCompositeSlabListDTO::getBaseOrderNo));
            for (Map.Entry<String, List<PmCompositeSlabListDTO>> entry : lineMap.entrySet()) {
                if (!orderQtyMap.isEmpty() && orderQtyMap.containsKey(entry.getKey())) {
                    BigDecimal submitQty = new BigDecimal(entry.getValue().size());
                    PmProContProdTtr pmProContProdTtr = orderQtyMap.get(entry.getKey());
                    // 未编计划数
                    BigDecimal notUserOderQty = new BigDecimal(pmProContProdTtr.getNotUserOderQty());
                    // 合同件数
                    BigDecimal orderNoQty = pmProContProdTtr.getOrderQty();
                    // 已编计划数
                    BigDecimal userOrderNoQty = orderNoQty.subtract(notUserOderQty);
                    // 已编计划数+上此次提交数=计划数
                    BigDecimal planQty = submitQty.add(userOrderNoQty);
                    if (submitQty.compareTo(notUserOderQty) > 0) {
                        throw new CommonException("pm.composite_slab_001", entry.getValue().get(0).getBaseOrderNo(), planQty, orderNoQty);
                    }
                }
            }
        }



        // 生成指令编号
        // 获取当前时间
        LocalDate now = LocalDate.now();
        Map<String, String> paramsMap = new HashMap<>(4);
        paramsMap.put("slabType", dto.getSlabType());
        // 其中厂别区分，根据目的库区代码来判断。根据目的库区代码，调用仓储模块API，查询库区所属产线号，如果产线号为1或2，表示为宽厚板（A）,如果产线号为5表示为5米板（C）
        if ("1".equals(dto.getStockLine()) || "2".equals(dto.getStockLine())) {
            paramsMap.put("factoryCode", "A");
        } else if("5".equals(dto.getStockLine())){
            paramsMap.put("factoryCode", "C");
        } else {
            throw new CommonException("pm.composite_slab_list_003",dto.getStockLine());
        }
        paramsMap.put("year", String.format("%02d%02d%02d", now.getYear() % 100, now.getMonthValue(), now.getDayOfMonth()));

        String slabNo = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.COMPOSITE_SLAB_NO,
                CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, paramsMap);

        // 更新
        PmCompositeSlab pmCompositeSlab = new PmCompositeSlab();
        if (dto.getSlabId() != null) {
            // 删除行数据
            List<PmCompositeSlabList> compositeSlabs = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_SLAB_ID, dto.getSlabId()))
                    .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                    .build());
            pmCompositeSlabListRepository.batchDeleteByPrimaryKey(compositeSlabs);

            // 更新主表
            // 查出来主表这条数据
            List<PmCompositeSlab> pmCompositeSlabs = pmCompositeSlabRepository.selectByCondition(Condition.builder(PmCompositeSlab.class)
                    .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_SLAB_ID, dto.getSlabId()))
                    .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                    .build());
            if (CollectionUtils.isNotEmpty(pmCompositeSlabs)) {
                // 复制
                BeanUtils.copy(pmCompositeSlabs.get(0), pmCompositeSlab);
                // 判断复合坯类型是否修改
                if (!pmCompositeSlabs.get(0).getSlabType().equals(dto.getSlabType())) {
                    pmCompositeSlab.setSlabNo(slabNo);
                }
                // 赋值
                pmCompositeSlab.setSlabId(dto.getSlabId());
                pmCompositeSlab.setSlabType(dto.getSlabType());
                pmCompositeSlab.setDestStockId(dto.getStockCodeId());
                pmCompositeSlab.setDestStockCode(dto.getStockCode());
                pmCompositeSlab.setFactoryCode(dto.getFactoryCode());
                pmCompositeSlab.setFactoryName(dto.getFactoryName());
                pmCompositeSlab.setMscLineNo(dto.getMscLineNo());
                // 更新主表
                pmCompositeSlabRepository.updateByPrimaryKey(pmCompositeSlab);
            }

        } else {
            // 新增
            // 2.存表
            pmCompositeSlab.setSlabNo(slabNo);
            pmCompositeSlab.setStatusCode(Constants.StatusCode.STATUS_CODE_50);
            pmCompositeSlab.setSlabType(dto.getSlabType());
            pmCompositeSlab.setDestStockId(dto.getStockCodeId());
            pmCompositeSlab.setDestStockCode(dto.getStockCode());
            pmCompositeSlab.setFactoryCode(dto.getFactoryCode());
            pmCompositeSlab.setFactoryName(dto.getFactoryName());
            pmCompositeSlab.setMscLineNo(dto.getMscLineNo());
            pmCompositeSlab.setCorrectionFlag(BaseConstants.FlagChar.NO);
            pmCompositeSlab.setTenantId(tenantId);
            // 插入主表
            pmCompositeSlabRepository.insertSelective(pmCompositeSlab);
        }

        // 组装明细表数据
        List<PmCompositeSlabList> pmCompositeSlabList = new ArrayList<>();
        for (PmCompositeSlabListDTO compositeSlabListDTO : dto.getLineList()) {
            PmCompositeSlabList compositeSlabList = new PmCompositeSlabList();
            compositeSlabList.setSlabId(pmCompositeSlab.getSlabId());
            compositeSlabList.setLayerNo(compositeSlabListDTO.getLayerNo());
            compositeSlabList.setBaseOrderId(compositeSlabListDTO.getBaseOrderId());
            compositeSlabList.setBaseOrderNo(compositeSlabListDTO.getBaseOrderNo());
            compositeSlabList.setTenantId(tenantId);
            pmCompositeSlabList.add(compositeSlabList);
        }
        // 插入明细表
        pmCompositeSlabListRepository.batchInsertSelective(pmCompositeSlabList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyData(Long tenantId, PmCompositeSlabCopyDTO dto) {
        // 校验是否为空
        if (Objects.isNull(dto) || CollectionUtils.isEmpty(dto.getSlabIdList())) {
            return;
        }

        // 查询基本信息表数据
        Map<Long, String> idStockLineMap = dto.getSlabIdList().stream().collect(Collectors
                .toMap(PmCompositeSlabCopyIdDTO::getSlabId, PmCompositeSlabCopyIdDTO::getStockLine));
        List<Long> idList = dto.getSlabIdList().stream().map(PmCompositeSlabCopyIdDTO::getSlabId).collect(Collectors.toList());
        List<PmCompositeSlab> pmCompositeSlabs = pmCompositeSlabRepository.selectByCondition(Condition.builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlab.FIELD_SLAB_ID, idList))
                .build());
        // 查询明细表数据
        List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlabList.FIELD_SLAB_ID, idList))
                .build());
        // 如果未查到，则返回
        if (CollectionUtils.isEmpty(pmCompositeSlabs)) {
            return;
        }
        // 获取明细表数据根据主键id映射
        Map<Long, List<PmCompositeSlabList>> pmCompositeSlabListMap = new HashMap<>(pmCompositeSlabLists.size());
        if (CollectionUtils.isNotEmpty(pmCompositeSlabLists)) {
            // 校验合同件数
            // 1.获取合同号
            List<String> orderNoList = pmCompositeSlabLists.stream().map(PmCompositeSlabList::getBaseOrderNo).distinct().collect(Collectors.toList());
            // 2.查询出来合同号和未编计划数
            List<PmProContProdTtr> pmProContProdTtrList = pmCompositeSlabListRepository.queryOrderAttrByOrderNo(orderNoList, tenantId);
            Map<String, Long> orderQtyMap = new HashMap<>(pmProContProdTtrList.size());
            if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
                orderQtyMap = pmProContProdTtrList.stream().collect(Collectors.toMap(PmProContProdTtr::getOrderNo, PmProContProdTtr::getNotUserOderQty));
            }
            // 计算复制要提交的合同计划数
            Map<String, Long> submitOrderQtyMap = new HashMap<>(pmCompositeSlabLists.size());
            for (PmCompositeSlabList slabList : pmCompositeSlabLists) {

                if (!submitOrderQtyMap.isEmpty() && submitOrderQtyMap.containsKey(slabList.getBaseOrderNo())) {
                    Long addOrderQty = submitOrderQtyMap.get(slabList.getBaseOrderNo()) + 1 * dto.getCopies();
                    if (!orderQtyMap.isEmpty()) {
                        if (addOrderQty > orderQtyMap.getOrDefault(slabList.getBaseOrderNo(), 0L)) {
                            throw new CommonException("pm.composite_slab_002", slabList.getBaseOrderNo());
                        }
                        submitOrderQtyMap.put(slabList.getBaseOrderNo(), addOrderQty);
                    }
                } else {
                    Long qty = 1 * dto.getCopies();
                    submitOrderQtyMap.put(slabList.getBaseOrderNo(), qty);
                    if (qty > orderQtyMap.getOrDefault(slabList.getBaseOrderNo(), 0L)) {
                        throw new CommonException("pm.composite_slab_002", slabList.getBaseOrderNo());
                    }
                }
            }

            pmCompositeSlabListMap = pmCompositeSlabLists.stream()
                    .collect(Collectors.groupingBy(PmCompositeSlabList::getSlabId));
        }

        List<PmCompositeSlabList> newPmCompositeSlabLists = new ArrayList<>();


        // 获取当前时间
        LocalDate now = LocalDate.now();
        // 该条基表数据创建条数集合
        List<PmCompositeSlab> newPmCompositeSlabs = new ArrayList<>();
        Map<Long, String> slabIdNoMap = new HashMap<>(pmCompositeSlabs.size());
        // 遍历基本表数据
        for (PmCompositeSlab pmCompositeSlab : pmCompositeSlabs) {
            // 批量生成指令编号
            Map<String, String> paramsMap = new HashMap<>(4);
            paramsMap.put("slabType", pmCompositeSlab.getSlabType());
            // 其中厂别区分，根据目的库区代码来判断。根据目的库区代码，调用仓储模块API，查询库区所属产线号，如果产线号为1或2，表示为宽厚板（A）,如果产线号为5表示为5米板（C）
            if ("1".equals(idStockLineMap.get(pmCompositeSlab.getSlabId())) || "2".equals(idStockLineMap.get(pmCompositeSlab.getSlabId()))) {
                paramsMap.put("factoryCode", "A");
            } else if("5".equals(idStockLineMap.get(pmCompositeSlab.getSlabId()))){
                paramsMap.put("factoryCode", "C");
            } else {
                throw new CommonException("pm.composite_slab_list_003",idStockLineMap.get(pmCompositeSlab.getSlabId()));
            }
            paramsMap.put("year", String.format("%02d%02d%02d", now.getYear() % 100, now.getMonthValue(), now.getDayOfMonth()));
            List<String> slabNoList = codeRuleBuilder.batchGenerateCode(dto.getCopies().intValue(), tenantId, Constants.CodeRule.COMPOSITE_SLAB_NO,
                    CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, paramsMap);
            // 遍历所需份数
            for (int i = 0; i < dto.getCopies(); i++) {
                PmCompositeSlab newPmCompositeSlab = new PmCompositeSlab();
                newPmCompositeSlab.setSlabNo(slabNoList.get(i));
                newPmCompositeSlab.setStatusCode(Constants.StatusCode.STATUS_CODE_50);
                newPmCompositeSlab.setSlabType(pmCompositeSlab.getSlabType());
                newPmCompositeSlab.setDestStockId(pmCompositeSlab.getDestStockId());
                newPmCompositeSlab.setDestStockCode(pmCompositeSlab.getDestStockCode());
                newPmCompositeSlab.setFactoryCode(pmCompositeSlab.getFactoryCode());
                newPmCompositeSlab.setFactoryName(pmCompositeSlab.getFactoryName());
                newPmCompositeSlab.setMscLineNo(pmCompositeSlab.getMscLineNo());
                newPmCompositeSlab.setCorrectionFlag(BaseConstants.FlagChar.NO);
                newPmCompositeSlab.setTenantId(tenantId);
                newPmCompositeSlabs.add(newPmCompositeSlab);

                // 主键id和新的slabNo复合坯号映射关系
                slabIdNoMap.put(pmCompositeSlab.getSlabId() + i, slabNoList.get(i));
            }
        }
        // 插入基本表
        pmCompositeSlabRepository.batchInsertSelective(newPmCompositeSlabs);

        // 获取新建复合坯号和主键的映射关系
        Map<String, Long> newIdNoMap = newPmCompositeSlabs.stream().
                collect(Collectors.toMap(PmCompositeSlab::getSlabNo, PmCompositeSlab::getSlabId));


        // 遍历份数，复制行
        for (int i = 0; i < dto.getCopies(); i++) {
            // 遍历头
            for (PmCompositeSlab pmCompositeSlab : pmCompositeSlabs) {
                // 该条基表对应明细表数据创建条数集合
                List<PmCompositeSlabList> compositeSlabListList = new ArrayList<>();
                // 获取基表对应明细表集合
                if (!pmCompositeSlabListMap.isEmpty() && pmCompositeSlabListMap.containsKey(pmCompositeSlab.getSlabId())) {
                    compositeSlabListList = pmCompositeSlabListMap.get(pmCompositeSlab.getSlabId());
                }

                // 组装行
                for (PmCompositeSlabList compositeSlabList : compositeSlabListList) {
                    PmCompositeSlabList newPmCompositeSlabList = new PmCompositeSlabList();
                    newPmCompositeSlabList.setSlabId( newIdNoMap.get(slabIdNoMap.get(pmCompositeSlab.getSlabId()+ i)));
                    newPmCompositeSlabList.setLayerNo(compositeSlabList.getLayerNo());
                    newPmCompositeSlabList.setBaseOrderId(compositeSlabList.getBaseOrderId());
                    newPmCompositeSlabList.setBaseOrderNo(compositeSlabList.getBaseOrderNo());
                    newPmCompositeSlabList.setTenantId(tenantId);
                    newPmCompositeSlabLists.add(newPmCompositeSlabList);
                }
            }
        }
        // 插入明细表
        pmCompositeSlabListRepository.batchInsertSelective(newPmCompositeSlabLists);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteListBySlabId(Long tenantId, List<Long> slabIdList) {
        // 检查板坯ID列表是否为空，如果为空直接返回，不执行删除操作
        if (CollectionUtils.isEmpty(slabIdList)) {
            return;
        }
        // 获取当前用户id
        Long userId = DetailsHelper.getUserDetails().getUserId();
        // 根据主键获取信息
        List<PmCompositeSlab> pmCompositeSlabs = pmCompositeSlabRepository.selectByCondition(Condition.builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlab.FIELD_SLAB_ID, slabIdList))
                .build());
        // 如果未查到数据，则返回
        if (CollectionUtils.isEmpty(pmCompositeSlabs)) {
            return;
        }
        // 获取创建人名称
        List<Long> createdByList = pmCompositeSlabs.stream().map(PmCompositeSlab::getCreatedBy).collect(Collectors.toList());
        Map<Long, MtUserInfo> mtUserInfoMap = userClient.userInfoBatchGet(tenantId, createdByList);
        // 校验数据
        for (PmCompositeSlab pmCompositeSlab : pmCompositeSlabs) {
            // 状态代码必须为50
            if (!pmCompositeSlab.getStatusCode().equals(Constants.StatusCode.STATUS_CODE_50)) {
                throw new CommonException("pm.composite_slab_003");
            }
            // 操作人只能删除自己建立的计划
            if (!pmCompositeSlab.getCreatedBy().equals(userId)) {
                throw new CommonException("pm.composite_slab_004", mtUserInfoMap.getOrDefault(pmCompositeSlab.getCreatedBy(), null));
            }
        }

        // 批量删除复合板记录
        pmCompositeSlabRepository.batchDeleteByPrimaryKey(pmCompositeSlabs);
        // 查询明细表数据
        List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCompositeSlabList.FIELD_SLAB_ID, slabIdList))
                .build());
        // 批量删除
        pmCompositeSlabListRepository.batchDeleteByPrimaryKey(pmCompositeSlabLists);
    }

    @Override
    public Page<PmCompositeSlab> confirmList(PageRequest pageRequest, PmCompositeSlaParamDTO dto, Long tenantId) {
        //状态为组板完成， 根据条件查询
        Condition build = Condition.builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_DEST_STOCK_CODE, dto.getStockCode(), true))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_STATUS_CODE, dto.getStatusCode(), true))
                .andWhere(Sqls.custom().andLike(PmCompositeSlab.FIELD_SLAB_NO, dto.getSlabNo(), true))
                .andWhere(Sqls.custom().andLike(PmCompositeSlab.FIELD_SLAB_TYPE, dto.getSlabType(), true))
                .andWhere(Sqls.custom().andGreaterThanOrEqualTo(PmCompositeSlab.FIELD_CREATION_DATE, dto.getCreateDateFrom(), true))
                .andWhere(Sqls.custom().andLessThanOrEqualTo(PmCompositeSlab.FIELD_CREATION_DATE, dto.getCreateDateTo(), true))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_CREATED_BY, dto.getCreatedById(), true))
                .andWhere(Sqls.custom().andLike(PmCompositeSlab.FIELD_SAMPLE_LOT_NO, dto.getSampleLotNo(), true))
//                .andWhere(Sqls.custom().andLike(PmCompositeSlab.FIELD_STATUS_CODE, PdStatusHp.PD_STATUS_HP_56))
                .build();
        Page<PmCompositeSlab> page = PageHelper.doPageAndSort(pageRequest, () ->  pmCompositeSlabRepository.selectByCondition(build));
        return page;
    }
    
    @Override
    public Page<PmCompositeSlabPdDTO> compositePdList(PageRequest pageRequest, PmCompositeSlaParamDTO dto,
            Long organizationId) {
        dto.setTenantId(organizationId);
        return PageHelper.doPageAndSort(pageRequest, () ->  pmCompositeSlabRepository.compositePdList(dto));
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void release(Long organizationId, List<Long> idList , boolean singleLayer) {
        if(idList == null) {
            throw new CommonException("pm.composite_slab_006");
        }
        if(singleLayer  && idList.size() != 1) {
            // 请选择某层基材进行组板解散！
            throw new CommonException("pm.composite_slab_006");
        }
        List<PmCompositeSlabList> compositeSlabLists = pmCompositeSlabListRepository.selectByIds(idList.stream().map(Object::toString).collect(Collectors.joining(",")));
        if(compositeSlabLists == null || compositeSlabLists.isEmpty()) {
            throw new CommonException("pm.composite_slab_006");
        }
        PmCompositeSlab compositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(compositeSlabLists.get(0).getSlabId());
        List<String> baseMatNoList = new ArrayList<String>(16);
        List<String> matNoList = new ArrayList<String>(16);
        List<PmPdSlabInfo> deletePmPdSlabInfo = new ArrayList<>();
        Map<String , String> mscLineNoMap = new HashMap<>();
        if(PdStatusHp.PD_STATUS_HP_58.equals(compositeSlab.getStatusCode())) {
            throw new CommonException("pm.composite_slab_021" ,compositeSlab.getSlabNo() , compositeSlab.getStatusCode());
        }
        for (PmCompositeSlabList compositeSlabList : compositeSlabLists) {
            baseMatNoList.add(compositeSlabList.getBaseMatNo());
            if(!compositeSlab.getSlabId().equals(compositeSlabList.getSlabId())) {
                throw new CommonException("pm.composite_slab_007");
            }
            PmPdSlabInfo pmPdSlabInfo = new PmPdSlabInfo();
            pmPdSlabInfo.setTenantId(organizationId);
            pmPdSlabInfo.setSlabNo(compositeSlabList.getBaseMatNo());
            deletePmPdSlabInfo.add(pmPdSlabInfo);
            if(compositeSlabList.getLayerNo() != null && compositeSlabList.getLayerNo() == 1L) {
                // 单删除第一层基材时，需要删除复合坯的PmPdSlab
                baseMatNoList.add(compositeSlab.getSlabNo());
            }
        }
        pmPdSlabInfoRepository.batchDelete(deletePmPdSlabInfo);
        int slabCount = pmPdSlabInfoRepository.selectCountByCondition(Condition.builder(PmPdSlabInfo.class).andWhere(Sqls.custom()
                .andEqualTo(PmPdSlab.FIELD_TENANT_ID, compositeSlab.getTenantId()).andEqualTo(PmPdSlabInfo.FIELD_COMPOSITE_SLAB_NO, compositeSlab.getSlabNo())).build());
        if(slabCount == 0) {
            // 如果所有基材解散，删除组板信息表数据
            PmPdSlabInfo pmPdSlabInfo = new PmPdSlabInfo();
            pmPdSlabInfo.setTenantId(organizationId);
            pmPdSlabInfo.setSlabNo(compositeSlab.getSlabNo());
            pmPdSlabInfoRepository.delete(pmPdSlabInfo);
        }
        List<PmPdSlab> pmPdSlabs = pmPdSlabRepository.selectByCondition(Condition.builder(PmPdSlab.class).andWhere(Sqls.custom()
                .andEqualTo(PmPdSlab.FIELD_TENANT_ID,organizationId)
                .andIn(PmPdSlab.FIELD_SLAB_NO, baseMatNoList)).build());
        for (PmPdSlab pmPdSlab : pmPdSlabs) {
            matNoList.add(pmPdSlab.getVirtualSlabNo());
            mscLineNoMap.put(pmPdSlab.getVirtualSlabNo(), pmPdSlab.getMscLineNo());
        }
        // 修改欠件数
        if(matNoList != null && !matNoList.isEmpty()) {
            List<PmPdContSum> pdPmPdContSums = pmPdContSumRepository.selectByPdMatNoList(organizationId, matNoList);
            Map<String , List<PmPdContSum>> contSumMap = pdPmPdContSums.stream().collect(Collectors.groupingBy(PmPdContSum::getPdMatNo));
            PdMatTypeStrategy pdMatTypeStrategy = PdMatTypeStrategyFactory.matchStrategy(PdMatType.FHB);
            for (Entry<String, List<PmPdContSum>> entry : contSumMap.entrySet()) {
                pdMatTypeStrategy.pdDeleteEvent(entry.getValue(), entry.getKey()
                        , mscLineNoMap.get(entry.getKey()), Constants.PdProgram.FHB_PD_DELETED_PROGRAM, organizationId);
            }
        
            pmPdSlabRepository.batchDeleteByPrimaryKey(pmPdSlabs);
            pmPdContSumRepository.deleteByMatNo(organizationId, matNoList);
            pmSmallPltPosRepository.deleteByMatNo(organizationId, matNoList);
//          pmPdPlateCutRepository.deleteByMatNo(organizationId, matNoList);
            pmPdBlockPosRepository.deleteByMatNo(organizationId, matNoList);
        }
        summaryFhbPmPdSlabInfo(compositeSlab.getSlabNo(), organizationId);
        // 当全部组板完成时修改状态
        PmCompositeSlab updatePmCompositeSlab = new PmCompositeSlab();
        updatePmCompositeSlab.setSlabId(compositeSlab.getSlabId());
        updatePmCompositeSlab.setObjectVersionNumber(compositeSlab.getObjectVersionNumber());
        updatePmCompositeSlab.setStatusCode(PdStatusHp.PD_STATUS_HP_54);
        pmCompositeSlabRepository.updateByPrimaryKeySelective(updatePmCompositeSlab);
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void singleConfirm(Long organizationId, PmCompositeSlab pmCompositeSlab) {
        String key = String.format(PmPlateConstants.FHB_SINGLE_CONFIRM_KEY, organizationId.toString() , pmCompositeSlab.getSlabId().toString());
        PmCompositeSlab compositeSlab = pmCompositeSlabRepository.selectByPrimaryKey(pmCompositeSlab.getSlabId());
        if(redisHelper.hasKey(key )) {
            throw new CommonException("pm.composite_slab_011",compositeSlab.getSlabNo());
        }
        String oneBaseMatNo = Strings.EMPTY;
        try {
            redisHelper.strSet(key, "1", 1L, TimeUnit.MINUTES);
            if(compositeSlab == null) {
                throw new CommonException("pm.composite_slab_008");
            }
            if(!PdStatusHp.PD_STATUS_HP_56.equals(compositeSlab.getStatusCode())) {
                throw new CommonException("pm.composite_slab_019");
            }
            if(PdStatusHp.PD_STATUS_HP_58.equals(compositeSlab.getStatusCode())) {
                throw new CommonException("pm.composite_slab_010" ,compositeSlab.getSlabNo() , compositeSlab.getStatusCode());
            }
            List<String> virtaulSlabNoList = Lists.newArrayList();
            PmPdSlabInfo slabInfo = pmPdSlabInfoRepository.selectBySlabNo(compositeSlab.getSlabNo(), organizationId);
            if(slabInfo == null) {
                throw new CommonException("pm.composite_slab_009" , compositeSlab.getSlabNo());
            }
            // 生成复合坯的命令信息
            List<PmPdSlab> pmPdSlabs = pmPdSlabRepository.selectListBySlabNo(compositeSlab.getSlabNo(), organizationId);
            pmCmdSlabService.createPmCmdSlab(slabInfo, pmPdSlabs, compositeSlab.getMscLineNo());
            
            PmCompositeSlabList param = new PmCompositeSlabList();
            param.setTenantId(organizationId);
            param.setSlabId(compositeSlab.getSlabId());
            List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectList(param);
            List<PmCompositeSlabDiv> pmCompositeSlabDivs = new ArrayList<>();
            Map<Long , Map<BigDecimal, Long>> mlenMap = new HashMap<>(pmCompositeSlabLists.size());
            
            List<LovValueDTO> lovValueDTOs = lovAdapter.queryLovValue(Constants.LovCode.PM_CUT_LENGTH, organizationId, BaseConstants.Flag.YES);
            List<LovValueDTO> cutHeadLovValueDTOs = lovAdapter.queryLovValue(Constants.LovCode.PM_COMPOSITE_CUT_HEAD, organizationId, BaseConstants.Flag.YES);
            BigDecimal cutMax = null;
            BigDecimal cutHead = null;
            try {
                cutMax = new BigDecimal(lovValueDTOs.get(0).getValue());
            } catch (Exception e) {
                log.error(String.format("通过值集[%s]失败：%s", Constants.LovCode.PM_CUT_LENGTH , e.getMessage()));
                throw new CommonException("pm.composite_slab_012" , Constants.LovCode.PM_CUT_LENGTH);
            }
            try {
                cutHead = new BigDecimal(cutHeadLovValueDTOs.get(0).getValue());
            } catch (Exception e) {
                log.error(String.format("通过值集[%s]失败：%s", Constants.LovCode.PM_COMPOSITE_CUT_HEAD , e.getMessage()));
                throw new CommonException("pm.composite_slab_012" , Constants.LovCode.PM_COMPOSITE_CUT_HEAD);
            }
            List<String> baseMatNoList = new ArrayList<>();
            for (PmCompositeSlabList pmCompositeSlabList : pmCompositeSlabLists) {
                baseMatNoList.add(pmCompositeSlabList.getBaseMatNo());
            }
            List<PmPdSlabInfo> pmPdSlabInfos = pmPdSlabInfoRepository.selectByCondition(Condition.builder(PmPdSlabInfo.class).andWhere(Sqls.custom()
                    .andEqualTo(PmPdSlabInfo.FIELD_TENANT_ID, organizationId).andIn(PmPdSlabInfo.FIELD_SLAB_NO, baseMatNoList)).build());
            if(pmPdSlabInfos == null || pmPdSlabInfos.isEmpty()) {
                throw new CommonException("pm.composite_slab_009");
            }
            Map<String , PmPdSlabInfo> pmPdSlabInfoMap = Maps.uniqueIndex(pmPdSlabInfos, PmPdSlabInfo::getSlabNo);
            List<PmPdSlab> basePmPdSlabList = pmPdSlabRepository.selectByCondition(Condition.builder(PmPdSlab.class).andWhere(Sqls.custom()
                    .andEqualTo(PmPdSlab.FIELD_TENANT_ID, organizationId).andIn(PmPdSlab.FIELD_SLAB_NO, baseMatNoList)).build());
            if(basePmPdSlabList == null || basePmPdSlabList.isEmpty()) {
                throw new CommonException("pm.composite_slab_009");
            }
            Map<String , List<PmPdSlab>> basePmPdSlabMap = basePmPdSlabList.stream().collect(Collectors.groupingBy(PmPdSlab::getSlabNo));
            Map<String, String> slabVirtualNoMap = basePmPdSlabList.stream().collect(Collectors.toMap(PmPdSlab::getSlabNo, PmPdSlab::getVirtualSlabNo, (v1, v2) -> v1));
            
            List<String> axisOrderNoList = new ArrayList<>(pmCompositeSlabLists.size());

            String copyVirtualSlabNo = null;
            for (PmCompositeSlabList pmCompositeSlabList : pmCompositeSlabLists) {
                if (pmCompositeSlabList.getLayerNo().equals(1L)) {
                    oneBaseMatNo = pmCompositeSlabList.getBaseMatNo();
                }
                
                PmPdSlabInfo baseSlabInfo = pmPdSlabInfoMap.get(pmCompositeSlabList.getBaseMatNo());
                if(baseSlabInfo == null) {
                    throw new CommonException("pm.composite_slab_009" , pmCompositeSlabList.getBaseMatNo());
                }
                List<PmPdSlab> basePmPdSlabs =  basePmPdSlabMap.get(baseSlabInfo.getSlabNo());
                for (PmPdSlab pmPdSlab : basePmPdSlabs) {
                    virtaulSlabNoList.add(pmPdSlab.getVirtualSlabNo());
                    axisOrderNoList.add(pmPdSlab.getOrderNoAxis());
                }
                // 复合坯层数不会太多
                pmCmdSlabService.createPmCmdSlab(baseSlabInfo, basePmPdSlabs, compositeSlab.getMscLineNo());

                // 生成复合坯的命令小板表和命令参数表
                if (pmCompositeSlabList.getLayerNo().equals(1L)) {
//                    List<String> baseVirtualList = basePmPdSlabs.stream().map(PmPdSlab::getVirtualSlabNo).distinct().collect(Collectors.toList());
//                    if (CollectionUtils.isEmpty(pmPdSlabs)) {
//                        throw new CommonException("pm.pd_slab_001","复合坯号", compositeSlab.getSlabNo(), "组板板坯表");
//                    }
//                    self().createCmdContPlt(baseVirtualList, pmPdSlabs, organizationId);
                      copyVirtualSlabNo = basePmPdSlabs.get(0).getVirtualSlabNo();
                }
                
                PmCompositeSlabDiv pmCompositeSlabDiv = new PmCompositeSlabDiv();
                PmPdSlab basePmPdSlab = basePmPdSlabs.get(0);
                pmCompositeSlabDiv.setPonoSlab(CollectionUtils.isNotEmpty(pmPdSlabs) ? pmPdSlabs.get(0).getVirtualSlabNo() : null);
                pmCompositeSlabDiv.setAimPonoSlab(basePmPdSlab.getVirtualSlabNo());
                pmCompositeSlabDiv.setLayerNo(pmCompositeSlabList.getLayerNo());
                pmCompositeSlabDiv.setTenantId(organizationId);
                pmCompositeSlabDivs.add(pmCompositeSlabDiv);
                
            }
            // 校验当前组板合同的合同跟踪欠件大于当前组板合同的数量
            List<PmPdContSum> contSumList = pmPdContSumRepository.selectByPdMatNoList(organizationId, virtaulSlabNoList);
            List<String> orderNoList = new ArrayList<>(contSumList.size());
            Map<String, Long> contOrderMap = new HashMap<>(contSumList.size());
            if (CollectionUtils.isNotEmpty(contSumList)) {
                for (PmPdContSum pmPdContSum : contSumList) {
                    orderNoList.add(pmPdContSum.getOrderNo());
                }
                List<CtDetVO> ctDetVOList =  pmCompositeSlabRepository.selectCtDetByOrderList(orderNoList, organizationId);
                for (CtDetVO ctDetVO : ctDetVOList) {
                    Long stockNum = ctDetVO.getStockNum() == null ? 0L : ctDetVO.getStockNum();
                    if (stockNum.compareTo(contOrderMap.getOrDefault(ctDetVO.getOrderNo(), 0L)) < 0) {
                        throw new CommonException("pm.pd_cont_sum_001", ctDetVO.getOrderNo(), stockNum, contOrderMap.get(ctDetVO.getOrderNo()));
                    }
                }
            }
            
            // 生成复合板命令板坯号对照命令表（PM_COMPOSITE_SLAB_DIV）,复合板类型为K时，不生成
            if (!"K".equals(pmCompositeSlab.getSlabType())) {
                pmCompositeSlabDivRepository.batchInsertSelective(pmCompositeSlabDivs);
            }
            
            List<PmProContProdTtr> axisPmProContProdTtrs = this.pmProContProdTtrRepository.selectByOrderNoList(axisOrderNoList, organizationId);
            Map<String , PmProContProdTtr> axisOrderMap = Maps.uniqueIndex(axisPmProContProdTtrs, PmProContProdTtr::getOrderNo);
            // 生成大板粗切 
            Map<BigDecimal , Integer> lenMap = new TreeMap<>();
            BigDecimal maxLen = BigDecimal.ZERO; 
            for (PmCompositeSlabList pmCompositeSlabList : pmCompositeSlabLists) {
                List<PmPdSlab> basePmPdSlabs =  basePmPdSlabMap.get(pmCompositeSlabList.getBaseMatNo());
                PmPdSlab basePmPdSlab = basePmPdSlabs.get(0);
                FormPlateModeStrategy formPlateModeStrategy = FormPlateModeStrategyFactory.matchStrategy(basePmPdSlab.getFormPlateMode());
                List<BigDecimal> mlenEndPos = formPlateModeStrategy.motherableEndPosList(FormPlateMode.getByCode(basePmPdSlab.getFormPlateMode()),basePmPdSlab.getVirtualSlabNo(), organizationId, Utils.mscLineNoToRoolLineNo(basePmPdSlab.getMscLineNo())
                        , axisOrderMap.get(basePmPdSlab.getOrderNoAxis()));
                long i = 1 ;
                mlenMap.put(pmCompositeSlabList.getLayerNo(), new HashMap<>());
                for (BigDecimal mlen : mlenEndPos) {
                    mlenMap.get(pmCompositeSlabList.getLayerNo()).put(mlen, i++);
                }
                for (BigDecimal len : mlenEndPos) {
                    maxLen = Utils.maxValue(maxLen , len);
                    if(lenMap.containsKey(len)) {
                        lenMap.put(len, lenMap.get(len)+1);
                    } else {
                        lenMap.put(len, 1);
                    }
                }
            }
            Set<BigDecimal> cutLengthList = new LinkedHashSet<>();
            // 上一块相同母板长的位置
            BigDecimal lastSmallPlateLen = BigDecimal.ZERO;
            // 上一条粗切位置
            BigDecimal lastCutLength = BigDecimal.ZERO;
            if(cutMax.compareTo(maxLen) < 0) {
                for (Entry<BigDecimal, Integer> entry : lenMap.entrySet()) {
                    if(entry.getValue() == pmCompositeSlabLists.size()
                            && entry.getKey().compareTo(maxLen) < 0) {
                        if(cutMax.compareTo(entry.getKey().subtract(lastCutLength)) < 0) {
                            if(lastSmallPlateLen.compareTo(BigDecimal.ZERO) == 0) {
                                // 如果是第一款
                                lastCutLength = entry.getKey();
                                cutLengthList.add(entry.getKey());
                            } else {
                                cutLengthList.add(lastSmallPlateLen);
                                lastCutLength = lastSmallPlateLen;
                            }
                            lastCutLength = entry.getKey();
                        } else if(cutMax.compareTo(entry.getKey().subtract(lastCutLength)) == 0) {
                            lastCutLength = entry.getKey();
                            cutLengthList.add(entry.getKey());
                        } else {
                            lastSmallPlateLen = entry.getKey();
                        }
                        
                    }
                }
                if(cutLengthList.isEmpty() && lastSmallPlateLen.compareTo(BigDecimal.ZERO) > 0) {
                    cutLengthList.add(lastSmallPlateLen);
                }
            
                List<PmPdPlateCut> pmPdPlateCuts = new ArrayList<>();
                if(cutLengthList.isEmpty()) {
                    throw new CommonException("pm.pm_composite_list_009" , cutMax.toPlainString());
                } else {
                    for (BigDecimal cutLength : cutLengthList) {
                        BigDecimal currentValue = cutLength;
                        if(cutHead != null && currentValue != null) {
                            currentValue = currentValue.add(cutHead);
                        }
                        PmPdPlateCut pdPlateCut = new PmPdPlateCut();
                        pdPlateCut.setCutType(CutType.P.getCode());
                        pdPlateCut.setPdMatNo(pmPdSlabs.get(0).getVirtualSlabNo());
                        pdPlateCut.setPositionSeq(null);
                        pdPlateCut.setPositionType(CutPositionType.F.getCode());
                        pdPlateCut.setCutLength(currentValue);
                        pdPlateCut.setTenantId(pmPdSlabs.get(0).getTenantId());
                        pmPdPlateCuts.add(pdPlateCut);
                        for (PmCompositeSlabList pmCompositeSlabList : pmCompositeSlabLists) {
                            List<PmPdSlab> basePmPdSlabs =  basePmPdSlabMap.get(pmCompositeSlabList.getBaseMatNo());
                            PmPdSlab basePmPdSlab = basePmPdSlabs.get(0);
                            Map<BigDecimal , Long> layerMap = mlenMap.get(pmCompositeSlabList.getLayerNo());
                            PmPdPlateCut pdPlateCutBase = new PmPdPlateCut();
                            if(pmCompositeSlabList.getLayerNo() == 1L) {
                                pdPlateCut.setPositionSeq(layerMap.get(cutLength));
                            }
                            pdPlateCutBase.setCutType(CutType.P.getCode());
                            pdPlateCutBase.setPdMatNo(basePmPdSlab.getVirtualSlabNo());
                            pdPlateCutBase.setPositionSeq(layerMap.get(cutLength));
                            pdPlateCutBase.setPositionType(CutPositionType.F.getCode());
                            pdPlateCutBase.setCutLength(currentValue);
                            pdPlateCutBase.setTenantId(basePmPdSlab.getTenantId());
                            pmPdPlateCuts.add(pdPlateCutBase);
                        }
                    }
                }
                
                if(pmPdPlateCuts != null && ! pmPdPlateCuts.isEmpty()) {
                    pmPdPlateCutRepository.batchInsertSelective(pmPdPlateCuts);
                }
            }
            
            // 试样添加
            if(virtaulSlabNoList != null && !virtaulSlabNoList.isEmpty()) {
                List<PmCmdLargePlt> pmCmdLargePlts = pmCmdLargePltRepository.selectByCondition(Condition.builder(PmCmdLargePlt.class).andWhere(Sqls.custom()
                        .andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, virtaulSlabNoList)
                        .andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, organizationId)).build());
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.FHB).sampleAddition(organizationId, pmCmdLargePlts);
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.FHB).secondaryDesign(organizationId, pmCmdLargePlts);
                SecondaryDesignStrategyFactory.matchStrategy(PdMatType.FHB).commandCreate(organizationId, pmCmdLargePlts);
            }
            
            if(copyVirtualSlabNo != null) {
                self().createCmdContPlt(copyVirtualSlabNo, pmPdSlabs.get(0).getVirtualSlabNo() , compositeSlab.getSlabNo(),virtaulSlabNoList , organizationId);
            }
            
            PmCompositeSlab updatePmCompositeSlab = new PmCompositeSlab();
            updatePmCompositeSlab.setSlabId(pmCompositeSlab.getSlabId());
            updatePmCompositeSlab.setObjectVersionNumber(compositeSlab.getObjectVersionNumber());
            updatePmCompositeSlab.setStatusCode(PdStatusHp.PD_STATUS_HP_58);
            pmCompositeSlabRepository.updateByPrimaryKeySelective(updatePmCompositeSlab);

            // 对每块复合坯调用合同跟踪模块API进行抛合同跟踪处理（逻辑同单块复合坯的抛合同跟踪处理）。
            self().abandoningContract(compositeSlab.getSlabNo(), pmCompositeSlabLists, slabVirtualNoMap, compositeSlab.getMscLineNo(), organizationId);

            // 材料状态变更事件 测试展示修改
            //self().callMatStatusModify(compositeSlab, oneBaseMatNo, organizationId);
        } finally {
            redisHelper.delKey(key);
        }
        // 材料状态变更事件
        //测试使用
        String finalOneBaseMatNo = oneBaseMatNo;
        this.callMatStatusModify(compositeSlab, finalOneBaseMatNo, organizationId);
    }

    @Override
    public void confirm(Long tenantId, List<Long> idList) {

        // 查询复合/叠轧坯明细信息表
        List<PmCompositeSlabList> pmCompositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andIn(PmCompositeSlabList.FIELD_SLAB_ID, idList))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(pmCompositeSlabLists)) {
            throw new CommonException("pm.composite_slab_017", idList);
        }
//        Map<Long, List<PmCompositeSlabList>> pmCompositeSlabMap = pmCompositeSlabLists.stream().collect(Collectors.groupingBy(PmCompositeSlabList::getSlabId));

        // 查询复合/叠轧坯基本信息表
        List<PmCompositeSlab> compositeSlabList = pmCompositeSlabRepository.selectByCondition(Condition.builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andIn(PmCompositeSlab.FIELD_SLAB_ID, idList))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .build());
        compositeSlabList.forEach(item->{
            if (PdStatusHp.PD_STATUS_HP_56.compareTo(item.getStatusCode()) < 0) {
                throw new CommonException("pm.composite_slab_022", item.getSlabNo());
            }
        });
        Map<Long, PmCompositeSlab> compositeSlabMap = compositeSlabList.stream().collect(Collectors.toMap(PmCompositeSlab::getSlabId, Function.identity()));

        // 单条循环处理
        StringBuilder errorMsgBuilder = new StringBuilder();
        for (Long id : idList) {
            try {
                self().singleConfirm(tenantId, compositeSlabMap.get(id));
            }catch ( Exception e) {
                errorMsgBuilder.append("【坯号:"+compositeSlabMap.get(id).getSlabNo()+"确认失败，原因: "+e.getMessage()+"】");
            }
        }
        if (errorMsgBuilder.length() > 0) {
            throw new CommonException(errorMsgBuilder.toString());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void abandoningContract(String slabNo, List<PmCompositeSlabList> pmCompositeSlabLists,  Map<String, String> slabVirtualNoMap,
                                    String mscLineNo, Long tenantId) {

        // 基材号集合
        List<String> baseMatNoList = pmCompositeSlabLists.stream().map(PmCompositeSlabList::getBaseMatNo).distinct().collect(Collectors.toList());

        // 对每块基材，查询PM_CMD_SMALL_PLT表信息,查询条件：PM_CMD_SMALL_PLT表的板坯号（SLAB_NO）等于①中的基材号
        List<PmCmdSmallPlt> cmdSmallPltList = pmCmdSmallPltRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andIn(PmCmdSmallPlt.FIELD_SLAB_NO, baseMatNoList))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isEmpty(cmdSmallPltList)) {
            throw new CommonException("pm.composite_slab_018", Strings.join(baseMatNoList, ','), "命令小板表");
        }
        List<String> orderNoList = cmdSmallPltList.stream().map(PmCmdSmallPlt::getOrderNo).distinct().collect(Collectors.toList());
        Map<String,  List<PmCmdSmallPlt>> cmdSmallPltMap = cmdSmallPltList.stream().collect(Collectors
                .groupingBy(PmCmdSmallPlt::getSlabNo));

        // 根据合同号查询合约号
        List<QdToPoOrderVO> qdToPoOrderVOList =  pmCompositeSlabMapper.selectContractNum(orderNoList, tenantId);
        Map<String, QdToPoOrderVO> qdToPoOrderVOMap = new HashMap<>(qdToPoOrderVOList.size());
        if (CollectionUtils.isNotEmpty(qdToPoOrderVOList)) {
            qdToPoOrderVOMap = qdToPoOrderVOList.stream().collect(Collectors.toMap(QdToPoOrderVO::getOrderNo, Function.identity(), (v1, v2) -> v1));
        }

        // 查询进程代码
        List<MmSlabVO> mmSlabVOList = pmCompositeSlabMapper.getProcCdByMmSlan(tenantId, slabNo);

       List<MmPlateVO> mmPlateVOList = pmCompositeSlabMapper.selectPlateByBaseMatNo(baseMatNoList, tenantId);
        Map<String, MmPlateVO> mmPlateVOMap = new HashMap<>(mmPlateVOList.size());
       if (CollectionUtils.isNotEmpty(mmPlateVOList)) {
           mmPlateVOMap = mmPlateVOList.stream().collect(Collectors.toMap(MmPlateVO::getMatNo, Function.identity()));
       }


        // 抛合同跟踪原则：复合坯每层基材抛一次合同跟踪，每块基材上的每个合同抛一次合同跟踪。
        List<PmCompositeSlabListCtDTO> resList = new ArrayList<>();
        for (PmCompositeSlabList pmCompositeSlabList : pmCompositeSlabLists) {
            PmCompositeSlabListCtDTO res = new PmCompositeSlabListCtDTO();
            res.setContractNum(pmCompositeSlabList.getBaseOrderNo().substring(0, 8));
            res.setOrderNo(pmCompositeSlabList.getBaseOrderNo());
            res.setMoMatNo(slabNo);
            if (!slabVirtualNoMap.containsKey(pmCompositeSlabList.getBaseMatNo())) {
                throw new CommonException("pm.composite_slab_018", pmCompositeSlabList.getBaseMatNo(), "组板板坯表");
            }
            res.setMatNo(slabVirtualNoMap.get(pmCompositeSlabList.getBaseMatNo()));
            res.setMscLineNo(mscLineNo);
            res.setPpFlag("0");
            if (mmPlateVOMap.containsKey(pmCompositeSlabList.getBaseMatNo())) {
                MmPlateVO mmPlateVO = mmPlateVOMap.get(pmCompositeSlabList.getBaseMatNo());
                res.setThk(mmPlateVO.getMatActThk());
                res.setWid(mmPlateVO.getMatActWid());
                res.setLen(mmPlateVO.getMatActLen());
                res.setWgt(mmPlateVO.getMatActWgt());
            }
            res.setPdMatStatus("25");
            res.setProcCd(CollectionUtils.isNotEmpty(mmSlabVOList) ? mmSlabVOList.get(0).getProcCd() : null);
            res.setWholeBacklogCode(CollectionUtils.isNotEmpty(mmSlabVOList) ? mmSlabVOList.get(0).getWholeBacklogCode() : null);
            res.setStNo(null);
            res.setSgSign(null);
            res.setOrdFlag("2");
            resList.add(res);


            for (PmCmdSmallPlt pmCmdSmallPlt : cmdSmallPltMap.getOrDefault(pmCompositeSlabList.getBaseMatNo(), new ArrayList<>())) {
                PmCompositeSlabListCtDTO res1 = new PmCompositeSlabListCtDTO();
                if (!cmdSmallPltMap.containsKey(pmCompositeSlabList.getBaseMatNo())) {
                    throw new CommonException("pm.composite_slab_018", pmCompositeSlabList.getBaseMatNo(), "命令小板表");
                }

                if (!qdToPoOrderVOMap.containsKey(pmCmdSmallPlt.getOrderNo())) {
                    throw new CommonException("pm.cd_plate_030", pmCmdSmallPlt.getOrderNo(), "MES合同主档");
                }
                QdToPoOrderVO qdToPoOrderVO = qdToPoOrderVOMap.get(pmCmdSmallPlt.getOrderNo());
                res1.setContractNum(qdToPoOrderVO.getPactNo());
                res1.setOrderNo(pmCmdSmallPlt.getOrderNo());
                res1.setMoMatNo(slabNo);
                if (!slabVirtualNoMap.containsKey(pmCompositeSlabList.getBaseMatNo())) {
                    throw new CommonException("pm.composite_slab_018", pmCompositeSlabList.getBaseMatNo(), "组板板坯表");
                }
                res1.setMatNo(slabVirtualNoMap.get(pmCompositeSlabList.getBaseMatNo()) + pmCmdSmallPlt.getSmallPlateDivNo());
                res1.setMscLineNo(mscLineNo);
                res1.setPpFlag("11");
                res1.setThk(qdToPoOrderVO.getOrderThick());
                res1.setWid(qdToPoOrderVO.getOrderWidth());
                res1.setLen(qdToPoOrderVO.getOrderLen());
                res1.setWgt(qdToPoOrderVO.getOrderUnitAimWt());
                res1.setPdMatStatus("25");
                res1.setProcCd(CollectionUtils.isNotEmpty(mmSlabVOList) ? mmSlabVOList.get(0).getProcCd() : null);
                res1.setWholeBacklogCode(CollectionUtils.isNotEmpty(mmSlabVOList) ? mmSlabVOList.get(0).getWholeBacklogCode() : null);
                res1.setStNo(null);
                res1.setSgSign(null);
                res1.setOrdFlag("2");
                resList.add(res1);
            }

        }
        // 抛合同
        eventClient.sendEventWithOutResponse(tenantId,CtEventConstants.EVENT_PM_COMPOSITE_BOARD_ASSEMBLY_COMPLETED, resList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disband(Long tenantId, List<Long> idList) {
        List<PmCompositeSlabList> compositeSlabLists = pmCompositeSlabListRepository.selectByCondition(Condition.builder(PmCompositeSlabList.class)
                        .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                        .andWhere(Sqls.custom().andIn(PmCompositeSlabList.FIELD_SLAB_ID, idList))
                .build());

        // 调用单坯组板解散处理逻辑
        Map<Long, List<PmCompositeSlabList>> compositeSlabListsMap = compositeSlabLists.stream().collect(Collectors.groupingBy(PmCompositeSlabList::getSlabId));
        for (Map.Entry<Long, List<PmCompositeSlabList>> entry : compositeSlabListsMap.entrySet()) {
            List<Long> ListIdList = compositeSlabListsMap.get(entry.getKey()).stream().map(PmCompositeSlabList::getListId).collect(Collectors.toList());
            this.release(tenantId, ListIdList, false);
        }
    }

    @Override
    public List<PmCompositeSlabListResDTO> printList(Long slabId, Long tenantId) {

        // 查询复合坯表数据
        String slabNo = Strings.EMPTY;
        List<PmCompositeSlab> slabList = pmCompositeSlabRepository.selectByCondition(Condition
                .builder(PmCompositeSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_SLAB_ID, slabId))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlab.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isNotEmpty(slabList)) {
            slabNo = slabList.get(0).getSlabNo();
        }
        // 查询复合坯明细表数据
        List<PmCompositeSlabList> pmCompositeSlabList = pmCompositeSlabListRepository.selectByCondition(Condition
                .builder(PmCompositeSlabList.class)
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_SLAB_ID, slabId))
                .andWhere(Sqls.custom().andEqualTo(PmCompositeSlabList.FIELD_TENANT_ID, tenantId))
                .build());
        // 为空则结束
        if (CollectionUtils.isEmpty(pmCompositeSlabList)) {
            return Collections.emptyList();
        }

        // 获取基材号集合
        List<String> baseBatNoList = pmCompositeSlabList.stream().map(PmCompositeSlabList::getBaseMatNo).collect(Collectors.toList());

        // 查询小板表
        List<PmSmallPltPos> pmSmallPltPosList = pmSmallPltPosRepository.selectByCondition(Condition.builder(PmSmallPltPos.class)
                .andWhere(Sqls.custom().andIn(PmSmallPltPos.FIELD_SLAB_NO, baseBatNoList))
                .andWhere(Sqls.custom().andEqualTo(PmSmallPltPos.FIELD_TENANT_ID, tenantId))
                .build());
        // 未获取到则报错
        if (CollectionUtils.isEmpty(pmSmallPltPosList)) {
            throw new CommonException("pm.composite_slab_list_002",baseBatNoList);
        }

        Map<String, List<PmSmallPltPos>> pmSmallPltPosMap = pmSmallPltPosList.stream().collect(Collectors.groupingBy(PmSmallPltPos::getSlabNo));

        // 查询组板板坯表
        List<PmPdSlab> pdSlabList = pmPdSlabRepository.selectByCondition(Condition.builder(PmPdSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmPdSlab.FIELD_SLAB_NO, baseBatNoList))
                .build());
        Map<String, PmPdSlab> pdSlabMap = new HashMap<>(pdSlabList.size());
        if (CollectionUtils.isNotEmpty(pdSlabList)) {
            pdSlabMap = pdSlabList.stream()
                    .collect(Collectors.toMap(PmPdSlab::getSlabNo, Function.identity(), (k, v) -> k));
        }

        // 根据基材号匹配板坯号查询大板取样头部,尾部试材长度
        List<PmCmdLargePlt> largePltList = pmCmdLargePltRepository.selectBySlabNoList(baseBatNoList, tenantId).stream()
                .filter(item -> item.getSampleHeadLenPlate() != null || item.getSampleTailLenPlate() != null).collect(Collectors.toList());
        Map<String, PmCmdLargePlt> largePltMap = largePltList.stream().collect(Collectors.toMap(PmCmdLargePlt::getSlabNo, Function.identity(), (k, v) -> k));

        // 组装返回数据
        List<PmCompositeSlabListResDTO> resultList = new ArrayList<>(pmCompositeSlabList.size());
        for (PmCompositeSlabList compositeSlabList : pmCompositeSlabList) {
            PmCompositeSlabListResDTO res = new PmCompositeSlabListResDTO();
            res.setSlabNo(slabNo);
            res.setListId(compositeSlabList.getListId());
            res.setLayerNo(compositeSlabList.getLayerNo());
            res.setBaseMatNo(compositeSlabList.getBaseMatNo());
            res.setBaseMatThick(compositeSlabList.getBaseMatThick());
            res.setBaseMatWidth(compositeSlabList.getBaseMatWidth());
            res.setBaseMatLength(compositeSlabList.getBaseMatLength());
            // 判断基材在组板板坯表_厚板（PM_PD_SLAB）中是否存在记录，
            if (pdSlabMap.containsKey(compositeSlabList.getBaseMatNo())) {
                res.setIsConfirm(BaseConstants.FlagChar.YES);
                res.setFormPlateMode(pdSlabMap.get(compositeSlabList.getBaseMatNo()).getFormPlateMode());
            } else {
                res.setIsConfirm(BaseConstants.FlagChar.NO);
            }

            if (largePltMap.containsKey(compositeSlabList.getBaseMatNo())) {
                res.setSampleTailLenPlateValue(largePltMap.get(compositeSlabList.getBaseMatNo()).getSampleTailLenPlate());
                res.setSampleHeadLenPlateValue(largePltMap.get(compositeSlabList.getBaseMatNo()).getSampleHeadLenPlate());
            } else if ("K".equals(slabList.get(0).getSlabType()) && largePltList.size() > 0) {
                // 不分张类型的复合坯
                res.setSampleTailLenPlateValue(largePltList.get(0).getSampleTailLenPlate());
                res.setSampleHeadLenPlateValue(largePltList.get(0).getSampleHeadLenPlate());
            }
            if (pmSmallPltPosMap.containsKey(compositeSlabList.getBaseMatNo())) {
                List<PmSmallPltPos> smallPltPosList = pmSmallPltPosMap.get(compositeSlabList.getBaseMatNo());
                List<PmSmallPltPosDTO> pmSmallPltPosDTOList  = new ArrayList<>(smallPltPosList.size());
                List<PmSmallPltPos> sortSmallPltPosList = smallPltPosList.stream().sorted(Comparator.comparing(PmSmallPltPos::getPickModeLenDir))
                        .collect(Collectors.toList());
                for (PmSmallPltPos pmSmallPltPos : sortSmallPltPosList) {
                    PmSmallPltPosDTO pos = new PmSmallPltPosDTO();
                    pos.setOrderNo(pmSmallPltPos.getOrderNo());
                    pos.setOrderSeqNo(pmSmallPltPos.getOrderSeqNo());
                    pos.setPickModeWidDir(pmSmallPltPos.getPickModeWidDir());
                    pos.setPickModeLenDir(pmSmallPltPos.getPickModeLenDir());
                    pos.setOrderThick(pmSmallPltPos.getOrderThick());
                    pos.setOrderWidth(pmSmallPltPos.getOrderWidth());
                    pos.setOrderLen(pmSmallPltPos.getOrderLen());
                    pmSmallPltPosDTOList.add(pos);
                }
                res.setPmSmallPltPosList(pmSmallPltPosDTOList);
            }
            resultList.add(res);
        }
        return resultList;
    }

    @Override
    public List<PmPdBlockPosDTO> queryBoardResult(String baseMatNo, Long tenantId) {
        // 查询组板数据
        List<PmPdBlockPosDTO> blockPosList = new ArrayList<>();
        List<PmPdBlockPos> pmPdBlockPoList = pmPdBlockPosRepository.selectByCondition(Condition.builder(PmPdBlockPos.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdBlockPos.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmPdBlockPos.FIELD_SLAB_NO, baseMatNo))
                .build());
        if (CollectionUtils.isNotEmpty(pmPdBlockPoList)) {
            List<String> orderNoList = pmPdBlockPoList.stream().map(PmPdBlockPos::getOrderNo).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, orderNoList))
                    .build());
            Map<String, PmProContProdTtr> pmProContProdTtrMap = new HashMap<>(pmProContProdTtrList.size());
            if (CollectionUtils.isNotEmpty(pmProContProdTtrList)) {
                pmProContProdTtrMap = pmProContProdTtrList.stream()
                        .collect(Collectors.toMap(PmProContProdTtr::getOrderNo, Function.identity()));
            }

            List<PmPdSlab> pmPdSlabList = pmPdSlabRepository.selectByCondition(Condition.builder(PmPdSlab.class)
                    .andWhere(Sqls.custom().andEqualTo(PmPdSlab.FIELD_TENANT_ID, tenantId))
                    .andWhere(Sqls.custom().andEqualTo(PmPdSlab.FIELD_SLAB_NO, baseMatNo))
                    .build());

            for (PmPdBlockPos pmPdBlockPos : pmPdBlockPoList) {
                PmPdBlockPosDTO resposeDTO = new PmPdBlockPosDTO();
                resposeDTO.setOrderNo(pmPdBlockPos.getOrderNo());
                resposeDTO.setOrderSeqNo(pmPdBlockPos.getOrderSeqNo());
                resposeDTO.setOrderBlockNo(pmPdBlockPos.getOrderBlockNo());
                resposeDTO.setBlockPlateNum(pmPdBlockPos.getBlockPlateNum());
                if (CollectionUtils.isNotEmpty(pmPdSlabList)) {
                    resposeDTO.setFormPlateMode(pmPdSlabList.get(0).getFormPlateMode());
                }

                if (!pmProContProdTtrMap.isEmpty() && pmProContProdTtrMap.containsKey(pmPdBlockPos.getOrderNo())) {
                    resposeDTO.setOrderThick(pmProContProdTtrMap.get(pmPdBlockPos.getOrderNo()).getOrderThick());
                    resposeDTO.setOrderWidth(pmProContProdTtrMap.get(pmPdBlockPos.getOrderNo()).getOrderWidth());
                    resposeDTO.setOrderLen(pmProContProdTtrMap.get(pmPdBlockPos.getOrderNo()).getOrderLen());
                }
                blockPosList.add(resposeDTO);
            }
        }
        return blockPosList;
    }
    
    @Override
    public void summaryFhbPmPdSlabInfo(String slabNo , Long tenantId) {
        List<PmPdSlab> pdSlabs = pmPdSlabRepository.selectListBySlabNo(slabNo , tenantId);
        if(pdSlabs == null || pdSlabs.isEmpty()) {
            // 未生成，不计算
            return ;
        }
        PmPdSlab pmPdSlab = pdSlabs.get(0);
        PmPdSlab updatePmPdSlab = new PmPdSlab();
        List<PmPdSlabInfo> pmPdSlabInfos = pmPdSlabInfoRepository.selectByCondition(Condition.builder(PmPdSlabInfo.class).andWhere(Sqls.custom()
                .andEqualTo(PmPdSlab.FIELD_TENANT_ID,tenantId).andEqualTo(PmPdSlabInfo.FIELD_COMPOSITE_SLAB_NO, slabNo)).build());
        List<String> slabNoList = new ArrayList<>();
        for (PmPdSlabInfo pmPdSlabInfo : pmPdSlabInfos) {
            slabNoList.add(pmPdSlabInfo.getSlabNo());
        }
        List<PmPdSlab> pdSlabsList = this.pmPdSlabRepository.selectByCondition(Condition.builder(PmPdSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdSlab.FIELD_TENANT_ID, tenantId)
                        .andIn(PmPdSlab.FIELD_SLAB_NO, slabNoList)).build());
        Long orderNumInPlate = 0L;
        Long totSmallPlateNum = 0L;
        updatePmPdSlab.setRollWtHp(BigDecimal.ZERO);
        for (PmPdSlab pmPdSlab2 : pdSlabsList) {
            if(pmPdSlab2.getRollWtHp() != null) {
                updatePmPdSlab.setRollWtHp(updatePmPdSlab.getRollWtHp().add(pmPdSlab2.getRollWtHp()));
            }
        }
        updatePmPdSlab.setPmPdSlabId(pmPdSlab.getPmPdSlabId());
        updatePmPdSlab.setObjectVersionNumber(pmPdSlab.getObjectVersionNumber());
        pmPdSlabRepository.updateByPrimaryKeySelective(updatePmPdSlab);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createCmdContPlt(String baseVirtualSlabNo, String ponoSlabNo , String slabNo,List<String> virtaulSlabNoList, Long tenantId) {
        List<PmCmdSlab> pmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TMP_SLAB_NO, baseVirtualSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId)).build());
        List<PmCmdSlab> updatePpmCmdSlabs = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TMP_SLAB_NO, ponoSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId)).build());
        PmCmdSlab pmCmdSlab = updatePpmCmdSlabs.get(0);
        PmCmdSlab pmCmdSlabFirst = pmCmdSlabs.get(0);
        pmCmdSlab.setPdStatusHp(pmCmdSlabFirst.getPdStatusHp());
        pmCmdSlab.setSlabPreProc1(pmCmdSlabFirst.getSlabPreProc1());
        pmCmdSlab.setSlabPreProc2(pmCmdSlabFirst.getSlabPreProc2());
        pmCmdSlab.setSlabPreProc3(pmCmdSlabFirst.getSlabPreProc3());
        pmCmdSlab.setSlabPreProc4(pmCmdSlabFirst.getSlabPreProc4());
        pmCmdSlab.setSlabPreProc5(pmCmdSlabFirst.getSlabPreProc5());
        pmCmdSlab.setSlabPreProc6(pmCmdSlabFirst.getSlabPreProc6());
        pmCmdSlab.setSlabPreProc7(pmCmdSlabFirst.getSlabPreProc7());
        pmCmdSlab.setSlabPreProc8(pmCmdSlabFirst.getSlabPreProc8());
        pmCmdSlab.setSlabPreProc9(pmCmdSlabFirst.getSlabPreProc9());
        pmCmdSlab.setSlabPreProc10(pmCmdSlabFirst.getSlabPreProc10());
        pmCmdSlab.setSlabPreProc11(pmCmdSlabFirst.getSlabPreProc11());
        pmCmdSlab.setSlabPreProc12(pmCmdSlabFirst.getSlabPreProc12());
        pmCmdSlab.setSlabPreProc13(pmCmdSlabFirst.getSlabPreProc13());
        pmCmdSlab.setSlabPreProc14(pmCmdSlabFirst.getSlabPreProc14());
        pmCmdSlab.setSlabPreProc15(pmCmdSlabFirst.getSlabPreProc15());
        pmCmdSlabRepository.updateByPrimaryKeySelective(pmCmdSlab);
        
        List<PmCmdLargePlt> pmCmdLargePlts = pmCmdLargePltRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TMP_SLAB_NO, baseVirtualSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId)).build());
        List<PmCmdLargePlt> pmCmdLargePltDbs = pmCmdLargePltRepository.selectByCondition(Condition.builder(PmCmdLargePlt.class).andWhere(Sqls.custom()
                .andIn(PmCmdLargePlt.FIELD_TMP_SLAB_NO, virtaulSlabNoList)
                .andEqualTo(PmCmdLargePlt.FIELD_TENANT_ID, tenantId)).build());
        
        List<PmCmdLargePlt> updatePmCmdLargePlt = pmCmdLargePltRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TMP_SLAB_NO, ponoSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId)).build());
        PmCmdLargePlt pmCmdLargePlt = updatePmCmdLargePlt.get(0);
        PmCmdLargePlt pmCmdLargePltFirst = pmCmdLargePlts.get(0);
        pmCmdLargePlt.setMaxRollThick(BigDecimal.ZERO);
        pmCmdLargePlt.setMinRollThick(BigDecimal.ZERO);
        pmCmdLargePlt.setPlatePreProc1(pmCmdLargePltFirst.getPlatePreProc1());
        pmCmdLargePlt.setPlatePreProc2(pmCmdLargePltFirst.getPlatePreProc2());
        pmCmdLargePlt.setPlatePreProc3(pmCmdLargePltFirst.getPlatePreProc3());
        pmCmdLargePlt.setPlatePreProc4(pmCmdLargePltFirst.getPlatePreProc4());
        pmCmdLargePlt.setPlatePreProc5(pmCmdLargePltFirst.getPlatePreProc5());
        pmCmdLargePlt.setPlatePreProc6(pmCmdLargePltFirst.getPlatePreProc6());
        pmCmdLargePlt.setPlatePreProc7(pmCmdLargePltFirst.getPlatePreProc7());
        pmCmdLargePlt.setPlatePreProc8(pmCmdLargePltFirst.getPlatePreProc8());
        pmCmdLargePlt.setPlatePreProc9(pmCmdLargePltFirst.getPlatePreProc9());
        pmCmdLargePlt.setPlatePreProc10(pmCmdLargePltFirst.getPlatePreProc10());
        pmCmdLargePlt.setPlatePreProc11(pmCmdLargePltFirst.getPlatePreProc11());
        pmCmdLargePlt.setPlatePreProc12(pmCmdLargePltFirst.getPlatePreProc12());
        pmCmdLargePlt.setPlatePreProc13(pmCmdLargePltFirst.getPlatePreProc13());
        pmCmdLargePlt.setPlatePreProc14(pmCmdLargePltFirst.getPlatePreProc14());
        pmCmdLargePlt.setPlatePreProc15(pmCmdLargePltFirst.getPlatePreProc15());
        pmCmdLargePlt.setPlatePreProc16(pmCmdLargePltFirst.getPlatePreProc16());
        pmCmdLargePlt.setPlatePreProc17(pmCmdLargePltFirst.getPlatePreProc17());
        pmCmdLargePlt.setPlatePreProc18(pmCmdLargePltFirst.getPlatePreProc18());
        pmCmdLargePlt.setPlatePreProc19(pmCmdLargePltFirst.getPlatePreProc19());
        pmCmdLargePlt.setPlatePreProc20(pmCmdLargePltFirst.getPlatePreProc20());
        pmCmdLargePlt.setPlatePreProc21(pmCmdLargePltFirst.getPlatePreProc21());
        pmCmdLargePlt.setPlatePreProc22(pmCmdLargePltFirst.getPlatePreProc22());
        pmCmdLargePlt.setPlatePreProc23(pmCmdLargePltFirst.getPlatePreProc23());
        pmCmdLargePlt.setPlatePreProc24(pmCmdLargePltFirst.getPlatePreProc24());
        pmCmdLargePlt.setPlatePreProc25(pmCmdLargePltFirst.getPlatePreProc25());
        pmCmdLargePlt.setPlatePreProc26(pmCmdLargePltFirst.getPlatePreProc26());
        pmCmdLargePlt.setPlatePreProc27(pmCmdLargePltFirst.getPlatePreProc27());
        pmCmdLargePlt.setPlatePreProc28(pmCmdLargePltFirst.getPlatePreProc28());
        pmCmdLargePlt.setPlatePreProc29(pmCmdLargePltFirst.getPlatePreProc29());
        pmCmdLargePlt.setPlatePreProc30(pmCmdLargePltFirst.getPlatePreProc30());
        pmCmdLargePlt.setPdStatusHp(pmCmdLargePltFirst.getPdStatusHp());
        for (PmCmdLargePlt pmCmdLargePltDb : pmCmdLargePltDbs) {
            if(pmCmdLargePltDb.getSampleLen() != null && pmCmdLargePltDb.getSampleLen().compareTo(BigDecimal.ZERO) > 0) {
                pmCmdLargePlt.setSampleLenHead(pmCmdLargePltDb.getSampleLenHead());
                pmCmdLargePlt.setSampleLenMid(pmCmdLargePltDb.getSampleLenMid());
                pmCmdLargePlt.setSampleLenTail(pmCmdLargePltDb.getSampleLenTail());
                pmCmdLargePlt.setSampleLenGive(pmCmdLargePltDb.getSampleLenGive());
                pmCmdLargePlt.setSampleLen(pmCmdLargePltDb.getSampleLen());
                pmCmdLargePlt.setSampleHeadLenFree(pmCmdLargePltDb.getSampleHeadLenFree());
                pmCmdLargePlt.setSampleTailLenFree(pmCmdLargePltDb.getSampleTailLenFree());
                pmCmdLargePlt.setSampleHeadLenPlate(pmCmdLargePltDb.getSampleHeadLenPlate());
                pmCmdLargePlt.setSampleTailLenPlate(pmCmdLargePltDb.getSampleTailLenPlate());
            }
            
            if(pmCmdLargePlt.getRollAimLen() == null) {
                pmCmdLargePlt.setRollAimLen(pmCmdLargePltDb.getRollAimLen());
            } else {
                if(pmCmdLargePltDb.getRollAimLen() != null && pmCmdLargePltDb.getRollAimLen().compareTo(pmCmdLargePlt.getRollAimLen()) > 0) {
                    pmCmdLargePlt.setRollAimLen(pmCmdLargePltDb.getRollAimLen());
                }
            }
            if(pmCmdLargePltDb.getMaxRollThick() != null) {
                pmCmdLargePlt.setMaxRollThick(pmCmdLargePlt.getMaxRollThick().add(pmCmdLargePltDb.getMaxRollThick()));
            }
            if(pmCmdLargePltDb.getMinRollThick() != null) {
                pmCmdLargePlt.setMinRollThick(pmCmdLargePlt.getMinRollThick().add(pmCmdLargePltDb.getMinRollThick()));
            }
        }
        pmCmdLargePltRepository.updateByPrimaryKeySelective(pmCmdLargePlt);
        
        // 命令小板表
        List<PmCmdSmallPlt> cmdSmallPltList = pmCmdSmallPltRepository.selectByCondition(Condition.builder(PmCmdSmallPlt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TMP_SLAB_NO, baseVirtualSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSmallPlt.FIELD_TENANT_ID, tenantId)).build());
        if (CollectionUtils.isNotEmpty(cmdSmallPltList)) {
            List<PmCmdSmallPlt> insertSmallPltList = new ArrayList<>();
            cmdSmallPltList.forEach(item->{
                PmCmdSmallPlt pmCmdSmallPlt = new PmCmdSmallPlt();
                BeanUtils.copy(item, pmCmdSmallPlt);
                pmCmdSmallPlt.setPonoSlabNo(ponoSlabNo);
                pmCmdSmallPlt.setTmpSlabNo(ponoSlabNo);
                pmCmdSmallPlt.setSlabNo(slabNo);
                pmCmdSmallPlt.setPmCmdSmallPltId(null);
                insertSmallPltList.add(pmCmdSmallPlt);
            });
            pmCmdSmallPltRepository.batchInsertSelective(insertSmallPltList);
        }
        // 命令参数表
        List<PmCmdCont> pmCmdContList = pmCmdContRepository.selectByCondition(Condition.builder(PmCmdCont.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdCont.FIELD_TMP_SLAB_NO, baseVirtualSlabNo))
                .andWhere(Sqls.custom().andEqualTo(PmCmdCont.FIELD_TENANT_ID, tenantId)).build());
        if (CollectionUtils.isNotEmpty(pmCmdContList)) {
            List<PmCmdCont> insertPmCmdContList = new ArrayList<>();
            pmCmdContList.forEach(item->{
                PmCmdCont pmCmdCont = new PmCmdCont();
                BeanUtils.copy(item, pmCmdCont);
                pmCmdCont.setPonoSlabNo(ponoSlabNo);
                pmCmdCont.setTmpSlabNo(ponoSlabNo);
                pmCmdCont.setSlabNo(slabNo);
                pmCmdCont.setPmCmdContId(null);
                insertPmCmdContList.add(pmCmdCont);
            });
            pmCmdContRepository.batchInsertSelective(insertPmCmdContList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void callMatStatusModify(PmCompositeSlab compositeSlab, String baseMatNo, Long tenantId) {
        // 调用轧钢在制品余材组板挂合同事件
        //测试使用 后续需要改动 先保证数据能正常使用
        log.info("材料状态变更开始");
        List<PmCmdSlab> pmCmdSlabList = pmCmdSlabRepository.selectByCondition(Condition.builder(PmCmdSlab.class)
                .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmCmdSlab.FIELD_SLAB_NO, compositeSlab.getSlabNo()))
                .build());
        List<PmPdContSum> pmPdContSumList = pmPdContSumRepository.selectByCondition(Condition.builder(PmPdContSum.class)
                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andEqualTo(PmPdContSum.FIELD_SLAB_NO, baseMatNo))
                .orderByAsc(PmPdContSum.FIELD_ORDER_SEQ_NO)
                .build());

        // 获取基材命令板坯号
        List<PmCmdSlab> baseCmdSlabList = pmCmdSlabRepository.selectBySlabNoList(Arrays.asList(baseMatNo), tenantId);
        
        MatStatusModifyVO matStatusModifyVO = new MatStatusModifyVO();
        matStatusModifyVO.setMatNo(compositeSlab.getSlabNo());
        matStatusModifyVO.setPpFlag(Constants.PpFlag.SM);
        Map<String, String> jsonMap = new HashMap<>(2);
        String ponoSlab = CollectionUtils.isNotEmpty(pmCmdSlabList) ? pmCmdSlabList.get(0).getPonoSlabNo() : "";
        String matNo = compositeSlab.getSlabNo();
        // 当复合坯类型为K时候，命令板坯号改为基材命令板坯号
        if ("K".equals(compositeSlab.getSlabType())) {
            ponoSlab = CollectionUtils.isNotEmpty(baseCmdSlabList) ? baseCmdSlabList.get(0).getPonoSlabNo() : "";
            matNo = baseMatNo;
        }
        jsonMap.put("ponoSlab", ponoSlab);
        jsonMap.put("contractCode", CollectionUtils.isNotEmpty(pmPdContSumList) ? pmPdContSumList.get(0).getOrderNo() : "");
        matStatusModifyVO.setMatInformationString(JSONObject.toJSONString(jsonMap));
        Map<String, String> eventMap = new HashMap<>(16);
        List<EventFeignVO> ctEventList = new ArrayList<>();
        EventFeignVO eventFeignVO = new EventFeignVO();
        eventMap.put("contractNum", CollectionUtils.isNotEmpty(pmPdContSumList) ? pmPdContSumList.get(0).getOrderNo().substring(0, 8) : "");
        eventMap.put("orderNo", CollectionUtils.isNotEmpty(pmPdContSumList) ? pmPdContSumList.get(0).getOrderNo() : "");
        eventMap.put("matNo", matNo);
        eventMap.put("ppFlag", "9");
        eventMap.put("ordFlag", "1");
        eventMap.put("matStatus", "23");
        eventFeignVO.setEventContext(JSONObject.toJSONString(Collections.singletonList(eventMap)));
        eventFeignVO.setEventCode(Constants.EventCode.PM_MATERIAL_HANGING_CONTRACT);
        ctEventList.add(eventFeignVO);
        matStatusModifyVO.setCtEventList(ctEventList);
        log.info("<=====单坯组板确认调用api【matStatusModify】， matStatusModifyVO = {}", JSONObject.toJSON(matStatusModifyVO));
        if(CollectionUtils.isNotEmpty(pmCmdSlabList)) {
            List<String> ponoSlabNoList = new ArrayList<>();
            for (PmCmdSlab pmCmdSlabSlab : pmCmdSlabList) {
                ponoSlabNoList.add(pmCmdSlabSlab.getPonoSlabNo());
            }
            Map<String , PmCmdVO> pmCmdVoMap = pmCmdLargePltService.queryCmdVo(Arrays.asList(ponoSlab), tenantId, true);
            matStatusModifyVO.setCmdVOList(new ArrayList<>());
            if(pmCmdVoMap != null && !pmCmdVoMap.isEmpty()) {
                matStatusModifyVO.getCmdVOList().addAll(pmCmdVoMap.values());
            }
        }
        mmEventClient.matStatusModify(tenantId, Constants.EventCode.MM_RESIDUE_IN_PROCESS_MATERIAL_BOARD_HANG_CONTRACT, matStatusModifyVO);
//        mmEventClient.matStatusModify(tenantId, "SEATA_TEST", matStatusModifyVO);
    }
}

