package nccloud.pubimpl.cm.cmreport.meascostcontrast;

import nc.bd.framework.base.CMArrayUtil;
import nc.bd.framework.base.CMNumberUtil2;
import nc.bd.framework.base.CMStringUtil;
import nc.bs.cm.meascostcontrast.MeasCostQueryVOConverter;
import nc.cmpub.business.util.CMUtil;
import nc.vo.cm.meascostcontrast.*;
import nc.vo.cmpub.framework.report.CMConditionVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDouble;
import nc.vo.resa.factor.FactorVO;
import nccloud.pubitf.cm.meascostcontrast.ColumnInfo;
import nccloud.pubitf.cm.meascostcontrast.ColumnMultiHeadInfo;
import nccloud.pubitf.cm.meascostcontrast.IColumnInfo;
import nccloud.pubitf.cm.meascostcontrast.IMeascostcontrastComService;

import java.util.*;

/**
 * @author wangjwt
 * @version 2019-4-29 上午11:02:23
 * @since v6.3
 */
public class MeascostcontrastComServiceImpl implements IMeascostcontrastComService {
    /**
     * 动态汇总列
     */
    private List<String> sumFieldCode = null;

    @Override
    public Map<String, Object> queryMeascostcontrast(MeasCostShowVO showVO, MeasCostParamVO paramVO) throws BusinessException {
        this.sumFieldCode = new ArrayList<String>();
        // 取得逻辑查询条件
        Map<String, CMConditionVO> conditionMap = paramVO.getConditionMap();
        // 获取动态处理完的列
        List<IColumnInfo> itemgroupMap = null;
        // 返回处理完整的列对应的数据
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
        // 返回总的结果
        Map<String, Object> result = new HashMap<String, Object>();
        // 调用方法进行具体处理
        if (showVO != null) {
            Map<String, Integer> digitsMap = showVO.getDigitsMap();// 列表精度信息(单价、数量、金额)
            // 过滤要素
            FactorVO[] factorVOs = this.filteShowFactor(showVO.getFactorVOs(), showVO.getFactorMapShow(), paramVO);
            // 初始化动态表头------动态列只显示有数据的列
            if (factorVOs != null) {
                itemgroupMap = this.reBuildItem(conditionMap, factorVOs, digitsMap);
            }
            // 初始化数据
            List<MeasCostItemVO> itemVOList = showVO.getItemVOList();
            if (itemVOList != null) {
                MeasCostItemVO[] itemVOs = itemVOList.toArray(new MeasCostItemVO[itemVOList.size()]);
                // 组装列表数据
                data = this.dealQueryResult(itemVOs, digitsMap);
                // 合计行排序后不再最后一条，先注释掉排序
                this.sortVOByCode2(data);
            }
        }
        result.put("column", itemgroupMap);
        result.put("data", data);
        return result;
    }

