package com.friday.custody.service.trustService.gf.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.entity.*;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.service.trustService.gf.common.GFConstants;
import com.friday.custody.service.trustService.gf.utils.GFConverter;
import com.friday.custody.service.trustService.gf.utils.GFUtils;
import com.friday.custody.service.trustService.gtja.utils.RandomStrUtil;
import com.gf.iind.client.web.service.Param;
import com.gf.iind.client.web.service.ParamsBuilder;
import com.gf.iind.client.web.service.ParamsResult;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.GFAppSecretDTO;
import com.friday.custody.dto.GuangfaFundNetValueDTO;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.service.basicService.DataDictionaryTypeCertificateCsdcService;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.PullDataFailureLogService;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.trustService.OutsourceService;
import com.friday.custody.utils.BigDecimalUtil;
import com.friday.custody.utils.MatchDataDictionaryKeyUtil;
import com.friday.custody.utils.R;
import com.friday.custody.utils.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class OutSourceGFServiceImpl implements OutsourceService {
    @Autowired
    private InvokeRecordService invokeRecordService;
    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryOpenStateServiceImpl openStateService;
    @Autowired
    private DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private AccountInfoServiceImpl accountInfoService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;//a
    @Autowired
    private FundOpenInfoServiceImpl fundOpenInfoService;
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//b
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//b
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;//d
    @Autowired
    private CustShareSeqInfoServiceImpl custShareSeqInfoService;//d
    @Autowired
    private TgAccountBalanceInfoServiceImpl tgAccountBalanceInfoService;//e
    @Autowired
    private TgAccountSeqInfoServiceImpl tgAccountSeqInfoService;//f
    @Autowired
    private MjAccountBalanceInfoServiceImpl mjAccountBalanceInfoService;//g
    @Autowired
    private MjAccountSeqInfoServiceImpl mjAccountSeqInfoService;//h
    @Autowired
    private FundTradeInfoServiceImpl fundTradeInfoService;//i
    @Autowired
    private FundValueTableDataInfoServiceImpl fundValueTableDataInfoService;//j
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;//j
    @Autowired
    private DataDictionarySellerServiceImpl sellerService;
    @Autowired
    private FundFeeDataInfoServiceImpl fundFeeDataInfoService;
    @Autowired
    private DataDictionaryZxFndBasicInfoCyServiceImpl zxFndBasicInfoCyService;
    @Autowired
    private GFConverter gfConverter;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public R initTenantData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("广发托管数据初始化...");
        getDataFromGF(tenant, CustodyContants.INIT_BY_MONTH_LOOP_TIME); //先都拿1年，客户有需求再增加到3年
        log.info("广发托管数据初始化结束:");
        return R.ok("广发托管数据初始化结束！");
    }

    private void getDataFromGF(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "30";
        try {
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end uniqueKey
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processUpdateInvestorInfoData(tenant, trustNo);//end
            processInvestorInfoData(tenant, trustNo);//end
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);//end uniqueKey
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//end uniqueKey
            //19 募集⼾流⽔表（MJAccount_seq_info）
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo);//end
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo);//end
            processCustShareSeqInfoData(tenant, trustNo);//end uniqueKey
            // 基金费用数据表（fund_fee_data_info）
            processFundFeeDataInfoData(tenant, trustNo);
            //开放日 (fund_info+fund_open_info)
            processFundOpenInfoData(tenant, trustNo);

        } catch (Exception e) {
            log.error("广发托管数据拉取失败:", e);
        }
    }


    private void getUpdateDataFromGF(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "30";
        try {
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end uniqueKey
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processUpdateInvestorInfoData(tenant, trustNo);//end
            processInvestorInfoData(tenant, trustNo);//end
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//end uniqueKey
            //19 募集⼾流⽔表（MJAccount_seq_info）
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo);//end
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo);//end
            processCustShareSeqInfoData(tenant, trustNo);//end uniqueKey
            // 基金费用数据表（fund_fee_data_info）
            processFundFeeDataInfoData(tenant, trustNo);
            //开放日 (fund_info+fund_open_info)
            processFundOpenInfoData(tenant, trustNo);
        } catch (Exception e) {
            log.error("广发托管数据拉取失败:", e);
        }
    }

    private static final String TONGYI = "P1032800"; //通怡
    public void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo){
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = "";
            if (TONGYI.equals(tenant.getTenantName())) {
                indexName = GFConstants.FUND_OPEN_INFO_API + appKey.substring(appKey.length() - 8);
            } else {
                indexName = GFConstants.FUND_OPEN_INFO_API_TY;
            }
            //String indexName = "ora_api_ta_tfundopenday_ty";
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            log.info("map={}", JSONObject.toJSONString(map));
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            log.info("dataMap={}", JSONObject.toJSONString(dataMap));
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            log.info("resultDataSet={}", JSONObject.toJSONString(resultDataSet));
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                //saveInvokeRecord(tenant, trustNo, "ora_api_ta_tfundopenday_ty", "", "", map);
                saveInvokeRecord(tenant, trustNo, GFConstants.FUND_OPEN_INFO_API, "", "", map);
                //封装成标准表的对象 fundInfo
                List<FundInfoEntity> fundInfoentities = getFundInfoInFundOpenInfo(tenant, resultDataSet, trustNo);
                fundInfoService.saveData(null, fundInfoentities);
                //fundOpenInfo
                List<FundOpenInfoEntity> fundOpenInfoentities = getFundOpenInfo(tenant, resultDataSet, trustNo);
                fundOpenInfoService.saveData(null, fundOpenInfoentities);
            }
        } catch (Exception e) {
            log.error("广发托管processFundOpenInfoData数据拉取失败:", e);
        }

    }

    private List<FundInfoEntity> getFundInfoInFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> objects, String trustNo) {
        //封装数据
        List<FundInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (JSONObject data : objects) {
            dataMap = JSONObject.toJavaObject(data, Map.class);
            //String fundName = fundInfoService.getFundNameByFundCode(dataMap.get("c_fundcode"), trustNo);
            //String fundName = fundInfoService.getFundNameByFundCode(dataMap.get("inner_fund_code"), trustNo);
            String fundName = fundInfoService.getFundNameByInnerFundCode(dataMap.get("c_fundcode"), trustNo);

            log.info("fundName={},fundCode={}", fundName, dataMap.get("c_fundcode"));
            entityList.add(FundInfoEntity.builder()
                    .innerFundCode(dataMap.get("c_fundcode"))
                    .fundCode(dataMap.get("c_fundcode"))
                    .fundName(fundName)
                    .trustNo(tenant.getTrustNo())
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .remark("FundOpenInfo")
                    .build());
        }
        return entityList;
    }

    private List<FundOpenInfoEntity> getFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> objects, String trustNo) {
        //获取数据字典
        //开放日类型
        Map<String, String> typeOfOpenDayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, trustNo);
        //开放状态
        Map<String, Map<String, String>> openStateDic = openStateService.queryOpenStateWithDetail(trustNo);
        //封装数据
        List<FundOpenInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (JSONObject data : objects) {
            dataMap = JSONObject.toJavaObject(data, Map.class);
            log.info("dataMap={}", dataMap.toString());
            /*dataMap = JSON.parseObject(JSON.toJSONString(data), HashMap.class);
            log.info("dataMap2={}", dataMap.toString());*/
            //转义开放日类型
            String openType = MatchDataDictionaryKeyUtil.getKey(typeOfOpenDayDic, dataMap.get("c_openstatus"));
            log.info("开放日类型原值={},映射值={}", dataMap.get("c_bonustype"), openType);
            //转义开放状态
            String openStatus = MatchDataDictionaryKeyUtil.getKey(openType, openStateDic, dataMap.get("c_openstatus"));
            log.info("开放状态原值={},映射值={}", dataMap.get("c_bonustype"), openStatus);

            String fundName = fundInfoService.getFundNameByFundCode(dataMap.get("c_fundcode"), trustNo, tenant.getTenantName());
            log.info("fundName={},fundCode={}", fundName, dataMap.get("c_fundcode"));
            entityList.add(FundOpenInfoEntity.builder()
                    .fundCode(dataMap.get("c_fundcode"))
                    //.fundOpenDate(new SimpleDateFormat("yyyyMMdd").format(dataMap.get("busi_date")))
                    .fundOpenDate(StringUtils.isEmpty(dataMap.get("busi_date")) ? null : dataMap.get("busi_date").replaceAll("-", ""))
                    .innerFundCode(dataMap.get("c_fundcode"))
                    .openType(openType)
                    .openStatus(openStatus)
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processFundFeeDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.FUND_FEE_DATA_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                log.info("广发查询fundFeeDataInfo返回数据{}条", resultDataSet.size());
                saveInvokeRecord(tenant, trustNo, GFConstants.FUND_FEE_DATA_INFO_API, "", "", map);
                //封装成标准表的对象
                List<FundFeeDataInfoEntity> fundFeeDataInfoEntities = getFundFeeDataInfo(tenant, trustNo, resultDataSet);
                log.info("广发转化fundFeeDataInfo数据{}条", fundFeeDataInfoEntities.size());
                fundFeeDataInfoService.saveData(null, fundFeeDataInfoEntities);
            }
        } catch (Exception e) {
            log.error("广发托管批量保存fundFeeDataInfo数据失败:", e);
        }
    }

    private List<FundFeeDataInfoEntity> getFundFeeDataInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<JSONObject> resultDataSet) {
        //获取字典

        //封装数据
        List<FundFeeDataInfoEntity> entityList = new ArrayList<>();
        Map<String, String> remoteDataMap;
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundName = fundInfoService.getFundNameByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);//获取fundCode
            //托管费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyftgf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzftgf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_sytgf")))
                    .subjectCode("TGF")
                    .subjectName("托管费")
                    .fundName(fundName)
                    .updateDate(remoteDataMap.get("data_time"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //管理费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfglf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfglf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_syglf")))
                    .subjectCode("GLF")
                    .subjectName("管理费")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //业绩报酬
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfglf_yjbc")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfglf_yjbc")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_syglf_yjbc")))
                    .subjectCode("YJBC")
                    .subjectName("业绩报酬")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //外包服务费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfwbfwf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfwbfwf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfwbfwf")).subtract(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfwbfwf")))))
                    .subjectCode("WBF")
                    .subjectName("外包服务费")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //财顾费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfcwgwf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfcwgwf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_sycwgwf")))
                    .subjectCode("CGF")
                    .subjectName("财顾费")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //销售服务费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfxsfwf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfxsfwf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_syxsfwf")))
                    .subjectCode("XSF")
                    .subjectName("销售服务费")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //证券账户开立费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfqtfy_224199")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfqtfy_224199")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_syqtfy_224199")))
                    .subjectCode("KLF")
                    .subjectName("证券账户开立费")
                    .updateDate(remoteDataMap.get("data_time"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //税费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .confirmDate(StringUtils.isEmpty(remoteDataMap.get("d_make")) ? null : remoteDataMap.get("d_make").replaceAll("-", ""))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljyfsf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_ljzfsf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("f_sysf")))
                    .subjectCode("SF")
                    .subjectName("税费")
                    .fundName(fundName)
                    .updateDate(remoteDataMap.get("data_time"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processUpdateInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.INVESTOR_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.INVESTOR_API, "", "", map);
                //封装成标准表的对象
                List<InvestorInfoEntity> investorInfoEntities = getInvestorInfo(tenant, resultDataSet, trustNo);
                investorInfoService.saveData(null, investorInfoEntities);
            }
        } catch (Exception e) {
            log.error("广发托管investorInfo数据拉取失败:", e);
        }
    }

    private void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.INVESTOR_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.INVESTOR_INFO_API, "", "", map);
                //封装成标准表的对象
                List<InvestorInfoEntity> investorInfoEntities = getInvestorInfo(tenant, resultDataSet, trustNo);
                investorInfoService.saveData(null, investorInfoEntities);
            }
        } catch (Exception e) {
            log.error("广发托管investorInfo数据拉取失败:", e);
        }
    }

    private List<InvestorInfoEntity> getInvestorInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> custTypeCsdcDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CUST_TYPE_CSDC_SERVICE, trustNo);
        Map<String, Map<String, String>> identityTypeCsdcDic = certificateCsdcService.queryCertificateWithDetail(trustNo);

        //2、封装数据
        List<InvestorInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        List<JSONObject> list = JSONObject.parseArray(JSONObject.toJSONString(resultDataSet), JSONObject.class);
        for (JSONObject remoteData : list) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundAcco = investorInfoService.queryInvestor(remoteDataMap.get("c_custname"), remoteDataMap.get("c_identityno"));
            String key = MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("c_custtype"));
            String certiType = remoteDataMap.get("c_identitytype");
            String identityType = MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, certiType);
            result.add(InvestorInfoEntity.builder()
                    .custName(remoteDataMap.get("c_custname"))
                    .fundAcco(Objects.isNull(remoteDataMap.get("c_fundacco")) ? fundAcco : remoteDataMap.get("c_fundacco"))
                    .custType(key)
                    .identityType(identityType)
                    .identityNo(remoteDataMap.get("c_identityno"))
                    .accoOpenDate(Objects.isNull(remoteDataMap.get("d_opendate")) ? null : remoteDataMap.get("d_opendate").replace("-", ""))
                    .address(remoteDataMap.get("c_address"))
                    .zipCode(remoteDataMap.get("c_zipcode"))
                    .mobileNo(remoteDataMap.get("c_mobileno"))
                    .email(remoteDataMap.get("c_email"))
                    .updateDate(Objects.isNull(remoteDataMap.get("d_lastmodify")) ? null : remoteDataMap.get("d_lastmodify") + " 00:00:00")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processMJAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
        String appKey = appSecretDTO.getAppKey();
        String  userId = appSecretDTO.getUserId();
        String curDay;
        LocalDate localDate = LocalDate.now();
        //将loopNum的循环次数转变为日期
        loopTime = loopTime == 1 ? 31 : 365;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < loopTime; i++) {
            curDay = dateTimeFormatter.format(localDate);
            String finalCurDay = curDay;
            try {
                //定义传入参数的接口名称
                String indexName = GFConstants.ACCOUNT_INFO_API + appKey.substring(appKey.length() - 8);
                //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
                //定义一个参数实例
                ParamsResult paramsResult = new ParamsResult();
                List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
                ParamsBuilder param0 = new ParamsBuilder();
                //定义key值，为传入参数的接口名称
                param0.setKey(indexName);
                //定义传入参数的开始时间，包括参数名与具体的参数值
                Param p1 = new Param();
                p1.setName("trans_time");
                p1.setValue(finalCurDay);
                param0.getParams().add(p1);
                ps.add(param0);
                HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
                HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
                List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    saveInvokeRecord(tenant, trustNo, GFConstants.ACCOUNT_INFO_API, "", "", map);
                    //封装成标准表的对象
                    List<AccountInfoEntity> accountntities = getMJAccountInfo(tenant, resultDataSet, trustNo);
                    if (!CollectionUtils.isEmpty(accountntities)) {
                        accountInfoService.saveData(null, accountntities);
                    }
                    //封装成标准表的对象
                    List<MjAccountSeqInfoEntity> entities = getMJAccountSeqInfo(tenant, resultDataSet, trustNo);
                    if (!CollectionUtils.isEmpty(entities)) {
                        mjAccountSeqInfoService.saveData(null, entities);
                    }
                }
            } catch (Exception e) {
                log.error("广发托管MJAccountSeqInfo数据拉取失败:", e);
            }
            localDate = localDate.minusDays(1);
        }
    }

    private List<MjAccountSeqInfoEntity> getMJAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_DIRECTION_SERVICE, trustNo);

        //2、封装数据
        List<MjAccountSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            //查询fundcode
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fund_code"), trustNo);
            if (!"".equals(remoteDataMap.get("this_bank_acco"))) {
                result.add(MjAccountSeqInfoEntity.builder()
                        .fundCode(fundCode)//新增fundCode落库
                        .innerFundCode(remoteDataMap.get("fund_code"))
                        .fundName(remoteDataMap.get("fund_name"))
                        .account(remoteDataMap.get("this_bank_acco"))
                        .accountName(remoteDataMap.get("this_name_in_bank"))
                        .bankName(remoteDataMap.get("this_bank_name"))
                        .opAccount(remoteDataMap.get("that_bank_acco"))
                        .opAccountName(remoteDataMap.get("that_name_in_bank"))
                        .opBankName(remoteDataMap.get("that_bank_name"))
                        .transferInOut(MatchDataDictionaryKeyUtil.getKey(pay, remoteDataMap.get("trans_flag")))
                        .amount(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("trans_amount"))))
                        .transferDate(remoteDataMap.get("trans_time").split(" ")[0].replace("-", ""))
                        .transferTime(remoteDataMap.get("trans_time").split(" ")[1].split("\\.")[0])
                        .currency("".equals(remoteDataMap.get("currency")) ? "156" : MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("currency")))
                        .remark(remoteDataMap.get("memo"))
                        .seqNo(StrUtil.getSeqNoWithoutNoRandom(remoteDataMap.get("serial_no")))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }

        }
        return result;
    }

    private List<AccountInfoEntity> getMJAccountInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> type = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.ACCOUNT_TYPE_SERVICE, trustNo);


        //2、封装数据
        List<AccountInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            if (!"".equals(remoteDataMap.get("this_bank_acco"))) {
                //获取fundCode
                String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fund_code"), trustNo);
                result.add(AccountInfoEntity.builder()
                        .fundCode(fundCode)//新增fundCode
                        .innerFundCode(remoteDataMap.get("fund_code"))
                        .fundName(remoteDataMap.get("fund_name"))
                        .bankAcco(remoteDataMap.get("this_bank_acco"))
                        .nameInBank(remoteDataMap.get("this_name_in_bank"))
                        .branchBankName(remoteDataMap.get("this_bank_name"))
                        .currency("".equals(remoteDataMap.get("currency")) ? "156" : MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("currency")))
                        .accoTypeCode(MatchDataDictionaryKeyUtil.getKey(type, "ZJ002"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.CUST_SHARE_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.CUST_SHARE_INFO_API, "", "", map);
                //封装成标准表的对象
                List<CustShareInfoEntity> entities = getCustShareInfo(tenant, resultDataSet, trustNo);
                custShareInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("广发托管custShareInfo数据拉取失败:", e);
        }
    }

    private List<CustShareInfoEntity> getCustShareInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "广发证券");
