package weaver.fna.invoice.utils;

import com.api.integration.Base;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.dbutils.handlers.MapListHandler;
import weaver.conn.RecordSet;
import weaver.fna.invoice.common.FnaInvoiceCommon;
import weaver.fna.maintenance.BudgetfeeTypeComInfo;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.page.interfaces.element.flash.impl.FlashImplE7;
import weaver.systeminfo.SystemEnv;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @Author: lb2018
 * @Modify: Zjianru
 * @Description: 发票合并拆分工具类
 * @Date: 2020/6/9 10:45
 */
public class InvoiceMergeSplitUtil {

    /**
     * 发票主表需要带出字段
     */
    public static final Map<String, String> INVOICE_MAIN = new HashMap<>();
    /**
     * 发票明细表需要带出的字段
     */
    public static final Map<String, String> INVOICE_DETAIL = new HashMap<>();
    /**
     * 需要格式化double的列
     */
    public static final List<String> DOUBLE_FORMAT = new ArrayList<>();
    /**
     * 需要格式化Int的列
     */
    public static final List<String> INT_FORMAT = new ArrayList<>();
    /**
     * 需要格式百分比的列
     */
    public static final List<String> PERCENT_FORMAT = new ArrayList<>();
    /**
     * 发票类型格式化
     */
    public static final List<String> INVOICE_TYPE_FORMAT = new ArrayList<>();

    static {
        INVOICE_MAIN.put("fieldIdInvoice", "id");

        INVOICE_MAIN.put("fieldIdAmount", "taxIncludedPrice");
        INVOICE_MAIN.put("fieldIdDate", "billingDate");
        INVOICE_MAIN.put("fieldIdTax", "tax");
        INVOICE_MAIN.put("fieldIdPurchaser", "purchaser");
        INVOICE_MAIN.put("fieldIdPurchaserTaxNo", "purchaserTaxNo");
        INVOICE_MAIN.put("fieldIdSeller", "seller");
        INVOICE_MAIN.put("fieldIdSellerTaxNo", "salestaxno");
        INVOICE_MAIN.put("fieldIdInvoiceType", "invoiceType");
        // remark fnaInvoiceLedgerDtl表中，和在主表一样
        INVOICE_MAIN.put("fieldIdDesc", "remark");

        INVOICE_DETAIL.put("fieldIdServiceDetail", "invoiceServiceYype_dtl");
        INVOICE_DETAIL.put("fieldIdPriceDetail", "priceWithoutTax_dtl");
        INVOICE_DETAIL.put("fieldIdTaxRateDetail", "taxRate_dtl");
        INVOICE_DETAIL.put("fieldIdTaxDetail", "tax_dtl");

        DOUBLE_FORMAT.add("fieldIdAmount");
        DOUBLE_FORMAT.add("fieldIdTax");
        DOUBLE_FORMAT.add("fieldIdPriceDetail");
        DOUBLE_FORMAT.add("fieldIdTaxDetail");

        PERCENT_FORMAT.add("fieldIdTaxRateDetail");

        INVOICE_TYPE_FORMAT.add("fieldIdInvoiceType");

    }

    private static final DecimalFormat DF = new DecimalFormat("##########################0.00");

    /**
     * 根据拆分规则获取发票数据
     *
     * @param workflowId workflowId
     * @param dtlNumber  dtlNumber
     * @return JSONArray
     */
    public static JSONArray getInvoiceInfo(int workflowId, int dtlNumber, String invoiceIds, User user) {
        JSONArray jsonArray = new JSONArray();
        if (dtlNumber == 0) {
            //主表，无拆分与合并
            JSONObject invoiceInfo = getMainInvoiceInfo(invoiceIds, user);
            jsonArray.add(invoiceInfo);
        } else {
            //明细表 拆分与合并
            jsonArray = getDetailInvoiceInfo(workflowId, dtlNumber, invoiceIds, user);
        }
        return jsonArray;
    }

