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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.dto.ZhongXinEmailDto;
import com.friday.custody.entity.*;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.utils.*;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.enums.EmailConfigPurposeEnum;
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.citicZhongXin.common.ZhongXinConstants;
import com.friday.custody.service.trustService.citicZhongXin.utils.DateTimeTransUtil;
import com.friday.custody.service.trustService.citicZhongXin.utils.FrequencyUtil;
import com.friday.custody.service.trustService.citicZhongXin.utils.ZhongXinHttpUtil;
import com.friday.custody.service.trustService.cmsc.utils.RandomStrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
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 javax.mail.*;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
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.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author wulifeng
 * @Date: 2022/3/29
 */
@Slf4j
@Service
public class OutsourceZhongXinService implements OutsourceService {
    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 FundOpenInfoServiceImpl fundOpenInfoService;//15
    @Autowired
    private DataDictionaryOpenStateServiceImpl openStateService;//15

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

    @Autowired
    private ZhongXinHttpUtil zhongXinHttpUtil;

    @Autowired
    private FrequencyUtil frequencyUtil;

    @Autowired
    private DataDictionarySellerServiceImpl sellerService;

    @Autowired
    private TenantEmailAuthorizationInfoServiceImpl tenantEmailInfoService;
    @Autowired
    private DataDictionaryTypeOfFundValuationServiceImpl typeOfFundValuationService;
    @Autowired
    private FundValuationServiceImpl fundValuationService;

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

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        if (!Objects.isNull(tenant)) {
            getDataFromZhongXin(tenant, 12);
        }
        return null;

    }

    public void initByMail(TenantEscrowAuthorizationInfoDto tenant, String date) {

        getDataFromZhongXin(tenant, 12);

    }

    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        boolean hasUpdate = false;
        for (TenantEscrowAuthorizationInfoDto tenant : tenants) {
            if ("35".equals(tenant.getTrustNo())) {
                getDataFromZhongXinWithoutTgMj(tenant, 1);
                hasUpdate = true;
            }
        }
        if (!hasUpdate) {
            log.error("没有租户，updateDataDaily未更新中信!");
        }
        return null;
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        if (!Objects.isNull(tenant)) {
            getDataFromZhongXinWithoutTgMj(tenant, 1);
        }
        return null;
    }

    @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;
        try {
            switch (versionStr) {
                case CustodyContants.R_PT_S_CUSTODY_3_2_8:
                    String token = zhongXinHttpUtil.getToken(tenant);
                    if (StringUtils.isBlank(token)) {
                        log.error("获取token失败，停止中信提数!");
                    }
                    processFundOpenInfoData(tenant, trustNo, token, loopNum);
                    log.info("管理人{}中信开放日更新完成!", tenant.getTenantName());
                    break;
            }
        }catch (Exception e){
            log.error("中信流水表更新失败!");
        }
        return null;
    }

    @Override
    public R initByAppointedTrustNoAndMouth(TenantEscrowAuthorizationInfoDto tenant, int mouth) {
        getDataFromZhongXin(tenant, mouth);
        return R.ok();
    }

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

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        String trustNo = tenant.getTrustNo(); //35

        log.info("中信每半小时更新进度：开始");
        String token = zhongXinHttpUtil.getToken(tenant);
        if (StringUtils.isBlank(token)) {
            log.error("获取token失败，停止中信提数!");
        }
        //7 & 11_2
        processMJAccountBalanceInfoAndAccountInfo2(tenant, trustNo, token);
        log.info("中信每半小时更新进度：1/2");

        //8
        processMjAccountSeqInfoData(tenant, trustNo, token);
        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) {
        try {
            log.info("中信托管数据每8点、12点、20点更新开始...");
            String trustNo = tenant.getTrustNo();
            Integer loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
            String token = zhongXinHttpUtil.getToken(tenant);
            if (StringUtils.isBlank(token)) {
                log.error("获取token失败，停止中信净值提数!");
            }
            processFundNetValueInfoData(tenant, trustNo, loopTime, token);
            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 {
            String token = zhongXinHttpUtil.getToken(tenant);
            if (StringUtils.isBlank(token)) {
                log.error("获取token失败，停止中信提数!");
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "获取token失败，停止中信提数!");
            }
            processMJAccountBalanceInfoAndAccountInfo2(tenant, tenant.getTrustNo(), token);

            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            String token = zhongXinHttpUtil.getToken(tenant);
            if (StringUtils.isBlank(token)) {
                log.error("获取token失败，停止中信提数!");
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "获取token失败，停止中信提数!");
            }
            processMjAccountSeqInfoData(tenant, tenant.getTrustNo(), token);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户流水失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            String token = zhongXinHttpUtil.getToken(tenant);
            if (StringUtils.isBlank(token)) {
                log.error("获取token失败，停止中信提数!");
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "获取token失败，停止中信提数!");
            }
            processTGAccountBalanceInfoDataAndAccountInfo1(tenant, tenant.getTrustNo(), token);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            String trustNo = tenant.getTrustNo();
            List<AccountInfoEntity> accountInfoEntities = accountInfoService.getDataList(trustNo, "ZJ001", tenant.getTenantName());
            if (CollectionUtils.isEmpty(accountInfoEntities)) {
                log.error("手动更新托管户流水，未能查询到接口入参，账户信息表托管户数据为空");
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户流水，未能查询到接口入参，账户信息表托管户数据为空");
            }
            String token = zhongXinHttpUtil.getToken(tenant);
            if (StringUtils.isBlank(token)) {
                log.error("获取token失败，停止中信提数!");
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "获取token失败，停止中信提数!");
            }
            processTGAccountSeqInfo1(tenant, trustNo, token, accountInfoEntities);
            // 更新最近一个月的
            processTGAccountSeqInfo2(tenant, trustNo, CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME, accountInfoEntities, token);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户流水失败" + e.getMessage());
        }
    }

    public R updateSingleDataByAppointedScheduled(TenantEscrowAuthorizationInfoDto tenant) {
        String trustNo = tenant.getTrustNo(); //35

        log.info("中信每天9、11、13、15、17点更新进度：开始");
        String token = zhongXinHttpUtil.getToken(tenant);
        if (StringUtils.isBlank(token)) {
            log.error("获取token失败，停止中信提数!");
        }
        //7 & 11_2
        List<AccountInfoEntity> accountInfoEntities = processTGAccountBalanceInfoDataAndAccountInfo1(tenant, trustNo, token);
        log.info("中信每天9、11、13、15、17点更新进度：1/2");

        //8
        processTGAccountSeqInfo1(tenant, trustNo, token, accountInfoEntities);
        log.info("中信每天9、11、13、15、17点更新进度：2/2");

        return null;
    }

    public void getDataFromZhongXin(TenantEscrowAuthorizationInfoDto tenant, int loopNum) {
        String trustNo = tenant.getTrustNo(); //35

        log.info("中信初始化进度：开始");
        String token = zhongXinHttpUtil.getToken(tenant);
        if (StringUtils.isBlank(token)) {
            log.error("获取token失败，停止中信提数!");
            //查询对应租户的邮箱权限
            List<TenantEmailAuthorizationInfoEntity> tenantEmails = tenantEmailInfoService.queryByTenantName(tenant.getTenantName(), trustNo);
            log.info("中信获取的邮件配置：{}", JSON.toJSONString(tenantEmails));
            if (!CollectionUtils.isEmpty(tenantEmails)) {
                for (TenantEmailAuthorizationInfoEntity tenantEmail : tenantEmails) {
                    String purpose = EmailConfigPurposeEnum.ALL.getPurpose();
                    log.info("getDataFromZhongXin:ALL.getPurpose={},tenantEmail.getPurpose={}", purpose, tenantEmail.getPurpose());
                    if (!ObjectUtils.isEmpty(tenantEmail) && !purpose.equals(tenantEmail.getPurpose())) {
                        log.info("getDataFromZhongXin 配置信息不为all,更新资产合计值");
                        //初始化资产合计值
                        updateTotalAsset(tenant, tenantEmail, loopNum);
                    }
                }
            }
            return;
        }
        //1
        processFundInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：1/13");
        //2 & 13
        processInvestorInfoAndInvestorBankInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：2/13");
        //3
        processFundNetValueInfoData(tenant, trustNo, loopNum, token);
        log.info("中信初始化进度：3/13");
        //4
        processCustShareInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：4/13");
        //11_3
        processAccountInfo3(tenant, trustNo, token);
        log.info("中信初始化进度：5/13");
        //7 & 11_2
        processMJAccountBalanceInfoAndAccountInfo2(tenant, trustNo, token);
        log.info("中信初始化进度：6/13");
        //5 & 11_1
        List<AccountInfoEntity> accountInfoEntities = processTGAccountBalanceInfoDataAndAccountInfo1(tenant, trustNo, token);
        log.info("中信初始化进度：7/13");

        if (accountInfoEntities != null && accountInfoEntities.size() > 0) {
            //6_1  --504
            processTGAccountSeqInfo1(tenant, trustNo, token, accountInfoEntities);
            log.info("中信初始化进度：8/13");
            //6_2
            processTGAccountSeqInfo2(tenant, trustNo, loopNum, accountInfoEntities, token);
            log.info("中信初始化进度：9/13");

        } else {
            log.info("中信进度：由于7返回的数据为空，所以8和9无法进行");
            log.error("accountInfoEntities为空导致不进行processTGAccountSeqInfo1");
        }
        //8
        processMjAccountSeqInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：10/13");
        //9
        processFundTradeInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：11/13");
        //14
        processFundProfitInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：12/13");
        //15
        processCustShareDetailInfoData(tenant, trustNo, token);
        log.info("中信初始化进度：13/13");
        processFundValueTableInfoForApi(tenant, trustNo, token, loopNum);
        processFundOpenInfoData(tenant, trustNo, token, loopNum);
        //查询对应租户的邮箱权限
 /*       List<TenantEmailAuthorizationInfoEntity> tenantEmails = tenantEmailInfoService.queryByTenantName(tenant.getTenantName(), trustNo);
        log.info("中信获取的邮件配置：{}", JSON.toJSONString(tenantEmails));
        if (!CollectionUtils.isEmpty(tenantEmails)) {
            for (TenantEmailAuthorizationInfoEntity tenantEmail : tenantEmails) {
                String purpose = EmailConfigPurposeEnum.ALL.getPurpose();
                log.info("updateTotalAsset:ALL.getPurpose={},tenantEmail.getPurpose={}", purpose, tenantEmail.getPurpose());
                if (!ObjectUtils.isEmpty(tenantEmail) && !purpose.equals(tenantEmail.getPurpose())) {
                    log.info("getDataFromZhongXin updateTotalAsset 配置的邮件不是all");
                    //初始化资产合计值
                    updateTotalAsset(tenant, tenantEmail, loopNum);
                }
            }
        }*/
    }

    public void getDataFromZhongXinWithoutTgMj(TenantEscrowAuthorizationInfoDto tenant, int loopNum) {
        String trustNo = tenant.getTrustNo(); //35

        log.info("中信每半天进度：开始");
        String token = zhongXinHttpUtil.getToken(tenant);
        if (StringUtils.isBlank(token)) {
            log.error("获取token失败，停止中信提数!");
            return;
        }
        //1
        processFundInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：1/13");
        //2 & 13
        processInvestorInfoAndInvestorBankInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：2/13");
        //4
        processCustShareInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：4/13");
        //11_3
        processAccountInfo3(tenant, trustNo, token);
        log.info("中信每半天进度：5/13");
        //7 & 11_2
        //processMJAccountBalanceInfoAndAccountInfo2(tenant,trustNo,token); 募集户银行余额查询接口
        log.info("中信每半天进度：6/13 修改为半天更新");
        //5 & 11_1
        //List<AccountInfoEntity> accountInfoEntities = processTGAccountBalanceInfoDataAndAccountInfo1(tenant, trustNo,token);
        List<AccountInfoEntity> accountInfoEntities = getAccountInfoFromDB(trustNo, tenant.getTenantName());
        log.info("中信每半天进度：7/13   修改为每天0点，12点更新");

        if (accountInfoEntities != null && accountInfoEntities.size() > 0) {
            //6_1  --504
            //processTGAccountSeqInfo1(tenant,trustNo,token,accountInfoEntities);
            log.info("中信每半天进度：8/13  修改为每天0点，12点更新");
            //6_2
            processTGAccountSeqInfo2(tenant, trustNo, loopNum, accountInfoEntities, token);
            log.info("中信每半天进度：9/13");

        } else {
            log.info("中信进度：由于7返回的数据为空，所以8和9无法进行");
            log.error("accountInfoEntities为空导致不进行processTGAccountSeqInfo1");
        }
        //8
        //processMjAccountSeqInfoData(tenant,trustNo,token); 募集户银行流水查询接口
        log.info("中信每半天进度：10/13 修改为半半天更新");
        //9
        processFundTradeInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：11/13");
        //14
        processFundProfitInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：12/13");
        //15
        processCustShareDetailInfoData(tenant, trustNo, token);
        log.info("中信每半天进度：13/13 结束！");

        processFundValueTableInfoForApi(tenant, trustNo, token, loopNum);

        processFundOpenInfoData(tenant, trustNo, token, loopNum);

    }

    private final String LINYUAN = "P1002894";
    public void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token, int loopNum) {
        //此接口为林园定制版,目前只支持林园管理人调用
        if (!LINYUAN.equals(tenant.getTenantName())){
            return;
        }
        if (loopNum > 12) {
            log.error("中信processFundOpenInfoData暂时只能更新一年");
        }

        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusMonths(loopNum);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String startDateStr = startDate.format(formatter);
        String endDateStr = endDate.format(formatter);
        Map<String, Map<String, String>> openStateMap = openStateService.queryOpenStateWithDetail(trustNo);
        Map<String, String> openDayTypeMap = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, trustNo);
        log.info("openStateMap:{}", JSON.toJSONString(openStateMap));
        log.info("openDayTypeMap:{}", JSON.toJSONString(openDayTypeMap));
        for (Map.Entry<String, String> openDayTypeEntry : openDayTypeMap.entrySet()) {
            String openType = MatchDataDictionaryKeyUtil.getKey(openDayTypeMap, openDayTypeEntry.getKey());
            for (Map.Entry<String, String> openStateEntry : openStateMap.get(openType).entrySet()) {

                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int pageSize = 500;
                int pageNo = 0;

                String api = ZhongXinConstants.FUND_OPEN_INFO;
                List<JSONObject> objects;


                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("openingType", openStateEntry.getKey());
                    params.put("openingSource", openDayTypeEntry.getKey());
                    params.put("beginDate", startDateStr);
                    params.put("endDate", endDateStr);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processFundOpenInfoData 入参为" + jsonString);

                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<FundOpenInfoEntity> openInfoEntities = getFundOpenInfo(tenant, trustNo, objects);
                            //4、调用 basicservice 的保存数据接口
                            fundOpenInfoService.saveData(null, openInfoEntities);
                        }
                        log.info("中信processFundOpenInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("processFundOpenInfoData查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processFundOpenInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        }
    }

    private List<FundOpenInfoEntity> getFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<JSONObject> objects) {
        List<FundOpenInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        Map<String, String> typeOfOpenDayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, trustNo);
        Map<String, Map<String, String>> openStateDic = openStateService.queryOpenStateWithDetail(trustNo);
        for (JSONObject data : objects){
            dataMap = JSONObject.toJavaObject(data, Map.class);
            String openType = MatchDataDictionaryKeyUtil.getKey(typeOfOpenDayDic, dataMap.get("OPENINGSOURCE"));
            entityList.add(FundOpenInfoEntity.builder()
                    .fundCode(dataMap.get("FUNDCODE"))
                    .fundOpenDate(dataMap.get("OPENINGDAY"))
                    .openStatus(MatchDataDictionaryKeyUtil.getKey(openType, openStateDic, dataMap.get("OPENINGTYPE")))
                    .openType(openType)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processFundValueTableInfoForApi(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token, int loopNum) {
        try {
            if (loopNum > 12) {
                log.error("中信processFundValueTableInfoForApi暂时只能更新一年");
            }

            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusMonths(loopNum);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String startDateStr = startDate.format(formatter);
            String endDateStr = endDate.format(formatter);
            List<String> fundCodeList = fundInfoService.getFundCodeList(trustNo, tenant.getTenantName());

            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int pageSize = 500;

                String api = ZhongXinConstants.FUND_VALUE_TABLE_DATA_INFO;
                List<JSONObject> objects;

                int pageNo = 0;
                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("fundCode", fundCode);
                    params.put("beginDate", startDateStr);
                    params.put("endDate", endDateStr);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processFundValueTableInfoForApi 入参为" + jsonString);

                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<FundValueTableDataInfoEntity> entities = getFundValueTableDataInfoForApi(tenant, objects, trustNo, fundCode);
                            //4、调用 basicservice 的保存数据接口
                            fundValueTableDataInfoService.saveData(null, entities);
                        }
                        log.info("中信processFundValueTableInfoForApi现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("中信processFundValueTableInfoForApi查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processFundValueTableInfoForApi返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundValueTableInfoForApi保存数据失败!", e);
        }
}

    public void processFundValueTableInfoForApiV2(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token, int loopNum) {
        try {
            if (loopNum > 12) {
                log.error("中信processFundValueTableInfoForApi暂时只能更新一年");
            }

            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusMonths(loopNum);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String startDateStr = startDate.format(formatter);
            String endDateStr = endDate.format(formatter);
            List<String> fundCodeList = fundInfoService.getFundCodeList(trustNo, tenant.getTenantName());

            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int pageSize = 500;

                String api = ZhongXinConstants.FUND_VALUE_TABLE_DATA_INFO;
                List<JSONObject> objects;

                int pageNo = 0;
                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("fundCode", fundCode);
                    params.put("beginDate", startDateStr);
                    params.put("endDate", endDateStr);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processFundValueTableInfoForApi 入参为" + jsonString);

                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<FundValueTableDataInfoEntity> entities = getFundValueTableDataInfoForApi(tenant, objects, trustNo, fundCode);
                            //4、调用 basicservice 的保存数据接口
                            fundValueTableDataInfoService.saveData(null, entities);
                        }
                        log.info("中信processFundValueTableInfoForApi现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("中信processFundValueTableInfoForApi查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processFundValueTableInfoForApi返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundValueTableInfoForApi保存数据失败!", e);
        }
    }

    private List<FundValueTableDataInfoEntity> getFundValueTableDataInfoForApi(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> objects, String trustNo, String fundCode) {
        List<FundValueTableDataInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        //获取币种数据字典
        Map<String, String> currencyDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        for (JSONObject data : objects){
            dataMap = JSONObject.toJavaObject(data, Map.class);
            entityList.add(FundValueTableDataInfoEntity.builder()
                    .fundCode(dataMap.get("fundCode"))
                    .fundName(dataMap.get("fundName"))
                    .valueDate(dataMap.get("valueDate"))
                    .kmCode(dataMap.get("accCode"))
                    .kmName(dataMap.get("accName"))
                    .currency(MatchDataDictionaryKeyUtil.getKey(currencyDic, dataMap.get("currency")))
                    .vaRate(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("exRate"), 4))
                    .amount(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("amt")))
                    .perCost(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("unitCst")))
                    .origCost(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("cst")))
                    .portCost(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("localCst")))
                    .costBi(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("percCst"), 4))
                    .vapPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("marketPrice")))
                    .origMv(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("mv")))
                    .portMv(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("localMV")))
                    .mvBl(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("percMV")))
                    .origIv(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("va")))
                    .portIv(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("localVa")))
                    .suspension(dataMap.get("suspension"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }


    //处理01
    private void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

            if (!"P1000869".equals(tenant.getTenantName())) {
                // 该接口为一村定制化接口，其他管理人通过净值接口获取产品信息
                return;
            }
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int pageSize = 500;


            String api = ZhongXinConstants.FUND_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<FundInfoEntity> entities = getFundInfoData(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        fundInfoService.saveData(null, entities);
                    }
                    log.info("中信processFundInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processFundInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processFundInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundInfoData:", e);
        }
    }

    //处理02 & 13
    private void processInvestorInfoAndInvestorBankInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

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

            String api = ZhongXinConstants.INVESTOR_INFO_AND_INVESTOR_BANK_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<InvestorInfoEntity> entities = getInvestorInfoData(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        investorInfoService.saveData(null, entities);

                        List<InvestorBankInfoEntity> investorBankInfo = getInvestorBankInfo(tenant, objects, trustNo);
                        investorBankInfoService.saveData(null, investorBankInfo);

                    }
                    log.info("中信processInvestorInfoAndInvestorBankInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processInvestorInfoAndInvestorBankInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processInvestorInfoAndInvestorBankInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("processInvestorInfoAndInvestorBankInfoData", e);
        }
    }

    //处理03
    private void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum, String token) {
        try {

            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int pageSize = 500;
            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusMonths(loopNum);

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            if (loopNum > 12) {
                log.info("中信fund_net_value_info暂时只能更新一年");
            }

            String endDateStr = endDate.format(formatter);
            String startDateStr = startDate.format(formatter);

            String api = ZhongXinConstants.FUND_NET_VALUE_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                params.put("netBeginDate", startDateStr);
                params.put("netEndDate", endDateStr);

                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
//                        List<InvestorInfoEntity> entities = getInvestorInfoData(tenant, objects, trustNo);
                        List<FundNetValueInfoEntity> entities = getFundNetValueInfoDate(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        fundNetValueInfoService.saveData(null, entities);

                        //3、封装成标准表的对象 //
                        List<FundInfoEntity> fundInfoEntity = getFundInfoDataByNetValue(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        fundInfoService.saveData(null, fundInfoEntity);
                    }
                    log.info("中信processFundNetValueInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processFundNetValueInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processFundNetValueInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("processInvestorInfoAndInvestorBankInfoData", e);
        }
    }


    //处理04.
    private void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {
            List<CustShareInfoEntity> entityList = new ArrayList<>();
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int pageSize = 500;

            String api = ZhongXinConstants.CUST_SHARE_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<CustShareInfoEntity> entities = getCustShareInfo(tenant, objects, trustNo);
                        //先将数据添加到一个list中，后续一起保存数据。
                        entityList.addAll(entities);
                    }
                    log.info("中信processCustShareInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processCustShareInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processCustShareInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);
            //4、调用 basicservice 的保存数据接口
            custShareInfoService.saveData(null, entityList);
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundInfoData:", e);
        }
    }

    private List<AccountInfoEntity> getAccountInfoFromDB(String trustNo, String admin) {
        List<AccountInfoEntity> accountInfoEntities = new ArrayList<>();
        accountInfoEntities = accountInfoService.getDataList(trustNo, "ZJ001", admin);
        if (accountInfoEntities == null || accountInfoEntities.size() == 0) {
            log.error("processTGAccountBalanceInfoDataAndAccountInfo1 未能查询到接口入参");
            return new ArrayList<>();
        }
        return accountInfoEntities;
    }

    //处理5 & 11_1
    private List<AccountInfoEntity> processTGAccountBalanceInfoDataAndAccountInfo1(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        List<AccountInfoEntity> accountInfoEntities = new ArrayList<>();
        try {

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

            String api = ZhongXinConstants.TG_ACCOUNT_BALANCE_INFO_AND_ACCOUNT_INFO_1;
            List<JSONObject> objects = new ArrayList<>();

            accountInfoEntities = accountInfoService.getDataList(trustNo, "ZJ001", tenant.getTenantName());
            if (accountInfoEntities == null || accountInfoEntities.size() == 0) {
                log.error("processTGAccountBalanceInfoDataAndAccountInfo1 未能查询到接口入参");
                return new ArrayList<>();
            }
            log.info("processTGAccountBalanceInfoDataAndAccountInfo1中AccountInfoEntities信息" + JSON.toJSONString(accountInfoEntities));

            for (AccountInfoEntity accountInfoEntity : accountInfoEntities) {
                String fundCode = accountInfoEntity.getFundCode();
                String branchBankName = accountInfoEntity.getBranchBankName();
                String bankAcco = accountInfoEntity.getBankAcco();

                int pageNo = 0;
                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("pdCode", fundCode);
                    params.put("bankName", branchBankName);
                    params.put("account", bankAcco);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processTGAccountBalanceInfoDataAndAccountInfo1 入参为" + jsonString);
                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<TgAccountBalanceInfoEntity> entities = getTGAccountBalanceInfoData(tenant, objects, trustNo);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountBalanceInfoService.saveData(null, entities);
                        }
                        log.info("中信processTGAccountBalanceInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("中信processTGAccountBalanceInfoData查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processTGAccountBalanceInfoDataAndAccountInfo1返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processTGAccountBalanceInfoData:", e);
        }
        return accountInfoEntities;
    }

    //处理5 & 11_2
    private void processMJAccountBalanceInfoAndAccountInfo2(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

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

            String api = ZhongXinConstants.MJ_ACCOUNT_BALANCE_INFO_AND_ACCOUNT_INFO_2;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<AccountInfoEntity> entities = getAccountInfo2(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        accountInfoService.saveData(null, entities);
                        List<MjAccountBalanceInfoEntity> mjAccountBalanceInfo = getMJAccountBalanceInfo(tenant, objects, trustNo);
                        mjAccountBalanceInfoService.saveData(null, mjAccountBalanceInfo);
                    }
                    log.info("中信processMJAccountBalanceInfoAndAccountInfo2现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processMJAccountBalanceInfoAndAccountInfo2查询入库结束");
                        break;
                    }
                } else {
                    log.error("processMJAccountBalanceInfoAndAccountInfo2返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processMJAccountBalanceInfoAndAccountInfo2:", e);
        }
    }

    //处理 6_1loopNum
    private void processTGAccountSeqInfo1(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token, List<AccountInfoEntity> accountInfoEntities) {
        try {

            for (AccountInfoEntity accountInfoEntity : accountInfoEntities) {
                String fundCode = accountInfoEntity.getFundCode();
                String branchBankName = accountInfoEntity.getBranchBankName();
                String bankAcco = accountInfoEntity.getBankAcco();

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

                String api = ZhongXinConstants.TG_ACCOUNT_SEQ_INFO_1;
                List<JSONObject> objects = new ArrayList<>();

                int pageNo = 0;
                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("pdCode", fundCode);
                    params.put("bankName", branchBankName);
                    params.put("account", bankAcco);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processTGAccountSeqInfo1 入参为" + jsonString);

                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<TgAccountSeqInfoEntity> entities = getTGAccountSeqInfoData(tenant, objects, trustNo, fundCode);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountSeqInfoService.saveData(null, entities);
                        }
                        log.info("中信processTGAccountSeqInfo1现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("中信processTGAccountSeqInfo1查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processTGAccountSeqInfo1返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processTGAccountBalanceInfoData:", e);
        }
    }

    //处理 6_2
    private void processTGAccountSeqInfo2(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum, List<AccountInfoEntity> accountInfoEntities, String token) {
        try {
            if (loopNum > 12) {
                log.error("中信TGAccountSeqInfo暂时只能更新一年");
            }

            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusMonths(loopNum);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String startDateStr = startDate.format(formatter);
            String endDateStr = endDate.format(formatter);

            List<String> fundCodeList = accountInfoEntities.stream().map(AccountInfoEntity::getFundCode).distinct().collect(Collectors.toList());
            log.info("processTGAccountSeqInfo2_fundCodeList={}", JSON.toJSONString(fundCodeList));

            for (String fundCode : fundCodeList) {
                if (StringUtils.isBlank(fundCode)) {
                    continue;
                }
                //1、封装请求参数
                HashMap<String, Object> params = new HashMap<>();
                int pageSize = 500;

                String api = ZhongXinConstants.TG_ACCOUNT_SEQ_INFO_2;
                List<JSONObject> objects = new ArrayList<>();

                int pageNo = 0;
                do {
                    pageNo++;
                    params.put("pageSize", pageSize);
                    params.put("pdCode", fundCode);
                    params.put("beginDate", startDateStr);
                    params.put("endDate", endDateStr);
                    params.put("pageNum", pageNo);
                    String jsonString = JSON.toJSONString(params);
                    log.info("processTGAccountSeqInfo2 入参为" + jsonString);

                    //2、获取远端数据
                    Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                    boolean result = (boolean) stringObjectMap.get("result");
                    if (result) {
                        objects = (List<JSONObject>) stringObjectMap.get("data");
                        Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                        if (!CollectionUtils.isEmpty(objects)) {
                            //3、封装成标准表的对象 //
                            List<TgAccountSeqInfoEntity> entities = getTGAccountSeqInfoData2(tenant, objects, trustNo, fundCode);
                            //4、调用 basicservice 的保存数据接口
                            tgAccountSeqInfoService.saveData(null, entities);
                        }
                        log.info("中信processTGAccountSeqInfo1现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                        if (pageNo * pageSize > totalCountInt) {
                            log.info("中信processTGAccountSeqInfo1查询入库结束");
                            break;
                        }
                    } else {
                        log.error("processTGAccountSeqInfo2返回错误{}", JSON.toJSONString(stringObjectMap));
                        break;
                    }
                } while (objects != null && objects.size() == pageSize);
            }
        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processTGAccountBalanceInfoData:", e);
        }
    }

    //8
    private void processMjAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int pageSize = 500;

            String api = ZhongXinConstants.MJ_ACCOUNT_SEQ_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<MjAccountSeqInfoEntity> entities = getMjAccountSeqInfo(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        mjAccountSeqInfoService.saveData(null, entities);
                    }
                    log.info("中信processMJAccountBalanceInfoAndAccountInfo2现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processMJAccountBalanceInfoAndAccountInfo2查询入库结束");
                        break;
                    }
                } else {
                    log.error("processMjAccountSeqInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processMJAccountBalanceInfoAndAccountInfo2:", e);
        }
    }

    //9
    private void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {
            //1、封装请求参数
            HashMap<String, Object> params = new HashMap<>();
            int pageSize = 500;

            String api = ZhongXinConstants.FUND_TRADE_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<FundTradeInfoEntity> entities = getFundTradeInfo(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        fundTradeInfoService.saveData(null, entities);
                    }
                    log.info("中信processFundTradeInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processFundTradeInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processFundTradeInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundTradeInfoData:", e);
        }
    }

    //11_3
    private void processAccountInfo3(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

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

            String api = ZhongXinConstants.ACCOUNT_INFO_3;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<AccountInfoEntity> entities = getAccountInfo3(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        accountInfoService.saveData(null, entities);
                    }
                    log.info("中信processMJAccountBalanceInfoAndAccountInfo2现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processMJAccountBalanceInfoAndAccountInfo2查询入库结束");
                        break;
                    }
                } else {
                    log.error("processAccountInfo3返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processMJAccountBalanceInfoAndAccountInfo2:", e);
        }
    }

    //处理14
    private void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

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

            String api = ZhongXinConstants.FUND_PROFIT_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<FundProfitInfoEntity> entities = getFundProfitInfo(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        fundProfitInfoService.saveData(null, entities);
                    }
                    log.info("中信processFundProfitInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processFundProfitInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processFundProfitInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundInfoData:", e);
        }
    }

    //处理15
    private void processCustShareDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        try {

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

            String api = ZhongXinConstants.CUST_SHARE_DETAIL_INFO;
            List<JSONObject> objects = new ArrayList<>();

            int pageNo = 0;
            do {
                pageNo++;
                params.put("pageSize", pageSize);
                params.put("pageNum", pageNo);
                String jsonString = JSON.toJSONString(params);
                //2、获取远端数据
                Map<String, Object> stringObjectMap = zhongXinHttpUtil.sendMessage(jsonString, api, tenant, trustNo, token);
                boolean result = (boolean) stringObjectMap.get("result");
                if (result) {
                    objects = (List<JSONObject>) stringObjectMap.get("data");
                    Integer totalCountInt = (Integer) stringObjectMap.get("totalCount");
                    if (!CollectionUtils.isEmpty(objects)) {
                        //3、封装成标准表的对象 //
                        List<CustShareDetailInfoEntity> entities = getCustShareDetailInfo(tenant, objects, trustNo);
                        //4、调用 basicservice 的保存数据接口
                        custShareDetailInfoService.saveData(null, entities);
                    }
                    log.info("中信processFundProfitInfoData现查询页为{}，页容量为{}，总数为{}", pageNo, pageSize, totalCountInt);
                    if (pageNo * pageSize > totalCountInt) {
                        log.info("中信processFundProfitInfoData查询入库结束");
                        break;
                    }
                } else {
                    log.error("processCustShareDetailInfoData返回错误{}", JSON.toJSONString(stringObjectMap));
                    break;
                }
            } while (objects != null && objects.size() == pageSize);

        } catch (Exception e) {
            log.error("OutsourceHaiTongServiceImpl:processFundInfoData:", e);
        }
    }

    //转换1.产品信息查询
    private List<FundInfoEntity> getFundInfoData(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {

//1、获取字典表数据
        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);

            String fundType = remoteDataMap.get("pdType");
            String fundTypeIn = MatchDataDictionaryKeyUtil.getKey(fundTypeDir, fundType);
            String peType = MatchDataDictionaryKeyUtil.getKey(privateFundType, remoteDataMap.get("pdType"));
            log.info("getFundInfoData_fundType_原值={}，映射值fundType={},peType={}", fundType, fundTypeIn, peType);

            String fundStatus = MatchDataDictionaryKeyUtil.getKey(proDir, remoteDataMap.get("status"));
            log.info("getFundInfoData_fundStatus_原值={}，映射值={}", remoteDataMap.get("status"), fundStatus);
//
            String createDate = remoteDataMap.get("setUpDate");
            log.info("getFundInfoData_createDate=" + createDate);

            result.add(FundInfoEntity.builder()
                    .fundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("pdName"))
                    .fundType(fundTypeIn)
                    .peType(peType)
                    .fundStatus(fundStatus)
                    .createDate(createDate)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换1.产品信息查询
    private List<FundInfoEntity> getFundInfoDataByNetValue(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //2、封装数据
        List<FundInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();

        // 一村通过定制化接口获取产品信息
        if (!"P1000869".equals(tenant.getTenantName())) {
            for (JSONObject remoteData : remoteDatas) {
                remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);

                // 总基金是 S 代码且 flag=1
                // A类要查 S 代码且 flag=2
                // B类之后的产品都是独立的 T 代码 flag=2
                // 中信基金类型为分级基金，注意与字典表含义不一致！！！
                String fundType = remoteDataMap.get("flag");

                // 0：一致，托管复核一致
                // 1：不一致，未经托管确认
                // 3：无托管方产品，无托管方复核
                // 与字典含义不一致，暂不存
                String fundStatus = remoteDataMap.get("checkStatus");
                result.add(FundInfoEntity.builder()
                        .fundCode(remoteDataMap.get("fundCode"))
                        .fundName(remoteDataMap.get("fundName"))
                        .fundType(fundType)
//                        .fundStatus(fundStatus)
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
            return result;
        }
        return result;
    }

    //转换2
    private List<InvestorInfoEntity> getInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> 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<>();
        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"));
            log.info("getInvestorInfoData_custName原值为{},映射值为{}", remoteDataMap.get("custType"), key);

            String identityType = MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, remoteDataMap.get("certiType"));
            log.info("getInvestorInfoData_identityType原值为{},映射值为{}", remoteDataMap.get("certiType"), identityType);

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

    //转换 03
    private List<FundNetValueInfoEntity> getFundNetValueInfoDate(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> reviewStatusDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.REVIEW_STATUS_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 checkStatus1 = remoteDataMap.get("checkStatus");
            if (!checkStatus1.equals("0") && !checkStatus1.equals("3")) {
                log.info("核对不为0或3，状态为{}，原数据为{}，不落库", checkStatus1, JSON.toJSONString(remoteDataMap));
                continue;
            }

            log.info("getFundNetValueInfoDate_返回netValueDate" + remoteDataMap.get("netDate"));

            String checkStatus = MatchDataDictionaryKeyUtil.getKey(reviewStatusDir, checkStatus1);
            log.info("getFundNetValueInfoDate_checkStatus_原值={}，映射值={}", remoteDataMap.get("checkStatus"), checkStatus);

            result.add(FundNetValueInfoEntity.builder()
                    .netValueDate(remoteDataMap.get("netDate"))
                    .fundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .shares(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("assetShares")))
                    .assetValue(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("assetNet")))
//                    .totalAsset(new BigDecimal(0)) //资产总值(暂停使用，返回值均为0)
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netAssetVal"), 4))
                    .totalNetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalAssetVal"), 4))
                    .checkStatus(checkStatus)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换4
    private List<CustShareInfoEntity> getCustShareInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> sellerServiceDir = 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 agencyNo1 = MatchDataDictionaryKeyUtil.getKey(sellerServiceDir, agencyNo);
            log.info("getCustShareInfo_agencyNo原值={},映射值={}", agencyNo, agencyNo1);

            String bonusType = remoteDataMap.get("bonusType");
            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(dividendDir, bonusType);
            log.info("getCustShareInfo_bonusMethod原值={},映射值={}", bonusType, bonusMethod);


            String ackDate = remoteDataMap.get("ackDate");
            String ackDateAfter = DateTimeTransUtil.transDateFormat("yyyyMMdd", "yyyy-MM-dd", ackDate);

            String fundCode = remoteDataMap.get("fundCode");
            String netValueDate = remoteDataMap.get("lastNav");
            String lastHoldSharesStr = remoteDataMap.get("realShares");
            BigDecimal lastHoldShares = BigDecimalUtil.obj2BigDecimal(lastHoldSharesStr);
            //设置fund_name
            String fundName = getFundNameByFundCode(tenant.getTenantName(), fundCode, trustNo);
            //设置agencyName
            String agencyName = sellerService.queryAgencyName("中信证券", agencyNo);
            //设置share_ratio
            BigDecimal shareRadio = null;
            if (StringUtils.isNotBlank(netValueDate)) {
                SimpleDateFormat oldF = new SimpleDateFormat("yyyyMMdd");
                SimpleDateFormat newF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String format = null;
                try {
                    Date parse = oldF.parse(netValueDate);
                    format = newF.format(parse);
                } catch (ParseException e) {
                    log.error("中信getCustShareInfo转换日期异常，预期为yyyyMMdd格式，返回的内容为{}", netValueDate);
                    e.printStackTrace();
                }

                FundNetValueInfoEntity itemByFundCodeAndNetValueDate = fundNetValueInfoService.getItemByFundCodeAndNetValueDate(fundCode, format, trustNo);
                BigDecimal shares = null;
                if (itemByFundCodeAndNetValueDate == null) {  //2
                    log.error("中信getCustShareInfo设置share_radio时未能找到相应的fund_net_value_info表记录");
                } else {
                    shares = itemByFundCodeAndNetValueDate.getShares();
                }

                if (lastHoldShares == null
                        || shares == null
                        || shares.compareTo(BigDecimal.ZERO) == 0) {
                    shareRadio = new BigDecimal("0.0000");
                    log.error("中信getCustShareInfo设置share_radio时计算异常lastHoldShares={}，shares={}", lastHoldShares, shares);
                } else {
                    shareRadio = lastHoldShares.divide(shares, 6, RoundingMode.HALF_DOWN).multiply(new BigDecimal("100")).setScale(4, RoundingMode.HALF_DOWN);
                }
            } else {
                log.error("中信getCustShareInfo 返回的netValueDate(lastNav) 为空 原数据为{}", JSON.toJSONString(remoteDataMap));
            }

            result.add(CustShareInfoEntity.builder()
                    .updateDate(ackDateAfter + " 00:00:00")
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .fundCode(fundCode)
                    .bonusMethod(bonusMethod)
                    .lastHoldShares(lastHoldShares)
                    .enableShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("enableShares")))
                    .netValueDate(netValueDate)
                    .frozenShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("frozenShares")))
                    .agencyNo(agencyNo1)
                    .fundName(fundName)
                    .agencyName(agencyName)
                    .shareRatio(shareRadio)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        log.info("中信cust_share_info 处理好的数据{}", JSON.toJSONString(result));
        return result;
    }

    //转换5
    private List<TgAccountBalanceInfoEntity> getTGAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "资金清算系统银行编码");

        //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 bankCode = remoteDataMap.get("YHDM");
            String bankCode1 = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, bankCode);
            log.info("getTGAccountBalanceInfoData_bankCode原值={},映射值={}", bankCode, bankCode1);

            String currency = remoteDataMap.get("JSBZ");
            String currency1 = MatchDataDictionaryKeyUtil.getKey(currencyDir, currency);
            log.info("getTGAccountBalanceInfoData_currency原值={},映射值={}", currency, currency1);

            String bankAcco = remoteDataMap.get("YHZH");
            accountInfoService.updateBankCodeAndCurrencyByBankAcco(bankCode1, currency1, bankAcco, trustNo, tenant.getTenantName());
            log.info("getTGAccountBalanceInfoData_updateBankCodeAndCurrencyByBankAcco bankCode={},currency={},bankAcco={}", bankCode1, currency1, bankAcco);

            log.info("updateDate={}", remoteDataMap.get("YHSJ"));

            result.add(TgAccountBalanceInfoEntity.builder()
                    .bankAcco(bankAcco)
                    .accoBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("ZHYE")))
                    .currency(currency1)
                    .updateDate(remoteDataMap.get("YHSJ"))
                    .availableBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("ZHKYYE")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换6_1
    private List<TgAccountSeqInfoEntity> getTGAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo, String fundCode) {
        //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 jdbz = remoteDataMap.get("JDBZ");
            log.info("getTGAccountSeqInfoData_jdbz={}", jdbz);
            String account = null;
            String opAccount = null;
            String accountName = null;
            String opAccountName = null;
            String bankName = null;
            String opBankName = null;

            String transferInOut = MatchDataDictionaryKeyUtil.getKey(paymentDir, jdbz);
            log.info("getTGAccountSeqInfoData_transferInOut原值={},映射值={}", jdbz, transferInOut);

            if ("2".equals(transferInOut)) {
                account = remoteDataMap.get("FKFZH");
                opAccount = remoteDataMap.get("SKFZH");
                accountName = remoteDataMap.get("FKFHM");
                opAccountName = remoteDataMap.get("SKFHM");
                bankName = remoteDataMap.get("FKHHM");
                opBankName = remoteDataMap.get("SKHHM");
            } else if ("1".equals(transferInOut)) {
                account = remoteDataMap.get("SKFZH");
                opAccount = remoteDataMap.get("FKFZH");
                accountName = remoteDataMap.get("SKFHM");
                opAccountName = remoteDataMap.get("FKFHM");
                bankName = remoteDataMap.get("SKHHM");
                opBankName = remoteDataMap.get("FKHHM");
            } else {
                log.error("queryTgAccountCurrentFlowForApi返回值jdbz为{},映射后为{}", jdbz, transferInOut);
            }


//
            String currency = remoteDataMap.get("JSBZ");
            String currency1 = MatchDataDictionaryKeyUtil.getKey(currencyDir, currency);
            log.info("getTGAccountSeqInfoData_currency原值={},映射值={}", currency, currency1);

            String dateStr = null;
            String timeStr = null;
            String fssj = remoteDataMap.get("FSSJ");
            if (StringUtils.isNotBlank(fssj)) {
                String[] dateTimeArray = fssj.split(" ");
                if (dateTimeArray.length == 2) {
                    dateStr = DateTimeTransUtil.transDateFormat("yyyy-MM-dd", "yyyyMMdd", dateTimeArray[0]);
                    timeStr = dateTimeArray[1];
                } else {
                    log.error("中信getTGAccountSeqInfoData_上游接口fssj数据异常，数据为{}", fssj);
                }
            } else {
                log.error("中信getTGAccountSeqInfoData_上游接口fssj为空导致transferDate、transferTime为空");
            }

            String seqNo = remoteDataMap.get("XY_SEQUENCE");
            log.info("getTGAccountSeqInfoData_seqNo" + seqNo);
            if (StringUtils.isNotBlank(seqNo)) {
                seqNo = seqNo.length() > 32 ? seqNo.substring(0, 32) : seqNo;
            }

            //补充fund_name
            List<AccountInfoEntity> listByFundCode = accountInfoService.getListByFundCode(fundCode, trustNo);
            if (CollectionUtils.isEmpty(listByFundCode)) {
                log.error("中信getTGAccountSeqInfoData根据Account_info补充fund_name失败，没有相应数据!");
            }
            String fundName = null;
            for (AccountInfoEntity accountInfoEntity : listByFundCode) {
                fundName = accountInfoEntity.getFundName();
                if (StringUtils.isNotBlank(fundName)) {
                    break;
                }
            }

            result.add(TgAccountSeqInfoEntity.builder()
                    .account(account)
                    .opAccount(opAccount)
                    .accountName(accountName)
                    .opAccountName(opAccountName)
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("FSJE")))
                    .currency(currency1)
                    .transferInOut(transferInOut)
                    .summary(remoteDataMap.get("ZYMC"))
                    .transferDate(dateStr)
                    .transferTime(timeStr)
                    .balance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ZHYE")))
                    .bankName(bankName)
                    .opBankName(opBankName)
                    .memo(remoteDataMap.get("POSTSCRIPT"))
                    .seqNo(seqNo)
                    .fundCode(fundCode)
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换6_2
    private List<TgAccountSeqInfoEntity> getTGAccountSeqInfoData2(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo, String fundCode) {
        //1、获取字典表数据
        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 jdbz = remoteDataMap.get("fway");
            log.info("getTGAccountSeqInfoData_jdbz={}", jdbz);
            String account = null;
            String opAccount = null;
            String bankName = null;
            String opBankName = null;
            String largePayAcco = null;
            String opLargePayAcco = null;
            String largeBankName = null;
            String opLargeBankName = null;

            String transferInOut = MatchDataDictionaryKeyUtil.getKey(paymentDir, jdbz);
            log.info("getTGAccountSeqInfoData_transferInOut原值={},映射值={}", jdbz, transferInOut);

            if ("2".equals(transferInOut)) {
                account = remoteDataMap.get("fpayerAcctCode");
                opAccount = remoteDataMap.get("fpayeeAcctCode");
                bankName = remoteDataMap.get("fpayerBank");
                opBankName = remoteDataMap.get("fpayeeBank");
                largePayAcco = remoteDataMap.get("fpayerLargePaymentNum");
                opLargePayAcco = remoteDataMap.get("fpayeeLargePaymentNum");
                largeBankName = remoteDataMap.get("fpayerLargePaymentName");
                opLargeBankName = remoteDataMap.get("fpayeeLargePaymentName");
            } else if ("1".equals(transferInOut)) {
                account = remoteDataMap.get("fpayeeAcctCode");
                opAccount = remoteDataMap.get("fpayerAcctCode");
                bankName = remoteDataMap.get("fpayeeBank");
                opBankName = remoteDataMap.get("fpayerBank");
                opLargePayAcco = remoteDataMap.get("fpayerLargePaymentNum");
                largePayAcco = remoteDataMap.get("fpayeeLargePaymentNum");
                largeBankName = remoteDataMap.get("fpayeeLargePaymentName");
                opLargeBankName = remoteDataMap.get("fpayerLargePaymentName");
            } else {
                log.error("queryTgAccountCurrentFlowForApi返回值jdbz为{},映射后为{}", jdbz, transferInOut);
            }

            String dateFormatted = DateTimeTransUtil.transDateFormat("yyyy-MM-dd", "yyyyMMdd", remoteDataMap.get("date"));

            //补充fundName字段
            List<AccountInfoEntity> listByFundCode = accountInfoService.getListByFundCode(fundCode, trustNo);
            if (CollectionUtils.isEmpty(listByFundCode)) {
                log.error("中信getTGAccountSeqInfoData2根据Account_info补充fund_name失败，没有相应数据!");
            }
            String fundName = null;
            for (AccountInfoEntity accountInfoEntity : listByFundCode) {
                fundName = accountInfoEntity.getFundName();
                if (StringUtils.isNotBlank(fundName)) {
                    break;
                }
            }

            result.add(TgAccountSeqInfoEntity.builder()
                    .account(account)
                    .opAccount(opAccount)
                    .bankName(bankName)
                    .opBankName(opBankName)
                    .largePayAcco(largePayAcco)
                    .opLargePayAcco(opLargePayAcco)
                    .largeBankName(largeBankName)
                    .opLargeBankName(opLargeBankName)
                    .transferDate(dateFormatted)
                    .transferTime("00:00:00")
                    .transferInOut(transferInOut)
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("famount")))
                    .summary(remoteDataMap.get("fsummary"))
                    .fundCode(fundCode)
                    .fundName(fundName)
                    .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 curType = remoteDataMap.get("curType");
            String currency = MatchDataDictionaryKeyUtil.getKey(currencyDir, curType);
            log.info("getTGAccountBalanceInfoData_currency原值={},映射值={}", curType, currency);

            result.add(MjAccountBalanceInfoEntity.builder()
                    .bankAcco(remoteDataMap.get("bankAcco"))
                    .currency(currency)
                    .accoBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("acctBal")))
                    .summary(remoteDataMap.get("bankNote"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换08
    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 curType = remoteDataMap.get("curType");
            String currency = MatchDataDictionaryKeyUtil.getKey(currencyDir, curType);
            log.info("getMjAccountSeqInfo_currency原值={},映射值={}", curType, currency);

            String directFlag = remoteDataMap.get("directFlag");
            String transferInOut = MatchDataDictionaryKeyUtil.getKey(paymentDir, directFlag);
            log.info("getTGAccountSeqInfoData_transferInOut原值={},映射值={}", directFlag, transferInOut);

            String occurTime = remoteDataMap.get("occurTime");
            log.info("getMjAccountSeqInfo的 occurTime={}", occurTime);
            String dateStr = null;
            String timeStr = null;
            if (StringUtils.isNotBlank(occurTime)) {
                String[] dateTimeArray = occurTime.split(" ");
                if (dateTimeArray.length == 2) {
                    dateStr = DateTimeTransUtil.transDateFormat("yyyy-MM-dd", "yyyyMMdd", dateTimeArray[0]);
                    timeStr = dateTimeArray[1];
                } else {
                    log.error("中信getMjAccountSeqInfo_上游接口occurTime数据异常，数据为{}", occurTime);
                }
            } else {
                log.error("中信getMjAccountSeqInfo_上游接口occurTime为空导致transferDate、transferTime为空");
            }

            result.add(MjAccountSeqInfoEntity.builder()
                    .transferDate(dateStr)
                    .transferTime(timeStr)
                    .fundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .account(remoteDataMap.get("bankAcco"))
                    .accountName(remoteDataMap.get("accName"))
                    .bankName(remoteDataMap.get("openBankName"))
                    .opAccount(remoteDataMap.get("othBankAcco"))
                    .opAccountName(remoteDataMap.get("othAccName"))
                    .opBankName(remoteDataMap.get("othOpenBankName"))
                    .currency(currency)
                    .transferInOut(transferInOut)
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("occurAmt")))
                    .balance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("acctBal")))
                    .seqNo(StrUtil.getSeqNoWithoutNoRandom(remoteDataMap.get("bankJour")))
                    .summary(remoteDataMap.get("bankNote"))
                    .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> sellerDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "中信证券");
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> businessDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> taLaunchDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TA_LAUNCH_FLAG_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);
        Map<String, String> confirmStatusDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CONFIRM_STATUS_SERVICE, trustNo);
        Map<String, String> shareAdjustDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SHARE_ADJUST_SERVICE, trustNo);

        //2、封装数据
        List<FundTradeInfoEntity> 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("fundCode");
            String fundName = new String();
            List<FundInfoEntity> dataByFundCode = fundInfoService.getDataByFundCode(fundCode, trustNo, tenant.getTenantName());
            log.info("getDataByFundCode_入参fundCode={}，trustNo={},出参dataByFundCode={}", fundCode, trustNo, JSON.toJSONString(dataByFundCode));
            if (!CollectionUtils.isEmpty(dataByFundCode)) {
                fundName = dataByFundCode.get(0).getFundName();
            }

            String taFlag = remoteDataMap.get("taFlag");
            String taFlag1 = MatchDataDictionaryKeyUtil.getKey(taLaunchDir, taFlag);
            log.info("getFundTradeInfo_taFlag原值={},映射值={}", taFlag, taFlag1);

            String apkind = remoteDataMap.get("apkind");
            String businessName = MatchDataDictionaryKeyUtil.getKey(businessDir, apkind);
            log.info("getFundTradeInfo_businessName原值={},映射值={}", apkind, businessName);

            String curType = remoteDataMap.get("currency");
            String currency = MatchDataDictionaryKeyUtil.getKey(currencyDir, curType);
            log.info("getFundTradeInfo_currency原值={},映射值={}", curType, currency);

            String bonusType = remoteDataMap.get("bonusType");
            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(dividendDir, bonusType);
            log.info("getTGAccountSeqInfoData_transferInOut原值={},映射值={}", bonusType, bonusMethod);

            String agencyNo = remoteDataMap.get("agencyNo");
            String agencyNo1 = MatchDataDictionaryKeyUtil.getKey(sellerDir, agencyNo);
            log.info("getFundTradeInfo_agencyNo原值={},映射值={}", agencyNo, agencyNo1);

            String adjustCause = remoteDataMap.get("adjustCause");
            String adjustCause1 = MatchDataDictionaryKeyUtil.getKey(shareAdjustDir, adjustCause);
            log.info("getFundTradeInfo_adjustCause原值={},映射值={}", adjustCause, adjustCause1);

            String ackStatus = remoteDataMap.get("ackStatus");
            String confirmStatus = MatchDataDictionaryKeyUtil.getKey(confirmStatusDir, ackStatus);
            log.info("getFundTradeInfo_confirmStatus原值={},映射值={}", ackStatus, confirmStatus);

            result.add(FundTradeInfoEntity.builder()
                    .cserialNo(remoteDataMap.get("ackNo"))
                    .requestNo(remoteDataMap.get("exRequestNo"))
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .businessName(businessName)
                    .taFlag(taFlag1)
                    .fundCode(remoteDataMap.get("fundCode"))
                    .currency(currency)
                    .applyBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("subAmt")))
                    .applyShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("subQuty")))
                    .bonusMethod(bonusMethod)
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("nav"), 4))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ackAmt")))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ackQuty")))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tradeFee")))
                    .taFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("taFee")))
                    .backFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("backFee")))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitBalance")))
                    .profitBalanceAgt(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitBalanceForAgency")))
                    .totalFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalFee")))
                    .agencyFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agencyFee")))
                    .fundFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundFee")))
                    .registFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("registFee")))
                    .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")))
                    .requestDate(remoteDataMap.get("applyDate"))
                    .confirmDate(remoteDataMap.get("ackDate"))
                    .confirmStatus(confirmStatus)
                    .agencyNo(agencyNo1)
                    .agencyName(remoteDataMap.get("agencyName"))
                    .adjustCause(adjustCause)
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换11_2
    private List<AccountInfoEntity> getAccountInfo2(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "CNAPS 银行编号");
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> accoTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.ACCOUNT_TYPE_SERVICE, trustNo);

        //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 bankCode = remoteDataMap.get("bankNo");
            String bankCode1 = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, bankCode);
            log.info("getAccountInfo2_bankCode原值={},映射值={}", bankCode, bankCode1);

            String curType = remoteDataMap.get("curType");
            String currency = MatchDataDictionaryKeyUtil.getKey(currencyDir, curType);
            log.info("getAccountInfo2_currency原值={},映射值={}", curType, currency);

            String accoType = remoteDataMap.get("accoType");
            String accoTypeCode = MatchDataDictionaryKeyUtil.getKey(accoTypeDir, accoType);
            log.info("getAccountInfo2_accoTypeCode原值={},映射值={}", accoType, accoTypeCode);

            result.add(AccountInfoEntity.builder()
                    .fundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .accoTypeCode(accoTypeCode)
                    .bankAcco(remoteDataMap.get("bankAcco"))
                    .nameInBank(remoteDataMap.get("accName"))
                    .branchBankName(remoteDataMap.get("openBankName"))
                    .bankCode(bankCode1)
                    .currency(currency)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    //转换11_3
    private List<AccountInfoEntity> getAccountInfo3(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
//        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "中信TA");

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

            result.add(AccountInfoEntity.builder()
                    .fundCode(remoteDataMap.get("pdCode"))
                    .fundName(remoteDataMap.get("pdName"))
                    .nameInBank(remoteDataMap.get("accName"))
                    .bankAcco(remoteDataMap.get("account"))
                    .branchBankName(remoteDataMap.get("bankName"))
                    .largePayAcco(remoteDataMap.get("lrgAmtNo"))
                    .accoTypeCode("ZJ001")
                    .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);

            String bankNo = remoteDataMap.get("bankNo");

            String bankCode = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, bankNo);
            log.info("getInvestorBankInfoData_bankCode原值为{},映射值为{}", bankNo, bankCode);

            result.add(InvestorBankInfoEntity.builder()
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .bankCode(bankCode)
                    .bankNo(remoteDataMap.get("bankAccount"))
                    .branchBankName(remoteDataMap.get("bankOpenName"))
                    .nameInBank(remoteDataMap.get("bankAccountName"))
                    .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> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "中信TA");
        Map<String, String> sellerDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "中信证券");
        Map<String, String> businessDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> handleDir = 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 bankNo = remoteDataMap.get("bankNo");
            String bankCode = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, bankNo);
            log.info("getInvestorBankInfoData_bankCode原值为{},映射值为{}", bankNo, bankCode);

            String agencyNo = remoteDataMap.get("agencyNo");
            String agencyNo1 = MatchDataDictionaryKeyUtil.getKey(sellerDir, agencyNo);
            log.info("getFundTradeInfo_agencyNo原值={},映射值={}", agencyNo, agencyNo1);

            String sortFlag = remoteDataMap.get("sortFlag");
            String sortFlag1 = MatchDataDictionaryKeyUtil.getKey(handleDir, sortFlag);
            log.info("getFundTradeInfo_agencyNo原值={},映射值={}", sortFlag, sortFlag1);

            String businFlag = remoteDataMap.get("businFlag");
            String businessName = MatchDataDictionaryKeyUtil.getKey(businessDir, businFlag);
            log.info("getFundTradeInfo_businessName原值={},映射值={}", businFlag, businessName);

            String requestDate = remoteDataMap.get("requestDate");
            log.info("getFundProfitInfo_requestDate={}", requestDate);
            String confirmDate = remoteDataMap.get("confirmDate");
            log.info("getFundProfitInfo_confirmDate={}", confirmDate);
            String registDate = remoteDataMap.get("registDate");
            log.info("getFundProfitInfo_registDate={}", registDate);
            String beginDate = remoteDataMap.get("beginDate");
            log.info("getFundProfitInfo_beginDate ={}", beginDate);

            String oriCserialNo = remoteDataMap.get("oriCserialNo");
            if (StringUtils.isNotBlank(oriCserialNo)) {
                oriCserialNo = oriCserialNo.length() > 32 ? oriCserialNo.substring(0, 32) : oriCserialNo;
            } else {
                oriCserialNo = RandomStrUtil.getRandomStr(32);
            }

            String fundCode = remoteDataMap.get("fundCode");
            //设置fund_name
            String fundName = getFundNameByFundCode(tenant.getTenantName(), fundCode, trustNo);

            result.add(FundProfitInfoEntity.builder()
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .agencyNo(agencyNo1)
                    .agencyName(remoteDataMap.get("agencyName"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .businessName(businessName)
                    .sortFlag(sortFlag1)
                    .requestDate(requestDate)
                    .confirmDate(confirmDate)
                    .fundCode(fundCode)
                    .shareLevel(remoteDataMap.get("shareTypeCn"))
                    .cserialNo(remoteDataMap.get("cserialNo"))
                    .registDate(registDate)
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shares")))
                    .oriDate(beginDate)
                    .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))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriBalance")))
                    .factBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factBalance")))
                    .factShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factShares")))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("bonusBalance")))
                    .oriCserialNo(oriCserialNo)
                    .holdDay(remoteDataMap.get("hold"))
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private String getFundNameByFundCode(String admin, String fundCode, String trustNo) {
        String fundName = null;
        List<FundInfoEntity> listByFundCode = fundInfoService.getListByFundCode(fundCode, trustNo);
        if (CollectionUtils.isEmpty(listByFundCode)) {
            return null;
        }
        for (FundInfoEntity fundInfoEntity : listByFundCode) {
            fundName = fundInfoEntity.getFundName();
            if (StringUtils.isNotBlank(fundName)) {
                break;
            }
        }
        if (StringUtils.isEmpty(fundName)) {
            List<FundNetValueInfoEntity> netValueInfoList = fundNetValueInfoService.getFundNameByCode(admin, fundCode, trustNo);
            if (!CollectionUtils.isEmpty(netValueInfoList)) {
                for (FundNetValueInfoEntity netValueInfo : netValueInfoList) {
                    fundName = netValueInfo.getFundName();
                    if (StringUtils.isNotBlank(fundName)) {
                        break;
                    }
                }
            }
        }
        log.info("getFundNameByFundCode_fundCode={},trustNo={},fundName={}", fundCode, trustNo, fundName);
        return fundName;
    }

    //转换15
    private List<CustShareDetailInfoEntity> getCustShareDetailInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> remoteDatas, String trustNo) {
        //1、获取字典表数据
        Map<String, String> sellerDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "中信证券");

        //2、封装数据
        List<CustShareDetailInfoEntity> 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 agencyNo1 = MatchDataDictionaryKeyUtil.getKey(sellerDir, agencyNo);
            log.info("getFundTradeInfo_agencyNo原值={},映射值={}", agencyNo, agencyNo1);

            String cserialNo = remoteDataMap.get("cserialNo");
            if (StringUtils.isNotBlank(cserialNo)) {
                cserialNo = cserialNo.length() > 32 ? cserialNo.substring(0, 32) : cserialNo;
            } else {
                cserialNo = RandomStrUtil.getRandomStr(32);
            }
            String fundCode = remoteDataMap.get("fundCode");
            //补充基金名称
            List<FundInfoEntity> listByFundCode = fundInfoService.getListByFundCode(fundCode, trustNo);
            if (CollectionUtils.isEmpty(listByFundCode)) {
                log.error("中信getCustShareDetailInfo根据fund_info表补充基金名称失败listByFundCode为空");
            }
            String fundName = null;
            for (FundInfoEntity fundInfoEntity : listByFundCode) {
                fundName = fundInfoEntity.getFundName();
                if (StringUtils.isNotBlank(fundName)) {
                    break;
                }
            }

            //补充 agency_name
            String agencyName = sellerService.queryAgencyName("中信证券", agencyNo);


            result.add(CustShareDetailInfoEntity.builder()
                    .fundAcco(remoteDataMap.get("fundAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .tradeAcco(remoteDataMap.get("tradeAcco"))
                    .agencyNo(agencyNo1)
                    .fundCode(fundCode)
                    .oriBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriBalance")))
                    .oriShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oriShares")))
                    .remainShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("remainShares")))
                    .confirmDate(remoteDataMap.get("confirmDate"))
                    .seqNo(cserialNo)
                    .fundName(fundName)
                    .agencyName(agencyName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void initTenantDataBy305Patch02(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopNum) {
        //获取token
        String token = zhongXinHttpUtil.getToken(tenant);
        if (StringUtils.isBlank(token)) {
            log.error("获取token失败，停止中信提数!");
            return;
        }
        //3
        processFundNetValueInfoData(tenant, trustNo, loopNum, token);
        log.info("中信进度：3/13");
        //4
        processCustShareInfoData(tenant, trustNo, token);
        log.info("中信进度：4/13");

        //11_3
        processAccountInfo3(tenant, trustNo, token);
        log.info("中信进度：5/13");
        //7 & 11_2
        processMJAccountBalanceInfoAndAccountInfo2(tenant, trustNo, token);
        log.info("中信进度：6/13");
        //5 & 11_1
        List<AccountInfoEntity> accountInfoEntities = processTGAccountBalanceInfoDataAndAccountInfo1(tenant, trustNo, token);
        log.info("中信进度：7/13");
        if (accountInfoEntities != null && accountInfoEntities.size() > 0) {
            //6_1  --504
            processTGAccountSeqInfo1(tenant, trustNo, token, accountInfoEntities);
            log.info("中信进度：8/13");
            //6_2
            processTGAccountSeqInfo2(tenant, trustNo, loopNum, accountInfoEntities, token);
            log.info("中信进度：9/13");

        } else {
            log.info("中信进度：由于7返回的数据为空，所以8和9无法进行");
            log.error("accountInfoEntities为空导致不进行processTGAccountSeqInfo1");
        }

        //14
        processFundProfitInfoData(tenant, trustNo, token);
        log.info("中信进度：12/13");

        //15
        processCustShareDetailInfoData(tenant, trustNo, token);
        log.info("中信进度：13/13 结束！");
    }

    private void initTenantDataBy306(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopNum) {

        //查询对应租户的邮箱权限
        List<TenantEmailAuthorizationInfoEntity> tenantEmailAuthorizationInfoEntities = tenantEmailInfoService.queryByTenantName(tenant.getTenantName(), trustNo);
        for (TenantEmailAuthorizationInfoEntity tenantEmail : tenantEmailAuthorizationInfoEntities) {
            String purpose = EmailConfigPurposeEnum.ALL.getPurpose();
            log.info("initTenantDataBy306:ALL.getPurpose={},tenantEmail.getPurpose={}", purpose, tenantEmail.getPurpose());
            if (purpose.equals(tenantEmail.getPurpose())) {
                log.info("initTenantDataBy306 邮件配置为all，跳过");
                continue;
            }
            log.info("查询到的email权限信息为{}", JSON.toJSONString(tenantEmail));
            if (!ObjectUtils.isEmpty(tenantEmail)) {
                //初始化资产合计值
                log.info("用邮件初始化资产合计值开始");
                updateTotalAsset(tenant, tenantEmail, loopNum);
                log.info("用邮件初始化资产合计值结束");

            }
        }
    }

    @Autowired
    Environment env;

    @Autowired
    MailNewUtils mailNewUtils;

    public static final String[] OFFICIAL_PROFILES = {"prod", "ty-prod"};

    public void updateTotalAsset(TenantEscrowAuthorizationInfoDto tenant, TenantEmailAuthorizationInfoEntity tenantEmail, int loopTime) {
        try {
            //获取邮件
            LocalDate localDate = LocalDate.now();
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String startTime = dateTimeFormatter.format(localDate.minusMonths((long) loopTime));
            //拿到所有邮件
            //Message[] weMessage = MailUtil.getWEMessage(tenantEmail.getEmailHost(), tenantEmail.getEmailAddress(), tenantEmail.getEmailSecret(), ZhongXinConstants.PROTOCOL);
            Message[] weMessage = MailUtil.getMessageByTenantEmail(tenantEmail);
            //过滤符合条件的邮件
//            log.info("updateTotalAsset_tenantEmail={}",JSON.toJSONString(tenantEmail));
//            Message[] filterMessage = new Message[800];
//            System.arraycopy(weMessage,weMessage.length - 2000, filterMessage,0,800);

            List<Message> messages = MailUtil.filterMessage(weMessage,
                    tenantEmail.getFromEmail(),
                    startTime,
                    tenantEmail.getEmailSubject(),
                    Boolean.TRUE);

            if(CollectionUtils.isEmpty(messages)){
                log.error("中信updateTotalAsset+邮件获取fund_value_table_data_info 数据，得到的邮件为空,授权信息为{},邮箱信息为{}",JSON.toJSONString(tenant),JSON.toJSONString(tenantEmail));
                MailNewUtils.saveMailFailureLog(tenant.getTenantName(),tenant.getTrustNo(),"中信updateTotalAsset+邮件获取fund_value_table_data_info 数据，得到的邮件为空");
            }

            //生产且没有配置附件路径 就不保存
            Profiles profiles = Profiles.of(OFFICIAL_PROFILES);
            boolean isOfficial = env.acceptsProfiles(profiles);
            String dirFilePath = tenantEmail.getDirFilePath();
            if(StringUtils.isBlank(dirFilePath) && isOfficial){
                log.info("生产环境且没有配置路径，不保存附件！");
            }else{
                if(StringUtils.isBlank(dirFilePath)){
                    dirFilePath = mailNewUtils.getDefaultAttachmentParentPath(tenantEmail);
                }
            }
            for (Message message : messages) {
                if (StringUtils.isNotBlank(dirFilePath)) {
                    mailNewUtils.saveAttachment(message, dirFilePath);
                }
            }

            //打印邮件相关信息，获取totalAsset并更新
            log.info("过滤后邮箱数量为{}",messages==null?0:messages.size());
            for (Message message : messages) {
                try {
                    log.info("updateTotalAsset 处理邮件{}",message.getSubject());
                    MailUtil re = new MailUtil((MimeMessage) message);
//                    log.error("after filter email name is:{}",message.getSubject());
                    getTotalAsset(message, tenant, re.getSubject());
                } catch (Exception e) {
                    log.error("updateTotalAsset 处理邮件异常",e);
                    MailNewUtils.saveMailFailureLog(tenant.getTenantName(),tenant.getTrustNo(),"中信updateTotalAsset 处理邮件异常");
                }
            }
        } catch (ParseException pe) {
            pe.printStackTrace();
            log.error("时间转化异常！", pe);
            MailNewUtils.saveMailFailureLog(tenant.getTenantName(),tenant.getTrustNo(),"时间转化异常！"+pe);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("更新中信totalAsset异常！", e);
            MailNewUtils.saveMailFailureLog(tenant.getTenantName(),tenant.getTrustNo(),"时间转化异常！"+e);
        }

    }


    /**
     * 处理20221229号后中信邮件不落库问题
     * @param tenant
     * @param tenantEmail
     * @param loopTime
     */
    public void updateTotalAssetV2(TenantEscrowAuthorizationInfoDto tenant, TenantEmailAuthorizationInfoEntity tenantEmail, int loopTime) throws ParseException, MessagingException, IOException {
            //获取邮件
            LocalDate localDate = LocalDate.now();
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String startTime = dateTimeFormatter.format(localDate.minusMonths((long) loopTime));
            //拿到所有邮件
            Message[] weMessage = MailUtil.getMessageByTenantEmail(tenantEmail);
            //过滤符合条件的邮件
        log.error("mail total count:{}",weMessage.length);
        Message[] filterMessage = new Message[800];
        System.arraycopy(weMessage,weMessage.length - 2000, filterMessage,0,800);
        List<Message> messageList = Arrays.asList(filterMessage);
        List<Message> svr666Emails = messageList.stream().filter(t -> {
            try {
                return t.getSubject().contains("SVR666");
            } catch (MessagingException e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
        log.error("convert mail array to list finished");
//        for (Message message : svr666Emails){
//            log.error("messageList:{}",message.getSubject());
//        }

        for (Message email : svr666Emails){
            MailUtil re = new MailUtil((MimeMessage) email);
            parseSVR666Email(email, tenant, re.getSubject());
        }
    }

    public void parseSVR666Email(Part part, TenantEscrowAuthorizationInfoDto tenant, String subject) throws MessagingException, IOException {
        //parse email
        if (part.isMimeType("multipart/*")){
            Multipart mp = (Multipart) part.getContent();
            BodyPart mPart;
            for (int i = 0; i < mp.getCount(); i++) {
                mPart = mp.getBodyPart(i);
                String fileName = mPart.getFileName();
//                log.error("parseSVR666Email fileName:{}",mPart.getFileName());
                if (fileName !=null){
                    log.error("parseSVR666Email fileName:{}",fileName);
                    fileName = MailUtil.decodeText(fileName);
                    log.error("MailUtil fileName:{}",fileName);
                    if(TY_TENANT_NAME.equals(tenant.getTenantName())){
                        fileName = new String(fileName.getBytes(),"GBK");
                        log.error("TY_TENANT_NAME fileName:{}",fileName);
                    }
                }
            }
        //update net value

        //update fund value table data info
    }
    }



    /**
     * 打印邮件
     *
     * @param messageList
     * @throws IOException
     * @throws MessagingException
     */
    public void printMailInfo(List<Message> messageList, String filePath, TenantEscrowAuthorizationInfoDto tenant) throws IOException, MessagingException {
        log.info("邮件数量:" + messageList.size());

        //到这里邮箱应该是从最近到从前的，我觉得修改数据库的话，从之前的开始更新，更新到最近比较好
        if (!CollectionUtils.isEmpty(messageList)) {
            Collections.reverse(messageList);
        }

        MailUtil re;
        Message message;
        for (int i = 0, leng = messageList.size(); i < leng; i++) {
            try {
                message = messageList.get(i);
                re = new MailUtil((MimeMessage) message);
                log.info("邮件[" + i + "]主题:" + re.getSubject());
                log.info("邮件[" + i + "]是否包含附件:" + re.isContainAttach(message));
                log.info("邮件[" + i + "]发送人地址:" + re.getFrom());
                re.getMailContent(message);
                log.info("邮件[" + i + "]正文内容:\r\n" + re.getBodyText());
                re.setAttachPath(filePath);
                re.saveAttachMent(message, null);
                getTotalAsset(message, tenant, re.getSubject());
            } catch (Exception e) {
                log.error("", e);
                continue;
            }
        }
    }

    public static final String DATE_PATTERN = "yyyyMMdd";

    public static final String START_ROW_FLAG = "科目代码";

    //中文字符
    public static final Pattern CHINESE_REGEX = Pattern.compile("[^\\u4e00-\\u9fa5]+");

    public static final String TY_TENANT_NAME = "P1000869";

    /**
     * 更新totalAsset
     *
     * @param part
     * @throws MessagingException
     * @throws IOException
     */
    public void getTotalAsset(Part part, TenantEscrowAuthorizationInfoDto tenant, String subject) throws MessagingException, IOException, ParseException {
        log.info("中信处理邮件 getTotalAsset tenant={} subject={}",JSON.toJSONString(tenant),subject);
        String fileName;
        Map<String, String> currencyDict = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, tenant.getTrustNo());//币种
        Map<String, String> typeOfFundValuationDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_FUND_VALUATION, tenant.getTrustNo());//币种
        Map<String, String> keyValue = typeOfFundValuationService.queryKeyValue();
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            BodyPart mPart;
            for (int i = 0; i < mp.getCount(); i++) {
                try{
                    mPart = mp.getBodyPart(i);
                    fileName = mPart.getFileName();
                    if ((fileName != null)) {
                        fileName = MailUtil.decodeText(fileName);
                        HSSFWorkbook hssfWorkbook = new HSSFWorkbook(mPart.getInputStream());
                        HSSFSheet sheet = hssfWorkbook.getSheetAt(0);
                        ZhongXinEmailDto zhongXinEmailDto = parseExcelZhongXin(sheet,currencyDict, typeOfFundValuationDic, keyValue);
                      //  log.error("zhongXinEmailDto:{}",zhongXinEmailDto);
                        FundNetValueInfoEntity fundNetValueInfo = zhongXinEmailDto.getFundNetValueInfoEntity();
                        fundNetValueInfo.setAdmin(tenant.getTenantName());
                        fundNetValueInfo.setTrustNo(tenant.getTrustNo());
                        fundNetValueInfo.setUpdateTime(new Date());
                        //更新资产合计
                     //   log.error("更新资产合计0112:{}",fundNetValueInfo);
                        fundNetValueInfoService.updateTotalAsset(fundNetValueInfo);
                        //更新估值表
                        List<FundValueTableDataInfoEntity> fundValueTableDataInfoList = zhongXinEmailDto.getFundValueTableDataInfoEntity();
                        List<FundValuationEntity> fundValuationEntityList = zhongXinEmailDto.getFundValuationEntityList();
                        if (!CollectionUtils.isEmpty(fundValueTableDataInfoList)){
                            for (FundValueTableDataInfoEntity entity: fundValueTableDataInfoList
                                 ) {
                                entity.setAdmin(tenant.getTenantName());
                                entity.setTrustNo(tenant.getTrustNo());
                                entity.setCreateTime(new Date());
                                entity.setUpdateTime(new Date());
                             //   log.error("更新估值表0112：{}",entity);
                            }
                        }
                        fundValueTableDataInfoService.saveData(null,fundValueTableDataInfoList);
                        if (!CollectionUtils.isEmpty(fundValuationEntityList)){
                            for (FundValuationEntity entity: fundValuationEntityList) {
                                entity.setAdmin(tenant.getTenantName());
                                entity.setTrustNo(tenant.getTrustNo());
                                entity.setCreateTime(new Date());
                                entity.setUpdateTime(new Date());
                            }
                        }
                        fundValuationService.saveData(null,fundValuationEntityList);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    public static final String YEAR_MONTH_DAY_REGEX = "((\\d{3}[1-9]|\\d{2}[1-9]\\d|\\d[1-9]\\d{2}|[1-9]\\d{3})(((0[13578]|1[02])(0[1-9]|[12]\\d|3[01]))|((0[469]|11)(0[1-9]|[12]\\d|30))|(02(0[1-9]|[1]\\d|2[0-8]))))|(((\\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229)";

    /**
     * 中信邮件解析
     * @param sheet
     * @param currencyDict
     * @return
     */
    public ZhongXinEmailDto parseExcelZhongXin(HSSFSheet sheet, Map<String, String> currencyDict, Map<String, String> typeOfFUndValuationDic,Map<String, String> keyValueDic) {
        String fundName = null;
        String fundCode = null;
        String fundValueDate = null;
        BigDecimal totalAsset = new BigDecimal(0);
        ZhongXinEmailDto result = new ZhongXinEmailDto();
        int LAST_ROW_OF_SUBJECT_CODE = getLastRowOfSubjectCode(sheet);
        List<FundValueTableDataInfoEntity> fundValueTableDataInfoEntityList = new ArrayList<>();
        List<FundValuationEntity> fundValuationEntityList = new ArrayList<>();
        Pattern yyyyMMddPattern = Pattern.compile(YEAR_MONTH_DAY_REGEX);

        for (int rowNum=0; rowNum <=sheet.getLastRowNum(); rowNum++){
            HSSFRow sheetRow = sheet.getRow(rowNum);
            if (sheetRow == null){
                continue;
            }
            for (int cellNum=0; cellNum <=sheetRow.getLastCellNum(); cellNum++){
                HSSFCell cell = sheetRow.getCell(cellNum);
                if (cell == null){
                    continue;
                }
                //获取基金编码 2种格式
                //SVR666_一村新机遇1号私募证券投资基金_资产估值表_20221230
                //SVR666_资产估值表_20221229_4级
                if (cell.getRowIndex() == 0 && cell.getColumnIndex() ==0){
                   String fundCodeTitle = getValue(cell);
                    Matcher matcher = yyyyMMddPattern.matcher(fundCodeTitle);
                    if (matcher.find()){
                        fundValueDate = matcher.group();
                    }else {
                        log.error("中信上游excel格式变化fundValueDate无法解析，fundValueDate:{}",fundCodeTitle);

                    }
                    if (fundCodeTitle.contains("_")){
                        fundCode = fundCodeTitle.trim().split("_")[0];
                   }else {
                       log.error("中信上游excel格式变化fundCode无法解析，fundCode:{}",fundCodeTitle);
                   }
                }
                //获取基金名称
                if (cell.getRowIndex() == 2 && cell.getColumnIndex() == 0){
                    String excelTitle = getValue(cell);
                    if (excelTitle.contains("__")){
                        fundName = excelTitle.trim().split("__")[1];
                    }else if (excelTitle.contains("_")){
                       fundName =  excelTitle.trim().split("_")[1];
                    }else {
                        log.error("中信上游excel格式变化fundName无法解析，fundName:{}",excelTitle);
                    }
                }
                //获取资产合计
                if ("资产合计".equals(getValue(cell))){
                    HSSFCell totalAssetCell = sheetRow.getCell(11);
                    if (totalAssetCell==null){
                        log.error("中信上游excel格式变化,资产合计无法解析，fundName:{}",fundName);
                    }else {
                        double totalAssetDouble = totalAssetCell.getNumericCellValue();
                        totalAsset = BigDecimalUtil.obj2BigDecimalTrunToZero(totalAssetDouble);
                    }
                }
                //解析估值表数据 获取A列非中文字段
                if (cell.getColumnIndex() == 0
                        && !CellType.BLANK.equals(cell.getCellTypeEnum())
                        && !"".equals(getValue(cell))
                        && cell.getRowIndex() > LAST_ROW_OF_SUBJECT_CODE){
                    String kmCode = getValue(cell);
                    String kmName = sheetRow.getCell(1)!=null? getValue(sheetRow.getCell(1)):null;
                    BigDecimal vaRate = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(3)));
                    BigDecimal amount =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(4)));
                    BigDecimal perCost =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(5)));
                    BigDecimal origCost =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(6)));
                    BigDecimal portCost =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(7)));
                    BigDecimal costBi = getBigDecimalFromCell(ExcelUtils.getStringValue( sheetRow.getCell(8)));
                    BigDecimal vapPrice =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(9)));
                    BigDecimal origMv =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(10)));
                    BigDecimal portMv =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(11)));
                    BigDecimal mvBl =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(12)));
                    BigDecimal origIv =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(13)));
                    BigDecimal portIv =getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(14)));
                    String suspension = sheetRow.getCell(15)!=null?getValue(sheetRow.getCell(15)):null;

                    FundValueTableDataInfoEntity entity = FundValueTableDataInfoEntity.builder()
                            .fundCode(fundCode)
                            .fundName(fundName)
                            .valueDate(fundValueDate)
                            .kmCode(kmCode)
                            .kmName(kmName)
                            .currency(MatchDataDictionaryKeyUtil.getKey(currencyDict, getValue(sheetRow.getCell(2))))
                            .vaRate(vaRate)
                            .amount(amount)
                            .perCost(perCost)
                            .origCost(origCost)
                            .portCost(portCost)
                            .costBi(costBi)
                            .vapPrice(vapPrice)
                            .origMv(origMv)
                            .portMv(portMv)
                            .mvBl(mvBl)
                            .origIv(origIv)
                            .portIv(portIv)
                            .suspension(suspension)
                            .build();
                  //  log.error("FundValueTableDataInfoEntity:{}",entity);
                    fundValueTableDataInfoEntityList.add(entity);
                    String targetKmCode = MatchDataDictionaryKeyUtil.getKey(typeOfFUndValuationDic, kmCode);
                    String targetKmName = MatchDataDictionaryKeyUtil.getKey(keyValueDic, targetKmCode);
                    if (StringUtils.isNotBlank(targetKmCode)) {
                        FundValuationEntity fundValuationEntity = FundValuationEntity.builder()
                                .fundCode(fundCode)
                                .fundName(fundName)
                                .valueDate(fundValueDate)
                                .kmCode(targetKmCode)
                                .kmName(targetKmName)
                                .currency(MatchDataDictionaryKeyUtil.getKey(currencyDict, getValue(sheetRow.getCell(2))))
                                .vaRate(vaRate)
                                .amount(amount)
                                .perCost(perCost)
                                .origCost(origCost)
                                .portCost(portCost)
                                .costBi(costBi)
                                .vapPrice(vapPrice)
                                .origMv(origMv)
                                .portMv(portMv)
                                .mvBl(mvBl)
                                .origIv(origIv)
                                .portIv(portIv)
                                .suspension(suspension)
                                .build();
                        fundValuationEntityList.add(fundValuationEntity);
                    }
                }
            }

        }
        FundNetValueInfoEntity fundNetValueInfo = FundNetValueInfoEntity.builder()
                .fundCode(fundCode)
                .totalAsset(totalAsset)
                .netValueDate(fundValueDate)
                .build();
        result.setFundNetValueInfoEntity(fundNetValueInfo);
        result.setFundValueTableDataInfoEntity(fundValueTableDataInfoEntityList);
        result.setFundValuationEntityList(fundValuationEntityList);
        return result;

    }

    public static String getValue(Cell hssfCell){
        if(hssfCell.getCellType()==HSSFCell.CELL_TYPE_BOOLEAN){
            return String.valueOf(hssfCell.getBooleanCellValue());
        }else if(hssfCell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC){
            return String.valueOf(hssfCell.getNumericCellValue());
        }else{
            return  String.valueOf(hssfCell.getStringCellValue());
        }
    }

    public static BigDecimal getBigDecimalFromCell(String cell){
        if (org.apache.commons.lang3.StringUtils.isEmpty(cell) || org.apache.commons.lang3.StringUtils.isBlank(cell)){
            return null;
        }
        if (cell.contains("%")){
            return BigDecimalUtil.str2BigDecimal(cell);
        }
        return new BigDecimal(cell);
    }


    /**
     * 表头-科目代码有多行时，获取最后一行的行号
     * @param sheet
     * @return
     */
    public int getLastRowOfSubjectCode(Sheet sheet){
        int lastRowOfSubjectCode=0;
        for (int rowNum=0; rowNum <=sheet.getLastRowNum(); rowNum++){
            Row sheetRow = sheet.getRow(rowNum);
            if (sheetRow == null){
                continue;
            }
            Cell cell = sheetRow.getCell(0);
            if (cell == null){
                continue;
            }
            if ("科目代码".equals(getValue(cell))){
                lastRowOfSubjectCode = cell.getRowIndex();
            }

        }
        return lastRowOfSubjectCode;
    }
    public static void getFile(InputStream is, String fileName) throws IOException {
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        try {
            in = new BufferedInputStream(is);
            out = new BufferedOutputStream(new FileOutputStream(fileName));
            int len = -1;
            byte[] b = new byte[1024];
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
        } catch (Exception e) {
            log.error("获取文件失败", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }
}
