package com.friday.custody.service.trustService.XingYe.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.XingYe.common.XYConstants;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.dto.XyAppSecretDTO;
import com.friday.custody.enums.DataDictionaryTypeEnum;
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.service.trustService.XingYe.utils.XYHttpUtil;
import com.friday.custody.service.trustService.gtja.utils.RandomStrUtil;
import com.friday.custody.utils.BigDecimalUtil;
import com.friday.custody.utils.MatchDataDictionaryKeyUtil;
import com.friday.custody.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OutSourceXYServiceImpl implements OutsourceService {
    @Autowired
    private XYHttpUtil xyHttpUtil;
    //private RestTemplate restTemplate = new RestTemplate();
    @Autowired
    private InvokeRecordService invokeRecordService;
    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private AccountInfoServiceImpl accountInfoService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;//a
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//b
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//b
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;//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 DataDictionaryTypesOfFeeServiceImpl typesOfFeeService;
    @Autowired
    private DataDictionaryOpenStateServiceImpl openStateService;
    @Autowired
    private FundOpenInfoServiceImpl fundOpenInfoService;

    @Autowired
    private FundFeeDataInfoServiceImpl fundFeeDataInfoService;
    private static final ThreadLocal<List<String>> innerFundCodeTL = new ThreadLocal<>();
    @Autowired
    private FundValuationServiceImpl fundValuationService;
    @Autowired
    private DataDictionaryTypeOfFundValuationServiceImpl typeOfFundValuationService;

    private ObjectMapper objectMapper = new ObjectMapper();


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

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

    private void getDataFromXY(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "36";
        try {
            //15 资金账户基本信息表 account_info，16 托管户银⾏账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processMJAccountInfoData(tenant, trustNo, loopTime);//end
            processTGAccountInfoData(tenant, trustNo, loopTime);//end
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processInvestorInfoData(tenant, trustNo);//end
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);//end
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//end
            //19 募集户流水表（MJAccount_seq_info）
            prepareInnerFundCode(tenant);
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);//end
            //17 托管户流水表（TGAccount_seq_info）
            processTGAccountSeqInfoData(tenant, trustNo, loopTime);//end
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopTime);//end
            //20 基金估值报表数据表 fund_value_table_data_info
            processFundValueTableDataInfoData(tenant, trustNo, loopTime);//end
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopTime);//end
            //26.基金费用数据表(fund_fee_data_info)
            processFundFeeDataInfoData(tenant, trustNo, loopTime);
            //基金开放日信息表
            processFundOpenInfoData(tenant, trustNo, loopTime);
        } catch (Exception e) {
            log.error("兴业托管数据拉取失败:", e);
        } finally {
            innerFundCodeTL.remove();
        }
    }
    private void getUpdateDataFromXY(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "36";
        try {
            //15 资金账户基本信息表 account_info，16 托管户银⾏账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processMJAccountInfoData(tenant, trustNo, loopTime);//end
            processTGAccountInfoData(tenant, trustNo, loopTime);//end
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processInvestorInfoData(tenant, trustNo);//end
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//end
            //19 募集户流水表（MJAccount_seq_info）
            prepareInnerFundCode(tenant);
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);//end
            //17 托管户流水表（TGAccount_seq_info）
            processTGAccountSeqInfoData(tenant, trustNo, loopTime);//end
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopTime);//end
            //20 基金估值报表数据表 fund_value_table_data_info
            processFundValueTableDataInfoData(tenant, trustNo, loopTime);//end
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopTime);//end
            //26.基金费用数据表(fund_fee_data_info)
            processFundFeeDataInfoData(tenant, trustNo, loopTime);
            //基金开放日信息表
            processFundOpenInfoData(tenant, trustNo, loopTime);
        } catch (Exception e) {
            log.error("兴业托管数据拉取失败:", e);
        } finally {
            innerFundCodeTL.remove();
        }
    }

    private void prepareInnerFundCode(TenantEscrowAuthorizationInfoDto tenant) {
        List<FundInfoEntity> fundInfoEntities = fundInfoService.getListByTrustNoAndAdmin(tenant);
        if(!CollectionUtils.isEmpty(fundInfoEntities)){
            List<String> innerFundCodeList = fundInfoEntities.stream().map(FundInfoEntity::getInnerFundCode).collect(Collectors.toList());
            innerFundCodeTL.set(innerFundCodeList);
        }
    }

    public void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        List<String> fundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
        String year;
        LocalDate lastYear;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy");
        lastYear = LocalDate.now().minusYears(1);
        year = dateTimeFormatter.format(lastYear);
        for (String fundCode : fundCodeList) {
            if (StringUtils.isBlank(fundCode)) {
                continue;
            }
            try {
                int currentPage = 1;
                for (; ; ) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("fundcode", fundCode);
                    param.put("year", year);
                    param.put("currentpage", currentPage);
                    param.put("rows", "5000");
                    String api = XYConstants.FUND_OPEN_INFO + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&fundcode=" + fundCode + "&year=" + year + "&currentpage=" + currentPage + "&rows=300";
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_OPEN_INFO, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundOpenInfoEntity> fundOpenInfoEntities = getFundOpenInfo(tenant, trustNo, resultDataSet);
                        log.info("兴业证券获取上游数据{}条, 封装之后数据{}条",resultDataSet.size(), fundOpenInfoEntities.size());
                        fundOpenInfoService.saveData(null, fundOpenInfoEntities);
                        currentPage++;
                    } else if ("-3".equals(map.get("returnCode"))) {
                        Map<String, Object> newMap = getApiAuthCode(tenant);
                        token = String.valueOf(newMap.get("access_token"));
                        continue;
                    } else if ("0".equals(map.get("returnCode"))) {
                        log.error("xy:processFundOpenInfoData获取失败, fundCode = {},返回结果 = {}", fundCode, map);
                        continue;
                    } else {
                        log.error("processFundFeeOpenInfoData获取数据失败!");
                    }
                }
            } catch (Exception e) {
                log.error("批量保存fundOpenDataInfo失败！", e);
            }
        }
    }

    private List<FundOpenInfoEntity> getFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<JSONObject> resultDataSet) {
        //获取数据字典
        //开放日类型
        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 : resultDataSet){
            dataMap = JSONObject.toJavaObject(data, Map.class);
            //开放状态和临时开放状态只会存在一个，保存存在的状态
            String openState = "";
            String openType = "";
            if (StringUtils.isNotBlank(dataMap.get("fdstatus")) || StringUtils.isNotBlank(dataMap.get("fdlskf"))) {
                openState = StringUtils.isBlank(dataMap.get("fdstatus")) ? dataMap.get("fdlskf") : dataMap.get("fdstatus");
                openType = StringUtils.isBlank(dataMap.get("fdstatus")) ? "0" : "1";
            }
            String fundcode = fundInfoService.getFundCodeByInnerFundCode(dataMap.get("fundcode"), trustNo);
            entityList.add(FundOpenInfoEntity.builder()
                    .innerFundCode(dataMap.get("fundcode"))
                    .openStatus(MatchDataDictionaryKeyUtil.getKey(openType, openStateDic, openState))
                    .fundOpenDate(dataMap.get("date").replaceAll("-",""))
                    .openType(openType)
                    .fundCode(fundcode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processFundFeeDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        List<String> fundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if (loopTime == 12) {
            loopTime = 52;
        } else {
            loopTime = 5;
        }
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusWeeks(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
//            StringBuffer fundCodeStr = new StringBuffer();
//            fundCodeList.stream().forEach(str->{
//                fundCodeStr.append(str).append(",");
//            });
//            fundCodeStr.deleteCharAt(fundCodeStr.length()-1);
            String feetype = "1,2,3,4,5,6";
            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)){
                    continue;
                }
                try {
                    int currentPage = 1;
                    for (; ; ) {
                        Map<String, Object> param = new HashMap<>();
                        param.put("access_token", token);
                        param.put("version", "V1.0");
                        param.put("prodcode", fundCode);
                        param.put("feetype", feetype);
                        param.put("startdate", finalStartDate);
                        param.put("enddate", finalEndDate);
                        param.put("currentpage", currentPage);
                        param.put("rows", "5000");
                        String api = XYConstants.FUND_FEE_DATA_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                                "&prodcode=" + fundCode + "&feetype=" + feetype + "&startDate=" + finalStartDate + "&endDate=" + finalEndDate
                                + "&currentpage=" + currentPage + "&rows=300";
                        Long startTime = System.currentTimeMillis();
                        log.info("开始调用兴业UstodianFeeQuery接口。。。时间：{}", startTime);
                        HashMap map = xyHttpUtil.sendMessage(api);
                        Long endTime = System.currentTimeMillis();
                        log.info("结束调用兴业UstodianFeeQuery接口。。。时间：{}", endTime);
                        Long tempTime = (endTime - startTime)/1000;
                        log.info("调用接口耗时:{}", tempTime);
                        List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                        saveInvokeRecord(tenant, trustNo, XYConstants.FUND_FEE_DATA_INFO_API, "", param, map);
                        if (CollectionUtils.isEmpty(resultDataSet)) {
                            break;
                        }
                        log.info("兴业证券获取fundFeeDataInfo数据{}条" ,resultDataSet.size());
                        if ("1".equals(map.get("returnCode"))) {
                            //封装成标准表的对象
                            List<FundFeeDataInfoEntity> entityList = getFundFeeDataInfo(tenant, trustNo, resultDataSet);
                            log.info("兴业证券获得上游数据：{}条，封装fundFeeDataInfo数据{}条", resultDataSet, entityList.size());
                            //保存数据
                            fundFeeDataInfoService.saveData(null, entityList);
                            currentPage++;
                        } else if ("-3".equals(map.get("returnCode"))) {
                            Map<String, Object> newMap = getApiAuthCode(tenant);
                            token = String.valueOf(newMap.get("access_token"));
                            continue;
                        }else if ("0".equals(map.get("returnCode"))) {
                            log.error("xy:processFundFeeDataInfoData获取失败, fundCode = {},返回结果 = {}", fundCode, map);
                            continue;
                        } else {
                            log.error("processFundFeeDataInfoData获取数据失败!");
                            continue;
                        }
                    }
                } catch (Exception e) {
                    log.error("批量保存fundFeeDataInfo失败！", e);
                }
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<FundFeeDataInfoEntity> getFundFeeDataInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<JSONObject> resultDataSet) {
        //获取字典
        Map<String, String> typesOfFeeDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPES_OF_FEE_SERVICE, trustNo);
        //封装成标准数据
        List<FundFeeDataInfoEntity> entityList = new ArrayList<>();
        Map<String,String> remoteDataMap;
        for (JSONObject remoteData : resultDataSet){
            remoteDataMap = JSONObject.toJavaObject(remoteData,Map.class);
            //根据subjectCOde查询subjectName
            DataDictionaryTypesOfFeeEntity entity = typesOfFeeService.queryByOriginValue(remoteDataMap.get("feeType"), trustNo);
            //根据获取到的inner_fund_code查询fundCode
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("prodcode"), trustNo);
            if (!ObjectUtils.isEmpty(entity)) {
                entityList.add(FundFeeDataInfoEntity.builder()
                        .innerFundCode(remoteDataMap.get("prodcode"))
                        .subjectCode(MatchDataDictionaryKeyUtil.getKey(typesOfFeeDic, remoteDataMap.get("feeType")))
                        .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("jtAmount")))
                        .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("zfAmount")))
                        .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("feeYe")))
                        .confirmDate(StringUtils.isNotBlank(remoteDataMap.get("ywDate")) ? remoteDataMap.get("ywDate").replaceAll("-","") : null)
                        .fundName(remoteDataMap.get("prodsName"))
                        .fundCode(fundCode)
                        .subjectName(entity.getValue())
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(new Date())
                        .updateTime(new Date())
                        .build());
            }
        }
        return entityList;
    }

    public void processFundValueTableDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        List<String> fundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if (loopTime == 12) {
            loopTime = 52;
        } else {
            loopTime = 5;
        }
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusWeeks(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                try {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("fundcode", fundCode);
                    param.put("scdate", finalStartDate);
                    param.put("ecdate", finalEndDate);
                    String api = XYConstants.FUND_VALUE_TABLE_DATA_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&fundcode=" + fundCode + "&startDate=" + finalStartDate + "&endDate=" + finalEndDate;
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_VALUE_TABLE_DATA_INFO_API, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundValueTableDataInfoEntity> entities = getFundValueTableDataInfo(tenant, resultDataSet, trustNo, fundCode);
                        log.info("兴业获取上游FundValueTableDataInfo数据{}条，封装FundValueTableDataInfo数据{}条" , resultDataSet.size() , entities.size());
                        fundValueTableDataInfoService.saveData(null, entities);
                        //封装为FUndValuationEntity
                        List<FundValuationEntity> fundValuationEntityList = getFundValuationInfo(tenant.getTenantName(), trustNo, resultDataSet, trustNo, fundCode);
                        fundValuationService.saveData(null, fundValuationEntityList);
                    } else if ("-3".equals(map.get("returnCode"))) {
                        Map<String, Object> newMap = getApiAuthCode(tenant);
                        token = String.valueOf(newMap.get("access_token"));
                        continue;
                    } else if ("0".equals(map.get("returnCode"))) {
                        log.error("xy:processFundValueTableDataInfoData获取失败, fundCode = {},返回结果 = {}", fundCode, map);
                        continue;
                    } else {
                        log.error("processFundValueTableDataInfoData获取数据失败!");
                    }
                } catch (Exception e) {
                    log.error("批量保存mjAccountSeqInfo失败！", e);
                }
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<FundValuationEntity> getFundValuationInfo(String tenantName, String trustNo, List<JSONObject> resultDataSet, String trustNo1, String fundCode) {
        //封装数据
        List<FundValuationEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Map<String, String> map;
        Date now = new Date();
        //获取kmCode数据字典
        Map<String, String> typeOfFundValuationDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_FUND_VALUATION, trustNo);
        Map<String, String> fundValuationMap = typeOfFundValuationService.queryKeyValue();
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            log.info("remoteDataMap" + JSON.toJSONString(remoteDataMap));
            List<JSONObject> rows = JSONArray.parseArray(JSONObject.toJSONString(remoteDataMap.get("rows")), JSONObject.class);
            for (int j = rows.size() - 1; j >= 0; j--) {
                map = JSONObject.toJavaObject(rows.get(j), Map.class);
                String sl;
                if (map.get("sl").startsWith(".")) {
                    sl = "0" + map.get("sl");
                } else if (map.get("sl").startsWith("-.")) {
                    sl = map.get("sl").split("\\.")[0] + "0." + map.get("sl").split("\\.")[1];
                } else {
                    sl = map.get("sl");
                }
                String dwcb;
                if (map.get("dwcb").startsWith(".")) {
                    dwcb = "0" + map.get("dwcb");
                } else if (map.get("dwcb").startsWith("-.")) {
                    dwcb = map.get("dwcb").split("\\.")[0] + "0." + map.get("dwcb").split("\\.")[1];
                } else {
                    dwcb = map.get("dwcb");
                }
                String cb;
                if (map.get("cb").startsWith(".")) {
                    cb = "0" + map.get("cb");
                } else if (map.get("cb").startsWith("-.")) {
                    cb = map.get("cb").split("\\.")[0] + "0." + map.get("cb").split("\\.")[1];
                } else {
                    cb = map.get("cb");
                }
                String cbzjz;
                if (map.get("cbzjz").startsWith(".")) {
                    cbzjz = "0" + map.get("cbzjz");
                } else if (map.get("cbzjz").startsWith("-.")) {
                    cbzjz = map.get("cbzjz").split("\\.")[0] + "0." + map.get("cbzjz").split("\\.")[1];
                } else {
                    cbzjz = map.get("cbzjz");
                }
                String hqjz;
                if (map.get("hqjz").startsWith(".")) {
                    hqjz = "0" + map.get("hqjz");
                } else if (map.get("hqjz").startsWith("-.")) {
                    hqjz = map.get("hqjz").split("\\.")[0] + "0." + map.get("hqjz").split("\\.")[1];
                } else {
                    hqjz = map.get("hqjz");
                }
                String sz;
                if (map.get("sz").startsWith(".")) {
                    sz = "0" + map.get("sz");
                } else if (map.get("sz").startsWith("-.")) {
                    sz = map.get("sz").split("\\.")[0] + "0." + map.get("sz").split("\\.")[1];
                } else {
                    sz = map.get("sz");
                }
                String szzjz;
                if (map.get("szzjz").startsWith(".")) {
                    szzjz = "0" + map.get("szzjz");
                } else if (map.get("szzjz").startsWith("-.")) {
                    szzjz = map.get("szzjz").split("\\.")[0] + "0." + map.get("szzjz").split("\\.")[1];
                } else {
                    szzjz = map.get("szzjz");
                }
                String gzzz;
                if (map.get("gzzz").startsWith(".")) {
                    gzzz = "0" + map.get("gzzz");
                } else if (map.get("gzzz").startsWith("-.")) {
                    gzzz = map.get("gzzz").split("\\.")[0] + "0." + map.get("gzzz").split("\\.")[1];
                } else {
                    gzzz = map.get("gzzz");
                }
                String dwjz;
                if (remoteDataMap.get("dwjz").startsWith(".")) {
                    dwjz = "0" + remoteDataMap.get("dwjz");
                } else if (remoteDataMap.get("dwjz").startsWith("-.")) {
                    dwjz = remoteDataMap.get("dwjz").split("\\.")[0] + "0." + remoteDataMap.get("dwjz").split("\\.")[1];
                } else {
                    dwjz = remoteDataMap.get("dwjz");
                }
//                String code = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
                String code = fundInfoService.getFundCodeByInnerFundCode(fundCode, trustNo);
                String kmCode = MatchDataDictionaryKeyUtil.getKey(typeOfFundValuationDic, map.get("kmdm"));
                if (StringUtils.isBlank(kmCode)){
                    continue;
                }
                result.add(FundValuationEntity.builder()
                        .fundCode(code)
                        .innerFundCode(fundCode)
                        .netValue(BigDecimalUtil.str2BigDecimal(dwjz, 4))
                        .valueDate(remoteDataMap.get("gzrq").replace("-", ""))
                        .fundName(remoteDataMap.get("fundname"))
                        .kmCode(kmCode)
                        .kmName(fundValuationMap.get(kmCode))
                        .amount(BigDecimalUtil.str2BigDecimal(sl))
                        .perCost(BigDecimalUtil.str2BigDecimal(dwcb))//
                        .portCost(BigDecimalUtil.str2BigDecimal(cb))//cb
                        .costBi(BigDecimalUtil.str2BigDecimal(cbzjz, 4))//cbzjz
                        .vapPrice(BigDecimalUtil.str2BigDecimal(hqjz))//hqjz
                        .portMv(BigDecimalUtil.str2BigDecimal(sz))//sz
                        .mvBl(BigDecimalUtil.str2BigDecimal(szzjz, 4))//szzjz
                        .portIv(BigDecimalUtil.str2BigDecimal(gzzz))//gzzz
                        .suspension(map.get("tpxx"))
                        .trustNo(trustNo)
                        .admin(tenantName)
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    public void processFundValueTableDataInfoDataV2(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        List<String> fundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if (loopTime == 12) {
            loopTime = 52;
        } else {
            loopTime = 5;
        }
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusWeeks(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                try {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("fundcode", fundCode);
                    param.put("scdate", finalStartDate);
                    param.put("ecdate", finalEndDate);
                    String api = XYConstants.FUND_VALUE_TABLE_DATA_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&fundcode=" + fundCode + "&startDate=" + finalStartDate + "&endDate=" + finalEndDate;
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_VALUE_TABLE_DATA_INFO_API, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundValueTableDataInfoEntity> entities = getFundValueTableDataInfo(tenant, resultDataSet, trustNo, fundCode);
                        log.info("兴业获取上游FundValueTableDataInfo数据{}条，封装FundValueTableDataInfo数据{}条" , resultDataSet.size() , entities.size());
//                        fundValueTableDataInfoService.saveData(null, entities);
                        //fundValueTableDataInfoService.saveFundValueDataBatch(null, entities);
                    } else if ("-3".equals(map.get("returnCode"))) {
                        Map<String, Object> newMap = getApiAuthCode(tenant);
                        token = String.valueOf(newMap.get("access_token"));
                        continue;
                    } else if ("0".equals(map.get("returnCode"))) {
                        log.error("xy:processFundValueTableDataInfoData获取失败, fundCode = {},返回结果 = {}", fundCode, map);
                        continue;
                    } else {
                        log.error("processFundValueTableDataInfoData获取数据失败!");
                    }
                } catch (Exception e) {
                    log.error("批量保存mjAccountSeqInfo失败！", e);
                }
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }


    private List<FundValueTableDataInfoEntity> getFundValueTableDataInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo, String fundCode) {
        //封装数据
        List<FundValueTableDataInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Map<String, String> map;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            log.info("remoteDataMap" + JSON.toJSONString(remoteDataMap));
            List<JSONObject> rows = JSONArray.parseArray(JSONObject.toJSONString(remoteDataMap.get("rows")), JSONObject.class);
            for (int j = rows.size() - 1; j >= 0; j--) {
                map = JSONObject.toJavaObject(rows.get(j), Map.class);
                String sl;
                if (map.get("sl").startsWith(".")) {
                    sl = "0" + map.get("sl");
                } else if (map.get("sl").startsWith("-.")) {
                    sl = map.get("sl").split("\\.")[0] + "0." + map.get("sl").split("\\.")[1];
                } else {
                    sl = map.get("sl");
                }
                String dwcb;
                if (map.get("dwcb").startsWith(".")) {
                    dwcb = "0" + map.get("dwcb");
                } else if (map.get("dwcb").startsWith("-.")) {
                    dwcb = map.get("dwcb").split("\\.")[0] + "0." + map.get("dwcb").split("\\.")[1];
                } else {
                    dwcb = map.get("dwcb");
                }
                String cb;
                if (map.get("cb").startsWith(".")) {
                    cb = "0" + map.get("cb");
                } else if (map.get("cb").startsWith("-.")) {
                    cb = map.get("cb").split("\\.")[0] + "0." + map.get("cb").split("\\.")[1];
                } else {
                    cb = map.get("cb");
                }
                String cbzjz;
                if (map.get("cbzjz").startsWith(".")) {
                    cbzjz = "0" + map.get("cbzjz");
                } else if (map.get("cbzjz").startsWith("-.")) {
                    cbzjz = map.get("cbzjz").split("\\.")[0] + "0." + map.get("cbzjz").split("\\.")[1];
                } else {
                    cbzjz = map.get("cbzjz");
                }
                String hqjz;
                if (map.get("hqjz").startsWith(".")) {
                    hqjz = "0" + map.get("hqjz");
                } else if (map.get("hqjz").startsWith("-.")) {
                    hqjz = map.get("hqjz").split("\\.")[0] + "0." + map.get("hqjz").split("\\.")[1];
                } else {
                    hqjz = map.get("hqjz");
                }
                String sz;
                if (map.get("sz").startsWith(".")) {
                    sz = "0" + map.get("sz");
                } else if (map.get("sz").startsWith("-.")) {
                    sz = map.get("sz").split("\\.")[0] + "0." + map.get("sz").split("\\.")[1];
                } else {
                    sz = map.get("sz");
                }
                String szzjz;
                if (map.get("szzjz").startsWith(".")) {
                    szzjz = "0" + map.get("szzjz");
                } else if (map.get("szzjz").startsWith("-.")) {
                    szzjz = map.get("szzjz").split("\\.")[0] + "0." + map.get("szzjz").split("\\.")[1];
                } else {
                    szzjz = map.get("szzjz");
                }
                String gzzz;
                if (map.get("gzzz").startsWith(".")) {
                    gzzz = "0" + map.get("gzzz");
                } else if (map.get("gzzz").startsWith("-.")) {
                    gzzz = map.get("gzzz").split("\\.")[0] + "0." + map.get("gzzz").split("\\.")[1];
                } else {
                    gzzz = map.get("gzzz");
                }
                String dwjz;
                if (remoteDataMap.get("dwjz").startsWith(".")) {
                    dwjz = "0" + remoteDataMap.get("dwjz");
                } else if (remoteDataMap.get("dwjz").startsWith("-.")) {
                    dwjz = remoteDataMap.get("dwjz").split("\\.")[0] + "0." + remoteDataMap.get("dwjz").split("\\.")[1];
                } else {
                    dwjz = remoteDataMap.get("dwjz");
                }
//                String code = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
                String code = fundInfoService.getFundCodeByInnerFundCode(fundCode, trustNo);
                result.add(FundValueTableDataInfoEntity.builder()
                        .fundCode(code)
                        .innerFundCode(fundCode)
                        .netValue(BigDecimalUtil.str2BigDecimal(dwjz, 4))
                        .valueDate(remoteDataMap.get("gzrq").replace("-", ""))
                        .fundName(remoteDataMap.get("fundname"))
                        .kmCode(map.get("kmdm"))
                        .kmName(map.get("kmmc"))
                        .amount(BigDecimalUtil.str2BigDecimal(sl))
                        .perCost(BigDecimalUtil.str2BigDecimal(dwcb))//
                        .portCost(BigDecimalUtil.str2BigDecimal(cb))//cb
                        .costBi(BigDecimalUtil.str2BigDecimal(cbzjz, 4))//cbzjz
                        .vapPrice(BigDecimalUtil.str2BigDecimal(hqjz))//hqjz
                        .portMv(BigDecimalUtil.str2BigDecimal(sz))//sz
                        .mvBl(BigDecimalUtil.str2BigDecimal(szzjz, 4))//szzjz
                        .portIv(BigDecimalUtil.str2BigDecimal(gzzz))//gzzz
                        .suspension(map.get("tpxx"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        int currentPage = 0;
        for (; ; ) {
            currentPage++;
            Map<String, Object> param = new HashMap<>();
            param.put("access_token", token);
            param.put("version", "V1.0");
            param.put("currentpage", String.valueOf(currentPage));
            param.put("rows", "5000");
            String fundInfoApi = XYConstants.FUND_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                    "&currentpage=" + currentPage + "&rows=300";
            HashMap map = xyHttpUtil.sendMessage(fundInfoApi);
            JSONObject remoteDataSet = (JSONObject)map.get("resultDataSet");
            List<JSONObject> remoteDataList = JSONObject.parseArray(JSONObject.toJSONString(remoteDataSet.get("list")), JSONObject.class);
            log.info("兴业获取fundInfo数据{}条" , remoteDataList.size());
            int total = Integer.parseInt(remoteDataSet.get("total").toString());
            saveInvokeRecord(tenant, trustNo, XYConstants.FUND_INFO_API, "", param, map);
            if (CollectionUtils.isEmpty(remoteDataList)) {
                break;
            }
            if ("1".equals(map.get("returnCode"))) {
                //封装成标准表的对象
                List<FundInfoEntity> entities = getFundInfo(tenant, remoteDataList, trustNo);
                log.info("兴业获取上游fundInfo数据{}条，封装fundInfo数据{}条" , remoteDataList.size() , entities.size());
                fundInfoService.saveData(null, entities);
            }
            if ("-3".equals(map.get("returnCode"))) {
                try {
                    token = getApiToken(tenant);
                } catch (IOException e) {
                    log.error("获取token失败!", e);
                    return;
                }
                continue;
            }
            if (currentPage * 5000 > total){
                break;
            }
        }
    }

    private List<FundInfoEntity> getFundInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> productStatusDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_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);
            if (StringUtils.isNotEmpty(remoteDataMap.get("fundcode"))) {
                result.add(FundInfoEntity.builder()
                        .fundCode(remoteDataMap.get("xhbadm"))
                        .innerFundCode(remoteDataMap.get("fundcode"))
                        .fundName(remoteDataMap.get("fundname"))
                        .createDate(StringUtils.isEmpty(remoteDataMap.get("setupdate")) ? null : remoteDataMap.get("setupdate"))
                        .fundStatus(MatchDataDictionaryKeyUtil.getKey(productStatusDic, remoteDataMap.get("pdtstatus")))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private void processMJAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                List<String> innerFundCodeList = innerFundCodeTL.get();
                if(CollectionUtils.isEmpty(innerFundCodeList)){
                    log.error("接口{}的入参fundCode为空",XYConstants.MJACCOUNT_SEQ_INFO_API);
                    throw new IllegalArgumentException("接口"+ XYConstants.MJACCOUNT_SEQ_INFO_API + "的入参fundCode为空");
                }
                for (String fundCode:innerFundCodeList) {
                    int currentPage = 1;
                    for (; ; ) {
                        Map<String, Object> param = new HashMap<>();
                        param.put("access_token", token);
                        param.put("fundcode", fundCode);
                        param.put("version", "V1.0");
                        param.put("scdate", finalStartDate);
                        param.put("ecdate", finalEndDate);
                        param.put("currentpage", String.valueOf(currentPage));
                        param.put("rows", "300");
                        String api = XYConstants.MJACCOUNT_SEQ_INFO_API +
                                "&access_token=" + token +
                                "&version=" + XYConstants.VERSION +
                                "&fundcode=" + fundCode +
                                "&startdate=" + finalStartDate +
                                "&enddate=" + finalEndDate +
                                "&currentpage=" + currentPage +
                                "&rows=300";
                        HashMap map = xyHttpUtil.sendMessage(api);

                        if ("1".equals(map.get("returnCode"))) {
                            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                            if (CollectionUtils.isEmpty(resultDataSet)) {
                                break;
                            }
                            saveInvokeRecord(tenant, trustNo, XYConstants.MJACCOUNT_SEQ_INFO_API, "", param, map);
                            //封装成标准表的对象
                            List<MjAccountSeqInfoEntity> entities = getMJAccountSeqInfo(tenant, resultDataSet, trustNo);
                            mjAccountSeqInfoService.saveData(null, entities);
                            currentPage++;
                        } else if ("-3".equals(map.get("returnCode"))) {
                            Map<String, Object> newMap = getApiAuthCode(tenant);
                            token = String.valueOf(newMap.get("access_token"));
                            continue;
                        } else {
                            saveInvokeRecord(tenant, trustNo, XYConstants.MJACCOUNT_SEQ_INFO_API, "", param, map);
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("批量保存mjAccountSeqInfo失败！", e);
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<MjAccountSeqInfoEntity> getMJAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_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);
//            String code = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
            String code = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(MjAccountSeqInfoEntity.builder()
                    .fundCode(code)
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .account(remoteDataMap.get("inaccount"))
                    .accountName(remoteDataMap.get("inbanklname"))
//                    .bankName(remoteDataMap.get(""))
                    .opAccount(remoteDataMap.get("outaccount"))
                    .opAccountName(remoteDataMap.get("outbankname"))
//                    .opBankName(remoteDataMap.get("optOpenBankName"))
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("showbalance")))
                    .transferDate(remoteDataMap.get("tallydate").split(" ")[0].replace("-", ""))
                    .transferTime(remoteDataMap.get("tallydate").split(" ")[1])
                    .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("moneytype")))
                    .summary(remoteDataMap.get("remark"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processTGAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                List<String> fundCodeList = innerFundCodeTL.get();
                if(CollectionUtils.isEmpty(fundCodeList)){
                    log.error("接口{}的入参fundCode为空",XYConstants.TGACCOUNT_SEQ_API);
                    throw new IllegalArgumentException("接口"+ XYConstants.TGACCOUNT_SEQ_API + "的入参fundCode为空");
                }
                for (String fundCode:fundCodeList) {
                    int currentPage = 1;
                    for (; ; ) {
                        Map<String, Object> param = new HashMap<>();
                        param.put("access_token", token);
                        param.put("version", "V1.0");
                        param.put("fundcode", fundCode);
                        param.put("scdate", finalStartDate);
                        param.put("ecdate", finalEndDate);
                        param.put("currentpage", String.valueOf(currentPage));
                        param.put("rows", "300");
                        String api = XYConstants.TGACCOUNT_SEQ_API +
                                "&access_token=" + token +
                                "&version=" + XYConstants.VERSION +
                                "&fundcode=" + fundCode +
                                "&startdate=" + finalStartDate +
                                "&enddate=" + finalEndDate +
                                "&currentpage=" + currentPage +
                                "&rows=300";
                        HashMap map = xyHttpUtil.sendMessage(api);
                        if ("1".equals(map.get("returnCode"))) {
                            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                            if (CollectionUtils.isEmpty(resultDataSet)) {
                                break;
                            }
                            saveInvokeRecord(tenant, trustNo, XYConstants.TGACCOUNT_SEQ_API, "", param, map);
                            //封装成标准表的对象
                            List<TgAccountSeqInfoEntity> entities = getTGAccountSeqInfo(tenant, resultDataSet, trustNo);
                            tgAccountSeqInfoService.saveData(null, entities);
                            currentPage++;
                        }else if ("-3".equals(map.get("returnCode"))) {
                            Map<String, Object> newMap = getApiAuthCode(tenant);
                            token = String.valueOf(newMap.get("access_token"));
                            continue;
                        }else {
                            saveInvokeRecord(tenant, trustNo, XYConstants.TGACCOUNT_SEQ_API, "", param, map);
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("批量保存tgAccountSeqInfo失败！", e);
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

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

        //2、封装数据
        List<TgAccountSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
//            String code = fundInfoService.getFundCodeByName(remoteDataMap.get("od_sname"), trustNo);
            String code = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("od_code"), trustNo);
            result.add(TgAccountSeqInfoEntity.builder()
                    .fundCode(code)
                    .innerFundCode(remoteDataMap.get("od_code"))
                    .fundName(remoteDataMap.get("od_sname"))
                    .transferInOut(MatchDataDictionaryKeyUtil.getKey(paymentDir, remoteDataMap.get("sffx")))
                    .account(remoteDataMap.get("bfzh"))
                    .accountName(remoteDataMap.get("bfzhmc"))
                    .opAccount(remoteDataMap.get("dsfzh"))
                    .opAccountName(remoteDataMap.get("dsfmc"))
                    .amount(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("je")))
                    .transferDate(remoteDataMap.get("rq").replace("-", ""))
                    .transferTime("00:00:00")
                    .summary(remoteDataMap.get("hksy"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    public void processMJAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        if (loopTime == 1) {
            String curDay;
            LocalDate localDate = LocalDate.now();
            //将loopNum的循环次数转变为日期
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            for (int i = 0; i < loopTime; i++) {
                curDay = dateTimeFormatter.format(localDate);
                String finalCurDay = curDay;
                try {
                    int currentPage = 1;
                    for (; ; ) {
                        Map<String, Object> param = new HashMap<>();
                        param.put("access_token", token);
                        param.put("version", "V1.0");
                        param.put("currentpage", String.valueOf(currentPage));
                        param.put("rows", "5000");
                        String api = XYConstants.MJACCOUNT_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                                "&date=" + finalCurDay + "&currentpage=" + currentPage + "&rows=5000";
                        HashMap map = xyHttpUtil.sendMessage(api);
                        List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                        saveInvokeRecord(tenant, trustNo, XYConstants.MJACCOUNT_INFO_API, "", param, map);
                        if (CollectionUtils.isEmpty(resultDataSet)) {
                            break;
                        }
                        if ("1".equals(map.get("returnCode"))) {
                            //封装成标准表的对象
                            List<AccountInfoEntity> accountntities = getMJAccountInfo(tenant, resultDataSet, trustNo);
                            accountInfoService.saveData(null, accountntities);
                            List<MjAccountBalanceInfoEntity> entities = getMJAccountBanlance(tenant, resultDataSet, trustNo);
                            mjAccountBalanceInfoService.saveData(null, entities);
                            currentPage++;
                        }
                        if ("-3".equals(map.get("returnCode"))) {
                            Map<String, Object> newMap = getApiAuthCode(tenant);
                            token = String.valueOf(newMap.get("access_token"));
                            continue;
                        }
                    }
                } catch (Exception e) {
                    log.error("批量保存TGAccountBalanceInfo失败！", e);
                }
            }
        } else {
            int currentPage = 1;
            List<JSONObject> list = new ArrayList<>();
            Map<String, Object> param = new HashMap<>();
            HashMap map = new HashMap();
            for (; ; ) {
                param.put("access_token", token);
                param.put("version", "V1.0");
                param.put("currentpage", String.valueOf(currentPage));
                param.put("rows", "5000");
                String fundInfoApi = XYConstants.MJACCOUNT_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                        "&currentpage=" + currentPage + "&rows=5000";
                map = xyHttpUtil.sendMessage(fundInfoApi);
                List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                saveInvokeRecord(tenant, trustNo, XYConstants.MJACCOUNT_INFO_API, "", param, map);
                if (CollectionUtils.isEmpty(resultDataSet)) {
                    break;
                }
                if ("1".equals(map.get("returnCode"))) {
                    //封装成标准表的对象
                    List<AccountInfoEntity> accountntities = getMJAccountInfo(tenant, resultDataSet, trustNo);
                    accountInfoService.saveData(null, accountntities);
                    List<MjAccountBalanceInfoEntity> entities = getMJAccountBanlance(tenant, resultDataSet, trustNo);
                    mjAccountBalanceInfoService.saveData(null, entities);
                    currentPage++;
                }
                if ("-3".equals(map.get("returnCode"))) {
                    try {
                        token = getApiToken(tenant);
                    } catch (IOException e) {
                        log.error("获取token失败!", e);
                        return;
                    }
                    continue;
                }
            }
        }
    }

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

        //2、封装数据
        List<MjAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            result.add(MjAccountBalanceInfoEntity.builder()
                    .bankAcco(remoteDataMap.get("recipientacco"))
                    .accoBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("amount")))
                    .updateDate(remoteDataMap.get("date") + " 00:00:00")
                    .currency(MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("moneytype")))
                    .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);

        //2、封装数据
        List<AccountInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
//            String code = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
            String code = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(AccountInfoEntity.builder()
                    .fundCode(code)
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .bankAcco(remoteDataMap.get("recipientacco"))
                    .branchBankName(remoteDataMap.get("recipientbankname"))
                    .currency(MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("moneytype")))
                    .accoTypeCode("ZJ002")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    public void processTGAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        if (loopTime == 1) {
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            endDate = dateTimeFormatter.format(localDate);
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                try {
                    int currentPage = 1;
                    for (; ; ) {
                        Map<String, Object> param = new HashMap<>();
                        param.put("access_token", token);
                        param.put("version", "V1.0");
                        param.put("currentpage", String.valueOf(currentPage));
                        param.put("rows", "5000");
                        String fundInfoApi = XYConstants.TGACCOUNT_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                                "&startdate=" + finalStartDate + "&enddate=" + finalEndDate + "&currentpage=" + currentPage + "&rows=5000";
                        HashMap map = xyHttpUtil.sendMessage(fundInfoApi);
                        List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                        saveInvokeRecord(tenant, trustNo, XYConstants.TGACCOUNT_INFO_API, "", param, map);
                        if (CollectionUtils.isEmpty(resultDataSet)) {
                            break;
                        }
                        if ("1".equals(map.get("returnCode"))) {
                            //封装成标准表的对象
                            List<AccountInfoEntity> accountntities = getTGAccountInfo(tenant, resultDataSet, trustNo);
                            accountInfoService.saveData(null, accountntities);
                            List<TgAccountBalanceInfoEntity> entities = getTGAccountBanlance(tenant, resultDataSet, trustNo);
                            tgAccountBalanceInfoService.saveData(null, entities);
                            currentPage++;
                        }
                        if ("-3".equals(map.get("returnCode"))) {
                            Map<String, Object> newMap = getApiAuthCode(tenant);
                            token = String.valueOf(newMap.get("access_token"));
                            continue;
                        }
                    }
                } catch (Exception e) {
                    log.error("批量保存TGAccountBalanceInfo失败！", e);
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } else {
            int currentPage = 1;
            for (; ; ) {
                Map<String, Object> param = new HashMap<>();
                param.put("access_token", token);
                param.put("version", "V1.0");
                param.put("currentpage", String.valueOf(currentPage));
                param.put("rows", "300");
                String api = XYConstants.TGACCOUNT_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                        "&currentpage=" + currentPage + "&rows=5000";
                HashMap map = xyHttpUtil.sendMessage(api);
                List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                saveInvokeRecord(tenant, trustNo, XYConstants.TGACCOUNT_INFO_API, "", param, map);
                if (CollectionUtils.isEmpty(resultDataSet)) {
                    break;
                }
                if ("1".equals(map.get("returnCode"))) {
                    //封装成标准表的对象
                    List<AccountInfoEntity> accountntities = getTGAccountInfo(tenant, resultDataSet, trustNo);
                    accountInfoService.saveData(null, accountntities);
                    List<TgAccountBalanceInfoEntity> entities = getTGAccountBanlance(tenant, resultDataSet, trustNo);
                    tgAccountBalanceInfoService.saveData(null, entities);
                    currentPage++;
                }
                if ("-3".equals(map.get("returnCode"))) {
                    try {
                        token = getApiToken(tenant);
                    } catch (IOException e) {
                        log.error("获取token失败!", e);
                        return;
                    }
                    continue;
                }
            }
        }

    }

    private List<TgAccountBalanceInfoEntity> getTGAccountBanlance(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        //2、封装数据
        List<TgAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            result.add(TgAccountBalanceInfoEntity.builder()
                    .bankAcco(remoteDataMap.get("zh"))
                    .accoBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("ye")))
                    .updateDate(remoteDataMap.get("rq") + " 00:00:00")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

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

        //2、封装数据
        List<AccountInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            result.add(AccountInfoEntity.builder()
                    .bankAcco(remoteDataMap.get("zh"))
                    .nameInBank(remoteDataMap.get("zhmc"))
                    .branchBankName(remoteDataMap.get("khhmc"))
                    .accoTypeCode("ZJ001")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!");
            return;
        }
        List<CustShareInfoEntity> entityList = new ArrayList<>();
        int currentPage = 1;
        for (; ; ) {
            Map<String, Object> param = new HashMap<>();
            param.put("access_token", token);
            param.put("version", "V1.0");
            param.put("currentpage", String.valueOf(currentPage));
            param.put("rows", "300");
            String fundInfoApi = XYConstants.CUST_SHARE_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                    "&currentpage=" + currentPage + "&rows=300";
            HashMap map = xyHttpUtil.sendMessage(fundInfoApi);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
            saveInvokeRecord(tenant, trustNo, XYConstants.CUST_SHARE_INFO_API, "", param, map);
            if (CollectionUtils.isEmpty(resultDataSet)) {
                break;
            }
            if ("1".equals(map.get("returnCode"))) {
                //封装成标准表的对象
                List<CustShareInfoEntity> entities = getCustShareInfo(tenant, resultDataSet, trustNo);
                entityList.addAll(entities);
                currentPage++;
            }
            if ("-3".equals(map.get("returnCode"))) {
                try {
                    token = getApiToken(tenant);
                } catch (IOException e) {
                    log.error("获取token失败!", e);
                    return;
                }
                continue;
            }
        }
        custShareInfoService.saveData(null, entityList);
    }

    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 key = sellerService.queryKey("兴业证券", remoteDataMap.get("agencyname"));
//            String code = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
            String code = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            BigDecimal shares = fundNetValueInfoService.getSharesByFundInfo(FundNetValueInfoEntity.builder().admin(tenant.getTenantName()).innerFundCode(remoteDataMap.get("fundcode")).fundName(remoteDataMap.get("fundname")).build());
            result.add(CustShareInfoEntity.builder()
                    .fundCode(code)
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .agencyNo(key)
                    .agencyName(remoteDataMap.get("agencyname"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .enableShares(new BigDecimal(remoteDataMap.get("enableShares") == null ? "0" : remoteDataMap.get("enableShares").replace(",", "")).setScale(2))
                    .lastHoldShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("realshares").replace(",", "")))
                    .shareRatio(BigDecimalUtil.getShareRatio(shares, BigDecimalUtil.obj2BigDecimal(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("realshares").replace(",", "")))))
                    .netValueDate(remoteDataMap.get("busiDate"))
                    .frozenShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("frozenshares").replace(",", "")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("bonustype")))
                    .updateDate(remoteDataMap.get("lastmodify") == null ? null : remoteDataMap.get("lastmodify") + " 00:00:00")
                    .enableShares(new BigDecimal(remoteDataMap.get("realshares").replace(",", "")).subtract(new BigDecimal(remoteDataMap.get("frozenshares").replace(",", ""))))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!", e);
            return;
        }
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                int currentPage = 1;
                for (; ; ) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("scdate", finalStartDate);
                    param.put("ecdate", finalEndDate);
                    param.put("currentpage", String.valueOf(currentPage));
                    param.put("rows", "300");
                    String api = XYConstants.FUND_PROFIT_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&scdate=" + finalStartDate + "&ecdate=" + finalEndDate + "&currentpage=" + currentPage + "&rows=300";
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_PROFIT_INFO_API, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundProfitInfoEntity> entities = getFundProfitInfo(tenant, resultDataSet, trustNo);
                        fundProfitInfoService.saveData(null, entities);
                        currentPage++;
                    }
                    if ("-3".equals(map.get("returnCode"))) {
                        try {
                            token = getApiToken(tenant);
                        } catch (IOException e) {
                            log.error("获取token失败!", e);
                            return;
                        }
                        continue;
                    }
                }
            } catch (Exception e) {
                log.error("批量保存fundNetValueInfo失败！", e);
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<FundProfitInfoEntity> getFundProfitInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> handle = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_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 key = sellerService.queryKey("兴业证券", remoteDataMap.get("agencyname"));
//            String fundCode = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"),trustNo);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(FundProfitInfoEntity.builder()
                    .fundCode(fundCode)
                    .confirmDate(remoteDataMap.get("cdate").replace("-", ""))
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .agencyNo(key)
                    .agencyName(remoteDataMap.get("agencyname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .fundName(remoteDataMap.get("fundname"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("businname")))
                    .sortFlag(MatchDataDictionaryKeyUtil.getKey(handle, remoteDataMap.get("profitflag")))
                    .requestDate(remoteDataMap.get("date").replace("-", ""))
                    .registDate(remoteDataMap.get("registdate").replace("-", ""))
                    .holdDay(remoteDataMap.get("holddays"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confshares")))
                    .oriNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("beginnetvalue"), 4))
                    .oriTotalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("begintotalnetvalue"), 4))
                    .nav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netvalue"), 4))
                    .totalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalnetvalue"), 4))
                    .currRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("curratio"), 4))
                    .yearRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("yearratio"), 4))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("deductbalance")))
                    .factBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factdeductbalance")))
                    .factShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factdeductshares")))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("bonusbalance")))
                    .oriDate(remoteDataMap.get("begindate").replace("-", ""))
                    .cserialNo(RandomStrUtil.getRandomStr(32))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    public void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!", e);
            return;
        }
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                int currentPage = 1;
                for (; ; ) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("scdate", finalStartDate);
                    param.put("ecdate", finalEndDate);
                    param.put("currentpage", String.valueOf(currentPage));
                    param.put("rows", "300");
                    String api = XYConstants.FUND_TRADE_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&scdate=" + finalStartDate + "&ecdate=" + finalEndDate + "&currentpage=" + currentPage + "&rows=300";
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_TRADE_INFO_API, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundTradeInfoEntity> entities = getFundTradeInfo(tenant, resultDataSet, trustNo);
                        fundTradeInfoService.saveData(null, entities);
                        currentPage++;
                    }
                    if ("-3".equals(map.get("returnCode"))) {
                        try {
                            token = getApiToken(tenant);
                        } catch (IOException e) {
                            log.error("获取token失败!", e);
                            return;
                        }
                        continue;
                    }
                }
            } catch (Exception e) {
                log.error("批量保存fundNetValueInfo失败！", e);
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<FundTradeInfoEntity> getFundTradeInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        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 key = sellerService.queryKey("兴业证券", remoteDataMap.get("agencyname"));
//            String fundCode = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"), trustNo);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(FundTradeInfoEntity.builder()
                    .fundCode(fundCode)
                    .confirmDate(remoteDataMap.get("cdate").replace("-", ""))
                    .requestDate(remoteDataMap.get("date").replace("-", ""))
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .agencyNo(key)
                    .agencyName(remoteDataMap.get("agencyname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .confirmStatus(MatchDataDictionaryKeyUtil.getKey(confirm, remoteDataMap.get("statusname")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("bonusType")))
                    .applyBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("balance")))
                    .applyShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shares")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netvalue"), 4))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confirmbalance")))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confirmshares")))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tradefare")))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factdeductbalance")))
                    .totalFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalfare")))
                    .agencyFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agencyfare")))
                    .fundFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundfare")))
                    .registFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("registfare")))
                    .cserialNo(remoteDataMap.get("cserialno"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("businname")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    public void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!", e);
            return;
        }
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopTime; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                int currentPage = 1;
                for (; ; ) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("access_token", token);
                    param.put("version", "V1.0");
                    param.put("sdate", finalStartDate);
                    param.put("edate", finalEndDate);
                    param.put("currentpage", String.valueOf(currentPage));
                    param.put("rows", "300");
                    String api = XYConstants.FUND_NET_VALUE_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                            "&sdate=" + finalStartDate + "&edate=" + finalEndDate + "&currentpage=" + currentPage + "&rows=300";
                    HashMap map = xyHttpUtil.sendMessage(api);
                    List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
                    saveInvokeRecord(tenant, trustNo, XYConstants.FUND_NET_VALUE_INFO_API, "", param, map);
                    if (CollectionUtils.isEmpty(resultDataSet)) {
                        break;
                    }
                    if ("1".equals(map.get("returnCode"))) {
                        //封装成标准表的对象
                        List<FundNetValueInfoEntity> entities = getFundNetValInfo(tenant, resultDataSet, trustNo);
                        fundNetValueInfoService.saveData(null, entities);
                        currentPage++;
                    }
                    if ("-3".equals(map.get("returnCode"))) {
                        try {
                            token = getApiToken(tenant);
                        } catch (IOException e) {
                            log.error("获取token失败!", e);
                            return;
                        }
                        continue;
                    }
                }
            } catch (Exception e) {
                log.error("批量保存fundNetValueInfo失败！", e);
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<FundNetValueInfoEntity> getFundNetValInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> checkStatus = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.REVIEW_STATUS_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 fundCode = fundInfoService.getFundCodeByName(remoteDataMap.get("fundname"),trustNo);
            FundInfoEntity fundInfoEntity = fundInfoService.queryByInnerFundCode(trustNo, tenant.getTenantName(), remoteDataMap.get("fundcode"));
            String fundCode="";
            if (Objects.nonNull(fundInfoEntity)) {
                fundCode = fundInfoEntity.getFundCode();
            }
            if ("净值已确认".equals(remoteDataMap.get("sfqr"))) {
                FundNetValueInfoEntity build = FundNetValueInfoEntity.builder()
                        .fundCode(fundCode)
                        .netValueDate(remoteDataMap.get("rq"))
                        .innerFundCode(remoteDataMap.get("fundcode"))
                        .fundName(remoteDataMap.get("fundname"))
                        .shares(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("zcfe")))
                        .totalAsset(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("zchj")))
                        .assetValue(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("zcjz")))
                        .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("dwjz"), 4))
                        .totalNetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ljdwjz"), 4))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build();
                log.info("fundNetValue标准表结果：" + JSON.toJSONString(build));
                result.add(build);
            }
        }
        return result;
    }

    private void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        String token = null;
        try {
            token = getApiToken(tenant);
        } catch (IOException e) {
            log.error("获取token失败!", e);
            return;
        }
        int currentPage = 1;
        for (; ; ) {
            Map<String, Object> param = new HashMap<>();
            param.put("access_token", token);
            param.put("version", "V1.0");
            param.put("currentpage", String.valueOf(currentPage));
            param.put("rows", "300");
            String fundInfoApi = XYConstants.INVESTOR_INFO_API + "&access_token=" + token + "&version=" + XYConstants.VERSION +
                    "&currentpage=" + currentPage + "&rows=300";
            HashMap map = xyHttpUtil.sendMessage(fundInfoApi);
            List<JSONObject> resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("resultDataSet")), JSONObject.class);
            saveInvokeRecord(tenant, trustNo, XYConstants.INVESTOR_INFO_API, "", param, map);
            if (CollectionUtils.isEmpty(resultDataSet)) {
                break;
            }
            if ("1".equals(map.get("returnCode"))) {
                //封装成标准表的对象
                List<InvestorInfoEntity> investorInfoEntities = getInvestorInfo(tenant, resultDataSet, trustNo);
                investorInfoService.saveData(null, investorInfoEntities);
                currentPage++;
            }
            if ("-3".equals(map.get("returnCode"))) {
                try {
                    token = getApiToken(tenant);
                } catch (IOException e) {
                    log.error("获取token失败!", e);
                    return;
                }
                continue;
            }
        }
    }

    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 key = MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("custtype"));
            String certiType = remoteDataMap.get("identitytype");
            String identityType = MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, certiType);
            result.add(InvestorInfoEntity.builder()
                    .custName(remoteDataMap.get("custname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .custType(key)
                    .identityType(identityType)
                    .identityNo(remoteDataMap.get("identityno"))
                    .accoOpenDate(Objects.isNull(remoteDataMap.get("opendate")) ? null : remoteDataMap.get("opendate").replace("-", ""))
                    .address(remoteDataMap.get("address"))
                    .mobileNo(remoteDataMap.get("mobileno"))
                    .email(remoteDataMap.get("email"))
                    .updateDate(Objects.isNull(remoteDataMap.get("lastmodify")) ? null : remoteDataMap.get("lastmodify") + " 00:00:00")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //获取token
    private Map<String, Object> getApiAuthCode(TenantEscrowAuthorizationInfoDto tenant) throws IOException {
        String tenantAppSecret = tenant.getAppSecret();
        XyAppSecretDTO xyAppSecretDTO = new XyAppSecretDTO();
        if (ObjectUtil.isNotEmpty(tenantAppSecret)){
            xyAppSecretDTO = objectMapper.readValue(tenantAppSecret, XyAppSecretDTO.class);
        }
        String clientId = xyAppSecretDTO.getClientId();
        String clientSecret = xyAppSecretDTO.getClientSecret();
        String username = xyAppSecretDTO.getUsername();
        String password = xyAppSecretDTO.getPassword();
        String responseType = xyAppSecretDTO.getResponseType();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setReadTimeout(10 * 1000);
        requestFactory.setConnectTimeout(10 * 1000);
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> param = new HashMap<>();
        param.put("client_id", clientId);
        param.put("username",  username);
        param.put("password", password);
        param.put("response_type", XYConstants.RESPONSE_TYPE);
        param.put("redirect_uri", XYConstants.REDIRECT_URL);
        String codeApi = XYConstants.API_AUTH_CODE + "&client_id=" + clientId + "&username=" + username +
                "&password=" + password + "&response_type=" + XYConstants.RESPONSE_TYPE + "&redirect_uri=" + XYConstants.REDIRECT_URL;
        HashMap codeMap = xyHttpUtil.sendMessage(codeApi);
        if ("1".equals(codeMap.get("returnCode"))) {
            String code = String.valueOf(codeMap.get("code"));
            String tokenApi = XYConstants.API_TOKEN + "&client_id=" + clientId + "&client_secret=" + clientSecret +
                    "&code=" + code + "&grant_type=" + XYConstants.GRANT_TYPE + "&redirect_uri=" + XYConstants.REDIRECT_URL;
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", "application/x-www-form-urlencoded");
            String urlWithParam = XYConstants.URL + tokenApi;
            HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(null, headers);
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(urlWithParam, httpEntity, String.class);
            HashMap tokenMap = JSONObject.parseObject(responseEntity.getBody(), HashMap.class);
            if ("1".equals(tokenMap.get("returnCode"))) {
                map.put("access_token", String.valueOf(tokenMap.get("access_token")));
                map.put("refresh_token", String.valueOf(tokenMap.get("refresh_token")));
                return map;
            } else {
                log.info("获取token失败:" + JSON.toJSONString(tokenMap));
            }
        } else if ("-6".equals(codeMap.get("returnCode"))) {
            map.put("access_token", String.valueOf(codeMap.get("access_token")));
            map.put("refresh_token", "");
            return map;
        } else {
            log.info("获取code失败:response:{},api:{}", JSON.toJSONString(codeMap), codeApi);
        }
        map.put("access_token", "");
        return map;
    }

    //验证token是否有效
    private String validityToken(TenantEscrowAuthorizationInfoDto tenant, String token) {
        String codeApi = XYConstants.VAL_TOKEN + "&client_id=" + tenant.getAppKey() + "&access_token=" + token;
        HashMap map = xyHttpUtil.sendMessage(codeApi);
        if ("1".equals(map.get("returnCode"))) {
            return token;
        } else if ("-3".equals(map.get("returnCode"))) {
            return "";
        }
        return "";
    }

    //刷新token
    private Map<String, Object> refreshToken(TenantEscrowAuthorizationInfoDto tenant, String token, String refreshToken) {
        String codeApi = XYConstants.REFRESH_TOKEN + "&client_id=" + tenant.getAppKey() + "&refresh_token=" + refreshToken + "&access_token=" + token;
        HashMap map = xyHttpUtil.sendMessage(codeApi);
        Map<String, Object> refreshMap = new HashMap<>();
        if ("1".equals(map.get("returnCode"))) {
            refreshMap.put("access_token", String.valueOf(map.get("access_token")));
            refreshMap.put("refresh_token", String.valueOf(map.get("refresh_token")));
            return refreshMap;
        } else if ("-8".equals(map.get("returnCode"))) {
            refreshMap.put("access_token", "");
            refreshMap.put("refresh_token", "");
            return refreshMap;
        }
        return refreshMap;
    }

    private String getApiToken(TenantEscrowAuthorizationInfoDto tenant) throws IOException {
        Map<String, Object> apiAuthCode = getApiAuthCode(tenant);
        return String.valueOf(apiAuthCode.get("access_token"));
    }

    /*private Map<String , Object> getToken(Map<String,Object> map){
        Map<String , Object> token = new HashMap<>();
        String accessToken = String.valueOf(map.get("access_token"));
        String refreshToken = String.valueOf(map.get("refresh_token"));
        accessToken = validityToken(accessToken);
        if(StringUtils.isBlank(accessToken)){
            Map<String, Object> tokenMap = getApiAuthCode();
            accessToken = String.valueOf(tokenMap.get("access_token"));
        }
        if(StringUtils.isNotBlank(refreshToken)){
            Map<String, Object> getMap = refreshToken(accessToken, refreshToken);
            token.put("access_token",getMap.get("access_token"));
            token.put("refresh_token",getMap.get("refresh_token"));
        }
        return token;
    }*/

    public void saveInvokeRecord(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String invokeType, String headers, Map<String, Object> 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("兴业托管数据初始化...");
        getUpdateDataFromXY(tenant, 1); //先都拿1年，客户有需求再增加到3年
        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("xy: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:
                    prepareInnerFundCode(tenant);
                    //19 募集户流水表（MJAccount_seq_info）
                    processMJAccountSeqInfoData(tenant, trustNo, loopNum);//end
                    //17 托管户流水表（TGAccount_seq_info）
                    processTGAccountSeqInfoData(tenant, trustNo, loopNum);//end
                    break;
            }
        }catch (Exception e){
            log.error("更新兴业流水表失败!", e);
        }
        return null;
    }

    private void initTenantDataBy305(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopTime) {
        log.info("xy:initTenantDataBy318oatch01 is run...");
        try {
           processFundOpenInfoData(tenant, trustNo, loopTime);
            log.info("xy:initTenantDataBy318oatch01 is end...");
        } catch (Exception e) {
            log.error("xy:initTenantDataBy318oatch01 is error:", e);
        }
    }

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

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

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        try{
            log.info("兴业托管数据每20min跟新...");
            String trustNo = tenant.getTrustNo();
            Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
            //15 资金账户基本信息表 account_info，16 托管户银⾏账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processMJAccountInfoData(tenant, trustNo, loopTime);//end
            processTGAccountInfoData(tenant, trustNo, loopTime);//end
            prepareInnerFundCode(tenant);
            //19 募集户流水表（MJAccount_seq_info）
            processMJAccountSeqInfoData(tenant, trustNo, loopTime);//end
            //17 托管户流水表（TGAccount_seq_info）
            processTGAccountSeqInfoData(tenant, trustNo, loopTime);//end
            log.info("兴业托管数据每20min跟新结束:");
        }catch (Exception e){
            log.error("兴业每20min更新异常",e);
        }finally {
            innerFundCodeTL.remove();
        }

        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) {
        try{
            log.info("兴业托管数据每8点、12点、20点更新开始...");
            String trustNo = tenant.getTrustNo();
            Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);//end
            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 {
            processMJAccountInfoData(tenant, tenant.getTrustNo(), 1);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

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

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            processTGAccountInfoData(tenant, tenant.getTrustNo(), 1);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            prepareInnerFundCode(tenant);
            // 托管户流水表（TGAccount_seq_info）
            processTGAccountSeqInfoData(tenant, tenant.getTrustNo(), 1);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募托管户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募托管户流水失败" + e.getMessage());
        }
    }
}