    /**
     * 获取流程明细表单发票信息
     *
     * @param workflowId workflowId
     * @param dtlNumber  dtlNumber
     * @param invoiceIds invoiceIds
     * @return JSONArray
     */
    public static JSONArray getDetailInvoiceInfo(int workflowId, int dtlNumber, String invoiceIds, User user) {
        JSONArray resultArray = new JSONArray();
        RecordSet rs = new RecordSet();
        int id = 0;
        //是否启用明细合并 1 启用 -- 0 不启用
        int isMerge = 0;
        //所选择合并分组字段数据库字段名，多字段使用英文逗号分隔
        String mergeField = "";
        //合并分组字段外的字段取值规则 -- 1 取第一行,-- 2  取最后一行,-- 3 自然拼接,-- 4 合计
        int otherFieldRule = 1;
        //自然拼接的拼接符
        String operator = "";
        //多 id 使用英文逗号分隔,选择费用类型后的取值，记录 fnaInvoiceFieldConstType 的 Id
        String fieldConstType = "";
        //是否启用明细拆分 1 启用 -- 0 不启用
        int isSplit = 0;
        //1 按税率拆分2 按税额拆分 3 按费用类型拆分
        int spiltRule = 1;


        rs.executeQuery("select * from fnaInvoiceMergeRule where workflowid=? and dtlNumber=?", workflowId, dtlNumber);
        if (rs.next()) {
            id = Util.getIntValue(rs.getString("id"), 0);
            isMerge = Util.getIntValue(rs.getString("isMerge"), 0);
            mergeField = Util.null2String(rs.getString("mergeField"));
            otherFieldRule = Util.getIntValue(rs.getString("otherFieldRule"), 1);
            operator = Util.null2String(rs.getString("operator"));
            fieldConstType = Util.null2String(rs.getString("fieldConstType"));

            isSplit = Util.getIntValue(rs.getString("isSplit"), 0);
            spiltRule = Util.getIntValue(rs.getString("spiltRule"), 1);
        }

        String[] invoiceIdsArray = invoiceIds.split(",");
        Map<Integer, String> imageDocMap = getImageDocInfoByInvoice(invoiceIds);
        BudgetfeeTypeComInfo budgetfeeTypeComInfo = new BudgetfeeTypeComInfo();

        // 获取费用类型 Map
        Map<String, String> constTypeMap = getConsTypeMap(id);

        Map<String, String> invoiceTypeMap = getInvoiceTypeName(user);
        if (isMerge == 1) {
            //合并
            String[] mergeFieldList = mergeField.split(",");
            //合并规则
            Map<String, String> exceptionMergeRuleMap = new HashMap<>(16);
            //当合并规则为 3，即拼接，拼接符
            Map<String, String> exceptionOperatorMap = new HashMap<>(16);

            rs.executeQuery("select browserId,mergeRule,operator from fnaInvoiceExceptionRule  where mainid=?", id);
            while (rs.next()) {
                String browserId = Util.null2String(rs.getString("browserId"));
                String mergeRule = Util.null2String(rs.getString("mergeRule"));
                String operator2 = Util.null2String(rs.getString("operator"));
                if (!exceptionMergeRuleMap.containsKey("browserId")) {
                    exceptionMergeRuleMap.put(browserId, mergeRule);
                    exceptionOperatorMap.put(browserId, operator2);
                }
            }

            RecordSet rsQuery = FnaInvoiceCommon.executeInSql("select " +
                    " a.id,a.taxIncludedPrice,a.billingDate,a.tax,a.purchaser,a.purchaserTaxNo,a.seller,a.salestaxno," +
                    " a.invoiceNumber,a.invoiceType,a.imageDocId,a.cloudId," +
                    " c.remark," +
                    " b.invoiceServiceYype invoiceServiceYype_dtl,b.priceWithoutTax priceWithoutTax_dtl,b.taxRate taxRate_dtl,b.tax tax_dtl, " +
                    " d.subjectid " +
                    " from fnaInvoiceLedger a " +
                    " join fnaInvoiceledgerDetail b on a.id=b.mainid " +
                    " left join FnaInvoiceLedgerDtl c on a.id=c.mainid " +
                    " left join FnaInvoiceSubject d on b.invoiceServiceYype=d.invoiceServiceYype " +
                    " where a.id in(占位符标识) order by a.id desc,b.id asc", invoiceIds, "executeQuery");
            Map<String, Map<String, Object>> invoiceInfosMap = new HashMap<>(32);
            // key 为发票 id,value 为标识
            Map<String, String> orderByMap = new LinkedHashMap<String, String>();
            String startInvoiceId = "";
            while (rsQuery.next()) {
                String invoiceId = Util.null2String(rsQuery.getString("id"));
                String invoiceNumber = Util.null2String(rsQuery.getString("invoiceNumber"));
                String cloudId = Util.null2String(rsQuery.getString("cloudId"));
                String subjectId = Util.null2String(rsQuery.getString("subjectid"));
                String subjectName = budgetfeeTypeComInfo.getBudgetfeeTypename(subjectId);
                int imageDocId = Util.getIntValue(rsQuery.getString("imageDocId"), 0);

                //过滤详见销货清单
                String invoiceServiceYype_dtl = Util.null2String(rsQuery.getString("invoiceServiceYype_dtl"));
                if(invoiceServiceYype_dtl.contains("详见销货清单") && isFilter(invoiceId)){
                    continue;
                }

                if(invoiceServiceYype_dtl.contains("原价合计") && isFilter(invoiceId)){
                    continue;
                }
                if(invoiceServiceYype_dtl.contains("折扣额合计") && isFilter(invoiceId)){
                    continue;
                }

                boolean sameInvoice = false;
                if (!"".equals(startInvoiceId) && startInvoiceId.equals(invoiceId)) {
                    sameInvoice = true;
                }

                Map<String, Object> invoiceInfoMap = new HashMap<>(32);
                StringBuilder mergeSign = new StringBuilder();
                for (String key : mergeFieldList) {
                    String dbValue = "";
                    if (INVOICE_MAIN.containsKey(key)) {
                        dbValue = Util.null2String(rsQuery.getString(INVOICE_MAIN.get(key)));
                    } else if (INVOICE_DETAIL.containsKey(key)) {
                        dbValue = Util.null2String(rsQuery.getString(INVOICE_DETAIL.get(key)));
                        if ("fieldIdServiceDetail".equals(key) && constTypeMap.containsKey(dbValue)) {
                            //应货税服务类型 特殊处理
                            dbValue = constTypeMap.get(dbValue);
                        }
                    }
                    mergeSign.append(dbValue).append("___");
                }
                if (!orderByMap.containsKey(mergeSign.toString())) {
                    orderByMap.put(mergeSign.toString(), invoiceId);
                } else {
                    orderByMap.put(mergeSign.toString(), orderByMap.get(mergeSign.toString()) + "," + invoiceId);
                }
                if (invoiceInfosMap.containsKey(mergeSign.toString())) {
                    Map<String, Object> invoiceExistInfoMap = invoiceInfosMap.get(mergeSign.toString());
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        String dbColumn = INVOICE_MAIN.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        if (exceptionMergeRuleMap.containsKey(key)) {
                            dbValue = getExceptionOperateValue(Util.getIntValue(exceptionMergeRuleMap.get(key), 1), exceptionOperatorMap.get(key), invoiceExistInfoMap, key, dbValue, sameInvoice, true);
                        } else if ("fieldIdInvoice".equals(key)) {
                            // 附件字段特殊处理，必须以逗号隔开
                            if (!sameInvoice) {
                                dbValue = Util.null2String(invoiceExistInfoMap.get(key)) + "," + dbValue;
                            }else{
                                dbValue = Util.null2String(invoiceExistInfoMap.get(key));
                            }
                        } else {
                            dbValue = getExceptionOperateValue(otherFieldRule, operator, invoiceExistInfoMap, key, dbValue, sameInvoice, true);
                        }
                        invoiceInfoMap.put(key, dbValue);
                    }

                    // 明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        if (exceptionMergeRuleMap.containsKey(key)) {
                            dbValue = getExceptionOperateValue(Util.getIntValue(exceptionMergeRuleMap.get(key), 1), exceptionOperatorMap.get(key), invoiceExistInfoMap, key, dbValue, sameInvoice, false);
                        } else {
                            dbValue = getExceptionOperateValue(otherFieldRule, operator, invoiceExistInfoMap, key, dbValue, sameInvoice, false);
                        }
                        invoiceInfoMap.put(key, dbValue);
                    }

                    //科目单浏览按钮 使用第一个， 如果为空，不进行处理
                    invoiceInfoMap.put("fieldIdSubject", invoiceExistInfoMap.get("fieldIdSubject"));
                    invoiceInfoMap.put("subjectName", invoiceExistInfoMap.get("subjectName"));
                    //发票数组
                    List<Map<String, Object>> beforeInvoiceMapList = (List<Map<String, Object>>) invoiceExistInfoMap.get("invoiceBrowserArray");
                    if (!sameInvoice) {
                        Map<String, Object> map = new HashMap<>(2);
                        map.put("id", invoiceId);
                        map.put("name", invoiceNumber);
                        Map<String, Object> prop = new HashMap<>(2);
                        prop.put("cloudId", cloudId);
                        map.put("prop", prop);
                        beforeInvoiceMapList.add(map);
                    }
                    invoiceInfoMap.put("invoiceBrowserArray", beforeInvoiceMapList);

                } else {
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        String dbColumn = INVOICE_MAIN.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //科目单浏览按钮
                    invoiceInfoMap.put("fieldIdSubject", subjectId);
                    invoiceInfoMap.put("subjectName", subjectName);
                    //发票数组
                    List<Map<String, Object>> invoiceMapList = new ArrayList<>();
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", invoiceId);
                    map.put("name", invoiceNumber);
                    Map<String, Object> prop = new HashMap<>(2);
                    prop.put("cloudId", cloudId);
                    map.put("prop", prop);
                    invoiceMapList.add(map);
                    invoiceInfoMap.put("invoiceBrowserArray", invoiceMapList);
                }
                invoiceInfosMap.put(mergeSign.toString(), invoiceInfoMap);
                startInvoiceId = invoiceId;
            }
            //排序
            List<String> keyList = new ArrayList<String>();//已经添加的key,下次不添加
            for (String invoiceId : invoiceIdsArray) {
                for (String key : orderByMap.keySet()) {
                    String ids = orderByMap.get(key);
                    String[] idsSplit = ids.split(",");
                    for (String s : idsSplit) {
                        if (invoiceId.equals(s) && !keyList.contains(key)) {
                            //获取发票map
                            Map<String, Object> invoiceInfoMap = invoiceInfosMap.get(key);
                            resultArray.add(invoiceInfoMap);
                            keyList.add(key);
                            continue;
                        }
                    }
                }
            }
        } else if (isSplit == 1) {
            //拆分
            List<String> hjColumn = Arrays.asList("fieldIdAmount,fieldIdTax,fieldIdPriceDetail,fieldIdTaxDetail".split(","));
            RecordSet rsQuery = FnaInvoiceCommon.executeInSql("select " +
                    " a.id,a.taxIncludedPrice,a.billingDate,a.tax,a.purchaser,a.purchaserTaxNo,a.seller,a.salestaxno," +
                    " a.invoiceNumber,a.invoiceType,a.imageDocId,a.cloudId," +
                    " c.remark," +
                    " b.invoiceServiceYype invoiceServiceYype_dtl,b.priceWithoutTax priceWithoutTax_dtl,b.taxRate taxRate_dtl,b.tax tax_dtl, " +
                    " d.subjectid " +
                    " from fnaInvoiceLedger a " +
                    " join fnaInvoiceledgerDetail b on a.id=b.mainid " +
                    " left join FnaInvoiceLedgerDtl c on a.id=c.mainid " +
                    " left join FnaInvoiceSubject d on b.invoiceServiceYype=d.invoiceServiceYype " +
                    " where a.id in(占位符标识) order by a.id desc,b.id asc", invoiceIds, "executeQuery");
            Map<String, Map<String, Object>> invoiceInfosMap = new HashMap<>(32);
            // key 为发票 id,value 为标识
            Map<String, String> orderByMap = new LinkedHashMap<String, String>();
            String startInvoiceId = "";
            while (rsQuery.next()) {
                String invoiceId = Util.null2String(rsQuery.getString("id"));
                String invoiceNumber = Util.null2String(rsQuery.getString("invoiceNumber"));
                String cloudId = Util.null2String(rsQuery.getString("cloudId"));
                String subjectId = Util.null2String(rsQuery.getString("subjectid"));
                String subjectName = budgetfeeTypeComInfo.getBudgetfeeTypename(subjectId);
                int imageDocId = Util.getIntValue(rsQuery.getString("imageDocId"), 0);

                //过滤详见销货清单
                String invoiceServiceYype_dtl = Util.null2String(rsQuery.getString("invoiceServiceYype_dtl"));
                if(invoiceServiceYype_dtl.contains("详见销货清单") && isFilter(invoiceId)){
                    continue;
                }

                if(invoiceServiceYype_dtl.contains("原价合计") && isFilter(invoiceId)){
                    continue;
                }
                if(invoiceServiceYype_dtl.contains("折扣额合计") && isFilter(invoiceId)){
                    continue;
                }

                boolean sameInvoice = false;
                if (!"".equals(startInvoiceId) && startInvoiceId.equals(invoiceId)) {
                    sameInvoice = true;
                }
                Map<String, Object> invoiceInfoMap = new HashMap<>(32);
                String mergeSign = "";
                if(spiltRule==1){//按照税率拆分
                    mergeSign = Util.null2String(rsQuery.getString("taxRate_dtl"));
                }else if(spiltRule==2){//按照税额拆分
                    mergeSign = Util.null2String(rsQuery.getString("tax_dtl"));
                }else if(spiltRule==3){//按照费用类型拆分
                    mergeSign = Util.null2String(rsQuery.getString("invoiceServiceYype_dtl"));
                }
                mergeSign = mergeSign+"___"+invoiceId;
                if (!orderByMap.containsKey(mergeSign)) {
                    orderByMap.put(mergeSign, invoiceId);
                } else {
                    orderByMap.put(mergeSign, orderByMap.get(mergeSign) + "," + invoiceId);
                }
                if (invoiceInfosMap.containsKey(mergeSign)) {
                    Map<String, Object> invoiceExistInfoMap = invoiceInfosMap.get(mergeSign);
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        invoiceInfoMap.put(key, invoiceExistInfoMap.get(key));
                    }
                    //明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        String mapKeyValue = Util.null2String(invoiceExistInfoMap.get(key));
                        if (hjColumn.contains(key)) {
                            dbValue = DF.format(Util.getDoubleValue(mapKeyValue, 0.00) + Util.getDoubleValue(dbValue, 0.00));
                        } else {
                            if("fieldIdServiceDetail".equals(key) && spiltRule==3) {//货物或应货税服务类型  税率 取第一个
                                dbValue = mapKeyValue;
                            }else if("fieldIdTaxRateDetail".equals(key) && spiltRule==1){
                                dbValue = mapKeyValue;
                            }else{
                                dbValue = mapKeyValue + "," + dbValue;
                            }

                        }
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //科目单浏览按钮 使用第一个， 如果为空，不进行处理
                    invoiceInfoMap.put("fieldIdSubject", invoiceExistInfoMap.get("fieldIdSubject"));
                    invoiceInfoMap.put("subjectName", invoiceExistInfoMap.get("subjectName"));
                    invoiceInfoMap.put("invoiceBrowserArray", invoiceExistInfoMap.get("invoiceBrowserArray"));
                    invoiceInfoMap.put("fjBrowserArray", invoiceExistInfoMap.get("fjBrowserArray"));

                } else {
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        String dbColumn = INVOICE_MAIN.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //科目单浏览按钮
                    invoiceInfoMap.put("fieldIdSubject", subjectId);
                    invoiceInfoMap.put("subjectName", subjectName);
                    //发票数组
                    List<Map<String, Object>> invoiceMapList = new ArrayList<>();
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", invoiceId);
                    map.put("name", invoiceNumber);
                    Map<String, Object> prop = new HashMap<>(2);
                    prop.put("cloudId", cloudId);
                    map.put("prop", prop);
                    invoiceMapList.add(map);
                    invoiceInfoMap.put("invoiceBrowserArray", invoiceMapList);
                }
                invoiceInfosMap.put(mergeSign, invoiceInfoMap);
                startInvoiceId = invoiceId;
            }
            //排序
            List<String> keyList = new ArrayList<String>();//已经添加的key,下次不添加
            for (String invoiceId : invoiceIdsArray) {
                for (String key : orderByMap.keySet()) {
                    String ids = orderByMap.get(key);
                    String[] idsSplit = ids.split(",");
                    for (String s : idsSplit) {
                        if (invoiceId.equals(s) && !keyList.contains(key)) {
                            //获取发票map
                            Map<String, Object> invoiceInfoMap = invoiceInfosMap.get(key);
                            resultArray.add(invoiceInfoMap);
                            keyList.add(key);
                            continue;
                        }
                    }
                }
            }
        } else {
            //不进行拆分和合并
            //需要特殊处理的key
            String keySubject = "fieldIdSubject";
            String keyService = "fieldIdServiceDetail";
            List<String> hjColumn = Arrays.asList("fieldIdAmount,fieldIdTax,fieldIdPriceDetail,fieldIdTaxDetail".split(","));
            RecordSet rsQuery = FnaInvoiceCommon.executeInSql("select " +
                    " a.id,a.taxIncludedPrice,a.billingDate,a.tax,a.purchaser,a.purchaserTaxNo,a.seller,a.salestaxno," +
                    " a.invoiceNumber,a.invoiceType,a.imageDocId,a.cloudId," +
                    " c.remark," +
                    " b.invoiceServiceYype invoiceServiceYype_dtl,b.priceWithoutTax priceWithoutTax_dtl,b.taxRate taxRate_dtl,b.tax tax_dtl, " +
                    " d.subjectId " +
                    " from fnaInvoiceLedger a " +
                    " join fnaInvoiceledgerDetail b on a.id=b.mainid " +
                    " left join FnaInvoiceLedgerDtl c on a.id=c.mainid " +
                    " left join FnaInvoiceSubject d on b.invoiceServiceYype=d.invoiceServiceYype " +
                    " where a.id in(占位符标识) order by a.id desc,b.id asc", invoiceIds, "executeQuery");
            Map<String, Map<String, Object>> invoiceInfosMap = new HashMap<String, Map<String, Object>>();
            while (rsQuery.next()) {
                String invoiceId = Util.null2String(rsQuery.getString("id"));
                String invoiceNumber = Util.null2String(rsQuery.getString("invoiceNumber"));
                String cloudId = Util.null2String(rsQuery.getString("cloudId"));
                String subjectId = Util.null2String(rsQuery.getString("subjectid"));
                String subjectName = budgetfeeTypeComInfo.getBudgetfeeTypename(subjectId);
                int imageDocId = Util.getIntValue(rsQuery.getString("imageDocId"), 0);

                //过滤详见销货清单
                String invoiceServiceYype_dtl = Util.null2String(rsQuery.getString("invoiceServiceYype_dtl"));
                if(invoiceServiceYype_dtl.contains("详见销货清单") && isFilter(invoiceId)){
                    continue;
                }

                if(invoiceServiceYype_dtl.contains("原价合计") && isFilter(invoiceId)){
                    continue;
                }
                if(invoiceServiceYype_dtl.contains("折扣额合计") && isFilter(invoiceId)){
                    continue;
                }

                Map<String, Object> invoiceInfoMap = new HashMap<String, Object>();
                if (invoiceInfosMap.containsKey(invoiceId)) {
                    Map<String, Object> invoiceExistInfoMap = invoiceInfosMap.get(invoiceId);
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        invoiceInfoMap.put(key, invoiceExistInfoMap.get(key));
                    }
                    //明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        String mapKeyValue = Util.null2String(invoiceExistInfoMap.get(key));
                        if (hjColumn.contains(key)) {
                            dbValue = DF.format(Util.getDoubleValue(mapKeyValue, 0.00) + Util.getDoubleValue(dbValue, 0.00));
                        } else {
                            dbValue = mapKeyValue + "," + dbValue;
                        }
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //科目单浏览按钮 使用第一个， 如果为空，不进行处理
                    invoiceInfoMap.put("fieldIdSubject", invoiceExistInfoMap.get("fieldIdSubject"));
                    invoiceInfoMap.put("subjectName", invoiceExistInfoMap.get("subjectName"));
                    invoiceInfoMap.put("invoiceBrowserArray", invoiceExistInfoMap.get("invoiceBrowserArray"));
                    invoiceInfoMap.put("fjBrowserArray", invoiceExistInfoMap.get("fjBrowserArray"));
                } else {
                    //主表
                    for (String key : INVOICE_MAIN.keySet()) {
                        String dbColumn = INVOICE_MAIN.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //明细表
                    for (String key : INVOICE_DETAIL.keySet()) {
                        String dbColumn = INVOICE_DETAIL.get(key);
                        String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                        dbValue = formatData(key, dbValue, invoiceTypeMap);
                        invoiceInfoMap.put(key, dbValue);
                    }
                    //科目单浏览按钮
                    invoiceInfoMap.put("fieldIdSubject", subjectId);
                    invoiceInfoMap.put("subjectName", subjectName);
                    //发票数组
                    List<Map<String, Object>> invoiceMapList = new ArrayList<Map<String, Object>>();
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("id", invoiceId);
                    map.put("name", invoiceNumber);
                    Map<String, Object> prop = new HashMap<>(2);
                    prop.put("cloudId", cloudId);
                    map.put("prop", prop);
                    invoiceMapList.add(map);
                    invoiceInfoMap.put("invoiceBrowserArray", invoiceMapList);
                }
                invoiceInfosMap.put(invoiceId, invoiceInfoMap);
            }
            //排序
            for (String invoiceId : invoiceIdsArray) {
                Map<String, Object> invoiceInfoMap = invoiceInfosMap.get(invoiceId);
                resultArray.add(invoiceInfoMap);
            }
        }
        return resultArray;
    }

    /**
     * 获取费用类型配置关系
     *
     * @param id id
     * @return Map<String, String>
     */
    private static Map<String, String> getConsTypeMap(int id) {
        RecordSet rs = new RecordSet();
        Map<String, String> constTypeMap = new HashMap<>(2);
        rs.executeQuery("select fieldName,mergeGroup from fnaInvoiceFieldConstType where mainId=?", id);
        while (rs.next()) {
            String fieldName = Util.null2String(rs.getString("fieldName"));
            String mergeGroup = Util.null2String(rs.getString("mergeGroup"));
            if (!constTypeMap.containsKey(fieldName)) {
                constTypeMap.put(fieldName, mergeGroup);
            }
        }
        return constTypeMap;
    }

    /**
     * 根据合并取值规则，获取规则后的值
     *
     * @param mergeRuleType       合并规则
     * @param operate             操作符
     * @param invoiceExistInfoMap key为分组字段标识符 value为发票信息
     * @param key                 invoiceMain或invoiceDetail的key
     * @param dbValue             通过invoiceMain或invoiceDetail的key过去到的值
     * @param sameInvoice         和上一个比较，是否是同一个发票
     * @param mainColumn          是否是主表字段
     * @return String            规则后的值
     */
    public static String getExceptionOperateValue(int mergeRuleType, String operate, Map<String, Object> invoiceExistInfoMap,
                                                  String key, String dbValue, boolean sameInvoice, boolean mainColumn) {
        if (mergeRuleType == 1) {
            //取第一个
            dbValue = Util.null2String(invoiceExistInfoMap.get(key));
        } else if (mergeRuleType == 2) {
            //取最后一行,直接用本次的覆盖

        } else if (mergeRuleType == 3) {
            //自然拼接
            if (sameInvoice && mainColumn) {//同一个发票，并且是主表，取上一个
                dbValue = Util.null2String(invoiceExistInfoMap.get(key));
            } else {
                if (!"".equals(dbValue)) {
                    dbValue = invoiceExistInfoMap.get(key) + operate + dbValue;
                } else {
                    dbValue = Util.null2String(invoiceExistInfoMap.get(key));
                }
            }
        } else if (mergeRuleType == 4) {
            //合计
            if (sameInvoice && mainColumn) {//同一个发票，并且是主表，取上一个
                dbValue = Util.null2String(invoiceExistInfoMap.get(key));
            } else {
                dbValue = DF.format(Util.getDoubleValue(Util.null2String(invoiceExistInfoMap.get(key)), 0.00) + Util.getDoubleValue(dbValue, 0.00));
            }
        }
        return dbValue;
    }

    /**
     * 格式化字段
     *
     * @param key            key
     * @param value          value
     * @param invoiceTypeMap invoiceTypeMap
     * @return String
     */
    public static String formatData(String key, String value, Map<String, String> invoiceTypeMap) {
        if (DOUBLE_FORMAT.contains(key)) {
            value = DF.format(Util.getDoubleValue(value, 0.00));
        } else if (PERCENT_FORMAT.contains(key)) {
            value = DF.format(Util.getDoubleValue(value, 0.00)) + "%";
        } else if (INVOICE_TYPE_FORMAT.contains(key)) {
            value = invoiceTypeMap.get(value);
        } else if (INT_FORMAT.contains(key)) {
            value = Util.null2String(Util.getIntValue(value, 0));
        }
        return value;
    }

    /**
     * 获取当前发票关联的所有的 imageDocId 和 imageFileName
     *
     * @param invoiceIds invoiceIds
     * @return Map<Integer, String>
     */
    public static Map<Integer, String> getImageDocInfoByInvoice(String invoiceIds) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        RecordSet rsQuery = FnaInvoiceCommon.executeInSql("select a.imageDocId,b.imagefileName from  fnaInvoiceLedger a " +
                " join DocImageFile b on a.imageDocId=b.docid where a.id in(占位符标识) ", invoiceIds, "executeQuery");
        while (rsQuery.next()) {
            int imageDocId = Util.getIntValue(rsQuery.getString("imageDocId"), 0);
            String imageFileName = Util.null2String(rsQuery.getString("imagefileName"));
            map.put(imageDocId, imageFileName);
        }
        return map;
    }

    /**
     * 获取流程主表单发票信息
     *
     * @param invoiceIds invoiceIds
     * @return JSONObject
     */
    public static JSONObject getMainInvoiceInfo(String invoiceIds, User user) {
        JSONObject json = new JSONObject();
        JSONArray jaInvoice = new JSONArray();
        Map<String, String> invoiceTypeMap = getInvoiceTypeName(user);
        Map<Integer, String> imageDocMap = getImageDocInfoByInvoice(invoiceIds);
        BudgetfeeTypeComInfo budgetfeeTypeComInfo = new BudgetfeeTypeComInfo();
        //需要特殊处理的key
        String keySubject = "fieldIdSubject";
        String keyService = "fieldIdServiceDetail";
        List<String> hjColumn = Arrays.asList("fieldIdAmount,fieldIdTax,fieldIdPriceDetail,fieldIdTaxDetail".split(","));
        RecordSet rsQuery = FnaInvoiceCommon.executeInSql("select " +
                " a.id,a.taxIncludedPrice,a.billingDate,a.tax,a.purchaser,a.purchaserTaxNo,a.seller,a.salestaxno," +
                " a.invoiceNumber,a.invoiceType,a.imageDocId,a.cloudId," +
                " c.remark," +
                " b.invoiceServiceYype invoiceServiceYype_dtl,b.priceWithoutTax priceWithoutTax_dtl,b.taxRate taxRate_dtl,b.tax tax_dtl, " +
                " d.subjectId " +
                " from fnaInvoiceLedger a " +
                " join fnaInvoiceledgerDetail b on a.id=b.mainid " +
                " left join FnaInvoiceLedgerDtl c on a.id=c.mainid " +
                " left join FnaInvoiceSubject d on b.invoiceServiceYype=d.invoiceServiceYype " +
                " where a.id in(占位符标识) order by a.id desc,b.id asc", invoiceIds, "executeQuery");
        String startInvoiceId = "";
        while (rsQuery.next()) {
            String invoiceId = Util.null2String(rsQuery.getString("id"));
            String invoiceNumber = Util.null2String(rsQuery.getString("invoiceNumber"));
            String cloudId = Util.null2String(rsQuery.getString("cloudId"));

            String subjectId = Util.null2String(rsQuery.getString("subjectid"));
            String subjectName = budgetfeeTypeComInfo.getBudgetfeeTypename(subjectId);
            int imageDocId = Util.getIntValue(rsQuery.getString("imageDocId"), 0);

            //过滤详见销货清单
            String invoiceServiceYype_dtl = Util.null2String(rsQuery.getString("invoiceServiceYype_dtl"));
            if(invoiceServiceYype_dtl.contains("详见销货清单") && isFilter(invoiceId)){
                continue;
            }

            if(invoiceServiceYype_dtl.contains("原价合计") && isFilter(invoiceId)){
                continue;
            }
            if(invoiceServiceYype_dtl.contains("折扣额合计") && isFilter(invoiceId)){
                continue;
            }

            boolean sameInvoice = false;
            if (!"".equals(startInvoiceId) && startInvoiceId.equals(invoiceId)) {
                sameInvoice = true;
            } else {
                JSONObject joInvoice = new JSONObject();
                joInvoice.put("id", invoiceId);
                joInvoice.put("name", invoiceNumber);
                JSONObject prop = new JSONObject();
                prop.put("cloudId", cloudId);
                joInvoice.put("prop", prop);
                jaInvoice.add(joInvoice);
            }
            if (!sameInvoice) {
                for (String key : INVOICE_MAIN.keySet()) {
                    String dbColumn = INVOICE_MAIN.get(key);
                    String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                    dbValue = formatData(key, dbValue, invoiceTypeMap);
                    if (json.containsKey(key)) {
                        String mapKeyValue = json.getString(key);
                        if (hjColumn.contains(key)) {
                            json.put(key, DF.format(Util.getDoubleValue(mapKeyValue, 0.00) + Util.getDoubleValue(dbValue, 0.00)));
                        } else {
                            json.put(key, mapKeyValue + "," + dbValue);
                        }
                    } else {
                        if (hjColumn.contains(key)) {
                            json.put(key, DF.format(Util.getDoubleValue(dbValue, 0.00)));
                        } else {
                            json.put(key, dbValue);
                        }
                    }
                }
            }
            for (String key : INVOICE_DETAIL.keySet()) {
                String dbColumn = INVOICE_DETAIL.get(key);
                String dbValue = Util.null2String(rsQuery.getString(dbColumn));
                dbValue = formatData(key, dbValue, invoiceTypeMap);
                if (json.containsKey(key)) {
                    String mapKeyValue = json.getString(key);
                    if (hjColumn.contains(key)) {
                        json.put(key, DF.format(Util.getDoubleValue(mapKeyValue, 0.00) + Util.getDoubleValue(dbValue, 0.00)));
                    } else {
                        json.put(key, mapKeyValue + "," + dbValue);
                    }
                } else {
                    if (hjColumn.contains(key)) {
                        json.put(key, DF.format(Util.getDoubleValue(dbValue, 0.00)));
                    } else {
                        json.put(key, dbValue);
                    }
                }
                if (keyService.equals(key) && !json.containsKey(keySubject)) {
                    json.put("fieldIdSubject", subjectId);
                    json.put("subjectName", subjectName);
                }
            }
            startInvoiceId = invoiceId;
        }
        //发票附件排序
        JSONArray jaInvoiceOrder = new JSONArray();
        JSONArray jsonArrayAttachmentOrder = new JSONArray();
        String[] invoiceIdsSplit = invoiceIds.split(",");
        StringBuilder invoiceBuilder = new StringBuilder();
        for (String s : invoiceIdsSplit) {
            for (int j = 0; j < jaInvoice.size(); j++) {
                JSONObject jsonInvoice = jaInvoice.getJSONObject(j);
                if (s.equals(jsonInvoice.get("id"))) {
                    jaInvoiceOrder.add(jsonInvoice);
                    if (invoiceBuilder.length() == 0) {
                        invoiceBuilder.append(jsonInvoice.get("id"));
                    } else {
                        invoiceBuilder.append(",").append(jsonInvoice.get("id"));
                    }
                }
            }
        }
        json.put("fieldIdInvoice", invoiceBuilder.toString());
        json.put("invoiceBrowserArray", jaInvoiceOrder);
        json.put("fjBrowserArray", jsonArrayAttachmentOrder);
        //附件浏览按钮值去0和空
        json.put("fieldIdDoc", getAttachment(Util.null2String(json.get("fieldIdDoc"))));
        return json;
    }

    /**
     * 去掉附件中多余的0和空
     *
     * @param attachment 附件
     * @return String
     */
    public static String getAttachment(String attachment) {
        StringBuilder attachmentBuffer = new StringBuilder();
        String[] attachmentSplit = attachment.split(",");
        for (String s : attachmentSplit) {
            if (!"".equals(s) && !"0".equals(s)) {
                if (attachmentBuffer.length() == 0) {
                    attachmentBuffer.append(s);
                } else {
                    attachmentBuffer.append(",").append(s);
                }
            }
        }
        return attachmentBuffer.toString();
    }
    
    public static boolean isFilter(String invoiceId) {
    	RecordSet rs = new RecordSet();
    	int cnt = 0;
    	rs.executeQuery("select count(*) cnt from fnainvoiceledgerdetail where mainid = ?", invoiceId);
    	rs.next();
    	cnt = Util.getIntValue(rs.getString("cnt"));
    	if(cnt==1) {
    		return false;
    	}
    	return true;
    }

    public static Map<String, String> getInvoiceTypeName(User user) {
        // 发票类型 Map
        Map<String, String> invoiceTypeMap = new HashMap<>(24);
        invoiceTypeMap.put("1", SystemEnv.getHtmlLabelName(131508, user.getLanguage()));
        invoiceTypeMap.put("2", SystemEnv.getHtmlLabelName(131509, user.getLanguage()));
        invoiceTypeMap.put("3", SystemEnv.getHtmlLabelName(385371, user.getLanguage()));
        invoiceTypeMap.put("5", SystemEnv.getHtmlLabelName(385375, user.getLanguage()));
        invoiceTypeMap.put("6", SystemEnv.getHtmlLabelName(385376, user.getLanguage()));
        invoiceTypeMap.put("7", SystemEnv.getHtmlLabelName(385377, user.getLanguage()));
        invoiceTypeMap.put("8", SystemEnv.getHtmlLabelName(385373, user.getLanguage()));
        invoiceTypeMap.put("9", SystemEnv.getHtmlLabelName(388517, user.getLanguage()));
        invoiceTypeMap.put("10", SystemEnv.getHtmlLabelName(388518, user.getLanguage()));
        invoiceTypeMap.put("11", SystemEnv.getHtmlLabelName(388519, user.getLanguage()));
        invoiceTypeMap.put("12", SystemEnv.getHtmlLabelName(388520, user.getLanguage()));
        invoiceTypeMap.put("13", SystemEnv.getHtmlLabelName(388521, user.getLanguage()));
        invoiceTypeMap.put("14", SystemEnv.getHtmlLabelName(388525, user.getLanguage()));
        invoiceTypeMap.put("15", SystemEnv.getHtmlLabelName(10003274, user.getLanguage()));
        invoiceTypeMap.put("16", SystemEnv.getHtmlLabelName(504443, user.getLanguage()));
        invoiceTypeMap.put("17", SystemEnv.getHtmlLabelName(520210, user.getLanguage()));
        invoiceTypeMap.put("18", SystemEnv.getHtmlLabelName(520208, user.getLanguage()));
        invoiceTypeMap.put("19", SystemEnv.getHtmlLabelName(520209, user.getLanguage()));
        invoiceTypeMap.put("20", SystemEnv.getHtmlLabelName(530640, user.getLanguage()));
        invoiceTypeMap.put("21", SystemEnv.getHtmlLabelName(532541, user.getLanguage()));
        invoiceTypeMap.put("22", SystemEnv.getHtmlLabelName(532542, user.getLanguage()));
        invoiceTypeMap.put("23", SystemEnv.getHtmlLabelName(532543, user.getLanguage()));
        invoiceTypeMap.put("24", SystemEnv.getHtmlLabelName(537639, user.getLanguage()));
        invoiceTypeMap.put("32", SystemEnv.getHtmlLabelName(537640, user.getLanguage()));
        invoiceTypeMap.put("33", SystemEnv.getHtmlLabelName(537641, user.getLanguage()));
        invoiceTypeMap.put("34", SystemEnv.getHtmlLabelName(538279, user.getLanguage()));
        invoiceTypeMap.put("35", SystemEnv.getHtmlLabelName(538280, user.getLanguage()));
        invoiceTypeMap.put("36", SystemEnv.getHtmlLabelName(538281, user.getLanguage()));
        invoiceTypeMap.put("37", SystemEnv.getHtmlLabelName(538282, user.getLanguage()));
        invoiceTypeMap.put("39", SystemEnv.getHtmlLabelName(545508, user.getLanguage()));
        return invoiceTypeMap;
    }
}