//        Map<String, String> fundTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);

        //2、封装数据
        List<CustShareInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String name = fundInfoService.getFundNameByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            String agencyName = sellerService.queryAgencyName("广发证券", "GF8");
            BigDecimal shares = fundNetValueInfoService.getSharesByFundInfo(FundNetValueInfoEntity.builder().admin(tenant.getTenantName()).innerFundCode(remoteDataMap.get("c_fundcode")).fundName(name).build());
            //根查询fundCode
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            result.add(CustShareInfoEntity.builder()
                    .fundCode(fundCode)//新增fundCode
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundName(name)
                    .fundAcco(remoteDataMap.get("c_fundacco"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("c_agencyno")))
                    .agencyName(agencyName)
                    .tradeAcco(remoteDataMap.get("c_tradeacco"))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("f_remainshares")))
                    .shareRatio(BigDecimalUtil.getShareRatio(shares, BigDecimalUtil.obj2BigDecimal(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("f_remainshares")))))
                    .updateDate(remoteDataMap.get("data_time") == null ? null : remoteDataMap.get("data_time"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    public void processFundNetValueInfoDataV1(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
        String appKey = appSecretDTO.getAppKey();
        String  userId = appSecretDTO.getUserId();
        String curDay;
        LocalDate localDate = LocalDate.now();
        //将loopNum的循环次数转变为日期
        loopTime = loopTime == 1 ? 31 : 365;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < loopTime; i++) {
            curDay = dateTimeFormatter.format(localDate);
            String finalCurDay = curDay;
            try {
                //定义传入参数的接口名称
                String indexName = GFConstants.FUND_NET_VALUE_INFO_API + appKey.substring(appKey.length() - 8);
                //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
                //定义一个参数实例
                ParamsResult paramsResult = new ParamsResult();
                List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
                ParamsBuilder param0 = new ParamsBuilder();
                //定义key值，为传入参数的接口名称
                param0.setKey(indexName);
                //定义传入参数的开始时间，包括参数名与具体的参数值
                Param p1 = new Param();
                p1.setName("d_ywrq");
                p1.setValue(finalCurDay);
                param0.getParams().add(p1);
                ps.add(param0);
                HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
                HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
                List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    saveInvokeRecord(tenant, trustNo, GFConstants.FUND_NET_VALUE_INFO_API, "", "", dataMap);
                    //封装成标准表的对象
                    List<FundNetValueInfoEntity> entities = getFundNetValInfo(tenant, resultDataSet, trustNo);
                    if (!CollectionUtils.isEmpty(entities)) {
                        fundNetValueInfoService.saveData(null, entities);
                    }
                }
            } catch (Exception e) {
                log.error("广发托管fundNetValueInfo数据拉取失败:", e);
            }
            localDate = localDate.minusDays(1);
        }
    }


    public void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
        String appKey = appSecretDTO.getAppKey();
        String  userId = appSecretDTO.getUserId();
        String curDay;
        LocalDate localDate = LocalDate.now();
        //将loopNum的循环次数转变为日期
        loopTime = loopTime == 1 ? 31 : 365;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < loopTime; i++) {
            curDay = dateTimeFormatter.format(localDate);
            String finalCurDay = curDay;
            try {
                //定义传入参数的接口名称
                String indexName = GFConstants.FUND_NET_VALUE_INFO_API + appKey.substring(appKey.length() - 8);
                //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
                //定义一个参数实例
                ParamsResult paramsResult = new ParamsResult();
                List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
                ParamsBuilder param0 = new ParamsBuilder();
                //定义key值，为传入参数的接口名称
                param0.setKey(indexName);
                //定义传入参数的开始时间，包括参数名与具体的参数值
                Param p1 = new Param();
                p1.setName("d_ywrq");
                p1.setValue(finalCurDay);
                param0.getParams().add(p1);
                ps.add(param0);
                HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
                HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
                List<GuangfaFundNetValueDTO> resultDataList = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), GuangfaFundNetValueDTO.class);
                if (!CollectionUtils.isEmpty(resultDataList)) {
                    saveInvokeRecord(tenant, trustNo, GFConstants.FUND_NET_VALUE_INFO_API, "", "", dataMap);
                    //封装成标准表的对象
                    List<FundNetValueInfoEntity> entities = gfConverter.fundNetConvert(resultDataList, tenant);
                    if (!CollectionUtils.isEmpty(entities)) {
                        fundNetValueInfoService.saveData(null, entities);
                    }
                }
            } catch (Exception e) {
                log.error("广发托管fundNetValueInfo数据拉取失败:", e);
            }
            localDate = localDate.minusDays(1);
        }
    }

    private List<FundNetValueInfoEntity> getFundNetValInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> checkStatus = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.REVIEW_STATUS_SERVICE, trustNo);
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //2、封装数据
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String innerFundCode = fundInfoService.getInnerFundCodeByName(remoteDataMap.get("product_cname"), trustNo, tenant.getTenantName());
            if (!"".equals(remoteDataMap.get("l_sfqr"))) {
                if ("1".equals(String.valueOf(remoteDataMap.get("l_sfqr")))) {
                    String vcKmdm = remoteDataMap.get("vc_kmdm");
                    String kmmc = "";
                    String ensz = "";
                    if ("基金单位净值：".equals(vcKmdm) || "累计单位净值:".equals(vcKmdm)) {
                        kmmc = String.valueOf(remoteDataMap.get("vc_kmmc"));
                    } else if ("基金资产净值:".equals(vcKmdm) || "实收资本".equals(vcKmdm) || "资产类合计:".equals(vcKmdm)) {
                        ensz = String.valueOf(remoteDataMap.get("en_sz"));
                    }
                    //获取fundCode
                    String fundCode = fundInfoService.getFundCodeByInnerFundCode(innerFundCode, trustNo);
                    FundNetValueInfoEntity build = FundNetValueInfoEntity.builder()
                            .fundCode(fundCode)//新增fundCode
                            .innerFundCode(innerFundCode)
                            .netValueDate(remoteDataMap.get("d_ywrq"))
                            .fundName(remoteDataMap.get("product_cname"))
                            .shares(BigDecimalUtil.str2BigDecimalDefaultZero("实收资本".equals(vcKmdm) ? ensz : ""))
                            .totalAsset(BigDecimalUtil.str2BigDecimalDefaultZero("资产类合计:".equals(vcKmdm) ? ensz : ""))
                            .assetValue(BigDecimalUtil.str2BigDecimalDefaultZero("基金资产净值:".equals(vcKmdm) ? ensz : ""))
                            .netValue(BigDecimalUtil.str2BigDecimal("基金单位净值：".equals(vcKmdm) ? kmmc : "", 4))
                            .totalNetValue(BigDecimalUtil.str2BigDecimal("累计单位净值:".equals(vcKmdm) ? kmmc : "", 4))
                            .currency("".equals(remoteDataMap.get("vc_jsbz")) ? "156" : MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("vc_jsbz")))
                            .trustNo(trustNo)
                            .admin(tenant.getTenantName())
                            .createTime(now)
                            .updateTime(now)
                            .build();
                    log.info("fundNetValue标准表结果：" + JSON.toJSONString(build));
                    result.add(build);
                }
            }

        }
        return result;
    }

    public void processCustShareSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.CUST_SHARE_SEQ_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.CUST_SHARE_SEQ_INFO_API, "", "", map);
                //封装成标准表的对象
                List<CustShareSeqInfoEntity> entities = getCustShareSeqInfo(tenant, resultDataSet, trustNo);
                custShareSeqInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("广发托管custShareSeqInfo数据拉取失败:", e);
        }
    }

    private List<CustShareSeqInfoEntity> getCustShareSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "广发证券");
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);
        Map<String, String> pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, trustNo);
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //2、封装数据
        List<CustShareSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundName = fundInfoService.getFundNameByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            String agencyName = sellerService.queryAgencyName("广发证券", "GF8");
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);//获取fundCode
            result.add(CustShareSeqInfoEntity.builder()
                    .confirmDate(remoteDataMap.get("d_cdate").replace("-", ""))
                    .fundCode(fundCode)//新增fundCode入库
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundName(fundName)
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("c_agencyno")))
                    .agencyName(agencyName)
                    .fundAcco(remoteDataMap.get("c_fundacco"))
                    .branchCode(remoteDataMap.get("c_netno"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("c_businflag")))
                    .shareType(MatchDataDictionaryKeyUtil.getKey(pay, remoteDataMap.get("c_sharetype")))
                    .tradeAcco(remoteDataMap.get("c_tradeacco"))
                    .seqNo(RandomStrUtil.getRandomStr(32))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_lastshares"))))
                    .lastFreezeShare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_lastfreezeshare"))))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("c_bonustype")))
                    .currency("".equals(remoteDataMap.get("c_moneytype")) ? "156" : MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("c_moneytype")))
                    .updateDate(remoteDataMap.get("data_time"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }


    public void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.FUND_PROFIT_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.FUND_PROFIT_INFO_API, "", "", map);
                //封装成标准表的对象
                List<FundProfitInfoEntity> entities = getFundProfitInfo(tenant, resultDataSet, trustNo);
                fundProfitInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("广发托管fundTradeInfo数据拉取失败:", e);
        }
    }

    private List<FundProfitInfoEntity> getFundProfitInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "广发证券");
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> handle = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_SERVICE, trustNo);
        Map<String, String> pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, trustNo);

        //2、封装数据
        List<FundProfitInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundName = fundInfoService.getFundNameByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            String agencyName = sellerService.queryAgencyName("广发证券", "GF8");
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);//获取fundCode
            result.add(FundProfitInfoEntity.builder()
                    .confirmDate(remoteDataMap.get("d_cdate").replace("-", ""))
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundCode(fundCode)//新增fundCode入库
                    .fundName(fundName)
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("c_agencyno")))
                    .agencyName(agencyName)
                    .fundAcco(remoteDataMap.get("c_fundacco"))
                    .branchCode(remoteDataMap.get("c_netno"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("c_businflag")))
                    .sortFlag(MatchDataDictionaryKeyUtil.getKey(handle, remoteDataMap.get("c_sortflag")))
                    .shareType(MatchDataDictionaryKeyUtil.getKey(pay, remoteDataMap.get("c_sharetype")))
                    .oriCserialNo(remoteDataMap.get("c_oricserialno"))
                    .requestDate(remoteDataMap.get("d_date").replace("-", ""))
                    .registDate(remoteDataMap.get("d_registdate").replace("-", ""))
                    .holdDay(String.valueOf(remoteDataMap.get("l_holddays")))
                    .tradeAcco(remoteDataMap.get("c_tradeacco"))
                    .shares(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_shares"))))
                    .oriNav(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_orinav")), 4))
                    .oriTotalNav(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_oritotalnav")), 4))
                    .nav(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_nav")), 4))
                    .totalNav(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_totalnav")), 4))
                    .currRatio(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_curratio")), 4))
                    .yearRatio(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_yearratio")), 4))
                    .returnFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_returnfare"))))
                    .factBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_factbalance"))))
                    .factShares(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_factshare"))))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_bonusbalance"))))
                    .deductRatio(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_standardratio"))))
                    .cserialNo(Objects.isNull(remoteDataMap.get("c_cserialno")) ? RandomStrUtil.getRandomStr(32) : remoteDataMap.get("c_cserialno"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.FUND_TRADE_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.FUND_TRADE_INFO_API, "", "", map);
                //封装成标准表的对象
                List<FundTradeInfoEntity> entities = getFundTradeInfo(tenant, resultDataSet, trustNo);
                fundTradeInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("广发托管fundTradeInfo数据拉取失败:", e);
        }
    }

    private List<FundTradeInfoEntity> getFundTradeInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "广发证券");
        Map<String, String> confirm = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CONFIRM_STATUS_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);

        //2、封装数据
        List<FundTradeInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundName = fundInfoService.getFundNameByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);
            String agencyName = sellerService.queryAgencyName("广发证券", "GF8");
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("c_fundcode"), trustNo);//获取fundCode
            result.add(FundTradeInfoEntity.builder()
                    .confirmDate(remoteDataMap.get("d_cdate").replace("-", ""))
                    .requestDate(remoteDataMap.get("d_requestdate").replace("-", ""))
                    .fundCode(fundCode)//新增fundCode入库
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("c_agencyno")))
                    .agencyName(agencyName)
                    .fundAcco(remoteDataMap.get("c_fundacco"))
                    .tradeAcco(remoteDataMap.get("c_tradeacco"))
                    .confirmStatus(MatchDataDictionaryKeyUtil.getKey(confirm, remoteDataMap.get("c_status")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("c_bonustype")))
                    .applyBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_balance"))))
                    .applyShares(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_shares"))))
                    .netValue(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_netvalue")), 4))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_confirmbalance"))))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_confirmshares"))))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_tradefare"))))
                    .taFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_tafare"))))
                    .stampTax(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_stamptax"))))
                    .backFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_backfare"))))
                    .breachFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_breachfare"))))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_profitbalance"))))
                    .totalFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_totalfare"))))
                    .interest(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_interest"))))
                    .frozenBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_frozenbalance"))))
                    .unfrozenBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_unfrozenbalance"))))
                    .fundFare(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_tradefare4fund"))))
                    .cserialNo(remoteDataMap.get("c_cserialno"))
                    .requestNo(remoteDataMap.get("c_requestno"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("c_businflag")))
                    .agio(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("f_agio"))))
                    .summary(remoteDataMap.get("c_memo"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private GFAppSecretDTO getAppSecretDTO(TenantEscrowAuthorizationInfoDto tenant){
        GFAppSecretDTO gfAppSecretDTO = new GFAppSecretDTO();
        String tenantAppSecret = tenant.getAppSecret();
        if (ObjectUtil.isEmpty(tenantAppSecret)){
            return gfAppSecretDTO;
        }
        try {
            gfAppSecretDTO = objectMapper.readValue(tenantAppSecret, GFAppSecretDTO.class);
        } catch (IOException e) {
            log.error("解析账密{}失败!{}",gfAppSecretDTO, e);
            throw new RRException("解析账密失败!");
        }
        return gfAppSecretDTO;
    }
    private void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            GFAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
            String appKey = appSecretDTO.getAppKey();
            String  userId = appSecretDTO.getUserId();
            //定义传入参数的接口名称
            String indexName = GFConstants.FUND_INFO_API + appKey.substring(appKey.length() - 8);
            //定义一个参数实例，包括传入参数中除appkey,userid及indexName之外的参数
            //定义一个参数实例
            ParamsResult paramsResult = new ParamsResult();
            List<ParamsBuilder> ps = paramsResult.getParamsBuilders();
            ParamsBuilder param0 = new ParamsBuilder();
            //定义key值，为传入参数的接口名称
            param0.setKey(indexName);
            //定义传入参数的开始时间，包括参数名与具体的参数值
            ps.add(param0);
            HashMap map = GFUtils.testDatasetByName(appKey, userId, indexName, paramsResult);
            HashMap dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get(indexName)), HashMap.class);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("rets")), JSONObject.class);
            if (!CollectionUtils.isEmpty(resultDataSet)) {
                saveInvokeRecord(tenant, trustNo, GFConstants.FUND_INFO_API, "", "", map);
                //封装成标准表的对象
                List<FundInfoEntity> entities = getFundInfo(tenant, resultDataSet, trustNo);
                fundInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("广发托管fundInfo数据拉取失败:", e);
        }

    }

    public static final Pattern letterPattern = Pattern.compile("^[a-zA-Z]$");

    private List<FundInfoEntity> getFundInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> status = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_SERVICE, trustNo);
        Map<String, String> type = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, trustNo);
        Map<String, String> privateType = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRIVATE_FUND_TYPE_SERVICE, trustNo);
        Map<String, String> level = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_CLASSIFICATION_LOGO_SERVICE, trustNo);

        //2、封装数据
        List<FundInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundLeval = "";
            if ("0".equals(remoteDataMap.get("c_isgraded"))) {
                fundLeval = MatchDataDictionaryKeyUtil.getKey(level, remoteDataMap.get("c_isgraded"));
            }
            //获取fundCode
            String fundCode = remoteDataMap.get("c_fundcode");

            String fundName = remoteDataMap.get("c_fundname");
            if (StringUtils.isEmpty(fundName)) {
                fundName = "null";
            }
            //设置fundCode
            log.info("getFundInfoData：上游拿到的fundCode={},fundName={}", fundCode, fundName);
            String fundInfoFundCode = "";
            if (StringUtils.isEmpty(fundName)) {
                log.error("当前接口上线数据为{},fundName为blank:{}", JSON.toJSONString(remoteDataMap), fundName);
            } else {
                String substring = fundName.substring(fundName.length() - 1);

                Matcher matcher = letterPattern.matcher(substring);
                boolean lastCharIsLetter = matcher.find();

                if (lastCharIsLetter) {
                    String fundNamePrefix = fundName.substring(0, fundName.length() - 1);
                    log.info("fundName为：{}末尾为字母，去掉字母后为{}去数据库查", fundName, fundNamePrefix);
                    fundInfoFundCode = getFundCodeByFundName(fundNamePrefix, tenant);
                    log.info("查询数据库、上游、字典表拿到的fundCode为{}", fundInfoFundCode);
                } else {
                    fundInfoFundCode = fundCode;
                }
            }

            log.info("getFundInfoData:入参fundCode{},入参fundName{},出参fundInfoFundCode{}", fundCode, fundName, fundInfoFundCode);
            result.add(FundInfoEntity.builder()
                    .fundCode(fundCode)//新增fundCode
                    .innerFundCode(remoteDataMap.get("c_fundcode"))
                    .fundName(remoteDataMap.get("c_fundname"))
                    .fundStatus(MatchDataDictionaryKeyUtil.getKey(status, remoteDataMap.get("c_fundstatus")))
                    .fundType(MatchDataDictionaryKeyUtil.getKey(type, remoteDataMap.get("c_fundtype")))
                    .peType(MatchDataDictionaryKeyUtil.getKey(privateType, remoteDataMap.get("c_fundtype")))
                    .fundLevel(fundLeval)
                    .createDate(String.valueOf(remoteDataMap.get("d_setupdate")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private String getFundCodeByFundName(String fundName, TenantEscrowAuthorizationInfoDto tenant) {
        //1先从数据库查，应该可能已经落过一些数据了
        String fundCode = fundInfoService.getFundCodeByFundName(fundName, tenant.getTrustNo(), tenant.getTenantName());
        if (org.apache.commons.lang.StringUtils.isNotBlank(fundCode)) {
            return fundCode;
        }

        //查询字典表
        return zxFndBasicInfoCyService.getFundCodeByFundname(fundName);
    }

    public void saveInvokeRecord(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String invokeType, String headers, String params, HashMap invokeResult) {
        Date now = new Date();
        InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                .trustNo(trustNo)
                .admin(tenant.getTenantName())
                .invokeType(invokeType)
                .reqHeader(JSON.toJSONString(headers))
                .reqParam(JSON.toJSONString(params))
                .invokeTime(now)
                .invokeResult(JSON.toJSONString(invokeResult))
                .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + invokeType)
                .createTime(now)
                .updateTime(now)
                .build();
        invokeRecordService.save(invokeRecordEntity);
    }

    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("广发托管数据初始化...");
        getUpdateDataFromGF(tenant, 1);
        log.info("广发托管数据初始化结束:");
        return R.ok("广发托管数据初始化结束！");
    }

    @Override
    public R PullRemoteDataFirstQueueJob() {
        return null;
    }

    @Override
    public R initLaterTenantData(String versionStr, List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R initLaterSingleTenantData(String versionStr, TenantEscrowAuthorizationInfoDto tenant) {
        log.info("gf:initLaterSingleTenantData is begin...the versionStr is {} ,the tenant is {}", versionStr, JSON.toJSONString(tenant));
        String trustNo = tenant.getTrustNo();
        Integer loopNum = CustodyContants.INIT_BY_MONTH_LOOP_TIME;
//        Integer loopNum = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        try {
            switch (versionStr) {
                case CustodyContants.R_PT_S_CUSTODY_3_2_6:
                    processMJAccountSeqInfoData(tenant, trustNo, loopNum);
                    log.info("管理人{}广发募集户流水更新完后!", tenant.getTenantName());
                    break;
            }
        }catch (Exception e){
            log.error("广发募集户流水更新失败!", e);
        }
        return null;
    }

    private void initTenantDataBy305(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopTime) {
        try {
            //开放日 (fund_info+fund_open_info)
            //processFundInfoData(tenant, trustNo);//end uniqueKey
            processFundOpenInfoData(tenant, trustNo);//end uniqueKey
        } catch (Exception e) {
            log.error("gf:initTenantDataBy305 is error:", e);
        }
    }

    @Override
    public R initByAppointedTrustNoAndMouth(TenantEscrowAuthorizationInfoDto tenant, int mouth) {
        log.info("initByAppointedTrustNoAndMouth_tenant={},mouth={}", JSON.toJSONString(tenant), mouth);
        getDataFromGF(tenant, mouth);
        return R.ok();
    }

    @Override
    public R updateData20min(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("广发托管数据每20min跟新...");
        String trustNo = tenant.getTrustNo();
        Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        //19 募集⼾流⽔表（MJAccount_seq_info）
        processMJAccountSeqInfoData(tenant, trustNo, loopTime);
        log.info("广发托管数据每20min跟新结束:");
        return R.ok("广发托管数据每20min跟新完成");
    }

    @Override
    public R updateData1h(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData1h(TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateDataCJ(String date, String flag, TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateNetValueData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleNetValueData(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("广发托管数据每8点、12点、20点更新数据开始...");
        try {
            String trustNo = tenant.getTrustNo();
            Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);//end uniqueKey
            log.info("广发托管数据每8点、12点、20点更新数据结束!");
        } catch (Exception e) {
            log.error("广发托管数据每8点、12点、20点更新数据异常！", e);
        }
        return R.ok("发托管数据每8点、12点、20点更新完成！");

    }

    @Override
    public DubboResult updateMJBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            String trustNo = tenant.getTrustNo();
            Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
            // 募集户流⽔表（MJAccount_seq_info）
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户流水失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新托管户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户流水失败" + e.getMessage());
        }
    }

}
