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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.gtja.common.GuoAnConstants;
import com.friday.custody.service.trustService.guosen.common.GuosenConstants;
import com.friday.custody.service.trustService.guosen.dto.RemoteDto;
import com.friday.custody.service.trustService.guosen.utils.MD5Util;
import com.friday.custody.service.trustService.htsc.utils.HTSCGetDataUtil;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.utils.*;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.service.basicService.DataDictionaryTypeCertificateCsdcService;
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.gtja.utils.GTJAHttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OutsourceGuoAnServiceImpl implements OutsourceService {
    @Value("${custody.remote.url.gtja.gtjaUrlPrefix}")
    private String gtjaUrlPrefix;

    @Autowired
    HTSCGetDataUtil hTSCGetDataUtil;

    @Autowired
    private DataDictionarySellerServiceImpl sellerService;

    @Autowired
    private GTJAHttpUtil gTJAHttpUtil;

    private RestTemplate restTemplate = new RestTemplate();
    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;//a
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//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 AccountInfoServiceImpl accountInfoService;//11
    @Autowired
    private CustShareSeqInfoServiceImpl custShareSeqInfoService;//12
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//13
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;//14
    @Autowired
    private CustShareDetailInfoServiceImpl custShareDetailInfoService;//15
    @Autowired
    private FundFeeDataInfoServiceImpl fundFeeDataInfoService;
    @Autowired
    private FundOpenInfoServiceImpl fundOpenInfoService;
    @Autowired
    private DataDictionaryOpenStateServiceImpl openStateService;


    @Resource(name = "pullDataThreadPool")
    private ExecutorService pullDataThreadPool;

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

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("国泰君安托管数据初始化...");
        getDataFromGTJA(tenant, 12); //先都拿1年，客户有需求再增加到3年
        log.info("国泰君安托管数据初始化结束:");
        return R.ok("国泰君安托管数据初始化结束！");

    }

    public void getDataFromGTJAWithoutTgMj(TenantEscrowAuthorizationInfoDto tenant, int loopNum) {
        String trustNo = "31"; //每分钟 30次
        try {
            log.info("国泰君安每半天更新：开始");
            //6&8 6.托管⼾流⽔表（TGAccount_seq_info） 8.募集⼾流⽔表（MJAccount_seq_info）
            processTGAccountSeqInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安每半天更新：1/12");
            //processTGAccountSeqInfoData1(tenant, trustNo, loopNum);  银行流水联机实时查询
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo,loopNum);
            log.info("国泰君安每半天更新：2/12");
            //删除fund_info表的fund_level字段
            //2&13  2.基金出资人信息表（investor_info）   13 基金出资人银行账户信息表(investor_bank_info)
            processInvestorInfoData(tenant, trustNo);
            log.info("国泰君安每半天更新：3/12");
            log.info("国泰君安每半天更新：4/12");
            //4 基金持有信息表（cust_share_info）
            processCustInfoData(tenant, trustNo);
            log.info("国泰君安每半天更新：5/12");
            //5&7&11 5.托管⼾银⾏账⼾余额信息表（TGAccount_balance_info）  7.募集户银行账余额信息表（MGAccount_balance_info） 11 account_info
            processTGAccountBalanceInfoData(tenant, trustNo);
            log.info("国泰君安每半天更新：6/12");
            //5&7&11 5.托管⼾银⾏账⼾余额信息表（TGAccount_balance_info）  7.募集户银行账余额信息表（MGAccount_balance_info） 11 account_info
            //processAccountInfoData(tenant, trustNo);  银行余额联机实时查询
            //9 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安每半天更新：7/12");
            //12 基金持有份额变化流水表（cust_share_seq_info）
            processCustShareSeqInfoData(tenant, trustNo, loopNum); //没有权限
            log.info("国泰君安每半天更新：8/12");
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopNum); //没有权限
            log.info("国泰君安每半天更新：9/12");
            //15 基金持有份额明细表（cust_share_detail_info)
            processCustShareDetailInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安每半天更新：10/12");
            //基金费用数据表（fund_fee_data_info）
            processFundFeeDataInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安每半天更新：11/12");
            processFundOpenInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安每半天更新：12/12");
        } catch (Exception e) {
            log.error("国信托管数据拉取失败:", e);
        } finally {
            //todo tl的remove
            fundInnerCodeAndCodeTL.remove();
            accountNumTL.remove();
        }
    }


    public void getDataFromGTJA(TenantEscrowAuthorizationInfoDto tenant, int loopNum) {
        String trustNo = "31"; //每分钟 30次
        try {
            log.info("国泰君安初始化：开始");
            //6&8 6.托管⼾流⽔表（TGAccount_seq_info） 8.募集⼾流⽔表（MJAccount_seq_info）
            processTGAccountSeqInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：1/14");
            processTGAccountSeqInfoData1(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：2/14");
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo,loopNum);
            log.info("国泰君安初始化：3/14");
            //删除fund_info表的fund_level字段
            //2&13  2.基金出资人信息表（investor_info）   13 基金出资人银行账户信息表(investor_bank_info)
            processInvestorInfoData(tenant, trustNo);
            log.info("国泰君安初始化：4/14");
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo,loopNum);
            log.info("国泰君安初始化：5/14");
            //4 基金持有信息表（cust_share_info）
            processCustInfoData(tenant, trustNo);
            log.info("国泰君安初始化：6/14");
            //5&7&11 5.托管⼾银⾏账⼾余额信息表（TGAccount_balance_info）  7.募集户银行账余额信息表（MGAccount_balance_info） 11 account_info
            processTGAccountBalanceInfoData(tenant, trustNo);
            log.info("国泰君安初始化：7/14");
            //5&7&11 5.托管⼾银⾏账⼾余额信息表（TGAccount_balance_info）  7.募集户银行账余额信息表（MGAccount_balance_info） 11 account_info
            processAccountInfoData(tenant, trustNo);
            log.info("国泰君安初始化：8/14");
            //9 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：9/14");
            //12 基金持有份额变化流水表（cust_share_seq_info）
            processCustShareSeqInfoData(tenant, trustNo, loopNum); //没有权限
            log.info("国泰君安初始化：10/14");
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopNum); //没有权限
            log.info("国泰君安初始化：11/14");
            //15 基金持有份额明细表（cust_share_detail_info)
            processCustShareDetailInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：12/14");
            //基金费用数据表（fund_fee_data_info）
            processFundFeeDataInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：13/14");
            processFundOpenInfoData(tenant, trustNo, loopNum);
            log.info("国泰君安初始化：14/14");
        } catch (Exception e) {
            log.error("国信托管数据拉取失败:", e);
        } finally {
            //todo tl的remove
            fundInnerCodeAndCodeTL.remove();
            accountNumTL.remove();
        }
    }

    private void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        //1、封装请求参数
        int pageSize = 100;
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        List<String> fundCodeList = fundInfoService.getFundCodeList(trustNo, tenant.getTenantName());
        for (int i = 0; i < loopNum; i++) {

            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                try {
                    //2、获取远端数据
                    int page = 0;
                    int totalCount = 0;
                    for (; ; ) {
                        page++;
                        HashMap<String, Object> params = new HashMap<>();
                        params.put("fundCode", fundCode);
                        params.put("beginDate", finalStartDate);
                        params.put("endDate", finalEndDate);
                        params.put("reqNum", String.valueOf(pageSize));
                        params.put("reqPageno", String.valueOf(page));
                        String jsonString = JSON.toJSONString(params);
                        TimeUnit.SECONDS.sleep(2L);
                        Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.FUND_OPEN_INFO_API, tenant);
                        Boolean result = (Boolean) stringObjectMap.get("result");
                        if (result) {
                            List<JSONObject> remoteDataList = (List<JSONObject>) stringObjectMap.get("data");
                            totalCount = Integer.valueOf(stringObjectMap.get("totalCount").toString());
                            if (!CollectionUtils.isEmpty(remoteDataList)) {
                                log.info("国泰君安获取fundOpenInfo数据{}条", remoteDataList.size());
                                //3、封装成标准表的对象 //
                                List<FundOpenInfoEntity> entities = getFundOpenInfo(tenant, remoteDataList, trustNo);
                                log.info("国泰君安封装fundOpenInfo数据{}条", entities.size());
                                //4、调用 basicservice 的保存数据接口
                                fundOpenInfoService.saveData(null, entities);
                            }
                        } else {
                            log.info("temp：processFundOpenInfoData： {}", JSON.toJSONString(stringObjectMap.get("data")));
                            Map<String, Object> remoteDataMap = (Map<String, Object>) stringObjectMap.get("data");
                            pullDataFailureLogService.saveErrorData(tenant.getTenantName(), remoteDataMap);
                            break;
                        }
                        if (page * pageSize > totalCount) {
                            break;
                        }
                    }
                } catch (InterruptedException ie) {
                    log.error("OutsourceGuosenServiceImpl:processFundOpenInfoData睡眠被打断！", ie);
                    Thread.currentThread().interrupt();
                } catch (Exception e){
                    log.error("OutsourceGuosenServiceImpl:processFundOpenInfoData获取数据异常！", e);
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        }
    }

    private List<FundOpenInfoEntity> getFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDataList, String trustNo) {
        //获取数据字典
        //开放日类型
        Map<String, String> typeOfOpenDayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, trustNo);
        //开放状态
        Map<String, Map<String, String>> openStateDic = openStateService.queryOpenStateWithDetail(trustNo);
        //封装数据
        List<FundOpenInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (JSONObject data : remoteDataList){
            dataMap = JSONObject.toJavaObject(data, Map.class);
            String openType = MatchDataDictionaryKeyUtil.getKey(typeOfOpenDayDic, dataMap.get("openType"));
            String openState = MatchDataDictionaryKeyUtil.getKey(openType, openStateDic, dataMap.get("openStatus"));
            entityList.add(FundOpenInfoEntity.builder()
                    .fundCode(dataMap.get("fundCode"))
                    .innerFundCode(dataMap.get("fjFundCode"))
                    .fundName(dataMap.get("FundName"))
                    .fundName(dataMap.get("FundName"))
                    .fundOpenDate(dataMap.get("openDate"))
                    .openStatus(openState)
                    .openType(openType)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processFundFeeDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        //1、封装请求参数
        int pageSize = 100;
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        List<String> fundCodeList = fundInfoService.getFundCodeList(trustNo, tenant.getTenantName());
        for (int i = 0; i < loopNum; i++) {

            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                try {
                    //2、获取远端数据
                    int page = 0;
                    int totalCount = 0;
                    for (; ; ) {
                        page++;
                        HashMap<String, Object> params = new HashMap<>();
                        params.put("fundCode", fundCode);
                        params.put("beginDate", finalStartDate);
                        params.put("endDate", finalEndDate);
                        params.put("showGrade", "1");
                        params.put("reqNum", String.valueOf(pageSize));
                        params.put("reqPageno", String.valueOf(page));
                        String jsonString = JSON.toJSONString(params);
                        TimeUnit.SECONDS.sleep(2L);
                        Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.FUND_FEE_DATA_INFO_API, tenant);
                        Boolean result = (Boolean) stringObjectMap.get("result");
                        if (result) {
                            List<JSONObject> remoteDataList = (List<JSONObject>) stringObjectMap.get("data");
                            totalCount = Integer.valueOf(stringObjectMap.get("totalCount").toString());
                            if (!CollectionUtils.isEmpty(remoteDataList)) {
                                log.info("国泰君安获取fundFeeDataInfo数据{}条", remoteDataList.size());
                                //3、封装成标准表的对象 //
                                List<FundFeeDataInfoEntity> entities = getFundFeeDataInfo(tenant, remoteDataList, trustNo);
                                log.info("国泰君安封装fundFeeDataInfo数据{}条", entities.size());
                                //4、调用 basicservice 的保存数据接口
                                fundFeeDataInfoService.saveData(null, entities);
                            }
                        } else {
                            log.info("temp：processFundFeeDataInfoData： {}", JSON.toJSONString(stringObjectMap.get("data")));
                            Map<String, Object> remoteDataMap = (Map<String, Object>) stringObjectMap.get("data");
                            pullDataFailureLogService.saveErrorData(tenant.getTenantName(), remoteDataMap);
                            break;
                        }
                        if (page * pageSize > totalCount) {
                            break;
                        }
                    }
                } catch (InterruptedException ie) {
                    log.error("OutsourceGuosenServiceImpl:processFundFeeDataInfoData:睡眠被打断！", ie);
                    Thread.currentThread().interrupt();
                } catch (Exception e) {
                    log.error("OutsourceGuosenServiceImpl:processFundFeeDataInfoData获取数据异常！", e);
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        }
    }

    private List<FundFeeDataInfoEntity> getFundFeeDataInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDataList, String trustNo) {
        //获取字典
        //封装数据
        List<FundFeeDataInfoEntity> entityList = new ArrayList<>();
        Map<String,String> remoteDataMap;
        for (JSONObject remoteData : remoteDataList){
            remoteDataMap = JSONObject.toJavaObject(remoteData,Map.class);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
            Date rq = null;
            if (!ObjectUtils.isEmpty(remoteDataMap.get("rq"))) {
                try {
                    rq = sdf.parse(remoteDataMap.get("rq"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            //托管费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjttgf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzftgf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yetgf")))
                    .subjectCode("TGF")
                    .subjectName("托管费")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //管理费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjtglf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzfglf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yeglf")))
                    .subjectCode("GLF")
                    .subjectName("管理费")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //运营服务费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjtyyf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzfyyf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yeyyf")))
                    .subjectCode("YYFWF")
                    .subjectName("运营服务费")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //投顾费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjtgwf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzfgwf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yegwf")))
                    .subjectCode("TGF2")
                    .subjectName("投顾费")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //销售服务费
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjtxsf")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzfxsf")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yexsf")))
                    .subjectCode("XSF")
                    .subjectName("销售服务费")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
            //业绩报酬
            entityList.add(FundFeeDataInfoEntity.builder()
                    .fundCode(remoteDataMap.get("cpdm"))
                    .fundName(remoteDataMap.get("cpmc"))
                    .innerFundCode(remoteDataMap.containsKey("fjcpdm") ? remoteDataMap.get("fjcpdm") : remoteDataMap.get("cpdm"))
                    .confirmDate(ObjectUtils.isEmpty(rq) ? null : sdf1.format(rq))
                    .fareDebit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqjtyjbc")))
                    .fareCredit(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("bqzfyjbc")))
                    .fareUnpaid(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("yeyjbc")))
                    .subjectCode("YJBC")
                    .subjectName("业绩报酬")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processCustShareDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        //1、封装请求参数
        int pageSize = 100;
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
//        localDate = localDate.minusYears(8);
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        Map<String, String> fundInnerCodeAndCodeMap = fundInnerCodeAndCodeTL.get();
        for (int i = 0; i < loopNum; i++) {
            int page = 1;
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //2、获取远端数据
                boolean continueLoop = true;
                while (continueLoop) {
                    HashMap<String, Object> params = new HashMap<>();
                    params.put("reqNum", String.valueOf(pageSize));
                    params.put("reqPageno", String.valueOf(page));
                    params.put("beginDate", finalStartDate);
                    params.put("endDate", finalEndDate);
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.SHARE_HOLDER_DETAIL_API, tenant);
                    log.info("processCustShareDetailInfoData_stringObjectMap={}",JSON.toJSONString(stringObjectMap));
                    Boolean result = (Boolean) stringObjectMap.get("result");
                    if (result) {
                        List<JSONObject> result1 = (List<JSONObject>) stringObjectMap.get("data");
                        String totalCount = (String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if (integer == null) {
                            integer = 0;
                        }
                        if (page * pageSize > integer) {
                            continueLoop = false;
                        }
                        if (!CollectionUtils.isEmpty(result1)) {
                            //3、封装成标准表的对象 //
                            List<CustShareDetailInfoEntity> entities = getCustShareDetailInfo(tenant, result1, trustNo, fundInnerCodeAndCodeMap);
                            //4、调用 basicservice 的保存数据接口
                            custShareDetailInfoService.saveData(null, entities);
                        }
                        page++;
                    } else {
                        log.info("temp：processFCustShareDetailInfoData： {}", JSON.toJSONString(stringObjectMap.get("data")));
                        Map<String, Object> result1 = (Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return;
                    }
                }
            } catch (Exception e) {
                log.error("OutsourceGuosenServiceImpl:processFCustShareDetailInfoData:", e);
                Thread.currentThread().interrupt();
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    private List<CustShareDetailInfoEntity> getCustShareDetailInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        Map<String, String> sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "国泰君安");
        Map<String, String> shareSourceDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SHARE_SOURCE_SERVICE, trustNo);
        //2、封装数据
        List<CustShareDetailInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap =  JSONObject.toJavaObject(remoteData, Map.class);
//            remoteDataMap = (HashMap<String, String>) remoteData;
            log.info("国君getCustShareDetailInfo：转换前：{}",JSON.toJSONString(remoteDataMap));

            String fundCode = custShareInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"), trustNo,tenant.getTenantName());
            CustShareDetailInfoEntity build = CustShareDetailInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(sellerDic, remoteDataMap.get("agencyNo")))
                    .agencyName(remoteDataMap.get("agencyName"))
                    .branchCode(remoteDataMap.get("netNo"))
                    .branchName(remoteDataMap.get("netName"))
                    .confirmDate(remoteDataMap.get("cdate"))
                    .sourceType(MatchDataDictionaryKeyUtil.getKey(shareSourceDic, remoteDataMap.get("sourceType")))
                    .remainShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("remainShares")))
                    .oriBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("oribalance")))
                    .oriShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("orishares")))
                    .oriNetValue(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("orinetvalue"), 4))
                    .oriSource(MatchDataDictionaryKeyUtil.getKey(shareSourceDic, remoteDataMap.get("orisource")))
                    .requestDate(remoteDataMap.get("reqdate"))
                    .holdDay(remoteDataMap.get("holdday"))
                    .lastDeductNav(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("lastDeductNav"), 4))
                    .lastDeductTotalNav((BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("lastDeductTotalNav"), 4)))
                    .lastDeductDate(remoteDataMap.get("lastDeductDate"))
                    .seqNo(remoteDataMap.get("cserialno"))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build();
            log.info("国君getCustShareDetailInfo：转换后：{}",JSON.toJSONString(build));
            result.add(build);
        }
        return result;
    }


    private List<FundNetValueInfoEntity> getFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        //todo 数据字典 复核状态
        Map<String, String> reviewStatusDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.REVIEW_STATUS_SERVICE, trustNo);
        //2、封装数据
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String fundCode = null;
            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
                fundCode = fundInnerCodeAndCodeMap.get(remoteDataMap.get("fundCode"));
            }
            result.add(FundNetValueInfoEntity.builder()
                    .fundName(remoteDataMap.get("fundName"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .netValueDate(remoteDataMap.get("netValueDate"))
                    .checkStatus(MatchDataDictionaryKeyUtil.getKey(reviewStatusDic,remoteDataMap.get("checkStatus")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netValue"),4))
                    .totalNetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netValue"),4))
                    .assetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundAssets")))
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundShares")))
                    .ettFundIncome(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ettFundIncome")))
                    .sevenDayRate(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ettFundIncome"),4))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;



    }




    private List<FundValueTableDataInfoEntity> getFundValueTableDataInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        //2、封装数据
        List<FundValueTableDataInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String fundCode = null;
            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
                fundCode = fundInnerCodeAndCodeMap.get(remoteDataMap.get("fundCode"));
            }
            result.add(FundValueTableDataInfoEntity.builder()
                    .kmCode(remoteDataMap.get("accountCode"))
                    .kmName(remoteDataMap.get("accountName"))
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("amount")))
                    .costBi(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("costRate"),4))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .vapPrice(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("price")))
                    .mvBl(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("priceRate"),4))
                    .suspension(remoteDataMap.get("suspension"))
                    .perCost(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unitCost")))
                    .portIv(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("valuationAppreciation")))
                    .valueDate(remoteDataMap.get("valuationDate"))
                    .portMv(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("value")))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }



    private List<FundTradeInfoEntity> getFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        Map<String, String> businessTypeDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        //2、封装数据
        List<FundTradeInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String fundCode = null;
            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
                fundCode = fundInnerCodeAndCodeMap.get(remoteDataMap.get("structuredFundCode"));
            }
            result.add(FundTradeInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("structuredFundCode"))
                    .fundName(remoteDataMap.get("structuredFundName"))
                    .requestDate(remoteDataMap.get("applyDate"))
                    .confirmDate(remoteDataMap.get("confirmDate"))
                    .applyBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("requestBalance")))
                    .applyShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("requestShare")))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confirmMoney")))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confirmShare")))
                    .agencyNo(remoteDataMap.get("agencyNumber"))
                    .agencyName(remoteDataMap.get("agency"))
                    .tradeAcco(remoteDataMap.get("tradeAccount"))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tradeFare")))
                    .totalFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalFare")))
                    .interest(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interest")))
                    .interestShare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interestShare")))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitBalance")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netValue"), 4))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDic, remoteDataMap.get("businessFlag")))
                    .requestNo(StrUtil.subString(remoteDataMap.get("requestNnumber")))
                    .cserialNo(StrUtil.subString(remoteDataMap.get("confirmNumber")))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;

    }



    private List<TgAccountSeqInfoEntity> getTGAccountHistorySeqInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo) {
        //1、获取字典表数据
        //2、封装数据
        List<TgAccountSeqInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String amount;
            String transferInOut;
            if (!StringUtils.isBlank(remoteDataMap.get("collectionMoney"))) {
                amount = remoteDataMap.get("collectionMoney");
                transferInOut = "1";
            } else {
                amount = remoteDataMap.get("paymentMoney");
                transferInOut = "2";
            }
            result.add(TgAccountSeqInfoEntity.builder()
                    .seqNo(StrUtil.getSeqNo(remoteDataMap.get("id")))
                    .account(remoteDataMap.get("collectNumber"))
                    .opAccountName(remoteDataMap.get("paymentAccount"))
                    .opAccount(remoteDataMap.get("paymentNumber"))
                    .amount(BigDecimalUtil.str2BigDecimal(amount))
                    .transferInOut(transferInOut)
                    .balance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("accountBalance")))
                    .summary(remoteDataMap.get("description"))
                    .transferDate(remoteDataMap.get("occurrenceTime"))
                    .updateDate(remoteDataMap.get("recordTime"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());

        }
        return result;

    }

    private List<TgAccountSeqInfoEntity> getTGAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        Map<String, String> paymentDirectionDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_DIRECTION_SERVICE, trustNo);
        //2、封装数据
        List<TgAccountSeqInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String fundCode = null;
            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
                fundCode = fundInnerCodeAndCodeMap.get(remoteDataMap.get("fundCode"));
            }
            result.add(TgAccountSeqInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .opBankName(remoteDataMap.get("otherPartyAccountBank"))
                    .opAccountName(remoteDataMap.get("otherPartyAccountName"))
                    .opAccount(remoteDataMap.get("otherPartyAccountNumber"))
                    .transferInOut(MatchDataDictionaryKeyUtil.getKey(paymentDirectionDic, remoteDataMap.get("paymentDirection")))
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("paymentMoney")))
                    .transferDate(remoteDataMap.get("paymentTime"))
                    .transferTime(remoteDataMap.get("paymentTime").split(" ")[1])
                    .summary(remoteDataMap.get("paymentRemark"))
                    .memo(remoteDataMap.get("paymentUse"))
                    .bankName(remoteDataMap.get("thePartyAccountBank"))
                    .accountName(remoteDataMap.get("thePartyAccountName"))
                    .account(remoteDataMap.get("thePartyAccountNumber"))
                    .updateDate(remoteDataMap.get("updateTime"))
                    .seqNo(StrUtil.getSeqNo(null))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());

        }
        return result;


    }


    private void processMJAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {
        try {
//            loopNum = loopNum == 1 ? 31 : 3 * 365;
            loopNum = loopNum == 1 ? 31 : 365;
            String startDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastDay;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            for (int i = 0; i < loopNum; i++) {
                lastDay = localDate.minusDays(1);
                startDate = dateTimeFormatter.format(lastDay);
                String finalStartDate = startDate + " 00:00:00";
                String finalEndDate = startDate + " 23:59:59";
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                params.put("startTime", finalStartDate);
                params.put("endTime", finalEndDate);
                //2、获取远端数据
                List<Object> remoteDatas = getRes(GuosenConstants.TURN_OVER_LIST_V2_API, tenant, params, trustNo);
                if (!CollectionUtils.isEmpty(remoteDatas)) {
                    //3、封装成标准表的对象
                    List<MjAccountSeqInfoEntity> entities = getMJAccountSeqInfoData(tenant, remoteDatas, trustNo);
                    //4、调用 basicservice 的保存数据接口
                    mjAccountSeqInfoService.saveData(null, entities);
                }
                localDate = lastDay;
            }
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processFundInfoData:", e);
            //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }
    }

    private List<MjAccountSeqInfoEntity> getMJAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo) {
        //1、获取字典表数据
        //2、封装数据
        List<MjAccountSeqInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            result.add(MjAccountSeqInfoEntity.builder()
                    .opAccountName(remoteDataMap.get("accountName"))
                    .opAccount(remoteDataMap.get("accountNumber"))
                    .fundCode(remoteDataMap.get("amacCode"))
                    .bankName(remoteDataMap.get("collectBank"))
                    .account(remoteDataMap.get("collectNumber"))
                    .updateDate(remoteDataMap.get("createTime"))
                    .summary(remoteDataMap.get("digest"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .seqNo(StrUtil.getSeqNoWithoutNoRandom(remoteDataMap.get("id")))
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("money")))
                    .remark(remoteDataMap.get("remark"))
                    .transferDate(remoteDataMap.get("tradeDate"))
                    .transferTime(remoteDataMap.get("tradeDate").split(" ")[1])
                    .transferInOut("1")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;

    }


    private static final ThreadLocal<List<String>> accountNumTL = new ThreadLocal<>();


    private List<MjAccountBalanceInfoEntity> getMJAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo) {
        //1、获取字典表数据 todo 账户类型
        Map<String, String> custTypeCsdcDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CUST_TYPE_CSDC_SERVICE, trustNo);
        //2、封装数据
        List<MjAccountBalanceInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            result.add(MjAccountBalanceInfoEntity.builder()
                    .updateDate(remoteDataMap.get("updateTime"))
//                    .acctType(MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("accountType")))
                    .bankAcco(remoteDataMap.get("accountNumber"))
                    .accoBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("balance")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }


    private List<CustShareInfoEntity> getCustInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo) {
        //1、获取字典表数据
        //2、封装数据
        List<CustShareInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        Map<String, String> fundInnerCodeAndCodeMap = fundInnerCodeAndCodeTL.get();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            result.add(CustShareInfoEntity.builder()
                    .agencyName(remoteDataMap.get("agencyName"))
                    .agencyNo(remoteDataMap.get("agencyNumber"))
                    .frozenShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("frozenShares")))
                    .fundAcco(remoteDataMap.get("fundAccount"))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("realShares")))
                    .updateDate(remoteDataMap.get("shareDate"))
                    .innerFundCode(remoteDataMap.get("structuredFundCode"))
                    .fundName(remoteDataMap.get("structuredFundName"))
                    .tradeAcco(remoteDataMap.get("tradeAccount"))
                    .fundCode(fundInnerCodeAndCodeMap.get(remoteDataMap.get("structuredFundCode")))//此字段的数值应取（fund_info）中 基金内部代码字段 为 该响应结果的 分级产品代码 的记录 的基金备案编码fund_code字段）
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }



    private void processInvestorInfoDetailData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String isShowShareNull) {
        try {
            //3.15 投资者信息查询接口全量
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            params.put("isShowShareNull", isShowShareNull);
            //2、获取远端数据
            List<Object> remoteDatas = getRes(GuosenConstants.INVESTOR_INFO_LIST_V2_API, tenant, params, trustNo);
            if (!CollectionUtils.isEmpty(remoteDatas)) {
                //3、封装成标准表的对象
                List<InvestorInfoEntity> entities = getInvestorInfoData(tenant, remoteDatas, trustNo);
                //4、调用 basicservice 的保存数据接口
                investorInfoService.saveData(null, entities);
            }
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processFundInfoData:", e);
            //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }
    }

    private List<InvestorInfoEntity> getInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, 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<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
            String key = MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("custormerType"));
            result.add(InvestorInfoEntity.builder()
                    .custName(remoteDataMap.get("customerName"))
                    .custType(key)
                    .fundAcco(remoteDataMap.get("fundAccount"))
                    .identityNo(remoteDataMap.get("identityNo"))
                    .identityType(MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, remoteDataMap.get("identityType")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private static final ThreadLocal<Map<String, String>> fundInnerCodeAndCodeTL = new ThreadLocal<>();


    //01.
    public void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo,int loopNum) {

        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            String jsonString = JSON.toJSONString(params);
            //2、获取远端数据
            Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.FUND_INFO_API,  tenant);
            Boolean result = (Boolean) stringObjectMap.get("result");
            if (result) {
                List<JSONObject> remoteDatas =(List<JSONObject>)  stringObjectMap.get("data");
                if(!CollectionUtils.isEmpty(remoteDatas)){
                    //3、封装成标准表的对象 //
                    List<FundInfoEntity> entities = getFundInfoData(tenant, remoteDatas, trustNo);
                    //4、调用 basicservice 的保存数据接口
                    fundInfoService.saveData(null, entities);
                }
            }else{
                Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                return ;

            }
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processFundInfoData:", e);
            //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }
    }

    //02 & 13
    private void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {

        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int page = 1;
            int pageSize = 100;

            //2、获取远端数据
            boolean continueLoop = true;
            while(continueLoop){
                params.put("reqNum",String.valueOf(pageSize));
                params.put("reqPageno", String.valueOf(page));
                String jsonString = JSON.toJSONString(params);
                TimeUnit.SECONDS.sleep(2L);
                Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.CUST_INFO_API,  tenant);
                Boolean result = (Boolean) stringObjectMap.get("result");

                if (result) {
                    List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                    String totalCount =(String) stringObjectMap.get("totalCount");
                    Integer integer = Integer.valueOf(totalCount);
                    if(integer ==null){
                        integer=0;
                    }

                    if(page * pageSize > integer){
                        continueLoop = false;
                    }

                    if(!CollectionUtils.isEmpty(result1)){
                        //3、封装成标准表的对象 //
                        List<InvestorInfoEntity> entities = getInvestorInfo(tenant, result1, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        investorInfoService.saveData(null, entities);

                        List<InvestorBankInfoEntity> investorBankInfo = getInvestorBankInfo(tenant, result1, trustNo);

                        investorBankInfoService.saveData(null, investorBankInfo);
                    }
                    page++;
                }else{
                    Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                    return ;

                }
            }
        } catch (InterruptedException e){
            log.error("processInvestorInfoData interrupted");
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processInvestorInfoData:", e);
            //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }

    }

    //03
    private void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopNum; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;

                //2、获取远端数据

                boolean continueLoop = true;
                while(continueLoop){
                    params.put("reqNum",String.valueOf(pageSize));
                    params.put("netDateBegin",finalStartDate);
                    params.put("netDateEnd",finalEndDate);
                    params.put("reqPageno", String.valueOf(page));
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.FUND_NET_VAL_API, tenant);
                    Boolean result = (Boolean) stringObjectMap.get("result");

                    if (result) {
                        List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                        String totalCount =(String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if(integer ==null){
                            integer=0;
                        }

                        if(page * pageSize > integer){
                            continueLoop = false;
                        }

                        if(!CollectionUtils.isEmpty(result1)){
                            //3、封装成标准表的对象 //
                            List<FundNetValueInfoEntity> entities = getFundNetValInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            fundNetValueInfoService.saveData(null, entities);
                        }
                        page++;
                    }else{
                        Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return ;

                    }
                }
            } catch (InterruptedException e){
                log.error("processFundNetValueInfoData interrupted");
                Thread.currentThread().interrupt();
            }
            catch (Exception e) {
                log.error("OutsourceGuosenServiceImpl:processFundNetValueInfoData:", e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            // TODO: 2022/1/13 加一个处理失败的日志统计表
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    //04
    private void processCustInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {

        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            List<CustShareInfoEntity> entityList = new ArrayList<>();
            int page = 1;
            int pageSize = 100;

            //2、获取远端数据

            boolean continueLoop = true;
            while(continueLoop){
                params.put("reqNum",String.valueOf(pageSize));
                params.put("reqPageno", String.valueOf(page));
                String jsonString = JSON.toJSONString(params);
                TimeUnit.SECONDS.sleep(2L);

                Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.SHARE_HOLDER_INFO_API,  tenant);
                Boolean result = (Boolean) stringObjectMap.get("result");

                if (result) {
                    List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                    String totalCount =(String) stringObjectMap.get("totalCount");
                    Integer integer = Integer.valueOf(totalCount);
                    if(integer ==null){
                        integer=0;
                    }

                    if(page * pageSize > integer){
                        continueLoop = false;
                    }

                    if(!CollectionUtils.isEmpty(result1)){
                        //3、封装成标准表的对象 //
                        List<CustShareInfoEntity> entities = getCustShareInfo(tenant, result1, trustNo);
                        entityList.addAll(entities);
                    }
                    page++;
                }else{
                    Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                    return ;
                }
            }
            //4、调用 basicservice 的保存数据接口
            custShareInfoService.saveData(null, entityList);
        }catch (InterruptedException e){
            log.error("processCustInfoData interrupted:{}",e.getMessage());
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processCustInfoData:", e);
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }
    }

    //05 & 07 & 11
    public void processTGAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {

        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int page = 1;
            int pageSize = 100;

            //2、获取远端数据
            boolean continueLoop = true;
            while(continueLoop){
                params.put("reqNum",String.valueOf(pageSize));
                params.put("reqPageno", String.valueOf(page));
                String jsonString = JSON.toJSONString(params);
                TimeUnit.SECONDS.sleep(2L);

                Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.ACCOUNT_BAL_API,  tenant);
                Boolean result = (Boolean) stringObjectMap.get("result");

                if (result) {
                    List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                    String totalCount = stringObjectMap.get("totalCount") == null ? null : stringObjectMap.get("totalCount").toString();
                    int integer = 0;
                    if (StringUtils.isNotEmpty(totalCount)) {
                        integer = Integer.parseInt(totalCount);
                    }

                    if(page * pageSize > integer){
                        continueLoop = false;
                    }

                    if(!CollectionUtils.isEmpty(result1)){
                        //3、封装成标准表的对象 //  05
                        List<TgAccountBalanceInfoEntity> entities = getTgAccountBalanceInfo(tenant, result1, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        tgAccountBalanceInfoService.saveData(null, entities);

                        //3、封装成标准表的对象 //  07
                        List<MjAccountBalanceInfoEntity> entitiesMj = getMJAccountBalanceInfo(tenant, result1, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        mjAccountBalanceInfoService.saveData(null, entitiesMj);

                        //3、封装成标准表的对象 //  11
                        List<AccountInfoEntity> entitiesAccountInfo = getAccountInfo(tenant, result1, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        accountInfoService.saveData(null, entitiesAccountInfo);
                    }
                    page++;
                }else{
                    Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                    return ;
                }
            }
        } catch (InterruptedException e){
            log.error("processFundInfoData interrupted:{}",e.getMessage());
            Thread.currentThread().interrupt();
        }catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processFundInfoData:", e);
            //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
        }
    }

    //05 & 07 & 11
    private void processAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {

        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int page = 1;
            int pageSize = 100;
            List<String> bankAccoListMj = mjAccountBalanceInfoService.getBankAccoList(trustNo,tenant.getTenantName());
            List<String> bankAccoListTg = tgAccountBalanceInfoService.getBankAccoList(trustNo,tenant.getTenantName());

            if(bankAccoListMj == null){
                bankAccoListMj = new ArrayList<>();
            }
            bankAccoListMj.addAll(bankAccoListTg);
            List<String> collect = bankAccoListMj.stream().distinct().collect(Collectors.toList());
            for (String bankAccoIter : collect) {
                //2、获取远端数据
                boolean continueLoop = true;
                while(continueLoop){
                    params.put("reqNum",String.valueOf(pageSize));
                    params.put("reqPageno", String.valueOf(page));
                    params.put("bankAcco", bankAccoIter);
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    log.info("开始调用accountbalOnline");
                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.ACCOUNT_BAL_ONLINE_API,  tenant);
                    log.info("accountbalOnline权限"+stringObjectMap);
                    Boolean result = (Boolean) stringObjectMap.get("result");

                    if (result) {
                        List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                        String totalCount =(String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if(integer ==null){
                            integer=0;
                        }

                        if(page * pageSize > integer){
                            continueLoop = false;
                        }

                        if(!CollectionUtils.isEmpty(result1)){
                            //3、封装成标准表的对象 //  05
                            List<TgAccountBalanceInfoEntity> entities = getTgAccountBalanceInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountBalanceInfoService.saveData(null, entities);

                            //3、封装成标准表的对象 //  07
                            List<MjAccountBalanceInfoEntity> entitiesMj = getMJAccountBalanceInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            mjAccountBalanceInfoService.saveData(null, entitiesMj);

                            //3、封装成标准表的对象 //  11
                            List<AccountInfoEntity> entitiesAccountInfo = getAccountInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            accountInfoService.saveData(null, entitiesAccountInfo);
                        }
                        page++;
                    }else{
                        log.info("accountbalOnline调用失败"+JSON.toJSONString(stringObjectMap.get("data")));
                        Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return ;
                    }
                }
            }


        }catch (InterruptedException e){
            log.error("processFundInfoData interrupted",e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("OutsourceGuosenServiceImpl:processFundInfoData:", e);
        }
    }

    //06&08
    private void processTGAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopNum; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;
                //2、获取远端数据
                boolean continueLoop = true;
                while(continueLoop){
                    params.put("reqNum",String.valueOf(pageSize));
                    params.put("beginDate",finalStartDate);
                    params.put("endDate",finalEndDate);
                    params.put("reqPageno", String.valueOf(page));
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.ACCOUNT_JOURNAL, tenant);
                    Boolean result = (Boolean) stringObjectMap.get("result");

                    if (result) {
                        List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                        String totalCount =(String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if(integer ==null){
                            integer=0;
                        }

                        if(page * pageSize > integer){
                            continueLoop = false;
                        }

                        if(!CollectionUtils.isEmpty(result1)){
                            //3、封装成标准表的对象 //
                            List<TgAccountSeqInfoEntity> entities = getTGAccountSeqInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountSeqInfoService.saveData(null, entities);

                            //3、封装成标准表的对象 //
                            List<MjAccountSeqInfoEntity> entitiesMj = getMJAccountSeqInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            mjAccountSeqInfoService.saveData(null, entitiesMj);
                        }
                        page++;
                    }else{
                        Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return ;

                    }
                }
            }catch (InterruptedException e){
                log.error("OutsourceGuosenServiceImpl:processFundNetValueInfoData:", e);
                Thread.currentThread().interrupt();
            }catch (Exception e) {
                log.error("OutsourceGuosenServiceImpl:processFundNetValueInfoData:", e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            // TODO: 2022/1/13 加一个处理失败的日志统计表
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    //06&08
    private void processTGAccountSeqInfoData1(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        List<String> bankAccoList = tgAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
        List<String> bankAccoList1 = mjAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
        if(bankAccoList==null){
            bankAccoList = new ArrayList<>();
        }
        bankAccoList.addAll(bankAccoList1);
        List<String> collect = bankAccoList.stream().distinct().collect(Collectors.toList());
        for (String bankAcco : collect) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;
                //2、获取远端数据
                boolean continueLoop = true;
                while(continueLoop){
                    params.put("reqNum",String.valueOf(pageSize));
                    params.put("reqPageno", String.valueOf(page));
                    params.put("bankAcco", bankAcco);
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    log.info("开始调用accountjournalOnline");
                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.ACCOUNT_JOURNAL_ONLINE, tenant);
                    log.info("accountjournalOnline"+stringObjectMap);
                    Boolean result = (Boolean) stringObjectMap.get("result");

                    if (result) {
                        List<JSONObject> result1 =(List<JSONObject>) stringObjectMap.get("data");
                        String totalCount =(String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if(integer ==null){
                            integer=0;
                        }

                        if(page * pageSize > integer){
                            continueLoop = false;
                        }

                        if(!CollectionUtils.isEmpty(result1)){
                            //3、封装成标准表的对象 //
                            List<TgAccountSeqInfoEntity> entities = getTGAccountSeqInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountSeqInfoService.saveData(null, entities);

                            //3、封装成标准表的对象 //
                            List<MjAccountSeqInfoEntity> entitiesMj = getMJAccountSeqInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            mjAccountSeqInfoService.saveData(null, entitiesMj);
                        }
                        page++;
                    }else{

                        Map<String, Object> result1 =(Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return ;

                    }
                }
            }catch (InterruptedException e){
                log.error("OutsourceGuosenServiceImpl:processTGAccountSeqInfoData1:", e);
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                log.error("OutsourceGuosenServiceImpl:processTGAccountSeqInfoData1:", e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            // TODO: 2022/1/13 加一个处理失败的日志统计表
            localDate = lastMonth;
            endDate = startDate;

        }
    }

    //09
    private void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {
        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopNum; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;
                //2、获取远端数据

                boolean continueLoop = true;
                while (continueLoop) {
                    params.put("reqNum", String.valueOf(pageSize));
                    params.put("beginDate", finalStartDate);
                    params.put("endDate", finalEndDate);
                    params.put("reqPageno", String.valueOf(page));
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.CONFIRM_INFO_API, tenant);
                    Boolean result = (Boolean) stringObjectMap.get("result");
                    if (result) {
                        List<JSONObject> result1 = (List<JSONObject>) stringObjectMap.get("data");
                        String totalCount = (String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if (integer == null) {
                            integer = 0;
                        }

                        if (page * pageSize > integer) {
                            continueLoop = false;
                        }

                        if (!CollectionUtils.isEmpty(result1)) {
                            //3、封装成标准表的对象 //

                            List<FundTradeInfoEntity> entities = getFundTradeInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            fundTradeInfoService.saveData(null, entities);
                        }
                        page++;
                    } else {
                        log.info("processFundTradeInfoData" + JSON.toJSONString(stringObjectMap.get("data")));
                        Map<String, Object> result1 = (Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return;
                    }
                }
            }catch (InterruptedException e){
                log.error("processFundTradeInfoData",e);
                Thread.currentThread().interrupt();
            }
            catch (Exception e) {
                log.error("processFundInfoData:", e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    //12
    private void processCustShareSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);

        for (int i = 0; i < loopNum; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            String finalStartDate = startDate;
            String finalEndDate = endDate;
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;
                //2、获取远端数据
                boolean continueLoop = true;
                while (continueLoop) {
                    params.put("reqNum", String.valueOf(pageSize));
                    params.put("confDateBegin", finalStartDate);
                    params.put("confDateEnd", finalEndDate);
                    params.put("reqPageno", String.valueOf(page));

                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.SHARE_CHANGE_INFO, tenant);
                    Boolean result = (Boolean) stringObjectMap.get("result");
                    if (result) {
                        List<JSONObject> result1 = (List<JSONObject>) stringObjectMap.get("data");
                        String totalCount = (String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if (integer == null) {
                            integer = 0;
                        }

                        if (page * pageSize > integer) {
                            continueLoop = false;
                        }

                        if (!CollectionUtils.isEmpty(result1)) {
                            //3、封装成标准表的对象 //
                            List<CustShareSeqInfoEntity> entities = getCustShareSeqInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            custShareSeqInfoService.saveData(null, entities);
                        }
                        page++;
                    } else {
                        log.info("processCustShareSeqInfoData" + JSON.toJSONString(stringObjectMap.get("data")));
                        Map<String, Object> result1 = (Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return;
                    }
                }
            } catch (InterruptedException e){
                log.error("processCustShareSeqInfoData",e);
                Thread.currentThread().interrupt();

            }catch (Exception e) {
                log.error("processCustShareSeqInfoData:",e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    //14
    private void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {

        String startDate;
        String endDate;
        LocalDate localDate = LocalDate.now();
        LocalDate lastMonth;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        endDate = dateTimeFormatter.format(localDate);
        for (int i = 0; i < loopNum; i++) {
            lastMonth = localDate.minusMonths(1);
            startDate = dateTimeFormatter.format(lastMonth);
            try {
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int page = 1;
                int pageSize = 100;

                //2、获取远端数据

                boolean continueLoop = true;
                while (continueLoop) {
                    params.put("reqNum", String.valueOf(pageSize));
                    params.put("reqPageno", String.valueOf(page));
                    String jsonString = JSON.toJSONString(params);
                    TimeUnit.SECONDS.sleep(2L);

                    Map<String, Object> stringObjectMap = gTJAHttpUtil.sendMessage(jsonString, GuoAnConstants.FUND_PROFIT_API, tenant);
                    Boolean result = (Boolean) stringObjectMap.get("result");

                    if (result) {
                        List<JSONObject> result1 = (List<JSONObject>) stringObjectMap.get("data");
                        String totalCount = (String) stringObjectMap.get("totalCount");
                        Integer integer = Integer.valueOf(totalCount);
                        if (integer == null) {
                            integer = 0;
                        }

                        if (page * pageSize > integer) {
                            continueLoop = false;
                        }

                        if (!CollectionUtils.isEmpty(result1)) {
                            //3、封装成标准表的对象 //
                            List<FundProfitInfoEntity> entities = getFundProfitInfo(tenant, result1, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            fundProfitInfoService.saveData(null, entities);
                        }
                        page++;
                        log.info("查询第"+page+"页");
                    } else {
                        Map<String, Object> result1 = (Map<String, Object>) stringObjectMap.get("data");
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), result1);
                        return;
                    }
                }
            }catch (InterruptedException e){
                log.error("processFundProfitInfoData",e);
                Thread.currentThread().interrupt();
            }catch (Exception e) {
                log.error("processFundProfitInfoData:",e);
                //todo 处理失败
//            pullDataFailureLogService.saveErrorData(tenant.getTenantName(),  PullDataFailureUtil.createErrorMap(trustNo, GuosenConstants.AMAC_CODE_QUERY_LIST_API, null, "appId=" + tenant.getAppKey(), e.getMessage()));
            }
            localDate = lastMonth;
            endDate = startDate;
        }
    }

    //1.产品信息查询
    private List<FundInfoEntity> getFundInfoData(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> seviceModelDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SERVICE_MODEL_SERVICE, trustNo);
        Map<String, String> taConfDaysDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TA_TRANSACTION_CONFIRM_ATION_DAYS_SERVICE, trustNo);
        Map<String, String> fundTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, trustNo);
        Map<String, String> proDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_SERVICE, trustNo);
        Map<String, String> privateFundType = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRIVATE_FUND_TYPE_SERVICE, trustNo);


        //2、封装数据
        List<FundInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            result.add(FundInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
//                            .fundCode(fundCode)
                    .serviceMode(MatchDataDictionaryKeyUtil.getKey(seviceModelDir, remoteDataMap.get("serviceMode")))
                    .fundType(MatchDataDictionaryKeyUtil.getKey(fundTypeDir, remoteDataMap.get("fundType")))
                    .peType(MatchDataDictionaryKeyUtil.getKey(privateFundType, remoteDataMap.get("fundType")))
                    .fundStatus(MatchDataDictionaryKeyUtil.getKey(proDir, remoteDataMap.get("fundStatus")))
                    .createDate(remoteDataMap.get("establishDate"))
                    .confDays(MatchDataDictionaryKeyUtil.getKey(taConfDaysDir, String.valueOf(remoteDataMap.get("confDays"))))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //2.投资者信息查询
    private List<InvestorInfoEntity> getInvestorInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> seviceModelDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SERVICE_MODEL_SERVICE, trustNo);
        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();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String key = MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("custType"));

            String certiType = remoteDataMap.get("certiType");
            String identityType = MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, certiType);
            log.info("getInvestorInfo的原值certiType为"+certiType + " 映射值identityType为"+identityType);
            log.info("custType__certiType__identityType"+certiType+" "+key+" "+identityType);

            result.add(InvestorInfoEntity.builder()
                    .custName(remoteDataMap.get("custName"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .custType(key)
                    .identityType(identityType)
                    .identityNo(remoteDataMap.get("certiNo"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //3.净值查询
    private List<FundNetValueInfoEntity> getFundNetValInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> seviceModelDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SERVICE_MODEL_SERVICE, trustNo);

        //2、封装数据
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundLevel = remoteDataMap.get("fundLevel");
            if(StringUtils.isNotBlank(fundLevel)&&fundLevel.equals("0")){
                fundLevel=null;
            }else{
                fundLevel="2";
            }
            String fundCode = remoteDataMap.get("cpdm");
            log.info("getFundCodeByInnerFundCode from "+ remoteDataMap.get("fundCode") +"to " + fundCode);

            FundNetValueInfoEntity build = FundNetValueInfoEntity.builder()
                    .netValueDate(remoteDataMap.get("netDate"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("assetShares")))
                    .totalAsset(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("assetTotal")))
                    .assetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("assetNet")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netAssetVal"),4))
                    .totalNetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalAssetVal"),4))
                    .ettFundIncome(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ettFundIncome")))
                    .sevenDayRate(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("sevenDayRate"),4))
                    .fundLevel(fundLevel)
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build();

            log.info("________"+JSON.toJSONString(build));
            result.add(build);
        }
        return result;
    }

    //4.份额持有人查询
    private List<CustShareInfoEntity> getCustShareInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "国泰君安");
        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 : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);

            String agencyNo = remoteDataMap.get("agencyNo");
            String agencyNoValue = MatchDataDictionaryKeyUtil.getKey(serviceDir, agencyNo);
            log.info("getCustShareInfo agencyNo"+agencyNo+" agencyNoValue"+agencyNoValue);

            String fundCode = remoteDataMap.get("cpdm");
            log.info("getFundCodeByInnerFundCode from "+ remoteDataMap.get("fundCode") +"to " + fundCode);
            BigDecimal shareRatio = BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shareRatio"),4);

            String agencyName = sellerService.queryAgencyName("国泰君安", agencyNo);
            log.info("getCustShareInfo_国泰君安_agencyNo={}_result={}", agencyNo, agencyName);
            //处理updateDate
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String updateDate = null;
            if (!StringUtils.isEmpty(remoteDataMap.get("lastModify"))) {
                try {
                    Date parse = sdf.parse(remoteDataMap.get("lastModify"));
                    updateDate = sdf1.format(parse);
                } catch (ParseException e) {
                    e.printStackTrace();
                    log.error("时间转化失败！", e);
                }
            }
            result.add(CustShareInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .agencyNo(agencyNoValue)
                    .enableShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("enableShares")))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("realShares")))
                    .shareRatio(shareRatio)
                    .netValueDate(remoteDataMap.get("busiDate"))
                    .frozenShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("frozenShares")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("bonusType")))
                    .income(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("income")))
                    .updateDate(updateDate)
                    .fundCode(fundCode)
                    .agencyName(agencyName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //5.银行余额本地查询
    private List<TgAccountBalanceInfoEntity> getTgAccountBalanceInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
//
        //2、封装数据
        List<TgAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String accType = remoteDataMap.get("accType");
            if("04".equals(accType)){
                result.add(TgAccountBalanceInfoEntity.builder()
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .bankAcco(remoteDataMap.get("bankAcco"))
                        .accoBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("acctBal")))
                        .updateDate(remoteDataMap.get("retTime")) //todo 可能格式不对
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    //6.银行流水本地查询
    private List<TgAccountSeqInfoEntity> getTGAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, 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 : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);

            String occurTime = remoteDataMap.get("occurTime");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
            String rightDate = "";
            String rightTime = "";
            try {
                Date parse = simpleDateFormat.parse(occurTime);
                rightDate = dateFormat.format(parse);
                rightTime = timeFormat.format(parse);
            } catch (ParseException e) {
                e.printStackTrace();
            }

            String accType = remoteDataMap.get("accType");
            if("04".equals(accType)) {
                result.add(TgAccountSeqInfoEntity.builder()
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .innerFundCode(remoteDataMap.get("fundCode"))
                        .fundName(remoteDataMap.get("fundName"))
                        .transferInOut(MatchDataDictionaryKeyUtil.getKey(paymentDir, remoteDataMap.get("directFlag")))
                        .account(remoteDataMap.get("bankAcco"))
                        .accountName(remoteDataMap.get("accName"))
                        .bankName(remoteDataMap.get("openBankName"))
                        .opAccount(remoteDataMap.get("othBankAcco"))
                        .opAccountName(remoteDataMap.get("othAccName"))
                        .opBankName(remoteDataMap.get("othOpenBankName"))
                        .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurAmt")))
                        .transferDate(rightDate)
                        .transferTime(rightTime)
                        .summary(remoteDataMap.get("bankNote"))
                        .fundCode(remoteDataMap.get("fundCode"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    //7.银行余额本地查询
    private List<MjAccountBalanceInfoEntity> getMJAccountBalanceInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //2、封装数据
        List<MjAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String accType = remoteDataMap.get("accType");
            if("02".equals(accType)) {
                result.add(MjAccountBalanceInfoEntity.builder()
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .bankAcco(remoteDataMap.get("bankAcco"))
                        .accoBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("acctBal")))
                        .updateDate(remoteDataMap.get("retTime"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    //8.银行流水本地查询
    private List<MjAccountSeqInfoEntity> getMJAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, 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<MjAccountSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String accType = remoteDataMap.get("accType");
            if("02".equals(accType)) {

                String occurTime = remoteDataMap.get("occurTime");
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
                SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
                String rightDate = "";
                String rightTime = "";
                try {
                    Date parse = simpleDateFormat.parse(occurTime);
                    rightDate = dateFormat.format(parse);
                    rightTime = timeFormat.format(parse);
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                result.add(MjAccountSeqInfoEntity.builder()
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .innerFundCode(remoteDataMap.get("fundCode"))
                        .fundName(remoteDataMap.get("fundName"))
                        .transferInOut(MatchDataDictionaryKeyUtil.getKey(paymentDir, remoteDataMap.get("directFlag")))
                        .account(remoteDataMap.get("bankAcco"))
                        .accountName(remoteDataMap.get("accName"))
                        .bankName(remoteDataMap.get("openBankName"))
                        .opAccount(remoteDataMap.get("othBankAcco"))
                        .opAccountName(remoteDataMap.get("othAccName"))
                        .opBankName(remoteDataMap.get("othOpenBankName"))
                        .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurAmt")))
                        .transferDate(rightDate)
                        .transferTime(rightTime)
                        .summary(remoteDataMap.get("bankNote"))
                        .fundCode(remoteDataMap.get("fundCode"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    //9.交易确认查询
    private List<FundTradeInfoEntity> getFundTradeInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "国泰君安");
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);

        log.info("getFundTradeInfo"+ JSON.toJSONString(remoteDatas));
        //2、封装数据
        List<FundTradeInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            log.info("remoteDataMap"+JSON.toJSONString(remoteDataMap));

            String fundCode = remoteDataMap.get("cpdm");
            log.info("getFundCodeByInnerFundCode from "+ remoteDataMap.get("fundCode") +"to " + fundCode);

            System.err.println("- "+ remoteDataMap.get("agencyNo") );
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("agencyNo"));
            System.err.println(agencyNo);

            result.add(FundTradeInfoEntity.builder()
                    .confirmDate(remoteDataMap.get("confDate"))
                    .requestDate(remoteDataMap.get("applyDate"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .agencyNo(agencyNo)
                    .agencyName(remoteDataMap.get("agencyName"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .taFlag(remoteDataMap.get("taFlag"))
                    .confirmStatus(remoteDataMap.get("confStatus"))
                    .agio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agio"),4))
                    .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("confBalance")))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confShares")))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tradeFare")))
                    .taFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("taFare")))
                    .stampTax(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("stampTax")))
                    .backFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("backFare")))
                    .breachFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachFare")))
                    .breachFareAgt(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachFare4Agt")))
                    .breachFareFund(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachFare4Fund")))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitBalance")))
                    .profitBalanceAgt(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitBalance4Agt")))
                    .totalFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalFare")))
                    .agencyFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agencyFare")))
                    .fundFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundFare")))
                    .registFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("registFare")))
                    .interest(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interest")))
                    .interestTax(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interestTax")))
                    .interestShare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interestShare")))
                    .frozenBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("frozenBalance")))
                    .unfrozenBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unfrozenBalance")))
                    .unShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unShares")))
                    .confirmNavVol(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netConfBalance")))
                    .cserialNo(remoteDataMap.get("cserialNo"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("busiFlag")))
                    .requestNo(remoteDataMap.get("originalNo"))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //10.基⾦估值报表数据表 没有

    //11.资金账户基本信息表
    private List<AccountInfoEntity> getAccountInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> accountTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.ACCOUNT_TYPE_SERVICE, trustNo);
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "资金清算系统银行编码");
        //2、封装数据
        List<AccountInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);

            String bankNo = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, remoteDataMap.get("bankNo"));
            log.info("getAccountInfo原值_映射值"+remoteDataMap.get("bankNo")+ " "+bankNo);

            AccountInfoEntity build = AccountInfoEntity.builder()
                    .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .accoTypeCode(MatchDataDictionaryKeyUtil.getKey(accountTypeDir, remoteDataMap.get("accType")))
                    .bankAcco(remoteDataMap.get("bankAcco"))
                    .nameInBank(remoteDataMap.get("accName"))
                    .bankCode(bankNo)
                    .branchBankName(remoteDataMap.get("openBankName"))
                    .fundCode(remoteDataMap.get("fundCode"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build();
            log.info("getAccountInfo封装数据"+JSON.toJSONString(build));

            result.add(build);
        }
        return result;
    }

    //12.基金持有份额变化流水表
    private List<CustShareSeqInfoEntity> getCustShareSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);

        //2、封装数据
        List<CustShareSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundCode = custShareInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"), trustNo,tenant.getTenantName());
            log.info("getFundCodeByInnerFundCode from "+ remoteDataMap.get("fundCode") +"to " + fundCode);

            String bonusType = remoteDataMap.get("bonusType");
            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(dividendDir, bonusType);
            log.info("getCustShareSeqInfo_bonusMethod转义前={}，转移后={}",bonusType,bonusMethod);

            //补充agencyNo
            String agencyName = remoteDataMap.get("agencyName");
            String agencyNo = sellerService.queryAgencyNo("国泰君安", agencyName);

            result.add(CustShareSeqInfoEntity.builder()
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .agencyName(agencyName)
                    .branchName(remoteDataMap.get("netName"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("businName")))
                    .confirmDate(remoteDataMap.get("cdate"))
                    .cserialNo(remoteDataMap.get("cserialNo"))
                    .requestNo(remoteDataMap.get("requestNo"))
                    .occurShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurShares")))
                    .occurBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurBalance")))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("lastShares")))
                    .occurSharesFreeze(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurFreeze")))
                    .lastFreezeShare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("lastFreezeShare")))
                    .requestDate(remoteDataMap.get("requestDate"))
                    .bonusMethod(bonusMethod)
                    .seqNo(remoteDataMap.get("serialNo"))
                    .fundCode(fundCode)
                    .agencyNo(agencyNo)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //13.基金出资人银行账户信息表
    private List<InvestorBankInfoEntity> getInvestorBankInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "国泰君安TA");
        //2、封装数据
        List<InvestorBankInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            if(remoteDataMap.get("bankAcco")==null){
                log.error("bankAcco不应为空"+remoteDataMap.get("bankAcco"));
                continue;
            }
            String bankNo = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, remoteDataMap.get("bankNo"));
            log.info("getInvestorBankInfo:bankNo为"+remoteDataMap.get("bankNo")+" 转义后bankCode为"+bankNo);
            result.add(InvestorBankInfoEntity.builder()
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .bankCode(bankNo)
                    .bankNo(remoteDataMap.get("bankAcco"))
                    .branchBankName(remoteDataMap.get("openBankName"))
                    .nameInBank(remoteDataMap.get("nameInBank"))
                    .bankNoType("银行账号")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //14.业绩报酬信息表
    private List<FundProfitInfoEntity> getFundProfitInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "国泰君安");
        Map<String, String> businessDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> handleTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_SERVICE, trustNo);

        //2、封装数据
        List<FundProfitInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : remoteDatas) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);

            String fundCode = remoteDataMap.get("cpdm");
            log.info("getFundCodeByInnerFundCode from "+ remoteDataMap.get("fundCode") +"to " + fundCode);
            String agencyNo = remoteDataMap.get("agencyNo");
            log.info("销售商原值"+agencyNo);
            log.info("销售商映射值"+MatchDataDictionaryKeyUtil.getKey(serviceDir, agencyNo));


            String agencyName = sellerService.queryAgencyName("国泰君安", agencyNo);

            result.add(FundProfitInfoEntity.builder()
                    .confirmDate(remoteDataMap.get("confDate"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("agencyNo")))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessDir, remoteDataMap.get("busiType")))
                    .sortFlag(MatchDataDictionaryKeyUtil.getKey(handleTypeDir, remoteDataMap.get("sortFlag")))
                    .requestDate(remoteDataMap.get("dDate"))
                    .registDate(remoteDataMap.get("registDate"))
                    .oriDate(remoteDataMap.get("dBeginDate"))
                    .holdDay(remoteDataMap.get("lhold"))
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shares")))
                    .oriNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriNav"),4))
                    .oriTotalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriTotalNav"),4))
                    .nav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("nav"),4))
                    .totalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalNav"),4))
                    .currRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("currRatio"),4))
                    .yearRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("yearRatio"),4))
                    .standardRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("standardRatio"),4))
                    .returnFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("returnFare")))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriBalance")))
                    .factBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factBalance")))
                    .factShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factShares")))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("bonusBalance")))
                    .income(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("income")))
                    .deductRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("deductRatio"),4))
                    .valueAddedFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("valueAddedFare")))
                    .costPrice(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("costPrice")))
                    .totalUnitBonus(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalUnitBonus")))
                    .oriCserialNo(remoteDataMap.get("oriCserialNo"))
                    .cserialNo(remoteDataMap.get("cserialNo"))
                    .fundCode(fundCode)
                    .agencyName(agencyName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private List<Object> getRes(String url, TenantEscrowAuthorizationInfoDto tenant, HashMap<String, Object> params, String trustNo) {
        HttpHeaders headers = null;
        HttpEntity<JSONObject> res = null;
        try {
            params.put("managerCode", tenant.getCompanyId());
            params.put("appId", tenant.getAppKey());
            StringBuffer stringBuffer = new StringBuffer();
            params.keySet().stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new)).forEach(key -> {
                stringBuffer.append(key).append("=").append(params.get(key)).append("&");
            });
            String paramStr = stringBuffer.toString();
            String paramStrForSign = tenant.getAppSecret() + paramStr.replace("&", "").replace("=", "");
            log.info("加密前： " + JSON.toJSONString(paramStrForSign));
            //2、 签名
            String sign = MD5Util.getMD5Str(paramStrForSign);
            log.info("加密后： " + JSON.toJSONString(sign));
            //3、将签名加到参数中
            paramStr += "sign=" + sign;
            headers = new HttpHeaders();
            String urlWithParam = gtjaUrlPrefix + url + "?" + paramStr;
            log.info("urlWithParam = " + urlWithParam);
            res = restTemplate
                    .exchange(urlWithParam,
                            HttpMethod.GET,
                            new HttpEntity<>(null, headers),
                            JSONObject.class);
            log.info("调用结果: " + JSON.toJSONString(res));
            JSONObject body = res.getBody();
            if (!Objects.isNull(body)) {
                RemoteDto remoteDto = body.toJavaObject(RemoteDto.class);
                List<Object> returnObject = remoteDto.getReturnObject();
                if (!CollectionUtils.isEmpty(returnObject)) {
                    return returnObject;
                }
            }
        } catch (Exception e) {
            log.error("调用国泰君安托管失败：", e);
        }
        //将错误的信息塞入错误表
        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, url, headers, "appId=" + tenant.getAppKey(), res));
        return null;
    }

    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        log.info("国泰君安托管数据初始化...");
        for (TenantEscrowAuthorizationInfoDto tenant : tenants) {
            if(tenant.getTrustNo().equals("31")){
                getDataFromGTJAWithoutTgMj(tenant, 1); //先都拿1年，客户有需求再增加到3年
                log.info("国泰君安托管数据初始化结束:");
                return R.ok("国泰君安托管数据初始化结束！");
            }
        }
        log.error("没有租户，updateDataDaily未更新国泰君安!");
        return null;
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("国泰君安托管数据初始化...");
        getDataFromGTJAWithoutTgMj(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("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;
//        Integer loopNum = 48;
        try {
            switch (versionStr) {
                case CustodyContants.R_PT_S_CUSTODY_3_2_6:
                    processTGAccountSeqInfoData(tenant, trustNo, loopNum);
                    processTGAccountSeqInfoData1(tenant, trustNo, loopNum);
                    break;
            }
        }catch (Exception e){
            log.error("国泰君更新流水表失败!", e);
        }
        return null;
    }

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

        getDataFromGTJA(tenant,mouth);
        return R.ok();
    }

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

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        String trustNo = "31"; //每分钟 30次
        log.info("国泰君安每半小时更新：开始");
        //银行流水联机实时查询
        processTGAccountSeqInfoData1(tenant, trustNo, 1);
        log.info("国泰君安每半小时更新：1/2");

        //银行余额联机实时查询
        processAccountInfoData(tenant, trustNo);
        log.info("国泰君安每半小时更新：2/2");
        return null;
    }

    @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) {
        String trustNo = "31";
        int loopNum = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        log.info("国泰君安每8点、12点、20点更新数据开始！");
        try {
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopNum);
            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 {

            // 托管户银行账户余额信息表（TGAccount_balance_info） 募集户银行账余额信息表（MGAccount_balance_info） account_info
            processTGAccountBalanceInfoData(tenant, tenant.getTrustNo());
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

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

            processTGAccountSeqInfoData1(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 {

            // 托管户银行账户余额信息表（TGAccount_balance_info） 募集户银行账余额信息表（MGAccount_balance_info） account_info
            processTGAccountBalanceInfoData(tenant, tenant.getTrustNo());
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

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

    private void initTenantDataBy303(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopNum) {
        try {
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo, loopNum);
            //15 基金持有份额明细表（cust_share_detail_info)
            processCustShareDetailInfoData(tenant, trustNo, loopNum);
        } catch (Exception e) {
            log.error("initTenantDataBy303 is error:", e);
        }finally {
            fundInnerCodeAndCodeTL.remove();
        }
    }

//    public GuoAnConstants getGuoAnConstantsFromTenant(TenantEscrowAuthorizationInfoDto tenant){
//        GuoAnConstants guoAnConstants = new GuoAnConstants();
//        String appSecret = tenant.getAppSecret();
//        guoAnConstants.setPropertyFromJsonGTJA(appSecret);
//        String appKey = tenant.getAppKey();
//        if (StringUtils.isNotBlank(appKey) && appKey.equals(guoAnConstants.appkey)) {
//            log.info("getCmscConstantsFromTenant 返回内容{}",JSON.toJSONString(guoAnConstants));
//            return guoAnConstants;
//        }
//        log.error("国泰君安appkey与appSecret不匹配,appkey为{}，appSecret为{}",appKey,appSecret);
//        throw new IllegalArgumentException("appkey与appSecret不匹配");
//    }

    public void initTenantDataBy305Patch02(TenantEscrowAuthorizationInfoDto tenant,String trustNo,Integer loopNum){
        log.info("************318Patch01国泰君安更新fundOpenInfo开始************");
        //4 基金持有信息表（cust_share_info）
        processFundOpenInfoData(tenant, trustNo, loopNum);
        log.info("************308Patch02国泰君安更新fundOpenInfo结束************");

    }

    public void getDataFromGTJAByType(TenantEscrowAuthorizationInfoDto tenant, int loopNum, String type) {

        String trustNo = "31"; //每分钟 30次
        try {
            log.info("国泰君安初始化：开始");
            switch(type) {
                case "1":
                    processTGAccountSeqInfoData(tenant, trustNo, loopNum);
                    processTGAccountSeqInfoData1(tenant, trustNo, loopNum);
                    break;
                case "2" :
                    processFundInfoData(tenant, trustNo,loopNum);
                    break;
                case "3":
                    processInvestorInfoData(tenant, trustNo);
                    break;
                case "4":
                    processFundNetValueInfoData(tenant, trustNo,loopNum);
                    break;
                case "5":
                    processCustInfoData(tenant, trustNo);
                    break;
                case "6":
                    processTGAccountBalanceInfoData(tenant, trustNo);
                    processAccountInfoData(tenant, trustNo);
                    break;
                case "7":
                    processFundTradeInfoData(tenant, trustNo, loopNum);
                    break;
                case "8":
                    processCustShareSeqInfoData(tenant, trustNo, loopNum);
                    break;
                case "9":
                    processFundProfitInfoData(tenant, trustNo, loopNum); //没有权限
                    break;
                case "10":
                    processCustShareDetailInfoData(tenant, trustNo, loopNum);
                    break;
                case "11":
                    processFundFeeDataInfoData(tenant, trustNo, loopNum);
                    break;
                case "12":
                    processFundOpenInfoData(tenant, trustNo, loopNum);
                    break;
                default:
                    log.error("type={}不存在", type);
                    break;
            }
        } catch (Exception e) {
            log.error("国信托管数据拉取{}失败:",type, e);
        } finally {
            //todo tl的remove
            fundInnerCodeAndCodeTL.remove();
            accountNumTL.remove();
        }
    }
}