    /**
     * 按照编码对VO进行排序。
     *
     * @param data
     */
    private void sortVOByCode2(List<Map<String, Object>> data) {
        if (data != null) {
            Collections.sort(data, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    // 排序调整：增加利润中心，工厂
                    int flag;
                    // 1.合计排最后
                    String code1 = (String) o1.get("bookname");
                    String ortname = (String) o1.get("orgname");
                    String code2 = (String) o2.get("bookname");
                    String ortname2 = (String) o2.get("orgname");
                    // 英文环境下及繁体环境Total  需要排最后 只有账簿有合计值，其他都没有值，防止后边报错
                    if (CMStringUtil.isNotEmpty(code1) && CMStringUtil.isEmpty(ortname)) {
                        flag = 1;
                        return flag;
                    } else if (CMStringUtil.isNotEmpty(code2) && CMStringUtil.isEmpty(ortname2)) {
                        return -1;
                    }
					/*if(code1.equals("Total")){
						flag = 1;
						return flag;
					}else if(code1.equals("合计")){
						flag = 1;
						return flag;

					}*/
                    // 2.利润中心
                    code1 = o1.get("profitcentername") == null ? "" : (String) o1.get("profitcentername");
                    code2 = o2.get("profitcentername") == null ? "" : (String) o2.get("profitcentername");
                    flag = code1.compareTo(code2);
                    if (flag != 0) {
                        return flag;
                    }
                    // 3.工厂
                    code1 = (String) o1.get("orgname") == null ? "" : (String) o1.get("orgname");
                    code2 = (String) o2.get("orgname") == null ? "" : (String) o2.get("orgname");
                    flag = code1.compareTo(code2);
                    if (flag != 0) {
                        return flag;
                    }
                    // 4.成本中心升序排序
                    code1 = (String) o1.get("cccode") == null ? "" : (String) o1.get("cccode");
                    code2 = (String) o2.get("cccode") == null ? "" : (String) o2.get("cccode");
                    flag = code1.compareTo(code2);
                    if (flag != 0) {
                        return flag;
                    }
                    // 5.再按产品编码升序排序
                    code1 = (String) o1.get("vcostobjcode") == null ? "" : (String) o1.get("vcostobjcode");
                    code2 = (String) o2.get("vcostobjcode") == null ? "" : (String) o2.get("vcostobjcode");
                    flag = code1.compareTo(code2);
                    return flag;
                }
            });
        }
    }

    /**
     * map中key为参数名，value为参数值
     * 将获取到的集合参数名和参数值拼装在一起
     *
     * @param itemVOs
     * @param digitsMap
     * @return
     */
    private List<Map<String, Object>> dealQueryResult(MeasCostItemVO[] itemVOs, Map<String, Integer> digitsMap) {
        /**
         * "data":[
         *           row  {
         *                 "nmeascostncost":"204.00",
         *                 "1002ncost":"1000.000",
         *                 "vcostobjcode":"001",
         *                 "vcostobjname":"物料分类001",
         *                 "nsumncost":"1020.000",
         *                 "nnum":"5.00",
         *                 "cccode":"",
         *                 "ccname":"",
         *                 "hx02ncost":"20.000"
         *             },
         */
        if (CMArrayUtil.isEmpty(itemVOs)) {
            return null;
        }
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
        MeasCostItemVO[] result = new MeasCostItemVO[itemVOs.length + 1];
        UFDouble nsumncost = UFDouble.ZERO_DBL;// 合计
        UFDouble nnum = UFDouble.ZERO_DBL;// 产量
        Map<String, UFDouble> sumMap = new HashMap<String, UFDouble>();
        for (String field : this.sumFieldCode) {
            sumMap.put(field, UFDouble.ZERO_DBL);
        }

        int i = 0;
        for (MeasCostItemVO item : itemVOs) {
            if (item.getNnum() != null) {
                nnum = CMNumberUtil2.add(nnum, item.getNnum());
            }
            if (item.getAttributeValue("nsumncost") != null) {
                nsumncost = CMNumberUtil2.add(nsumncost, (UFDouble) item.getAttributeValue("nsumncost"));
            }
            for (String key : sumMap.keySet()) {
                UFDouble oldVal = sumMap.get(key);
                if (item.getAttributeValue(key) != null) {
                    UFDouble newVal = CMNumberUtil2.add(oldVal, (UFDouble) item.getAttributeValue(key));
                    sumMap.put(key, newVal);
                }
            }
            result[i] = item;
            i++;
        }
        // 处理精度为空的数据，默认精度给2位，一定要在加入合计行之前处理
        this.processNullBignumber(result);
        // 获取合计行数量的精度，获取每一行的精度，然后取最大的精度给合计行
        Integer sumBignumber = this.getSumNumBignumber(result);

        MeasCostItemVO newItem = new MeasCostItemVO();
        MeasCostItemVO tempMeasCostItemVO = itemVOs[0];

        // 动态合计处理--将合计放在新增加的账簿上
		/*if (!CMStringUtil.isEmpty(tempMeasCostItemVO.getCccode())) {
			newItem.setCccode(CMLangConst1614.GET_NSUM_NAME());// res:合计到成本中心
		}else{
			newItem.setCccode("");
			newItem.setVcostobjcode(CMLangConst1614.GET_NSUM_NAME());// res:合计到产品/成本对象
		}*/
        newItem.setBookname(CMLangConst1614.GET_NSUM_NAME());
        newItem.setAttributeValue("nnum", nnum);
        newItem.setAttributeValue("nsumncost", nsumncost);
        for (String key : sumMap.keySet()) {
            newItem.setAttributeValue(key, sumMap.get(key));
        }
        result[itemVOs.length] = newItem;
        for (MeasCostItemVO measCostItemVO : result) {
            Map<String, Object> row = new HashMap<String, Object>();
            // 核算账簿
            row.put(CMCommonConst1614.BOOKNAME, measCostItemVO.getBookname());
            // 利润中心
            row.put(CMCommonConst1614.PROFITCENTERNAME, measCostItemVO.getProfitcentername());
            // 工厂
            row.put(CMCommonConst1614.ORGNAME, measCostItemVO.getOrgname());
            row.put(CMCommonConst1614.CCCODE, measCostItemVO.getCccode());
            row.put(CMCommonConst1614.CCNAME, measCostItemVO.getCcname());
            row.put(CMCommonConst1614.VCOSTOBJCODE, measCostItemVO.getVcostobjcode());
            row.put(CMCommonConst1614.VCOSTOBJNAME, measCostItemVO.getVcostobjname());
            // digitsMap.get("NumDigitsKey")最小精度2位导致精度有问题，需要直接读计量单位精度
            row.put(CMCommonConst1614.NNUM, this.setColumnScale(measCostItemVO.getNnum(), measCostItemVO.getBitnumber()));// 产量

            // 增加三个字段 型号 主计量单位 规格----将参数和值对应
            row.put(CMCommonConst1614.MEASDOCNAME, measCostItemVO.getMeasdocname());
            row.put(CMCommonConst1614.MATERIALSPEC, measCostItemVO.getMaterialspec());
            row.put(CMCommonConst1614.MATERIALTYPE, measCostItemVO.getMaterialtype());
            // 增加项目编码和项目名称
            row.put("projectcode", measCostItemVO.getProjectcode());
            row.put("projectname", measCostItemVO.getProjectname());
            if (measCostItemVO.getFactorMap() != null) {
                for (String str : measCostItemVO.getFactorMap().keySet()) {
                    if (str.equals("nmeascostncost")) {// 单位成本
                        row.put(str, this.setColumnScale(measCostItemVO.getFactorMap().get(str), digitsMap.get("PriceDigitsKey")));
                    } else if (str.equals("nsumncost")) {// 合计
                        row.put(str, this.setColumnScale(measCostItemVO.getFactorMap().get(str), digitsMap.get("MoneyDigitsKey")));
                    } else if (str.equals("nnum")) {// 产量
                        // digitsMap.get("NumDigitsKey")最小精度2位导致精度有问题，需要直接读计量单位精度
                        row.put(str, this.setColumnScale(measCostItemVO.getFactorMap().get(str), sumBignumber));
                    } else {// 所有核算要素
                        row.put(str, this.setColumnScale(measCostItemVO.getFactorMap().get(str), digitsMap.get("MoneyDigitsKey")));
                    }
                }
            }
            data.add(row);
        }
        return data;
    }

    /**
     * 获取合计行数量的精度，获取每一行的精度，然后取最大的精度给合计行
     *
     * @param measCostItemVOS
     * @return
     */
    public Integer getSumNumBignumber(MeasCostItemVO[] measCostItemVOS) {
        if (CMArrayUtil.isEmpty(measCostItemVOS)) {
            return 0;
        }
        Integer bignumber = 0;
        for (MeasCostItemVO measCostItemVO : measCostItemVOS) {
            if (measCostItemVO != null && measCostItemVO.getBitnumber() != null && measCostItemVO.getBitnumber() > bignumber) {
                bignumber = measCostItemVO.getBitnumber();
            }
        }
        return bignumber;
    }

    /**
     * 如果计量单位精度是null，按照物料产品分类、物料基本分类查询，拿不到计量单位，默认按照2位精度处理
     *
     * @param measCostItemVOS
     * @return
     */
    public void processNullBignumber(MeasCostItemVO[] measCostItemVOS) {
        if (CMArrayUtil.isEmpty(measCostItemVOS)) {
            return;
        }
        for (MeasCostItemVO measCostItemVO : measCostItemVOS) {
            if (measCostItemVO != null && measCostItemVO.getBitnumber() == null) {
                // 数量精度都按照计量单位获取，按照物料成本分类、物料基本分类读取数据时候拿不到精度，如果精度是null，则按照2位精度处理，修改时间：2023.08.23，修改人：xuluv
                measCostItemVO.setBitnumber(2);
            }
        }
    }

    /**
     * 精度处理
     *
     * @param value 返回的数据
     * @param scale 精度类型
     */
    private UFDouble setColumnScale(Object value, Integer scale) {
        if (value == null || ((UFDouble) value).equals(UFDouble.ZERO_DBL)) {
            return null;
        } else {
            UFDouble uf = new UFDouble(Double.valueOf(value.toString())).setScale(scale, 4);
            return uf;
        }
    }

    /**
     * 重构动态列表头
     *
     * @param factorVOs    "核算要素"动态列初始化所需数据
     * @param conditionMap 逻辑查询条件
     * @param digitsMap    列表精度----单价、数量、金额
     * @return 保存表头上下两层列的对应关系的map
     */
    private List<IColumnInfo> reBuildItem(Map<String, CMConditionVO> conditionMap, FactorVO[] factorVOs, Map<String, Integer> digitsMap) {

        // 取得列的显示明细区分（区分本下阶、显示标准成本、区分成本中心、默认）
        String[] showDetailDiff = MeasCostUtil.getShowDetailDiff(conditionMap);
        // 取得成本对象的显示方式（成本对象、产品、产品成本分类、产品基本分类）
        Integer ishowtype = MeasCostQueryConditionVO.PRODUCT_VALUE;
        if (conditionMap.containsKey(MeasCostQueryConditionVO.ISHOWTYPE) && conditionMap.get(MeasCostQueryConditionVO.ISHOWTYPE).getSingleValue() != null) {
            ishowtype = Integer.valueOf(conditionMap.get(MeasCostQueryConditionVO.ISHOWTYPE).getSingleValue());
        }

        // 保存列的list ----------getColumn
        List<IColumnInfo> itemsList = new ArrayList<IColumnInfo>();
        // // 保存两层列的对应关系
        // MapList<String, String> itemgroupMapList = new MapList<String, String>();
        // 设置固定的前三列，保存到list
        this.setCodeNameItems(itemsList, ishowtype, digitsMap, conditionMap);
        // 如果显示样式为单层，单层列保存到list
        if (CMArrayUtil.isEquals(CMCommonConst1614.DEFAULT_ITEMS, showDetailDiff)) {
            itemsList = this.setSingleItems(itemsList, factorVOs, digitsMap);
        }
        // 如果显示样式为双层，子父关系形式保存到list
        else {
            itemsList = this.setDoubleItems(itemsList, factorVOs, showDetailDiff, digitsMap);
        }
        //

        return itemsList;
    }

    /**
     * 设置固定列（包括三个列：产品编码、产品名称、产量）
     *
     * @param ishowtype 显示方式（成本对象、产品、产品成本分类、产品基本分类）
     */
    private void setCodeNameItems(List<IColumnInfo> itemsList, Integer ishowtype, Map<String, Integer> digitsMap, Map<String, CMConditionVO> conditionMap) {
        // 取得产品编码和产品名称这两列的列名{0：产品编码列名，1：产品名称列名}
        String[] itemNames = this.getItemNameByShowType(ishowtype);

        // 是否有按成本中心汇总，有则直接汇总成本中心
        Integer isSumByCostcenter = conditionMap.containsKey(MeasCostQueryConditionVO.ISSUMBYCOSTCENTER) ? Integer.valueOf(conditionMap.get(
                MeasCostQueryConditionVO.ISSUMBYCOSTCENTER).getSingleValue()) : MeasCostQueryConditionVO.IS_COSTCENTER_VALUE;
        // 核算账簿
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_ACCBOOK(), CMCommonConst1614.BOOKNAME, ColumnInfo.LEFT));
        // 利润中心
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_PROFITCENTER(), CMCommonConst1614.PROFITCENTERNAME, ColumnInfo.LEFT));
        // 工厂
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_ORG(), CMCommonConst1614.ORGNAME, ColumnInfo.LEFT));
        // 按照成本中心计算
        if (MeasCostQueryConditionVO.IS_COSTCENTER_VALUE.equals(isSumByCostcenter)) {
            itemsList.add(new ColumnInfo(itemNames[0], CMCommonConst1614.CCCODE, ColumnInfo.LEFT));
            // 设置"成本中心名称"列
            itemsList.add(new ColumnInfo(itemNames[1], CMCommonConst1614.CCNAME, ColumnInfo.LEFT));
        }
        // 按照成本中心计算
        // 创建集合放列的 编码名称
        // 设置"成本中心编码"列
        // 设置"产品编码"列
        itemsList.add(new ColumnInfo(itemNames[2], CMCommonConst1614.VCOSTOBJCODE, ColumnInfo.LEFT));

        // 设置"产品名称"列
        itemsList.add(new ColumnInfo(itemNames[3], CMCommonConst1614.VCOSTOBJNAME, ColumnInfo.LEFT));

        if (MeasCostQueryConditionVO.COSTOBJECT_VALUE.equals(ishowtype) || MeasCostQueryConditionVO.PRODUCT_VALUE.equals(ishowtype)) {
            // 设置规格
            itemsList.add(new ColumnInfo(CMLangConst1614.GET_MATERIALSPEC(), CMCommonConst1614.MATERIALSPEC, ColumnInfo.LEFT));
            // 设置型号
            itemsList.add(new ColumnInfo(CMLangConst1614.GET_MATERIALTYPE(), CMCommonConst1614.MATERIALTYPE, ColumnInfo.LEFT));
            // 设置计量单位
            itemsList.add(new ColumnInfo(CMLangConst1614.GET_MEASDOCNAME(), CMCommonConst1614.MEASDOCNAME, ColumnInfo.LEFT));
        }
        // todo 客开增加项目相关的列
        itemsList.add(new ColumnInfo("项目编码", "projectcode", ColumnInfo.LEFT));
        itemsList.add(new ColumnInfo("项目名称", "projectname", ColumnInfo.LEFT));
        // 设置"产量"列
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_NNUM_NAME(), CMCommonConst1614.NNUM, ColumnInfo.RIGTH));
    }

    /**
     * 根据显示方式不同，取前两列的列名
     *
     * @param ishowtype 显示方式（成本对象、产品、产品成本分类、产品基本分类）
     * @return 字符串数组：{0：产品编码列名，1：产品名称列名}
     */
    private String[] getItemNameByShowType(Integer ishowtype) {
        String[] itemName = new String[4];
        itemName[0] = CMLangConst1614.GET_CENTERCODE_NAME();
        itemName[1] = CMLangConst1614.GET_CENTERNAME_NAME();
        // 显示方式：成本对象
        if (MeasCostQueryConditionVO.COSTOBJECT_VALUE.equals(ishowtype)) {
            itemName[2] = CMLangConst1614.GET_OBJECT_CODE_NAME();
            itemName[3] = CMLangConst1614.GET_OBJECT_NAME();
        }
        // 显示方式：产品
        else if (MeasCostQueryConditionVO.PRODUCT_VALUE.equals(ishowtype)) {
            itemName[2] = CMLangConst1614.GET_PRODUCT_CODE_NAME();
            itemName[3] = CMLangConst1614.GET_PRODUCT_NAME();
        }
        // 显示方式：产品成本分类
        else if (MeasCostQueryConditionVO.PRODUCT_COST_VALUE.equals(ishowtype)) {
            itemName[2] = CMLangConst1614.GET_PRODUCT_COST_CODE_NAME();
            itemName[3] = CMLangConst1614.GET_PRODUCT_COST_NAME();
        }
        // 显示方式：产品基本分类
        else if (MeasCostQueryConditionVO.PRODUCT_BASIC_VALUE.equals(ishowtype)) {
            itemName[2] = CMLangConst1614.GET_PRODUCT_BASIC_CODE_NAME();
            itemName[3] = CMLangConst1614.GET_PRODUCT_BASIC_NAME();
        }
        return itemName;
    }

    /**
     * 过滤要素
     *
     * @param vos
     * @param factorMapShow
     * @param paramVO
     * @return
     */
    private FactorVO[] filteShowFactor(FactorVO[] vos, Map<String, String> factorMapShow, MeasCostParamVO paramVO) {
        // 查看前端条件，【显示所有要素】，默认为否，是则展示所有要素
        Map<String, CMConditionVO> conditionMap = paramVO.getConditionMap();
        Integer isshowallfactors = conditionMap.containsKey(MeasCostQueryConditionVO.ISSHOWALLFACTORS) ? Integer.valueOf(conditionMap.get(
                MeasCostQueryConditionVO.ISSHOWALLFACTORS).getSingleValue()) : MeasCostQueryConditionVO.NO_SHOW_FACTORS_VALUE;

        FactorVO[] result = null;

        // 当该值不为默认值时
        if (!MeasCostQueryConditionVO.NO_SHOW_FACTORS_VALUE.equals(isshowallfactors)) {
            // 不再需要对比要素，只需要将所有要素根据查询条件过滤后全部展示即可
            result = new MeasCostQueryVOConverter().getShowFactorByParam(paramVO, Arrays.asList(vos), factorMapShow);

        } else {
            List<FactorVO> tmp = new ArrayList<FactorVO>();
            String[] factorcodes = factorMapShow.keySet().toArray(new String[0]);
            for (String code : factorcodes) {
                for (FactorVO vo : vos) {
                    if (vo.getFactorcode().equals(code)) {
                        tmp.add(vo);
                        break;
                    }
                }
            }
            result = tmp.toArray(new FactorVO[0]);
        }

        // 对编码进行排序
        this.sortVOByCode(result);
        return result;
    }

    /**
     * 按照编码对VO进行排序。
     *
     * @param vos
     */
    private void sortVOByCode(FactorVO[] vos) {
        if (vos == null || vos.length < 2) {
            return;
        }
        Arrays.sort(vos, new Comparator<FactorVO>() {

            @Override
            public int compare(FactorVO o1, FactorVO o2) {
                String code1 = (String) o1.getAttributeValue(FactorVO.FACTORCODE);
                String code2 = (String) o2.getAttributeValue(FactorVO.FACTORCODE);
                return code1.compareTo(code2);
            }
        });
    }

    /**
     * 单层列时，将列保存到list
     *
     * @param itemsList 保存基本列的list
     * @param factorVOs "核算要素"动态列初始化所需数据
     */
    private List<IColumnInfo> setSingleItems(List<IColumnInfo> itemsList, FactorVO[] factorVOs, Map<String, Integer> digitsMap) {
        // 设置"单位成本"单列
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_NMEASCOST_NAME(), MeasCostUtil.getItemCodeByRule(CMCommonConst1614.NMEASCOST, CMCommonConst1614.NCOST), ColumnInfo.RIGTH));
        // 设置"合计"单列
        itemsList.add(new ColumnInfo(CMLangConst1614.GET_NSUM_NAME(), MeasCostUtil.getItemCodeByRule(CMCommonConst1614.NSUM, CMCommonConst1614.NCOST), ColumnInfo.RIGTH));
        // 设置"核算要素"列
        for (FactorVO factorVO : factorVOs) {
            String itemCode = MeasCostUtil.getItemCodeByRule(factorVO.getFactorcode(), CMCommonConst1614.NCOST);
            String itemName = factorVO.getFactorcode() + "-" + CMUtil.getNameByMultiLang(factorVO, FactorVO.FACTORNAME);
            // 添加动态列
            itemsList.add(new ColumnInfo(itemName, itemCode, ColumnInfo.RIGTH));
            this.sumFieldCode.add(itemCode);
        }
        return itemsList;
    }

    /**
     * 双层列时，将下层列保存到list，并返回保存表头上下两层列的对应关系Map
     *
     * @param itemsList      保存基本列的list
     * @param factorVOs      "核算要素"动态列初始化所需数据
     * @param showDetailDiff 列的显示样式（区分本下阶、显示标准成本、区分成本中心、默认）
     * @return 保存两层列的对应关系的Map
     */
    private List<IColumnInfo> setDoubleItems(List<IColumnInfo> itemsList, FactorVO[] factorVOs, String[] showDetailDiff, Map<String, Integer> digitsMap) {
        // 存放多表头时的儿子信息
        String[] childName = new String[showDetailDiff.length];
        String[] childAlign = new String[showDetailDiff.length];
        String[] childCode = new String[showDetailDiff.length];
        // 设置"单位成本"列
        for (int i = 0; i < showDetailDiff.length; i++) {
            String itemCode = MeasCostUtil.getItemCodeByRule(CMCommonConst1614.NMEASCOST, showDetailDiff[i]);
            String itemName = MeasCostUtil.getItemNameByCode(showDetailDiff[i]);
            if (CMLangConst1614.GET_NCOST_NAME().equals(itemName)) {
                itemName = CMLangConst1614.GET_ALL_NMEASCOST_NAME();
            }
            childName[i] = itemName;
            childCode[i] = itemCode;
            childAlign[i] = ColumnInfo.RIGTH;
            // itemsList.add(new ColumnInfo(itemName, itemCode, ColumnInfo.RIGTH));
        }
        // 多表头 时处理多表层的关系---单位成本
        itemsList.add(MeascostcontrastComServiceImpl.getMultHeadColum(CMLangConst1614.GET_NMEASCOST_NAME(), childName, childCode, childAlign));

        // 设置"合计"列
        for (int i = 0; i < showDetailDiff.length; i++) {
            String itemCode = MeasCostUtil.getItemCodeByRule(CMCommonConst1614.NSUM, showDetailDiff[i]);
            String itemName = MeasCostUtil.getItemNameByCode(showDetailDiff[i]);
            childName[i] = itemName;
            childCode[i] = itemCode;
            childAlign[i] = ColumnInfo.RIGTH;
            // itemsList.add(new ColumnInfo(itemName, itemCode, ColumnInfo.RIGTH));
        }
        // 多表头 时处理多表层的关系---合计
        itemsList.add(MeascostcontrastComServiceImpl.getMultHeadColum(CMLangConst1614.GET_NSUM_NAME(), childName, childCode, childAlign));

        // 设置"核算要素"列
        for (FactorVO factorVO : factorVOs) {
            String groupItemCode = factorVO.getFactorcode();
            String itemName = factorVO.getFactorcode() + "-" + CMUtil.getNameByMultiLang(factorVO, FactorVO.FACTORNAME);

            for (int i = 0; i < showDetailDiff.length; i++) {
                String itemCode = MeasCostUtil.getItemCodeByRule(groupItemCode, showDetailDiff[i]);
                String itemName1 = MeasCostUtil.getItemNameByCode(showDetailDiff[i]);
                childName[i] = itemName1;
                childCode[i] = itemCode;
                childAlign[i] = ColumnInfo.RIGTH;
                // itemsList.add(new ColumnInfo(itemName1, itemCode, ColumnInfo.RIGTH));
                this.sumFieldCode.add(MeasCostUtil.getItemCodeByRule(groupItemCode, showDetailDiff[0]));
            }
            // 多表头 时处理多表层的关系---核算要素
            itemsList.add(MeascostcontrastComServiceImpl.getMultHeadColum(itemName, childName, childCode, childAlign));
        }

        return itemsList;
    }

    /**
     * 构造子父关系
     */
    public static ColumnMultiHeadInfo getMultHeadColum(String multStr, String[] childStr, String[] childKey, String[] childAlign) {
        ColumnMultiHeadInfo multiHead = new ColumnMultiHeadInfo(multStr);
        ColumnInfo[] children = new ColumnInfo[childStr.length];
        for (int i = 0; i < children.length; i++) {
            children[i] = new ColumnInfo(childStr[i], childKey[i], childAlign[i]);
        }
        multiHead.setChildren(children);
        return multiHead;
    }

}
