/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.yifu.social.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TSettleDomain;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainListVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.util.BeanCopyUtils;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TPaymentBySalaryVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TPaymentVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.UpdateSocialFoundVo;
import com.yifu.cloud.plus.v1.yifu.social.constants.SocialConstants;
import com.yifu.cloud.plus.v1.yifu.social.entity.*;
import com.yifu.cloud.plus.v1.yifu.social.mapper.SysBaseSetInfoMapper;
import com.yifu.cloud.plus.v1.yifu.social.mapper.TAgentConfigMapper;
import com.yifu.cloud.plus.v1.yifu.social.mapper.TForecastLibraryMapper;
import com.yifu.cloud.plus.v1.yifu.social.mapper.TSocialFundInfoMapper;
import com.yifu.cloud.plus.v1.yifu.social.service.TForecastLibraryService;
import com.yifu.cloud.plus.v1.yifu.social.service.TIncomeDetailService;
import com.yifu.cloud.plus.v1.yifu.social.service.TIncomeService;
import com.yifu.cloud.plus.v1.yifu.social.util.DoJointSocialTask;
import com.yifu.cloud.plus.v1.yifu.social.util.ServiceUtil;
import com.yifu.cloud.plus.v1.yifu.social.vo.TForecastLibraryExportVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 预估费用
 *
 * @author hgw
 * @date 2022-07-18 16:21:40
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TForecastLibraryServiceImpl extends ServiceImpl<TForecastLibraryMapper, TForecastLibrary> implements TForecastLibraryService {

	private final TAgentConfigMapper agentConfigMapper;

	private final TSocialFundInfoMapper socialFundInfoMapper;

	private final SysBaseSetInfoMapper sysBaseSetInfoMapper;

	private final TIncomeDetailService detailService;

	private final TIncomeService incomeService;

	private final ArchivesDaprUtil archivesDaprUtil;

	private final RedisUtil redisUtil;

	@Autowired
	private DoJointSocialTask doJointSocialTask;

	/**
	 * 预估费用简单分页查询
	 *
	 * @param tForecastLibrary 预估费用
	 * @return
	 */
	@Override
	public IPage<TForecastLibrary> getTForecastLibraryPage(Page<TForecastLibrary> page, TForecastLibrary tForecastLibrary) {
		return baseMapper.getTForecastLibraryPage(page, tForecastLibrary);
	}

	/**
	 * 预估费用批量导出
	 *
	 * @param searchVo 预估费用
	 * @return
	 */
	@Override
	public void listExport(HttpServletResponse response, TForecastLibrary searchVo) {
		String fileName = "预估费用批量导出" + DateUtil.getThisTime() + CommonConstants.XLSX;
		//获取要导出的列表
		List<TForecastLibraryExportVo> list = new ArrayList<>();
		long count = noPageCountDiy(searchVo);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, "UTF-8"));
			ExcelUtil<TForecastLibraryExportVo> util = new ExcelUtil<>(TForecastLibraryExportVo.class);
			// 获取所有字典type
			Map<String,String> nameAndDicTypeMap = util.getConverterDicType();
			// 获取所有字典对应的值
			Map<String,String> redisLabelMap = (Map<String, String>) RedisUtil.redis.opsForValue().get(CacheConstants.REDIS_DICT_LABLE);
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			//EasyExcel.write(out, TEmpBadRecord.class).sheet("预估费用").doWrite(list)
			ExcelWriter excelWriter = EasyExcel.write(out, TForecastLibraryExportVo.class)
					.registerConverter(new DictConverter(nameAndDicTypeMap,redisLabelMap))
					.includeColumnFieldNames(searchVo.getExportFields()).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				WriteSheet writeSheet;
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = exportLibrary(searchVo);
					if (Common.isNotNull(list)) {
						writeSheet = EasyExcel.writerSheet("预估费用" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
					if (Common.isNotNull(list)) {
						list.clear();
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcel.writerSheet("预估费用" + index).build();
				excelWriter.write(list, writeSheet);
			}
			if (Common.isNotNull(list)) {
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		} catch (Exception e) {
			log.error("执行异常", e);
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	private List<TForecastLibraryExportVo> exportLibrary(TForecastLibrary searchVo) {
		return baseMapper.exportLibrary(searchVo);
	}

	private Long noPageCountDiy(TForecastLibrary searchVo) {
		LambdaQueryWrapper<TForecastLibrary> wrapper = buildQueryWrapper(searchVo);
		if (Common.isNotNull(searchVo.getIdList())) {
			wrapper.in(TForecastLibrary::getId, searchVo.getIdList());
		}
		return baseMapper.selectCount(wrapper);
	}

	private LambdaQueryWrapper<TForecastLibrary> buildQueryWrapper(TForecastLibrary entity) {
		LambdaQueryWrapper<TForecastLibrary> wrapper = Wrappers.lambdaQuery();
		if (Common.isNotNull(entity.getCreateTimeStart())) {
			wrapper.ge(TForecastLibrary::getCreateTime, entity.getCreateTimeStart());
		}
		if (Common.isNotNull(entity.getCreateTimeEnd())) {
			wrapper.le(TForecastLibrary::getCreateTime, entity.getCreateTimeEnd());
		}
		if (Common.isNotNull(entity.getCreateName())) {
			wrapper.eq(TForecastLibrary::getCreateName, entity.getCreateName());
		}
		return wrapper;
	}

	/**
	 * @param payMonths       缴纳月
	 * @param empIdCard       身份证
	 * @param settleDomainIds
	 * @Description: 按缴纳月生成
	 * @Author: hgw
	 * @Date: 2022/7/19 18:58
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.Boolean>
	 **/
	@Override
	public R<String> createForecastlibary(String payMonths, String empIdCard, String settleDomainIds) {
		YifuUser user = SecurityUtils.getUser();
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialListTemp = null;
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundListTemp = null;
		List<String> settleDomainIdList = Common.initStrToList(settleDomainIds, CommonConstants.COMMA_STRING);
		List<String> payMonthList = Common.initStrToList(payMonths, CommonConstants.COMMA_STRING);
		if (Common.isEmpty(payMonths) || payMonthList == null) {
			return R.failed("月份必填！");
		}
		//查询出所有符合条件的社保数据
		List<TSocialFundInfo> socialInfoList = null;
		List<TSocialFundInfo> fundList = null;
		// 查询当年所有的社保临时政策用于生成预估数据
		List<TAgentConfig> configList = agentConfigMapper.selectList(Wrappers.<TAgentConfig>query().lambda()
				.eq(TAgentConfig::getOpenFlag, CommonConstants.ZERO_INT));
		HashMap<String, TAgentConfig> agentConfigHashMap = new HashMap<>();
		if (Common.isNotNull(configList) && Common.isNotNull(payMonthList)) {
			initConfigByPayMonths(configList, payMonthList, agentConfigHashMap);
		}
		//查询出所有对应条件的预估数、社保数据、公积金数据据用于重新生成
		if (Common.isNotNull(empIdCard)) {
			librarySocialList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ZERO_STRING));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ONE_STRING)));
			libraryFundList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ZERO_STRING));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ONE_STRING)));
			socialInfoList = socialFundInfoMapper.getSocialList(empIdCard, null);
			fundList = socialFundInfoMapper.getFundList(empIdCard, null);
		} else if (settleDomainIdList != null) {
			librarySocialList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ZERO_STRING));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ONE_STRING)));

			libraryFundList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ZERO_STRING));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ONE_STRING)));
			socialInfoList = socialFundInfoMapper.getSocialList(null, settleDomainIdList);
			fundList = socialFundInfoMapper.getFundList(null, settleDomainIdList);
		}
		if (Common.isEmpty(socialInfoList)
				&& Common.isEmpty(fundList)) {
			return R.failed("无需要重新生成的数据(无数据或数据已结算不可重新生成！)");
		}
		//先删除然后重新生成
		if (Common.isNotNull(librarySocialList)) {
			baseMapper.deleteBatchIds(librarySocialList);
		}
		if (Common.isNotNull(libraryFundList)) {
			baseMapper.deleteBatchIds(libraryFundList);
		}
		// 未推送的预估明细Map
		HashMap<String, TForecastLibrary> socialHistoryMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundHistoryMap = new HashMap<>();
		// 已推送的预估明细Map
		HashMap<String, TForecastLibrary> socialPushMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundPushMap = new HashMap<>();
		// 组建基础Map
		this.getBaseMap(librarySocialList, librarySocialListTemp, libraryFundList, libraryFundListTemp
				, socialHistoryMap, fundHistoryMap, socialPushMap, fundPushMap);
		Map<String, TForecastLibrary> saveLibraryMap = new HashMap<>();
		boolean isReduceSocial = false;
		boolean isReduceFund = false;
		// 核心刷新
		R<String> coreR = this.doCore(payMonthList, socialInfoList, fundList, agentConfigHashMap, socialHistoryMap
				, fundHistoryMap, socialPushMap, fundPushMap, saveLibraryMap, isReduceSocial, isReduceFund, false);
		if (coreR != null) return coreR;
		boolean isSaveAndUpdate = false;

		TSocialFundInfo socialFundInfo;
		TSocialFundInfo socialFundInfoF;

		List<TForecastLibrary> libraryFundInfoListSocial = new ArrayList<>();
		List<TForecastLibrary> libraryFundInfoListFund = new ArrayList<>();

		Map<String,TSettleDomainSelectVo> mapSelectVo = this.getSelectVoMap();
		String redisKey = String.valueOf(UUID.randomUUID()).replaceAll("-", "") + "_incomePush";
		for (TForecastLibrary library : saveLibraryMap.values()) {
			if (Common.isEmpty(library.getSocialId()) && Common.isEmpty(library.getProvidentId())) {
				continue;
			}
			if (Common.isNotNull(library.getId())) {
				library.setUpdateBy(user.getId());
				long startTime = System.currentTimeMillis();
				baseMapper.updateForecastById(library);
				long times = System.currentTimeMillis() - startTime;
				log.info("更新一条预估耗时：" + times + "毫秒");
				isSaveAndUpdate = true;
			} else {
				if (BigDecimal.ZERO.compareTo(BigDecimalUtils.isNullToZero(library.getUnitSocialSum())) != CommonConstants.ZERO_INT
						|| BigDecimal.ZERO.compareTo(BigDecimalUtils.isNullToZero(library.getUnitFundSum())) != CommonConstants.ZERO_INT) {
					library.setCreateTime(LocalDateTime.now());
					baseMapper.insert(library);
					isSaveAndUpdate = true;
				}
			}
			//生成社保收入
			socialFundInfo = socialFundInfoMapper.selectOne(Wrappers.<TSocialFundInfo>query().lambda()
					.eq(TSocialFundInfo::getEmpIdcard, empIdCard)
					.eq(TSocialFundInfo::getSettleDomain, library.getSettleDomainId())
					.eq(TSocialFundInfo::getSocialHousehold, library.getSocialHousehold()));
			if (Common.isNotNull(socialFundInfo) && (Common.isNotNull(socialFundInfo.getSocialId())
					&& CommonConstants.FOUR_STRING.equals(socialFundInfo.getSocialStatus())
					|| CommonConstants.THREE_STRING.equals(socialFundInfo.getSocialStatus()))) {
				//办理成功生成收入
				createIncomeInfo(library,true,mapSelectVo,redisKey);
				if (CommonConstants.ZERO_INT == library.getDataPush()) {
					libraryFundInfoListSocial.add(library);
				}
			}
			//生成公积金收入
			socialFundInfoF = socialFundInfoMapper.selectOne(Wrappers.<TSocialFundInfo>query().lambda()
					.eq(TSocialFundInfo::getEmpIdcard, empIdCard)
					.eq(TSocialFundInfo::getSettleDomain, library.getSettleDomainId())
					.eq(TSocialFundInfo::getProvidentHousehold, library.getProvidentHousehold()));
			if (Common.isNotNull(socialFundInfoF) && (Common.isNotNull(socialFundInfoF.getFundId())
					&& CommonConstants.THREE_STRING.equals(socialFundInfoF.getFundStatus()))) {
				//办理成功生成收入
				createIncomeInfo(library,true,mapSelectVo,redisKey);
				if (CommonConstants.ZERO_INT == library.getDataPush()) {
					libraryFundInfoListFund.add(library);
				}
			}
		}
		//推送失败的数据重新推送
		if (Common.isNotNull(redisUtil.get(redisKey))) {
			List<TIncome> list = (List<TIncome>) redisUtil.get(redisKey);
			for (TIncome income:list) {
				doJointSocialTask.asynchronousEkpIncomeT(income);
			}
			redisUtil.remove(redisKey);
		}
		//推送社保明细
		if (Common.isNotNull(libraryFundInfoListSocial)) {
			pushForecastInfo(libraryFundInfoListSocial,true, mapSelectVo);
		}
		//推送公积金明细
		if (Common.isNotNull(libraryFundInfoListFund)) {
			pushForecastFundInfo(libraryFundInfoListFund,true, mapSelectVo);
		}
		if (isSaveAndUpdate) {
			return R.ok(null, "执行成功！");
		} else {
			return R.failed("执行失败！无需更新的数据！");
		}
	}

	/**
	 * @Description: 组装基础Map
	 * @Author: hgw
	 * @Date: 2022/7/25 19:41
	 * @return: void
	 **/
	private void getBaseMap(List<TForecastLibrary> librarySocialList, List<TForecastLibrary> librarySocialListTemp
			, List<TForecastLibrary> libraryFundList, List<TForecastLibrary> libraryFundListTemp
			, HashMap<String, TForecastLibrary> socialHistoryMap, HashMap<String, TForecastLibrary> fundHistoryMap
			, HashMap<String, TForecastLibrary> socialPushMap, HashMap<String, TForecastLibrary> fundPushMap) {
		// Map的key
		String sfMapKey;
		if (Common.isNotNull(librarySocialList)) {
			for (TForecastLibrary library : librarySocialList) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getSocialPayMonth(), library.getSocialCreateMonth(), CommonConstants.ZERO_STRING);
				socialHistoryMap.put(sfMapKey, library);
			}
		}
		if (Common.isNotNull(libraryFundList)) {
			for (TForecastLibrary library : libraryFundList) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getProvidentPayMonth(), library.getProvidentCreateMonth(), CommonConstants.ONE_STRING);
				fundHistoryMap.put(sfMapKey, library);
			}
		}

		if (Common.isNotNull(librarySocialListTemp)) {
			TForecastLibrary libraryOld;
			for (TForecastLibrary library : librarySocialListTemp) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getSocialPayMonth(), library.getSocialCreateMonth(), CommonConstants.ZERO_STRING);
				libraryOld = socialPushMap.get(sfMapKey);
				if (libraryOld != null) {
					this.getChangeAddData(libraryOld, library);
				}
				socialPushMap.put(sfMapKey, library);
				socialHistoryMap.put(sfMapKey, library);
			}
		}
		if (Common.isNotNull(libraryFundListTemp)) {
			TForecastLibrary libraryOld;
			for (TForecastLibrary library : libraryFundListTemp) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getProvidentPayMonth(), library.getProvidentCreateMonth(), CommonConstants.ONE_STRING);
				libraryOld = fundPushMap.get(sfMapKey);
				if (libraryOld != null) {
					this.getChangeAddData(libraryOld, library);
				}
				fundPushMap.put(sfMapKey, library);
				fundHistoryMap.put(sfMapKey, library);
			}
		}
	}

	/**
	 * @param type 类型：0社保，1公积金
	 * @Description:
	 * @Author: hgw
	 * @Date: 2022/8/4 9:50
	 * @return: java.lang.String
	 **/
	private String getMapKey(String empIdcard, String settleDomainId
			, String socialPayMonth, String socialCreateMonth, String type) {
		StringBuilder sfMapKey;
		sfMapKey = new StringBuilder(empIdcard);
		// 获取key
		sfMapKey.append(CommonConstants.DOWN_LINE_STRING).append(settleDomainId);
		sfMapKey.append(CommonConstants.DOWN_LINE_STRING).append(socialPayMonth);
		sfMapKey.append(CommonConstants.DOWN_LINE_STRING).append(socialCreateMonth);
		sfMapKey.append(CommonConstants.DOWN_LINE_STRING).append(type);
		return sfMapKey.toString();
	}

	/**
	 * @param libraryOld
	 * @param library
	 * @Description: 已推送的数据，社保公积金金额累加
	 * @Author: hgw
	 * @Date: 2022/7/20 11:16
	 * @return: void
	 **/
	private void getChangeAddData(TForecastLibrary libraryOld, TForecastLibrary library) {
		//单位社保
		library.setUnitPensionFee(BigDecimalUtils.safeAdd(libraryOld.getUnitPensionFee(), library.getUnitPensionFee()));
		library.setUnitMedicalFee(BigDecimalUtils.safeAdd(libraryOld.getUnitMedicalFee(), library.getUnitMedicalFee()));
		library.setUnitBirthFee(BigDecimalUtils.safeAdd(libraryOld.getUnitBirthFee(), library.getUnitBirthFee()));
		library.setUnitWorkInjuryFee(BigDecimalUtils.safeAdd(libraryOld.getUnitWorkInjuryFee(), library.getUnitWorkInjuryFee()));
		library.setUnitUnemploymentFee(BigDecimalUtils.safeAdd(libraryOld.getUnitUnemploymentFee(), library.getUnitUnemploymentFee()));
		library.setUnitBitailmentFee(BigDecimalUtils.safeAdd(libraryOld.getUnitBitailmentFee(), library.getUnitBitailmentFee()));
		library.setUnitInterestFee(BigDecimalUtils.safeAdd(libraryOld.getUnitInterestFee(), library.getUnitInterestFee()));
		library.setUnitSocialSum(BigDecimalUtils.safeAdd(libraryOld.getUnitSocialSum(), library.getUnitSocialSum()));
		// 个人社保
		library.setPersonalPensionFee(BigDecimalUtils.safeAdd(libraryOld.getPersonalPensionFee(), library.getPersonalPensionFee()));
		library.setPersonalMedicalFee(BigDecimalUtils.safeAdd(libraryOld.getPersonalMedicalFee(), library.getPersonalMedicalFee()));
		library.setPersonalUnemploymentFee(BigDecimalUtils.safeAdd(libraryOld.getPersonalUnemploymentFee(), library.getPersonalUnemploymentFee()));
		library.setPersonalInterestFee(BigDecimalUtils.safeAdd(libraryOld.getPersonalInterestFee(), library.getPersonalInterestFee()));
		library.setPersonalBigailmentFee(BigDecimalUtils.safeAdd(libraryOld.getPersonalBigailmentFee(), library.getPersonalBigailmentFee()));
		library.setPersonalSocialSum(BigDecimalUtils.safeAdd(libraryOld.getPersonalSocialSum(), library.getPersonalSocialSum()));
		// 单位公积金
		library.setUnitFundSum(BigDecimalUtils.safeAdd(libraryOld.getUnitFundSum(), library.getUnitFundSum()));
		// 个人公积金
		library.setPersonalFundSum(BigDecimalUtils.safeAdd(libraryOld.getPersonalFundSum(), library.getPersonalFundSum()));
	}

	/**
	 * @param libraryNew
	 * @param libraryOld
	 * @Description: 获取变更的部分
	 * @Author: hgw
	 * @Date: 2022/7/20 11:29
	 * @return: void
	 **/
	private void getChangeReduceData(TForecastLibrary libraryNew, TForecastLibrary libraryOld) {

		//单位社保
		libraryNew.setUnitPensionFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitPensionFee(), libraryOld.getUnitPensionFee()));
		libraryNew.setUnitMedicalFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitMedicalFee(), libraryOld.getUnitMedicalFee()));
		libraryNew.setUnitBirthFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitBirthFee(), libraryOld.getUnitBirthFee()));
		libraryNew.setUnitWorkInjuryFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitWorkInjuryFee(), libraryOld.getUnitWorkInjuryFee()));
		libraryNew.setUnitUnemploymentFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitUnemploymentFee(), libraryOld.getUnitUnemploymentFee()));
		libraryNew.setUnitBitailmentFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitBitailmentFee(), libraryOld.getUnitBitailmentFee()));
		libraryNew.setUnitInterestFee(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitInterestFee(), libraryOld.getUnitInterestFee()));
		libraryNew.setUnitSocialSum(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitSocialSum(), libraryOld.getUnitSocialSum()));
		// 个人社保
		libraryNew.setPersonalPensionFee(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalPensionFee(), libraryOld.getPersonalPensionFee()));
		libraryNew.setPersonalMedicalFee(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalMedicalFee(), libraryOld.getPersonalMedicalFee()));
		libraryNew.setPersonalUnemploymentFee(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalUnemploymentFee(), libraryOld.getPersonalUnemploymentFee()));
		libraryNew.setPersonalInterestFee(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalInterestFee(), libraryOld.getPersonalInterestFee()));
		libraryNew.setPersonalBigailmentFee(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalBigailmentFee(), libraryOld.getPersonalBigailmentFee()));
		libraryNew.setPersonalSocialSum(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalSocialSum(), libraryOld.getPersonalSocialSum()));
		// 单位公积金
		libraryNew.setUnitFundSum(BigDecimalUtils.safeSubtract(false, libraryNew.getUnitFundSum(), libraryOld.getUnitFundSum()));
		// 个人公积金
		libraryNew.setPersonalFundSum(BigDecimalUtils.safeSubtract(false, libraryNew.getPersonalFundSum(), libraryOld.getPersonalFundSum()));
		libraryNew.setSumAll(BigDecimalUtils.safeSubtract(false, libraryNew.getSumAll(), libraryOld.getSumAll()));
	}


	private void initConfigByPayMonths(List<TAgentConfig> configList, Collection<String> payMonths, HashMap<String, TAgentConfig> agentConfigHashMap) {
		for (TAgentConfig config : configList) {
			for (String payMonth : payMonths) {
				if (ServiceUtil.convertStringToInt(config.getStartMonth()) <= ServiceUtil.convertStringToInt(payMonth)
						&& ServiceUtil.convertStringToInt(config.getEndMonth()) >= ServiceUtil.convertStringToInt(payMonth)) {
					if (Common.isNotNull(config.getCity())) {
						agentConfigHashMap.put(config.getProvince() + CommonConstants.DOWN_LINE_STRING + config.getCity() + CommonConstants.DOWN_LINE_STRING + payMonth + CommonConstants.DOWN_LINE_STRING + config.getTarget(), config);
					} else {
						agentConfigHashMap.put(config.getProvince() + CommonConstants.DOWN_LINE_STRING + "null" + CommonConstants.DOWN_LINE_STRING + payMonth + CommonConstants.DOWN_LINE_STRING + config.getTarget(), config);
					}
				}
			}
		}
	}

	/**
	 * @Description: 获取可补缴的最大月份
	 * @Author: hgw
	 * @Date: 2020/10/10 15:26
	 * @return: java.lang.Integer
	 **/
	private Integer getOverpayMonth(TSocialFundInfo tSocialInfo) {
		Integer overpayMonth = null;
		if (CommonConstants.ZERO_STRING.equals(tSocialInfo.getCanOverpay())) {
			//补缴是否含当月: 含当月
			if (CommonConstants.ZERO_STRING.equals(tSocialInfo.getHaveThisMonth())) {
				overpayMonth = Integer.parseInt(DateUtil.getYearAndMonth(tSocialInfo.getCreateTime(), 0));
				//补缴是否含当月: 不含含当月
			} else {
				overpayMonth = Integer.parseInt(DateUtil.getYearAndMonth(tSocialInfo.getCreateTime(), CommonConstants.ONE_INT_NEGATE));
			}
		}
		return overpayMonth;
	}

	private void initSocialLibary(String diffType, String payMonth, Map<String, TForecastLibrary> saveLibraryMap
			, TSocialFundInfo tSocialInfo, boolean isReduceFund, HashMap<String, TAgentConfig> agentConfigMap
			, String sfMapKey, TForecastLibrary historyLibrary, boolean isOnly) {
		TForecastLibrary lib = new TForecastLibrary();
		lib.setSalarySocialFlag(CommonConstants.ZERO_STRING);
		lib.setDataPush(CommonConstants.ZERO_INT);
		lib.setSocialHousehold(tSocialInfo.getSocialHousehold());
		lib.setSocialHouseholdName(tSocialInfo.getSocialHouseholdName());
		lib.setDiffType(diffType);
		lib.setDataType(CommonConstants.ZERO_INT);
		lib.setEmpId(tSocialInfo.getEmpId());
		lib.setEmpIdcard(tSocialInfo.getEmpIdcard());
		lib.setEmpName(tSocialInfo.getEmpName());
		lib.setEmpNo(tSocialInfo.getEmpNo());
		lib.setEmpNatrue(tSocialInfo.getEmpType());
		lib.setSocialCreateMonth(ServiceUtil.initCreateMonth(tSocialInfo.getCreateTime(), payMonth));
		//lib.setProvidentCreateMonth(lib.getSocialCreateMonth())
		lib.setSocialPayMonth(payMonth);
		//同时处理公积金日期
		//lib.setProvidentPayMonth(payMonth)
		lib.setSocialProvince(tSocialInfo.getSocialProvince());
		lib.setSocialCity(tSocialInfo.getSocialCity());
		lib.setSocialTown(tSocialInfo.getSocialTown());
		lib.setSocialId(tSocialInfo.getId());
		lib.setUnitId(tSocialInfo.getUnitId());
		lib.setSettleDomainId(tSocialInfo.getSettleDomain());
		lib.setUnitName(tSocialInfo.getUnitName());
		lib.setDeptName(tSocialInfo.getSettleDomainName());
		lib.setDeptNo(tSocialInfo.getSettleDomainCode());

		//判断是否允许补缴 是否可补缴 0：是
		Integer monthT = this.getOverpayMonth(tSocialInfo);
		//初始化社保派减状态  按派减时间派单对应缴纳月是否已派减社保
		boolean isReduceSocial;
		if (null != tSocialInfo.getSocialReduceDate()) {
			isReduceSocial = Integer.parseInt(payMonth) >= DateUtil.formatDateInt(tSocialInfo.getSocialReduceDate());
		} else {
			isReduceSocial = false;
		}
		lib = initForecastLibrary(lib, tSocialInfo, null, monthT, isReduceFund, isReduceSocial, agentConfigMap
				, historyLibrary, isOnly);
		saveLibraryMap.put(sfMapKey, lib);
	}

	// historyLibrary_历史比例（暂时未用到）
	private TForecastLibrary initForecastLibrary(TForecastLibrary library
			, TSocialFundInfo socialInfo, TSocialFundInfo fund, Integer month, boolean isReduceFund
			, boolean isReduceSocial, HashMap<String, TAgentConfig> agentConfigMap
			, TForecastLibrary historyLibrary, boolean isOnly) {
		if (null != socialInfo && !isReduceSocial) {
			library.setSocialId(socialInfo.getId());
			library.setUnitBitailmentFee(BigDecimal.ZERO);
			library.setPersonalBigailmentFee(BigDecimal.ZERO);

			// 处理大病以外的金额 临时政策影响生成的预估数据（2020-08-03新增逻辑）
			// 获取省市临时政策  0 单位  1  个人  2 全部
			TAgentConfig configAll = getAgentConfig(agentConfigMap, socialInfo, library.getSocialPayMonth(), CommonConstants.TWO_STRING);
			TAgentConfig configUnit = getAgentConfig(agentConfigMap, socialInfo, library.getSocialPayMonth(), CommonConstants.ZERO_STRING);
			TAgentConfig configPersonal = getAgentConfig(agentConfigMap, socialInfo, library.getSocialPayMonth(), CommonConstants.ONE_STRING);

			// 初始化大病：
			this.initLibraryBigMoneyBySocial(library, socialInfo);

			initUnitAndPersonalLibrary(library, socialInfo, historyLibrary, isOnly);
			if (null != configAll || null != configUnit || null != configPersonal) {
				if (null != configPersonal) {
					initPersonalLibByConfig(library, configPersonal);
				} else if (null != configAll) {
					initPersonalLibByConfig(library, configAll);
				}
				if (null != configUnit) {
					initUnitLibByConfig(library, configUnit);
				} else if (null != configAll) {
					initUnitLibByConfig(library, configAll);
				}
			}

			// 补缴处理  不需要补缴的险种置为零
			if (null != month && Integer.parseInt(library.getSocialPayMonth()) <= month) {
				// 是否补缴大病：0是 1否
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsuranceBigailment())) {
					library.setUnitBitailmentFee(BigDecimal.ZERO);
					library.setPersonalBigailmentFee(BigDecimal.ZERO);
				}
				// 是否补缴养老：0是1 否
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsurancePension())) {
					library.setUnitPensionFee(BigDecimal.ZERO);
					library.setPersonalPensionFee(BigDecimal.ZERO);
				}
				// 是否补缴医疗：0是1否
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsuranceMedical())) {
					library.setUnitMedicalFee(BigDecimal.ZERO);
					library.setPersonalMedicalFee(BigDecimal.ZERO);
				}
				// 是否补缴生育
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsuranceBirth())) {
					library.setUnitBirthFee(BigDecimal.ZERO);
				}
				// 是否补缴工伤
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsuranceInjury())) {
					library.setUnitWorkInjuryFee(BigDecimal.ZERO);
				}
				// 是否补缴失业
				if (CommonConstants.ONE_STRING.equals(socialInfo.getInsuranceUnemployment())) {
					library.setUnitUnemploymentFee(BigDecimal.ZERO);
					library.setPersonalUnemploymentFee(BigDecimal.ZERO);
				}
			}
			library.setPersonalSocialSum(BigDecimalUtils.safeAdd(
					library.getPersonalBigailmentFee(),
					library.getPersonalPensionFee(),
					library.getPersonalMedicalFee(),
					library.getPersonalInterestFee(),
					library.getPersonalUnemploymentFee()));
			library.setUnitSocialSum(BigDecimalUtils.safeAdd(
					library.getUnitPensionFee(),
					library.getUnitMedicalFee(),
					library.getUnitBirthFee(),
					library.getUnitWorkInjuryFee(),
					library.getUnitUnemploymentFee(),
					library.getUnitInterestFee(),
					library.getUnitBitailmentFee()));
		} else if (isReduceSocial) {
			library.setUnitSocialSum(BigDecimal.ZERO);
			library.setPersonalSocialSum(BigDecimal.ZERO);
			library.setUnitPensionFee(BigDecimal.ZERO);
			library.setUnitMedicalFee(BigDecimal.ZERO);
			library.setUnitBirthFee(BigDecimal.ZERO);
			library.setUnitWorkInjuryFee(BigDecimal.ZERO);
			library.setUnitUnemploymentFee(BigDecimal.ZERO);
			library.setUnitBitailmentFee(BigDecimal.ZERO);
			library.setPersonalPensionFee(BigDecimal.ZERO);
			library.setPersonalMedicalFee(BigDecimal.ZERO);
			library.setPersonalUnemploymentFee(BigDecimal.ZERO);
			library.setPersonalBigailmentFee(BigDecimal.ZERO);
			library.setSocialId(null);
			library.setSocialProvince(null);
			library.setSocialCity(null);
			library.setSocialTown(null);
		}
		if (null != fund && !isReduceFund) {
			library.setProvidentId(fund.getId());
			library.setUnitFundBase(fund.getUnitProvidengCardinal());
			library.setPersonalFundBase(fund.getPersonalProvidentCardinal());

			library.setUnitFundProp(fund.getUnitProvidentPer());
			library.setPersonalFundProp(fund.getPersonalProvidentPer());

			library.setPersonalFundSum(fund.getPersonalFundSum());
			library.setUnitFundSum(fund.getUnitFundSum());
		} else if (isReduceFund) {
			library.setProvidentId(null);
			library.setUnitFundSum(BigDecimal.ZERO);
			library.setPersonalFundSum(BigDecimal.ZERO);
			library.setFundProvince(null);
			library.setFundCity(null);
			library.setFundTown(null);
		}
		library.setSumAll(BigDecimalUtils.safeAdd(library.getUnitSocialSum(), library.getPersonalSocialSum(), library.getUnitFundSum(), library.getPersonalFundSum()));
		return library;
	}

	/**
	 * 获取社保临时政策 优先地市政策 无地市政策 按省政策，即无省也无市的政策 正常生成
	 *
	 * @param agentConfigList
	 * @param tSocialInfo
	 * @return
	 * @Author fxj
	 * @Date 2020-08-03
	 **/
	private TAgentConfig getAgentConfig(HashMap<String, TAgentConfig> agentConfigList
			, TSocialFundInfo tSocialInfo, String payMonth, String target) {
		if (Common.isNotNull(agentConfigList) && null != tSocialInfo && Common.isNotNull(payMonth)) {
			TAgentConfig temp = agentConfigList.get(tSocialInfo.getSocialProvince()
					+ CommonConstants.DOWN_LINE_STRING
					+ tSocialInfo.getSocialCity()
					+ CommonConstants.DOWN_LINE_STRING
					+ payMonth
					+ CommonConstants.DOWN_LINE_STRING
					+ target);
			if (null != temp) {
				return temp;
			} else {
				return agentConfigList.get(tSocialInfo.getSocialProvince()
						+ CommonConstants.DOWN_LINE_STRING
						+ "null"
						+ CommonConstants.DOWN_LINE_STRING
						+ payMonth
						+ CommonConstants.DOWN_LINE_STRING
						+ target);
			}

		}
		return null;
	}

	/**
	 * @param library    预估库
	 * @param socialInfo 社保
	 * @Description: 从社保获取大病
	 * @Author: hgw
	 * @Date: 2020/11/25 15:51
	 * @return: void
	 **/
	private void initLibraryBigMoneyBySocial(TForecastLibrary library, TSocialFundInfo socialInfo) {
		int libraryPayMonth = Integer.parseInt(library.getSocialPayMonth());
		if (socialInfo.getBigailmentStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getBigailmentStart())) {
			if (CommonConstants.ONE_STRING.equals(socialInfo.getPaymentType())) {
				// 自定义类型大病随基数配置变化：0不随配置 1随配置 2.单位大病随配置 3个人大病随配置
				// 2022-7-20 11:46:32 与房工沟通，派单没这个逻辑，所以都是随配置直接计算
				// 直接计算单位大病
				library.setUnitBitailmentFee(socialInfo.getUnitBigailmentMoney());
				library.setPersonalBigailmentFee(socialInfo.getPersonalBigailmentMoney());
				// 非自定义，从社保基数配置取信息
			} else {
				// 大病处理: 0 收取  按派单的社保里的基数和比例来
				if (CommonConstants.ZERO_STRING.equals(socialInfo.getIsIllness())) {
					// 大病收取方式  0.按年  判断当前月份是否收取大病     按年收大病起缴月份收取一次，非当年的 大病 按实际收取月份收取大病金额

					this.setBigMoney(library, socialInfo, socialInfo.getPaymentType());
					// 大病处理: 1 不收取
				} else {
					library.setUnitBitailmentFee(BigDecimal.ZERO);
					library.setPersonalBigailmentFee(BigDecimal.ZERO);
				}
			}
		}
	}

	/**
	 * 初始化单位和个人的预估数据
	 *
	 * @param library
	 * @param socialInfo
	 * @return
	 * @Author fxj
	 * @Date 2020-08-03
	 **/
	private void initUnitAndPersonalLibrary(TForecastLibrary library, TSocialFundInfo socialInfo
			, TForecastLibrary historyLibrary, boolean isOnly) {
		initLibrayOfPersonal(library, socialInfo, historyLibrary, isOnly);
		initLibraryOfUnit(library, socialInfo, historyLibrary, isOnly);
	}

	private void initLibrayOfPersonal(TForecastLibrary library, TSocialFundInfo socialInfo
			, TForecastLibrary historyLibrary, boolean isOnly) {
		// 个人养老基数
		BigDecimal personalPersionBase;
		// 个人医疗基数
		BigDecimal personalMedicalBase;
		// 个人失业基数
		BigDecimal personalUnemploymentBase;
		// 个人养老比例
		BigDecimal personalPersionPro = BigDecimal.ZERO;
		// 个人医疗比例
		BigDecimal personalMedicalPro = BigDecimal.ZERO;
		// 个人失业比例
		BigDecimal personalUnemploymentPro = BigDecimal.ZERO;
		// 个人养老金额
		BigDecimal personalPersionMoney;
		// 个人医疗金额
		BigDecimal personalMedicalMoney;
		// 个人失业金额
		BigDecimal personalUnemploymentMoney;
		if (socialInfo != null) {
			personalPersionBase = socialInfo.getPersonalPensionCardinal();
			personalMedicalBase = socialInfo.getPersonalMedicalCardinal();
			personalUnemploymentBase = socialInfo.getPersonalUnemploymentCardinal();
			if (historyLibrary != null) {
				if (historyLibrary.getUnitPersionPro() != null) {
					personalPersionPro = historyLibrary.getPersonalPersionPro();
					personalMedicalPro = historyLibrary.getPersonalMedicalPro();
					personalUnemploymentPro = historyLibrary.getPersonalUnemploymentPro();
				}
			} else {
				personalPersionPro = socialInfo.getPersonalPensionPer();
				personalMedicalPro = socialInfo.getPersonalMedicalPer();
				personalUnemploymentPro = socialInfo.getPersonalUnemploymentPer();
			}
			personalPersionMoney = BigDecimalUtils.safeMultiply(personalPersionBase, personalPersionPro,
					CommonConstants.ONE_OF_PERCENT);
			personalMedicalMoney = BigDecimalUtils.safeMultiply(personalMedicalBase, personalMedicalPro,
					CommonConstants.ONE_OF_PERCENT);
			personalUnemploymentMoney = BigDecimalUtils.safeMultiply(personalUnemploymentBase, personalUnemploymentPro,
					CommonConstants.ONE_OF_PERCENT);

			// 户调基不看起缴时间
			if (isOnly) {
				library.setPersonalPensionBase(personalPersionBase);
				library.setPersonalPersionPro(personalPersionPro);
				library.setPersonalPensionFee(personalPersionMoney);
				library.setPersonalMedicalBase(personalMedicalBase);
				library.setPersonalMedicalPro(personalMedicalPro);
				library.setPersonalMedicalFee(personalMedicalMoney);
				library.setPersonalUnemploymentBase(personalUnemploymentBase);
				library.setPersonalUnemploymentPro(personalUnemploymentPro);
				library.setPersonalUnemploymentFee(personalUnemploymentMoney);
			} else if (library.getSocialPayMonth() != null) {
				int libraryPayMonth = Integer.parseInt(library.getSocialPayMonth());
				if (socialInfo.getPensionStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getPensionStart())) {
					library.setPersonalPensionBase(personalPersionBase);
					library.setPersonalPersionPro(personalPersionPro);
					library.setPersonalPensionFee(personalPersionMoney);
				}
				if (socialInfo.getMedicalStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getMedicalStart())) {
					library.setPersonalMedicalBase(personalMedicalBase);
					library.setPersonalMedicalPro(personalMedicalPro);
					library.setPersonalMedicalFee(personalMedicalMoney);
				}
				if (socialInfo.getUnemployStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getUnemployStart())) {
					library.setPersonalUnemploymentBase(personalUnemploymentBase);
					library.setPersonalUnemploymentPro(personalUnemploymentPro);
					library.setPersonalUnemploymentFee(personalUnemploymentMoney);
				}
			}
		}

	}

	private void initLibraryOfUnit(TForecastLibrary library, TSocialFundInfo socialInfo
			, TForecastLibrary historyLibrary, boolean isOnly) {
		// 单位养老基数
		BigDecimal unitPersionBase;
		// 单位医疗基数
		BigDecimal unitMedicalBase;
		// 单位失业基数
		BigDecimal unitUnemploymentBase;
		// 单位工伤基数
		BigDecimal unitInjuryBase;
		// 单位生育基数
		BigDecimal unitBirthBase;

		// 单位养老比例
		BigDecimal unitPersionPro = BigDecimal.ZERO;
		// 单位医疗比例
		BigDecimal unitMedicalPro = BigDecimal.ZERO;
		// 单位失业比例
		BigDecimal unitUnemploymentPro = BigDecimal.ZERO;
		// 单位工伤比例
		BigDecimal unitInjuryPro = BigDecimal.ZERO;
		// 单位生育比例
		BigDecimal unitBirthPro = BigDecimal.ZERO;

		// 单位养老金额
		BigDecimal unitPersionMoney;
		// 单位医疗金额
		BigDecimal unitMedicalMoney;
		// 单位失业金额
		BigDecimal unitUnemploymentMoney;
		// 单位工伤金额
		BigDecimal unitInjuryMoney;
		// 单位生育金额
		BigDecimal unitBirthMoney;

		if (socialInfo != null) {
			unitPersionBase = socialInfo.getUnitPensionCardinal();
			unitMedicalBase = socialInfo.getUnitMedicalCardinal();
			unitUnemploymentBase = socialInfo.getUnitUnemploymentCardinal();
			unitInjuryBase = socialInfo.getUnitWorkInjuryCardinal();
			unitBirthBase = socialInfo.getUnitBirthCardinal();
			if (historyLibrary != null) {
				if (historyLibrary.getUnitPersionPro() != null) {
					unitPersionPro = historyLibrary.getUnitPersionPro();
					unitMedicalPro = historyLibrary.getUnitMedicalPro();
					unitUnemploymentPro = historyLibrary.getUnitUnemploymentPro();
					unitInjuryPro = historyLibrary.getUnitInjuryPro();
					unitBirthPro = historyLibrary.getUnitBirthPro();
				} else if (historyLibrary.getUnitInjuryPro() != null) {
					unitInjuryPro = historyLibrary.getUnitInjuryPro();
				}
			} else {
				unitPersionPro = socialInfo.getUnitPensionPer();
				unitMedicalPro = socialInfo.getUnitMedicalPer();
				unitUnemploymentPro = socialInfo.getUnitUnemploymentPer();
				unitInjuryPro = socialInfo.getUnitWorkUnjuryPer();
				unitBirthPro = socialInfo.getUnitBirthPer();
			}
			unitPersionMoney = BigDecimalUtils.safeMultiply(unitPersionBase, unitPersionPro,
					CommonConstants.ONE_OF_PERCENT);
			unitMedicalMoney = BigDecimalUtils.safeMultiply(unitMedicalBase, unitMedicalPro,
					CommonConstants.ONE_OF_PERCENT);
			unitUnemploymentMoney = BigDecimalUtils.safeMultiply(unitUnemploymentBase, unitUnemploymentPro,
					CommonConstants.ONE_OF_PERCENT);
			unitInjuryMoney = BigDecimalUtils.safeMultiply(unitInjuryBase, unitInjuryPro,
					CommonConstants.ONE_OF_PERCENT);
			unitBirthMoney = BigDecimalUtils.safeMultiply(unitBirthBase, unitBirthPro,
					CommonConstants.ONE_OF_PERCENT);

			// 户调基不看起缴时间
			if (isOnly) {
				library.setUnitPensionBase(unitPersionBase);
				library.setUnitPersionPro(unitPersionPro);
				library.setUnitPensionFee(unitPersionMoney);
				library.setUnitMedicalBase(unitMedicalBase);
				library.setUnitMedicalPro(unitMedicalPro);
				library.setUnitMedicalFee(unitMedicalMoney);
				library.setUnitUnemploymentBase(unitUnemploymentBase);
				library.setUnitUnemploymentPro(unitUnemploymentPro);
				library.setUnitUnemploymentFee(unitUnemploymentMoney);
				library.setUnitInjuryBase(unitInjuryBase);
				library.setUnitInjuryPro(unitInjuryPro);
				library.setUnitWorkInjuryFee(unitInjuryMoney);
				library.setUnitBirthBase(unitBirthBase);
				library.setUnitBirthPro(unitBirthPro);
				library.setUnitBirthFee(unitBirthMoney);
			} else if (library.getSocialPayMonth() != null) {
				int libraryPayMonth = Integer.parseInt(library.getSocialPayMonth());
				if (socialInfo.getPensionStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getPensionStart())) {
					library.setUnitPensionBase(unitPersionBase);
					library.setUnitPersionPro(unitPersionPro);
					library.setUnitPensionFee(unitPersionMoney);
				}
				if (socialInfo.getMedicalStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getMedicalStart())) {
					library.setUnitMedicalBase(unitMedicalBase);
					library.setUnitMedicalPro(unitMedicalPro);
					library.setUnitMedicalFee(unitMedicalMoney);
				}
				if (socialInfo.getUnemployStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getUnemployStart())) {
					library.setUnitUnemploymentBase(unitUnemploymentBase);
					library.setUnitUnemploymentPro(unitUnemploymentPro);
					library.setUnitUnemploymentFee(unitUnemploymentMoney);
				}
				if (socialInfo.getWorkInjuryStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getWorkInjuryStart())) {
					library.setUnitInjuryBase(unitInjuryBase);
					library.setUnitInjuryPro(unitInjuryPro);
					library.setUnitWorkInjuryFee(unitInjuryMoney);
				}
				if (socialInfo.getBirthStart() != null && libraryPayMonth >= DateUtil.formatDateInt(socialInfo.getBirthStart())) {
					library.setUnitBirthBase(unitBirthBase);
					library.setUnitBirthPro(unitBirthPro);
					library.setUnitBirthFee(unitBirthMoney);
				}
			}
		}
	}

	/**
	 * 按临时政策初始化个人预估数据
	 *
	 * @param library
	 * @param agentConfig
	 * @return
	 * @Author fxj
	 * @Date 2020-08-03
	 **/
	private void initPersonalLibByConfig(TForecastLibrary library, TAgentConfig agentConfig) {
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getMedical())) {
			library.setPersonalMedicalFee(BigDecimalUtils.safeMultiply(library.getPersonalMedicalFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getMedical())) {
			library.setPersonalMedicalFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getUnemployed())) {
			library.setPersonalUnemploymentFee(BigDecimalUtils.safeMultiply(library.getPersonalUnemploymentFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getUnemployed())) {
			library.setPersonalUnemploymentFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getPension())) {
			library.setPersonalPensionFee(BigDecimalUtils.safeMultiply(library.getPersonalPensionFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getPension())) {
			library.setPersonalPensionFee(BigDecimal.ZERO);
		}
	}

	/**
	 * 按临时政策初始化单位社保预估数据
	 *
	 * @param library
	 * @param agentConfig
	 * @return
	 * @Author fxj
	 * @Date 2020-08-03
	 **/
	private void initUnitLibByConfig(TForecastLibrary library, TAgentConfig agentConfig) {
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getPension())) {
			library.setUnitPensionFee(BigDecimalUtils.safeMultiply(library.getUnitPensionFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getPension())) {
			library.setUnitPensionFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getMedical())) {
			library.setUnitMedicalFee(BigDecimalUtils.safeMultiply(library.getUnitMedicalFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getMedical())) {
			library.setUnitMedicalFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getBear())) {
			library.setUnitBirthFee(BigDecimalUtils.safeMultiply(library.getUnitBirthFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getBear())) {
			library.setUnitBirthFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getInjury())) {
			library.setUnitWorkInjuryFee(BigDecimalUtils.safeMultiply(library.getUnitWorkInjuryFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getInjury())) {
			library.setUnitWorkInjuryFee(BigDecimal.ZERO);
		}
		// 0 全额 1 减半  2 不收
		if (CommonConstants.ONE_STRING.equals(agentConfig.getUnemployed())) {
			library.setUnitUnemploymentFee(BigDecimalUtils.safeMultiply(library.getUnitUnemploymentFee()
					, CommonConstants.HALF_OF_ONE));
		} else if (CommonConstants.TWO_STRING.equals(agentConfig.getUnemployed())) {
			library.setUnitUnemploymentFee(BigDecimal.ZERO);
		}
	}

	/**
	 * @param library     预估库
	 * @param socialInfo  社保
	 * @param paymentType 0最低缴纳、1自定义、2最高缴纳
	 * @Description: 塞大病金额
	 * @Author: hgw
	 * @Date: 2020/11/25 15:51
	 * @return: void
	 **/
	private void setBigMoney(TForecastLibrary library, TSocialFundInfo socialInfo
			, String paymentType) {
		if (CommonConstants.ZERO_STRING.equals(socialInfo.getCollectType())) {
			if ((null != socialInfo.getCollectMoth()
					&& Integer.parseInt(library.getSocialPayMonth().substring(4, 6)) == socialInfo.getCollectMoth()
					&& Integer.parseInt(library.getSocialPayMonth().substring(0, 4)) != socialInfo.getBigailmentStart().getYear())
					|| library.getSocialPayMonth().equals(DateUtil.formatDatePatten(socialInfo.getBigailmentStart(), null))) {
				//  大病取值方式：0按定值
				library.setUnitBitailmentFee(socialInfo.getUnitBigailmentMoney());
				library.setPersonalBigailmentFee(socialInfo.getPersonalBigailmentMoney());
				//第一次收取费用逻辑：新员工入职是否收费处理逻辑：先按第一次不收取费用 (只针对按年收)
				if (library.getSocialPayMonth().equals(DateUtil.formatDatePatten(socialInfo.getBigailmentStart(), null))
						&& CommonConstants.ONE_STRING.equals(socialInfo.getIsChargePersonal())) {
					library.setUnitBitailmentFee(BigDecimal.ZERO);
					library.setPersonalBigailmentFee(BigDecimal.ZERO);
				}
			}
			//大病收取方式 : 1.按月
		} else if (CommonConstants.ONE_STRING.equals(socialInfo.getCollectType())) {

			//  大病取值方式：1 按比例   按派单的基数和比例来
			if (CommonConstants.ONE_STRING.equals(socialInfo.getValueType())) {
				library.setUnitBigailmentBase(socialInfo.getUnitBigailmentCardinal());
				library.setUnitBigailmentPro(socialInfo.getUnitBigailmentPer());
				library.setPersonalBigailmentBase(socialInfo.getPersonalBigailmentCardinal());
				library.setPersonalBigailmentPro(socialInfo.getPersonalBigailmentPer());
				library.setPersonalBigailmentFee(socialInfo.getPersonalBigailmentMoney());
				library.setUnitBitailmentFee(socialInfo.getUnitBigailmentMoney());
			} else {
				// 大病取值方式：0按定值
				library.setUnitBitailmentFee(socialInfo.getUnitBigailmentMoney());
				library.setPersonalBigailmentFee(socialInfo.getPersonalBigailmentMoney());
			}
		}
	}

	private void changeFundInfoByBase(TSocialFundInfo socialFund, SysBaseSetInfo socialSet) {
		if (Common.isNotNull(socialSet) && socialFund.getUnitFundSum() != null) {
			socialFund.setLowerLimitFund(socialSet.getLowerLimit());
			socialFund.setUpperLimitFund(socialSet.getUpperLimit());
			socialFund.setFundPayPoint(String.valueOf(socialSet.getFundPayPoint()));
			if (socialFund.getUnitProvidengCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
				socialFund.setUnitProvidengCardinal(socialSet.getLowerLimit());
				socialFund.setPersonalProvidentCardinal(socialSet.getLowerLimit());
			} else if (socialFund.getUnitProvidengCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
				socialFund.setUnitProvidengCardinal(socialSet.getUpperLimit());
				socialFund.setPersonalProvidentCardinal(socialSet.getUpperLimit());
			}
			//单边小数点处理逻辑
			if (Common.isNotNull(socialSet.getFundPayPoint())) {
				socialFund.setUnitFundSum(Common.formatMoneyForFund(BigDecimalUtils.safeMultiply(socialFund.getUnitProvidengCardinal(), socialFund.getUnitProvidentPer(), BigDecimal.valueOf(CommonConstants.ONE_OF_PERCENT.doubleValue())), Integer.parseInt(socialFund.getFundPayPoint())));
				socialFund.setPersonalFundSum(Common.formatMoneyForFund(BigDecimalUtils.safeMultiply(socialFund.getPersonalProvidentCardinal(), socialFund.getPersonalProvidentPer(), BigDecimal.valueOf(CommonConstants.ONE_OF_PERCENT.doubleValue())), Integer.parseInt(socialFund.getFundPayPoint())));
			}
		}
	}

	/**
	 * 初始化公积金预估信息
	 *
	 * @param payMonth
	 * @param saveLibraryMap
	 * @param providentFund
	 * @param isReduceSocial
	 * @return
	 * @Author fxj
	 * @Date 2020-07-21
	 **/
	private void initFundLibary(String diffType, String payMonth, Map<String, TForecastLibrary> saveLibraryMap
			, TSocialFundInfo providentFund, boolean isReduceSocial, String mapKeyStr
			, TForecastLibrary historyLibrary, boolean isOnly) {
		TForecastLibrary lib = new TForecastLibrary();
		lib.setDataPush(CommonConstants.ZERO_INT);
		lib.setSalaryFundFlag(CommonConstants.ZERO_STRING);
		lib.setProvidentHousehold(providentFund.getProvidentHousehold());
		lib.setProvidentHouseholdName(providentFund.getProvidentHouseholdName());
		lib.setDiffType(diffType);
		lib.setDataType(CommonConstants.ONE_INT);
		lib.setEmpId(providentFund.getEmpId());
		lib.setEmpIdcard(providentFund.getEmpIdcard());
		lib.setEmpName(providentFund.getEmpName());
		lib.setEmpNo(providentFund.getEmpNo());
		lib.setEmpNatrue(providentFund.getEmpType());
		lib.setProvidentCreateMonth(ServiceUtil.initCreateMonth(providentFund.getCreateTime(), payMonth));
		//lib.setSocialCreateMonth(lib.getProvidentCreateMonth())
		//同时处理社保日期
		//lib.setSocialPayMonth(payMonth)
		lib.setProvidentPayMonth(payMonth);
		lib.setFundProvince(providentFund.getFundProvince());
		lib.setFundCity(providentFund.getFundCity());
		lib.setFundTown(providentFund.getFundTown());
		lib.setProvidentId(providentFund.getId());
		lib.setUnitId(providentFund.getUnitIdFund());
		lib.setSettleDomainId(providentFund.getSettleDomainFund());
		lib.setUnitName(providentFund.getUnitNameFund());
		lib.setDeptName(providentFund.getSettleDomainNameFund());
		lib.setDeptNo(providentFund.getSettleDomainCodeFund());

		//判断是否允许补缴 是否可补缴 0：是
		Integer monthT = null;
		if (CommonConstants.ZERO_STRING.equals(providentFund.getCanOverpay())) {
			//补缴是否含当月: 含当月
			if (CommonConstants.ZERO_STRING.equals(providentFund.getHaveThisMonth())) {
				monthT = Integer.parseInt(DateUtil.getYearAndMonth(LocalDateTimeUtils.formatTime(providentFund.getCreateTime(), DateUtil.DATETIME_YYYYMM), 0));
				//补缴是否含当月: 不含含当月
			} else {
				monthT = Integer.parseInt(DateUtil.getYearAndMonth(LocalDateTimeUtils.formatTime(providentFund.getCreateTime(), DateUtil.DATETIME_YYYYMM), -CommonConstants.ONE_INT));
			}
		}
		// 判断公积金对应缴纳月份是否派减了
		boolean isReduceFund;
		if (null != providentFund.getFundReduceDate()) {
			isReduceFund = Integer.parseInt(payMonth) >= DateUtil.formatDateInt(providentFund.getFundReduceDate());
		} else {
			isReduceFund = false;
		}
		lib = initForecastLibrary(lib, null, providentFund, monthT, isReduceFund, isReduceSocial, null, historyLibrary, isOnly);
		saveLibraryMap.put(mapKeyStr, lib);
	}

	private void changeSocialInfoByBase(TSocialFundInfo social, SysBaseSetInfo socialSet) {
		if (Common.isNotNull(socialSet)) {
			social.setCanOverpay(socialSet.getCanOverpay());
			social.setSocialHousehold(socialSet.getDepartId());
			social.setCollectMoth(socialSet.getCollectMoth());
			social.setCollectType(socialSet.getCollectType());
			social.setHaveThisMonth(socialSet.getHaveThisMonth());
			social.setInsuranceBigailment(socialSet.getInsuranceBigailment());
			social.setInsuranceBirth(socialSet.getInsuranceBirth());
			social.setInsuranceInjury(socialSet.getInsuranceInjury());
			social.setInsuranceMedical(socialSet.getInsuranceMedical());
			social.setInsurancePension(socialSet.getInsurancePension());
			social.setInsuranceUnemployment(socialSet.getInsuranceUnemployment());
			social.setLatestCardinality(socialSet.getInsuranceIsLatestCardinality());
			social.setIsChargePersonal(socialSet.getIsChargePersonal());
			social.setIsIllness(socialSet.getIsIllness());
			social.setOverpayNumber(socialSet.getOverpayNumber());
			social.setValueType(socialSet.getValueType());
			social.setLowerLimit(socialSet.getLowerLimit());
			social.setUpperLimit(socialSet.getUpperLimit());
			// 比例初始化
			// 按最低
			if (CommonConstants.ZERO_STRING.equals(social.getPaymentType())) {
				this.setBaseInfo(social, socialSet);
			} else if (CommonConstants.TWO_STRING.equals(social.getPaymentType())) {
				//按最高
				this.setBaseInfo1(social, socialSet);
			} else if (CommonConstants.ONE_STRING.equals(social.getPaymentType())) {
				//自定义
				// 五险
				if (social.getUnitPensionCardinal() != null) {
					if (social.getUnitPensionCardinal().compareTo(socialSet.getLowerPersion()) < CommonConstants.ZERO_INT) {
						social.setPersonalPensionCardinal(socialSet.getLowerPersion());
						social.setUnitPensionCardinal(socialSet.getLowerPersion());
					} else if (social.getUnitPensionCardinal().compareTo(socialSet.getUpPersion()) > CommonConstants.ZERO_INT) {
						social.setPersonalPensionCardinal(socialSet.getUpPersion());
						social.setUnitPensionCardinal(socialSet.getUpPersion());
					}
					if (social.getUnitMedicalCardinal().compareTo(socialSet.getLowerMedical()) < CommonConstants.ZERO_INT) {
						social.setPersonalMedicalCardinal(socialSet.getLowerMedical());
						social.setUnitMedicalCardinal(socialSet.getLowerMedical());
					} else if (social.getUnitMedicalCardinal().compareTo(socialSet.getUpMedical()) > CommonConstants.ZERO_INT) {
						social.setPersonalMedicalCardinal(socialSet.getUpMedical());
						social.setUnitMedicalCardinal(socialSet.getUpMedical());
					}
					if (social.getUnitUnemploymentCardinal().compareTo(socialSet.getLowerUnemployment()) < CommonConstants.ZERO_INT) {
						social.setPersonalUnemploymentCardinal(socialSet.getLowerUnemployment());
						social.setUnitUnemploymentCardinal(socialSet.getLowerUnemployment());
					} else if (social.getUnitUnemploymentCardinal().compareTo(socialSet.getUpUnemployment()) > CommonConstants.ZERO_INT) {
						social.setPersonalUnemploymentCardinal(socialSet.getUpUnemployment());
						social.setUnitUnemploymentCardinal(socialSet.getUpUnemployment());
					}
					if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getLowerInjury()) < CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getLowerInjury());
					} else if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getUpInjury()) > CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getUpInjury());
					}
					if (social.getUnitBirthCardinal().compareTo(socialSet.getLowerBirth()) < CommonConstants.ZERO_INT) {
						social.setUnitBirthCardinal(socialSet.getLowerBirth());
					} else if (social.getUnitBirthCardinal().compareTo(socialSet.getUpBirth()) > CommonConstants.ZERO_INT) {
						social.setUnitBirthCardinal(socialSet.getUpBirth());
					}
					if (CommonConstants.ONE_STRING.equals(social.getCollectType())
							&& 	CommonConstants.ONE_STRING.equals(social.getValueType())) {
						if (BigDecimalUtils.isNullToZero(social.getUnitBigailmentCardinal()).compareTo(socialSet.getLowerBig()) < CommonConstants.ZERO_INT) {
							//按年收取大病方式按定值
							social.setPersonalBigailmentCardinal(socialSet.getLowerBig());
							social.setUnitBigailmentCardinal(socialSet.getLowerBig());
						} else if (BigDecimalUtils.isNullToZero(social.getUnitBigailmentCardinal()).compareTo(socialSet.getUpBig()) > CommonConstants.ZERO_INT) {
							social.setPersonalBigailmentCardinal(socialSet.getUpBig());
							social.setUnitBigailmentCardinal(socialSet.getUpBig());
						}
					}else {
						social.setPersonalBigailmentCardinal(BigDecimal.ZERO);
						social.setUnitBigailmentCardinal(BigDecimal.ZERO);
					}
				} else if (social.getUnitWorkInjuryCardinal() != null) {
					// 兼职工伤
					if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getLowerInjury()) < CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getLowerInjury());
					} else if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getUpInjury()) > CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getUpInjury());
					}
				}
			}
			// 比例与金额
			this.setProAndMoney(social, socialSet);
		}
	}

	/**
	 * @param social
	 * @param socialSet
	 * @Description: 塞基数
	 * @Author: hgw
	 * @Date: 2022/7/27 14:55
	 * @return: void
	 **/
	private void setBaseInfo(TSocialFundInfo social, SysBaseSetInfo socialSet) {
		if (social.getUnitPensionCardinal() != null) {
			// 基数
			social.setPersonalPensionCardinal(socialSet.getLowerPersion());
			social.setPersonalMedicalCardinal(socialSet.getLowerMedical());
			social.setPersonalUnemploymentCardinal(socialSet.getLowerUnemployment());
			social.setPersonalBigailmentCardinal(socialSet.getLowerBig());
			social.setUnitPensionCardinal(socialSet.getLowerPersion());
			social.setUnitMedicalCardinal(socialSet.getLowerMedical());
			social.setUnitUnemploymentCardinal(socialSet.getLowerUnemployment());
			social.setUnitWorkInjuryCardinal(socialSet.getLowerInjury());
			social.setUnitBigailmentCardinal(socialSet.getLowerBig());
			social.setUnitBirthCardinal(socialSet.getLowerBirth());
		} else if (social.getUnitWorkInjuryCardinal() != null) {
			social.setUnitWorkInjuryCardinal(socialSet.getLowerInjury());
		}
	}

	/**
	 * @param social
	 * @param socialSet
	 * @Description: 塞基数
	 * @Author: hgw
	 * @Date: 2022/7/27 14:55
	 * @return: void
	 **/
	private void setBaseInfo1(TSocialFundInfo social, SysBaseSetInfo socialSet) {
		if (social.getUnitPensionCardinal() != null) {
			// 基数
			social.setPersonalPensionCardinal(socialSet.getUpPersion());
			social.setPersonalMedicalCardinal(socialSet.getUpMedical());
			social.setPersonalUnemploymentCardinal(socialSet.getUpUnemployment());
			social.setPersonalBigailmentCardinal(socialSet.getUpBig());
			social.setUnitPensionCardinal(socialSet.getUpPersion());
			social.setUnitMedicalCardinal(socialSet.getUpMedical());
			social.setUnitUnemploymentCardinal(socialSet.getUpUnemployment());
			social.setUnitWorkInjuryCardinal(socialSet.getUpInjury());
			social.setUnitBigailmentCardinal(socialSet.getUpBig());
			social.setUnitBirthCardinal(socialSet.getUpBirth());
		} else if (social.getUnitWorkInjuryCardinal() != null) {
			social.setUnitWorkInjuryCardinal(socialSet.getUpInjury());
		}
	}

	/**
	 * @param social
	 * @param socialSet
	 * @Description: 塞比例与金额
	 * @Author: hgw
	 * @Date: 2022/7/27 14:55
	 * @return: void
	 **/
	private void setProAndMoney(TSocialFundInfo social, SysBaseSetInfo socialSet) {
		if (social.getUnitPensionCardinal() != null) {
			// 比例
			social.setPersonalPensionPer(socialSet.getPersonalPersionPro());
			social.setPersonalMedicalPer(socialSet.getPersonalMedicalPro());
			social.setPersonalUnemploymentPer(socialSet.getPersonalUnemploymentPro());
			social.setPersonalBigailmentPer(socialSet.getPayPersonalPro());
			social.setUnitPensionPer(socialSet.getUnitPersionPro());
			social.setUnitMedicalPer(socialSet.getUnitMedicalPro());
			social.setUnitUnemploymentPer(socialSet.getUnitUnemploymentPro());
			social.setUnitWorkUnjuryPer(socialSet.getUnitInjuryPro());
			social.setUnitBigailmentPer(socialSet.getPayCompanyPro());
			social.setUnitBirthPer(socialSet.getUnitBirthPro());

			// 金额
			social.setUnitPersionMoney(BigDecimalUtils.safeMultiply(social.getUnitPensionCardinal(), social.getUnitPensionPer(), CommonConstants.ONE_OF_PERCENT));
			social.setUnitMedicalMoney(BigDecimalUtils.safeMultiply(social.getUnitMedicalCardinal(), social.getUnitMedicalPer(), CommonConstants.ONE_OF_PERCENT));
			social.setUnitBirthMoney(BigDecimalUtils.safeMultiply(social.getUnitBirthCardinal(), social.getUnitBirthPer(), CommonConstants.ONE_OF_PERCENT));
			social.setUnitInjuryMoney(BigDecimalUtils.safeMultiply(social.getUnitWorkInjuryCardinal(), social.getUnitWorkUnjuryPer(), CommonConstants.ONE_OF_PERCENT));
			social.setUnitUnemploymentMoney(BigDecimalUtils.safeMultiply(social.getUnitUnemploymentCardinal(), social.getUnitUnemploymentPer(), CommonConstants.ONE_OF_PERCENT));

			social.setPersonalPersionMoney(BigDecimalUtils.safeMultiply(social.getPersonalPensionCardinal(), social.getPersonalPensionPer(), CommonConstants.ONE_OF_PERCENT));
			social.setPersonalMedicalMoney(BigDecimalUtils.safeMultiply(social.getPersonalMedicalCardinal(), social.getPersonalMedicalPer(), CommonConstants.ONE_OF_PERCENT));
			social.setPersonalUnemploymentMoney(BigDecimalUtils.safeMultiply(social.getPersonalUnemploymentCardinal(), social.getPersonalUnemploymentPer(), CommonConstants.ONE_OF_PERCENT));

			// 大病金额
			boolean flag = CommonConstants.ZERO_STRING.equals(social.getIsIllness()) && (CommonConstants.ZERO_STRING.equals(social.getCollectType()) || CommonConstants.ONE_STRING.equals(social.getCollectType()));
			if (flag) {
				//收取方式按年 且为指定月份时产生数据
				if (CommonConstants.ZERO_STRING.equals(social.getCollectType()) && Common.isNotNull(socialSet)) {
					//按年收取大病方式按定值
					social.setUnitBigailmentMoney(socialSet.getPayCompany());
					social.setPersonalBigailmentMoney(socialSet.getPayPersonal());
				} else if (CommonConstants.ONE_STRING.equals(social.getCollectType())) {
					//收取方式按月
					if (CommonConstants.ONE_STRING.equals(social.getValueType())) {
						//收取大病按比例
						social.setUnitBigailmentMoney(BigDecimalUtils.safeMultiply(social.getUnitBigailmentCardinal(), social.getUnitBigailmentPer(), BigDecimal.valueOf(CommonConstants.ONE_OF_PERCENT.doubleValue())));
						social.setPersonalBigailmentMoney(BigDecimalUtils.safeMultiply(social.getPersonalBigailmentCardinal(), social.getPersonalBigailmentPer(), BigDecimal.valueOf(CommonConstants.ONE_OF_PERCENT.doubleValue())));
					} else if (CommonConstants.ZERO_STRING.equals(social.getValueType()) && Common.isNotNull(socialSet)) {
						//收取大病方式按定值
						social.setUnitBigailmentMoney(socialSet.getPayCompany());
						social.setPersonalBigailmentMoney(socialSet.getPayPersonal());
					}
				}
			} else {
				social.setUnitBigailmentCardinal(BigDecimal.ZERO);
				social.setUnitBigailmentPer(BigDecimal.ZERO);
				social.setUnitBigailmentMoney(BigDecimal.ZERO);
				social.setPersonalBigailmentCardinal(BigDecimal.ZERO);
				social.setPersonalBigailmentPer(BigDecimal.ZERO);
				social.setPersonalBigailmentMoney(BigDecimal.ZERO);
			}
		} else if (social.getUnitWorkInjuryCardinal() != null) {
			social.setUnitWorkUnjuryPer(socialSet.getUnitInjuryPro());
			social.setUnitInjuryMoney(BigDecimalUtils.safeMultiply(social.getUnitWorkInjuryCardinal(), social.getUnitWorkUnjuryPer(), CommonConstants.ONE_OF_PERCENT));
		}
		social.setUnitSocialSum(BigDecimalUtils.safeAdd(social.getUnitPersionMoney()
				, social.getUnitMedicalMoney(), social.getUnitBirthMoney()
				, social.getUnitInjuryMoney()
				, social.getUnitUnemploymentMoney()
				, social.getUnitInterestFee()
				, social.getUnitBigailmentMoney()));
		social.setPersonalSocialSum(BigDecimalUtils.safeAdd(social.getPersonalBigailmentMoney()
				, social.getPersonalPersionMoney()
				, social.getPersonalMedicalMoney()
				, social.getPersonalInterestFee()
				, social.getPersonalUnemploymentMoney()));

	}

	/**
	 * @Description: 基数新增，同步社保公积金查询表，同步预估库
	 * @Author: hgw
	 * @Date: 2022/7/25 17:37
	 * @return: void
	 **/
	@Override
	public void updateForecastLibaryBySysBase(SysBaseSetInfo newSysBaseSetInfo) {
		List<SysBaseSetInfo> sysBaseSetInfoList = new ArrayList<>();
		if (newSysBaseSetInfo == null) {
			sysBaseSetInfoList = sysBaseSetInfoMapper.selectList(
					Wrappers.<SysBaseSetInfo>query().lambda()
							.eq(SysBaseSetInfo::getIsNew, CommonConstants.ONE_STRING));
		} else {
			sysBaseSetInfoList.add(newSysBaseSetInfo);
		}
		if (sysBaseSetInfoList != null && !sysBaseSetInfoList.isEmpty()) {
			Map<String, TSocialFundInfo> socialFundInfoMap = new HashMap<>();
			List<TSocialFundInfo> socialFundInfoList;
			Date startDate;
			for (SysBaseSetInfo sysBaseSetInfo : sysBaseSetInfoList) {
				// 社保
				if (CommonConstants.ZERO_STRING.equals(sysBaseSetInfo.getBaseType())) {
					socialFundInfoList = socialFundInfoMapper.selectList(Wrappers.<TSocialFundInfo>query().lambda()
							.eq(TSocialFundInfo::getSocialHousehold, sysBaseSetInfo.getDepartId())
							.in(TSocialFundInfo::getSocialStatus, CommonConstants.dingleDigitStrArray[3], CommonConstants.dingleDigitStrArray[4])
							.isNotNull(TSocialFundInfo::getSocialId)
					);
					for (TSocialFundInfo socialFundInfo : socialFundInfoList) {
						// 2022-8-9 15:26:20 新增逻辑：从不收取变为收取
						if (CommonConstants.ZERO_STRING.equals(sysBaseSetInfo.getIsIllness())
								&& socialFundInfo.getBigailmentStart() == null && Common.isNotNull(socialFundInfo.getUnitPensionCardinal())) {
							startDate = DateUtil.stringToDate(sysBaseSetInfo.getDoMonth() + "01", "yyyyMMdd");
							socialFundInfo.setBigailmentHandle(CommonConstants.ONE_STRING);
							socialFundInfo.setBigailmentStart(startDate);
						}
						this.changeSocialInfoByBase(socialFundInfo, sysBaseSetInfo);
						socialFundInfo.setDoMonth(sysBaseSetInfo.getDoMonth());
						socialFundInfo.setSocialSetInfo(sysBaseSetInfo);
						socialFundInfoMap.put(socialFundInfo.getId(), socialFundInfo);
					}
				}
				// 公积金
				if (CommonConstants.ONE_STRING.equals(sysBaseSetInfo.getBaseType())) {
					socialFundInfoList = socialFundInfoMapper.selectList(Wrappers.<TSocialFundInfo>query().lambda()
							.eq(TSocialFundInfo::getProvidentHousehold, sysBaseSetInfo.getDepartId())
							.eq(TSocialFundInfo::getFundStatus, CommonConstants.dingleDigitStrArray[3])
							.isNotNull(TSocialFundInfo::getFundId)
					);
					for (TSocialFundInfo socialFundInfo : socialFundInfoList) {
						this.changeFundInfoByBase(socialFundInfo, sysBaseSetInfo);
						socialFundInfo.setDoMonth(sysBaseSetInfo.getDoMonth());
						socialFundInfo.setFundSetInfo(sysBaseSetInfo);
						socialFundInfoMap.put(socialFundInfo.getId(), socialFundInfo);
					}
				}
				sysBaseSetInfo.setIsNew(CommonConstants.ZERO_STRING);
				sysBaseSetInfoMapper.updateById(sysBaseSetInfo);
			}
			for (TSocialFundInfo socialFundInfo : socialFundInfoMap.values()) {
				this.updateForecastLibaryCore(null,null,socialFundInfo, socialFundInfo.getDoMonth(), true, false,true);
				socialFundInfoMapper.updateById(socialFundInfo);
			}
		}
	}

	/**
	 * @param socialFundInfo
	 * @Description: 批量调基，同步预估库
	 * @Author: hgw
	 * @Date: 2022/7/25 17:37
	 * @return: void
	 **/
	@Override
	public R<String> updateToneForecastLibary(TSocialFundInfo socialFundInfo, String doMonth) {
		return this.updateForecastLibaryCore(null,null,socialFundInfo, doMonth, false, false,true);
	}

	/**
	 * @param socialFundInfo
	 * @Description: 派单，同步预估库
	 * @Author: hgw
	 * @Date: 2022/7/25 17:37
	 * @return: void
	 **/
	@Override
	public R<String> updateForecastLibaryByDispatch(ConcurrentHashMap<String, String> socialMap, ConcurrentHashMap<String, String> fundMap,TSocialFundInfo socialFundInfo) {
		return this.updateForecastLibaryCore(socialMap,fundMap,socialFundInfo, null, false, true,false);
	}

	/**
	 * @Description: 派单减少变更预估库-派减
	 * @Author: hgw
	 * @Date: 2022/7/28 17:11
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> updateForecastLibaryByDispatchReduce(TSocialFundInfo socialFundInfo, int forecastFlag) {
		String empIdCard = socialFundInfo.getEmpIdcard();
		List<TForecastLibrary> libraryFundInfoListSocial = new ArrayList<>();
		List<TForecastLibrary> libraryFundInfoListFund = new ArrayList<>();
		if (Common.isNotNull(empIdCard)) {
			Date minStartDate = this.getMinSocialDate(socialFundInfo);
			BigDecimal zero = BigDecimal.ZERO;
			if (forecastFlag == CommonConstants.ZERO_INT || forecastFlag == CommonConstants.ONE_INT) {
				// 查询已经生成的预估数据
				List<TForecastLibrary> socialLibraryList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT));
				if (Common.isNotNull(socialLibraryList)) {
					// 社保
					Date socialReduceDate = socialFundInfo.getSocialReduceDate();
					for (TForecastLibrary library : socialLibraryList) {
						if (Common.isNotNull(library.getSocialPayMonth())) {
							if (socialReduceDate != null) {
								// 存在社保派减且处于派减期间内，未被预估结算，工资结算引用则清空相关数据
								if (DateUtil.formatDateInt(socialReduceDate) <= Integer.parseInt(library.getSocialPayMonth())) {
									this.calculateSocialType(zero, library, libraryFundInfoListSocial);
								}
							} else {
								if (DateUtil.formatDateInt(minStartDate) <= Integer.parseInt(library.getSocialPayMonth())) {
									this.calculateSocialType(zero, library, libraryFundInfoListSocial);
								}
							}
						}
					}
				}
			}

			// 公积金
			if (forecastFlag == CommonConstants.ZERO_INT || forecastFlag == CommonConstants.TWO_INT) {
				List<TForecastLibrary> fundLibraryList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT));
				if (Common.isNotNull(fundLibraryList)) {
					minStartDate = socialFundInfo.getProvidentStart();
					Date fundReduceDate = socialFundInfo.getFundReduceDate();
					for (TForecastLibrary library : fundLibraryList) {
						if (Common.isNotNull(library.getProvidentPayMonth())) {
							if (fundReduceDate != null) {
								// 存在社保派减且处于派减期间内，未被预估结算，工资结算引用则清空相关数据
								if (DateUtil.formatDateInt(fundReduceDate) <= Integer.parseInt(library.getProvidentPayMonth())) {
									this.calculateFundType(zero, library,libraryFundInfoListFund);
								}
							} else {
								if (DateUtil.formatDateInt(minStartDate) <= Integer.parseInt(library.getProvidentPayMonth())) {
									this.calculateFundType(zero, library,libraryFundInfoListFund);
								}
							}
						}
					}
				}
			}
			//推送社保明细
			if (Common.isNotNull(libraryFundInfoListSocial)) {
				pushForecastInfo(libraryFundInfoListSocial,false,null);
			}
			//推送公积金明细
			if (Common.isNotNull(libraryFundInfoListFund)) {
				pushForecastFundInfo(libraryFundInfoListFund,false,null);
			}
		}
		return R.ok();
	}

	private void calculateSocialType(BigDecimal zero, TForecastLibrary library,List<TForecastLibrary> libraryFundInfoListSocial) {
		if (library.getDataPush() == CommonConstants.ONE_INT || CommonConstants.ONE_STRING.equals(library.getSalarySocialFlag())) {
			// 加负数
			TForecastLibrary negateLib = new TForecastLibrary();
			BeanUtil.copyProperties(library, negateLib);
			negateLib.setId(null);
			negateLib.setDataPush(CommonConstants.ZERO_INT);
			negateLib.setSalarySocialFlag(CommonConstants.ZERO_STRING);
			negateLib.setUnitPensionFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitPensionFee()));
			negateLib.setUnitMedicalFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitMedicalFee()));
			negateLib.setUnitBirthFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitBirthFee()));
			negateLib.setUnitWorkInjuryFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitWorkInjuryFee()));
			negateLib.setUnitUnemploymentFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitUnemploymentFee()));
			negateLib.setUnitBitailmentFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitBitailmentFee()));
			negateLib.setUnitInterestFee(BigDecimalUtils.safeSubtract(false, zero, library.getUnitInterestFee()));
			negateLib.setUnitSocialSum(BigDecimalUtils.safeSubtract(false, zero, library.getUnitSocialSum()));
			// 个人社保
			negateLib.setPersonalPensionFee(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalPensionFee()));
			negateLib.setPersonalMedicalFee(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalMedicalFee()));
			negateLib.setPersonalUnemploymentFee(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalUnemploymentFee()));
			negateLib.setPersonalInterestFee(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalInterestFee()));
			negateLib.setPersonalBigailmentFee(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalBigailmentFee()));
			negateLib.setPersonalSocialSum(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalSocialSum()));
			negateLib.setSumAll(BigDecimalUtils.safeSubtract(false, zero, library.getSumAll()));
			negateLib.setDiffType(SocialConstants.DIFF_TYPE_TWO);
			baseMapper.insert(negateLib);
			libraryFundInfoListSocial.add(negateLib);
		} else {
			// 删除
			baseMapper.deleteById(library.getId());
		}
		//删除停缴月以后的收入数据
		List<TIncomeDetail> updateList = detailService.list(Wrappers.<TIncomeDetail>query().lambda()
				.eq(TIncomeDetail::getEmpIdcard, library.getEmpIdcard())
				.eq(TIncomeDetail::getDeptId, library.getSettleDomainId())
				.eq(TIncomeDetail::getSourceType, CommonConstants.ONE_STRING)
				.eq(TIncomeDetail::getPayMonth, library.getSocialPayMonth())
				.eq(TIncomeDetail::getMrSettleType, CommonConstants.ONE_STRING));
		if (Common.isNotNull(updateList)) {
			String redisKey = String.valueOf(UUID.randomUUID()).replaceAll("-", "") + "_incomePush";
			for (TIncomeDetail upd : updateList) {
				TIncomeDetail detail = new TIncomeDetail();
				BeanCopyUtils.copyProperties(upd, detail);
				detail.setRedisKey(redisKey);
				detail.setId(CommonConstants.NULL);
				detail.setRedData(CommonConstants.ONE_STRING);
				detail.setMoney(detail.getMoney().negate());
				incomeService.saveDetail(detail,false);
			}
			//推送失败的数据重新推送
			if (Common.isNotNull(redisUtil.get(redisKey))) {
				List<TIncome> list = (List<TIncome>) redisUtil.get(redisKey);
				for (TIncome income:list) {
					doJointSocialTask.asynchronousEkpIncomeAssoT(income);
				}
				redisUtil.remove(redisKey);
			}
		}
	}

	private void calculateFundType(BigDecimal zero, TForecastLibrary library, List<TForecastLibrary> libraryFundInfoListFund) {
		if (library.getDataPush() == CommonConstants.ONE_INT || CommonConstants.ONE_STRING.equals(library.getSalaryFundFlag())) {
			// 加负数
			TForecastLibrary negateLib = new TForecastLibrary();
			BeanUtil.copyProperties(library, negateLib);
			negateLib.setId(null);
			negateLib.setDataPush(CommonConstants.ZERO_INT);
			negateLib.setSalaryFundFlag(CommonConstants.ZERO_STRING);
			// 单位公积金
			negateLib.setUnitFundSum(BigDecimalUtils.safeSubtract(false, zero, library.getUnitFundSum()));
			// 个人公积金
			negateLib.setPersonalFundSum(BigDecimalUtils.safeSubtract(false, zero, library.getPersonalFundSum()));
			negateLib.setSumAll(BigDecimalUtils.safeSubtract(false, zero, library.getSumAll()));
			negateLib.setDiffType(SocialConstants.DIFF_TYPE_TWO);
			baseMapper.insert(negateLib);
			libraryFundInfoListFund.add(negateLib);
		} else {
			// 删除
			baseMapper.deleteById(library.getId());
		}

		//删除停缴月以后的收入数据
		List<TIncomeDetail> updateList =  detailService.list(Wrappers.<TIncomeDetail>query().lambda()
				.eq(TIncomeDetail::getEmpIdcard,library.getEmpIdcard())
				.eq(TIncomeDetail::getDeptId,library.getSettleDomainId())
				.eq(TIncomeDetail::getSourceType,CommonConstants.TWO_STRING)
				.eq(TIncomeDetail::getPayMonth,library.getProvidentPayMonth())
				.eq(TIncomeDetail::getMrSettleType, CommonConstants.ONE_STRING));
		if (Common.isNotNull(updateList)) {
			String redisKey = String.valueOf(UUID.randomUUID()).replaceAll("-", "") + "_incomePush";
			for (TIncomeDetail upd : updateList) {
				TIncomeDetail detail = new TIncomeDetail();
				BeanCopyUtils.copyProperties(upd, detail);
				detail.setId(CommonConstants.NULL);
				detail.setRedisKey(redisKey);
				detail.setRedData(CommonConstants.ONE_STRING);
				detail.setMoney(detail.getMoney().negate());
				incomeService.saveDetail(detail,false);
			}
			//推送失败的数据重新推送
			if (Common.isNotNull(redisUtil.get(redisKey))) {
				List<TIncome> list = (List<TIncome>) redisUtil.get(redisKey);
				for (TIncome income:list) {
					doJointSocialTask.asynchronousEkpIncomeAssoT(income);
				}
				redisUtil.remove(redisKey);
			}
		}
	}

	/**
	 * @param isDispatch     是否是派单，是：区分社保数据与公积金数据
	 * @param isOnly         是否仅更新传过来的社保公积金，true：是(同时，true时，是户调基，要判断断缴)
	 * @param socialFundInfo
	 * @Description: 根据社保公积金信息表更新预估库
	 * @Author: hgw
	 * @Date: 2022/7/26 19:01
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	private R<String> updateForecastLibaryCore(ConcurrentHashMap<String, String> socialMap,ConcurrentHashMap<String, String> fundMap,TSocialFundInfo socialFundInfo, String doMonth, boolean isOnly, boolean isDispatch,boolean synFlag) {
		String empIdCard = socialFundInfo.getEmpIdcard();
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialListTemp = null;
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundListTemp = null;

		int monthDiff;
		// 获取要更新的月份
		if (Common.isNotNull(doMonth)) {
			try {
				if (Integer.parseInt(doMonth) > Integer.parseInt(DateUtil.addMonth(1))) {
					return R.failed("同步预估库，doMonth大于下月：" + doMonth);
				}
				monthDiff = DateUtil.getMonthDiff(DateUtil.parseDate(doMonth, "yyyyMM"), new Date()) + 2;
			} catch (Exception e) {
				return R.failed("同步预估库，doMonth格式错误：" + doMonth);
			}
		} else {
			// 获取最小的起缴月
			Date minStartDate = this.getMinDate(socialFundInfo);
			// 再计算月份
			monthDiff = DateUtil.getMonthDiff(minStartDate, new Date()) + 2;
		}
		List<String> payMonthList = new ArrayList<>();
		if (monthDiff <= 0) {
			return R.failed("同步预估库，起缴月份无法生成，monthDiff=" + monthDiff);
		}
		for (int i = 0; i < monthDiff; i++) {
			payMonthList.add(DateUtil.addMonth(1 - i));
		}

		//查询出所有符合条件的社保数据
		List<TSocialFundInfo> socialInfoList = null;
		List<TSocialFundInfo> fundList = null;
		// 查询当年所有的社保临时政策用于生成预估数据
		List<TAgentConfig> configList = agentConfigMapper.selectList(Wrappers.<TAgentConfig>query().lambda()
				.eq(TAgentConfig::getOpenFlag, CommonConstants.ZERO_INT));
		HashMap<String, TAgentConfig> agentConfigHashMap = new HashMap<>();
		if (Common.isNotNull(configList) && Common.isNotNull(payMonthList)) {
			initConfigByPayMonths(configList, payMonthList, agentConfigHashMap);
		}
		//查询出所有对应条件的预估数、社保数据、公积金数据据用于重新生成
		List<String> detailMonthList;
		if (Common.isNotNull(empIdCard)) {
			if (isDispatch) {
				if (socialFundInfo.getSocialStartDate() != null) {
					detailMonthList = new ArrayList<>();
					// 获取最小的起缴月
					Date minStartDate = this.getMinSocialDate(socialFundInfo);
					// 再计算月份
					monthDiff = DateUtil.getMonthDiff(minStartDate, new Date()) + 2;
					if (monthDiff <= 0) {
						return R.failed("派单同步预估库，社保起缴月份无法生成，monthDiff=" + monthDiff);
					}
					for (int i = 0; i < monthDiff; i++) {
						detailMonthList.add(DateUtil.addMonth(1 - i));
					}
					librarySocialList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
							.eq(TForecastLibrary::getEmpIdcard, empIdCard)
							.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
							.in(TForecastLibrary::getSocialPayMonth, detailMonthList)
							.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
							.eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ZERO_STRING));
					librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
							.eq(TForecastLibrary::getEmpIdcard, empIdCard)
							.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
							.in(TForecastLibrary::getSocialPayMonth, detailMonthList)
							.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
									.or().eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ONE_STRING)));
				}
			} else {
				librarySocialList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
						.in(TForecastLibrary::getSocialPayMonth, payMonthList)
						.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
						.eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ZERO_STRING));
				librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
						.in(TForecastLibrary::getSocialPayMonth, payMonthList)
						.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
								.or().eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ONE_STRING)));
			}
			if (isDispatch) {
				if (socialFundInfo.getProvidentStart() != null) {
					detailMonthList = new ArrayList<>();
					// 获取最小的起缴月
					Date minStartDate = socialFundInfo.getProvidentStart();
					// 再计算月份
					monthDiff = DateUtil.getMonthDiff(minStartDate, new Date()) + 2;
					if (monthDiff <= 0) {
						return R.failed("派单同步预估库，公积金起缴月份无法生成，monthDiff=" + monthDiff);
					}
					for (int i = 0; i < monthDiff; i++) {
						detailMonthList.add(DateUtil.addMonth(1 - i));
					}
					libraryFundList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
							.eq(TForecastLibrary::getEmpIdcard, empIdCard)
							.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
							.in(TForecastLibrary::getProvidentPayMonth, detailMonthList)
							.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
							.eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ZERO_STRING));
					libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
							.eq(TForecastLibrary::getEmpIdcard, empIdCard)
							.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
							.in(TForecastLibrary::getProvidentPayMonth, detailMonthList)
							.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
									.or().eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ONE_STRING)));
				}
			} else {
				libraryFundList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
						.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
						.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
						.eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ZERO_STRING));
				libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
						.eq(TForecastLibrary::getEmpIdcard, empIdCard)
						.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
						.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
						.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
								.or().eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ONE_STRING)));
			}
			if (isOnly) {
				if (Common.isNotNull(socialFundInfo.getSocialId())) {
					socialInfoList = new ArrayList<>();
					socialInfoList.add(socialFundInfo);
				}
				if (Common.isNotNull(socialFundInfo.getFundId())) {
					fundList = new ArrayList<>();
					fundList.add(socialFundInfo);
				}
			} else {
				socialInfoList = socialFundInfoMapper.getSocialList(empIdCard, null);
				fundList = socialFundInfoMapper.getFundList(empIdCard, null);
			}
		}
		if (Common.isEmpty(socialInfoList)
				&& Common.isEmpty(fundList)) {
			return R.failed("无需要重新生成的数据(无数据或数据已结算不可重新生成！)");
		}
		//先删除然后重新生成
		boolean isSaveAndUpdate = false;

		if (Common.isNotNull(librarySocialList)) {
			baseMapper.deleteBatchIds(librarySocialList);
		}
		if (Common.isNotNull(libraryFundList)) {
			baseMapper.deleteBatchIds(libraryFundList);
		}
		// 新基数，老比例，存放Map
		HashMap<String, TForecastLibrary> socialHistoryMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundHistoryMap = new HashMap<>();
		// 已推送的预估明细Map
		HashMap<String, TForecastLibrary> socialPushMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundPushMap = new HashMap<>();
		// 组建基础Map
		this.getBaseMap(librarySocialList, librarySocialListTemp, libraryFundList, libraryFundListTemp
				, socialHistoryMap, fundHistoryMap, socialPushMap, fundPushMap);
		boolean isReduceSocial = false;
		boolean isReduceFund = false;
		Map<String, TForecastLibrary> saveLibraryMap = new HashMap<>();
		// 核心刷新
		R<String> coreR = this.doCore(payMonthList, socialInfoList, fundList, agentConfigHashMap, socialHistoryMap
				, fundHistoryMap, socialPushMap, fundPushMap, saveLibraryMap, isReduceSocial, isReduceFund, isOnly);
		if (coreR != null) return coreR;
		YifuUser user = SecurityUtils.getUser();
		String userId = "305";
		String userName = "系统";
		if (user != null) {
			userId = user.getId();
			userName = user.getNickname();
		}

		for (TForecastLibrary library : saveLibraryMap.values()) {
			if (Common.isEmpty(library.getSocialId()) && Common.isEmpty(library.getProvidentId())) {
				continue;
			}
			if (Common.isNotNull(library.getId())) {
				library.setUpdateBy(userId);
				long startTime = System.currentTimeMillis();
				baseMapper.updateForecastById(library);
				long times = System.currentTimeMillis() - startTime;
				log.info("更新一条预估耗时：" + times + "毫秒");
				isSaveAndUpdate = true;
			} else {
				if (BigDecimal.ZERO.compareTo(BigDecimalUtils.isNullToZero(library.getUnitSocialSum())) != CommonConstants.ZERO_INT) {
					if (null != socialMap) {
						String sameKey = library.getEmpIdcard() + "_" + library.getSocialCreateMonth() + "_" + library.getSocialPayMonth();
						if (null == socialMap.get(sameKey)) {
							socialMap.put(sameKey,CommonConstants.ONE_STRING);
						} else {
							continue;
						}
					}
					library.setCreateBy(userId);
					library.setCreateName(userName);
					library.setCreateTime(LocalDateTime.now());
					baseMapper.insert(library);
					isSaveAndUpdate = true;
				} else if (BigDecimal.ZERO.compareTo(BigDecimalUtils.isNullToZero(library.getUnitFundSum())) != CommonConstants.ZERO_INT) {
					if (null != fundMap) {
						String sameKey = library.getEmpIdcard() + "_" + library.getProvidentCreateMonth() + "_" + library.getProvidentPayMonth();
						if (null == fundMap.get(sameKey)) {
							fundMap.put(sameKey,CommonConstants.ONE_STRING);
						} else {
							continue;
						}
					}
					library.setCreateBy(userId);
					library.setCreateName(userName);
					library.setCreateTime(LocalDateTime.now());
					baseMapper.insert(library);
					isSaveAndUpdate = true;
				}
			}
		}
		saveLibraryMap.clear();
		if (Common.isNotNull(socialFundInfo.getSocialId()) && CommonConstants.FOUR_STRING.equals(socialFundInfo.getSocialStatus())
				|| CommonConstants.THREE_STRING.equals(socialFundInfo.getSocialStatus())) {

			//获取所有的预估数据
			List<TForecastLibrary> librarySocialInfoList1 = new ArrayList<>();
			List<TForecastLibrary> librarySocialInfoList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					//.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSettleDomainId, socialFundInfo.getSettleDomain())
					.in(TForecastLibrary::getSocialPayMonth, payMonthList));
			if (Common.isNotNull(librarySocialInfoList)) {
				Map<String,TSettleDomainSelectVo> mapSelectVo = this.getSelectVoMap();
				String redisKey = String.valueOf(UUID.randomUUID()).replaceAll("-", "") + "_incomePush";
				for (TForecastLibrary library : librarySocialInfoList) {
					//办理成功生成收入
					createIncomeInfo(library, synFlag, mapSelectVo,redisKey);
					if (CommonConstants.ZERO_INT == library.getDataPush()) {
						librarySocialInfoList1.add(library);
					}
				}
				//推送失败的数据重新推送
				if (Common.isNotNull(redisUtil.get(redisKey))) {
					List<TIncome> list = (List<TIncome>) redisUtil.get(redisKey);
					for (TIncome income:list) {
						doJointSocialTask.asynchronousEkpIncomeT(income);
					}
					redisUtil.remove(redisKey);
				}
				if (Common.isNotNull(librarySocialInfoList1)) {
					this.pushForecastInfo(librarySocialInfoList1,synFlag,mapSelectVo);
				}
			}
		}
		if (isSaveAndUpdate) {
			return R.ok(null, "执行成功！");
		} else {
			return R.failed("执行失败！无需更新的数据！");
		}
	}

	/**
	 * @param socialFundInfo
	 * @Description: 获取最小起缴日
	 * @Author: hgw
	 * @Date: 2022/7/29 11:06
	 * @return: java.util.Date
	 **/
	private Date getMinDate(TSocialFundInfo socialFundInfo) {
		Date minStartDate = null;
		if (socialFundInfo.getSocialStartDate() != null) {
			minStartDate = socialFundInfo.getSocialStartDate();
			if (socialFundInfo.getUnitPersionMoney() != null && socialFundInfo.getPensionStart() != null && socialFundInfo.getPensionStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getPensionStart();
			}
			if (socialFundInfo.getUnitMedicalMoney() != null && socialFundInfo.getMedicalStart() != null && socialFundInfo.getMedicalStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getMedicalStart();
			}
			if (socialFundInfo.getUnitUnemploymentMoney() != null && socialFundInfo.getUnemployStart() != null && socialFundInfo.getUnemployStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getUnemployStart();
			}
			if (socialFundInfo.getUnitInjuryMoney() != null && socialFundInfo.getWorkInjuryStart() != null && socialFundInfo.getWorkInjuryStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getWorkInjuryStart();
			}
			if (socialFundInfo.getUnitBirthMoney() != null && socialFundInfo.getBirthStart() != null && socialFundInfo.getBirthStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getBirthStart();
			}
		}
		if (socialFundInfo.getProvidentStart() != null
				&& (null == minStartDate || socialFundInfo.getProvidentStart().before(minStartDate))) {
			minStartDate = socialFundInfo.getProvidentStart();
		}
		if (null == minStartDate) {
			minStartDate = new Date();
		}
		return minStartDate;
	}

	private Date getMinSocialDate(TSocialFundInfo socialFundInfo) {
		Date minStartDate = null;
		if (socialFundInfo.getSocialStartDate() != null) {
			minStartDate = socialFundInfo.getSocialStartDate();
			if (socialFundInfo.getUnitPersionMoney() != null && socialFundInfo.getPensionStart() != null && socialFundInfo.getPensionStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getPensionStart();
			}
			if (socialFundInfo.getUnitMedicalMoney() != null && socialFundInfo.getMedicalStart() != null && socialFundInfo.getMedicalStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getMedicalStart();
			}
			if (socialFundInfo.getUnitUnemploymentMoney() != null && socialFundInfo.getUnemployStart() != null && socialFundInfo.getUnemployStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getUnemployStart();
			}
			if (socialFundInfo.getUnitInjuryMoney() != null && socialFundInfo.getWorkInjuryStart() != null && socialFundInfo.getWorkInjuryStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getWorkInjuryStart();
			}
			if (socialFundInfo.getUnitBirthMoney() != null && socialFundInfo.getBirthStart() != null && socialFundInfo.getBirthStart().before(minStartDate)) {
				minStartDate = socialFundInfo.getBirthStart();
			}
		}
		if (null == minStartDate) {
			minStartDate = new Date();
		}
		return minStartDate;
	}

	/**
	 * @Description: 核心刷新
	 * @Author: hgw
	 * @Date: 2022/7/25 19:39
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	private R<String> doCore(List<String> payMonthList, List<TSocialFundInfo> socialInfoList
			, List<TSocialFundInfo> fundList, HashMap<String, TAgentConfig> agentConfigHashMap
			, HashMap<String, TForecastLibrary> socialHistoryMap, HashMap<String, TForecastLibrary> fundHistoryMap
			, HashMap<String, TForecastLibrary> socialPushMap, HashMap<String, TForecastLibrary> fundPushMap
			, Map<String, TForecastLibrary> saveLibraryMap, boolean isReduceSocial, boolean isReduceFund, boolean isOnly) {
		// 预估历史，存储基数
		TForecastLibrary historyLibrary;
		boolean flag;
		String createMonth;
		String sfMapKey;
		TForecastLibrary tForecastLibrary;
		TForecastLibrary newForecastLibrary;
		String diffType;
		Date minStartDate;
		for (String payMonth : payMonthList) {
			//封装社保预估数据
			if (Common.isNotNull(socialInfoList)) {
				for (TSocialFundInfo tSocialInfo : socialInfoList) {
					minStartDate = this.getMinSocialDate(tSocialInfo);
					createMonth = ServiceUtil.initCreateMonth(tSocialInfo.getCreateTime(), payMonth);
					sfMapKey = this.getMapKey(tSocialInfo.getEmpIdcard(), tSocialInfo.getSettleDomain(), payMonth, createMonth, CommonConstants.ZERO_STRING);

					// 变更：已推送的，计算变更值
					tForecastLibrary = socialPushMap.get(sfMapKey);
					diffType = SocialConstants.DIFF_TYPE_ONE;
					if (null != tForecastLibrary) {
						diffType = SocialConstants.DIFF_TYPE_TWO;
					} else if (CommonConstants.dingleDigitStrArray[5].equals(tSocialInfo.getSocialStatus())
							|| CommonConstants.dingleDigitStrArray[10].equals(tSocialInfo.getSocialStatus())) {
						// 5 办理失败 10 审核不通过，且无推送数据，不新增
						continue;
					}
					// 户调基，值看预估库历史数据有没有
					if (isOnly) {
						historyLibrary = socialHistoryMap.get(sfMapKey);
						if (historyLibrary != null) {
							// 初始化社保
							initSocialLibary(diffType, payMonth, saveLibraryMap, tSocialInfo, isReduceFund
									, agentConfigHashMap, sfMapKey, historyLibrary, isOnly);
							if (null != tForecastLibrary) {
								newForecastLibrary = saveLibraryMap.get(sfMapKey);
								if (null != newForecastLibrary) {
									this.getChangeReduceData(newForecastLibrary, tForecastLibrary);
								}
							}
						}
					} else {
						//起缴月份在要生成的月份前不处理 || 截止月份在要生成的月份后不处理
						if (Integer.parseInt(payMonth) < DateUtil.formatDateInt(minStartDate)
								|| (Common.isNotNull(tSocialInfo.getSocialReduceDate())
								&& Integer.parseInt(payMonth) >= DateUtil.formatDateInt(tSocialInfo.getSocialReduceDate()))) {
							continue;
						}
						flag = CommonConstants.ZERO_STRING.equals(tSocialInfo.getCanOverpay()) && (null == tSocialInfo.getOverpayNumber() || null == tSocialInfo.getHaveThisMonth() || null == minStartDate);
						if (flag) {
							return R.failed("员工" + tSocialInfo.getEmpName() + ":" + tSocialInfo.getEmpIdcard() + SocialConstants.SOCIAL_SET_ERROR);
						} else {
							historyLibrary = socialHistoryMap.get(sfMapKey);
							// 初始化社保
							initSocialLibary(diffType, payMonth, saveLibraryMap, tSocialInfo, isReduceFund
									, agentConfigHashMap, sfMapKey, historyLibrary, isOnly);
							if (null != tForecastLibrary) {
								newForecastLibrary = saveLibraryMap.get(sfMapKey);
								if (null != newForecastLibrary) {
									this.getChangeReduceData(newForecastLibrary, tForecastLibrary);
								}
							}
						}
					}
				}
			}
			//封装公积金预估数据
			if (Common.isNotNull(fundList)) {
				for (TSocialFundInfo providentFund : fundList) {
					createMonth = ServiceUtil.initCreateMonth(providentFund.getCreateTime(), payMonth);
					sfMapKey = this.getMapKey(providentFund.getEmpIdcard(), providentFund.getSettleDomainFund(), payMonth, createMonth, CommonConstants.ONE_STRING);
					// 变更：已推送的，计算变更值
					tForecastLibrary = fundPushMap.get(sfMapKey);
					diffType = SocialConstants.DIFF_TYPE_ONE;
					if (null != tForecastLibrary) {
						diffType = SocialConstants.DIFF_TYPE_TWO;
					} else if (CommonConstants.dingleDigitStrArray[4].equals(providentFund.getFundStatus())
							|| CommonConstants.dingleDigitStrArray[9].equals(providentFund.getFundStatus())) {
						// 4办理失败9 审核不通过，且无推送数据，不新增
						continue;
					}
					// 户调基，值看预估库历史数据有没有
					if (isOnly) {
						historyLibrary = fundHistoryMap.get(sfMapKey);
						if (historyLibrary != null) {
							// 初始化公积金
							initFundLibary(diffType, payMonth, saveLibraryMap, providentFund, isReduceSocial, sfMapKey, historyLibrary, isOnly);
							if (null != tForecastLibrary) {
								newForecastLibrary = saveLibraryMap.get(sfMapKey);
								if (null != newForecastLibrary) {
									this.getChangeReduceData(newForecastLibrary, tForecastLibrary);
								}
							}
						}
					} else {
						//起缴月份在要生成的月份后不处理 || 截止月份在要生成的月份后不处理
						if (Common.isNotNull(providentFund.getProvidentStart())
								&& Integer.parseInt(payMonth) < DateUtil.formatDateInt(providentFund.getProvidentStart())
								|| (Common.isNotNull(providentFund.getFundReduceDate())
								&& Integer.parseInt(payMonth) > DateUtil.formatDateInt(providentFund.getFundReduceDate()))) {
							continue;
						}
						flag = CommonConstants.ZERO_STRING.equals(providentFund.getCanOverpay()) && (null == providentFund.getOverpayNumber() || null == providentFund.getHaveThisMonth() || null == providentFund.getProvidentStart());
						if (flag) {
							return R.failed("员工" + providentFund.getEmpName() + ":" + providentFund.getEmpIdcard() + SocialConstants.SOCIAL_SET_ERROR);
						} else {
							historyLibrary = fundHistoryMap.get(sfMapKey);
							// 初始化公积金
							initFundLibary(diffType, payMonth, saveLibraryMap, providentFund, isReduceSocial, sfMapKey, historyLibrary, isOnly);
							if (null != tForecastLibrary) {
								newForecastLibrary = saveLibraryMap.get(sfMapKey);
								if (null != newForecastLibrary) {
									this.getChangeReduceData(newForecastLibrary, tForecastLibrary);
								}
							}
						}
					}

				}
			}
		}
		return null;
	}

	/**
	 * @Description: 每月1号定时生成下月预估库数据
	 * @Author: hgw
	 * @Date: 2022/7/27 19:30
	 * @return: void
	 **/
	@Override
	public void everyMonthCreateForecastLibary() {
		List<TSocialFundInfo> socialFundInfoList = socialFundInfoMapper.selectList(Wrappers.<TSocialFundInfo>query().lambda());
		if (socialFundInfoList != null && !socialFundInfoList.isEmpty()) {
			String payMonth = DateUtil.addMonth(1);
			for (TSocialFundInfo socialFundInfo : socialFundInfoList) {
				everyMonthCreateForecastLibaryCore(payMonth, socialFundInfo);
			}
		}
	}

	private R<String> everyMonthCreateForecastLibaryCore(String payMonth, TSocialFundInfo socialFundInfo) {
		String empIdCard = socialFundInfo.getEmpIdcard();
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> librarySocialListTemp = null;
		//定义未推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundList = null;
		//定义已推送的按条件查询得到的预估数据
		List<TForecastLibrary> libraryFundListTemp = null;
		List<String> payMonthList = new ArrayList<>();
		payMonthList.add(payMonth);
		//查询出所有符合条件的社保数据
		List<TSocialFundInfo> socialInfoList = null;
		List<TSocialFundInfo> fundList = null;
		// 查询当年所有的社保临时政策用于生成预估数据
		List<TAgentConfig> configList = agentConfigMapper.selectList(Wrappers.<TAgentConfig>query().lambda()
				.eq(TAgentConfig::getOpenFlag, CommonConstants.ZERO_INT));
		HashMap<String, TAgentConfig> agentConfigHashMap = new HashMap<>();
		if (Common.isNotNull(configList) && Common.isNotNull(payMonthList)) {
			initConfigByPayMonths(configList, payMonthList, agentConfigHashMap);
		}
		//查询出所有对应条件的预估数、社保数据、公积金数据据用于重新生成
		if (Common.isNotNull(empIdCard)) {
			librarySocialList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSocialPayMonth, payMonth)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ZERO_STRING));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSocialPayMonth, payMonth)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalarySocialFlag, CommonConstants.ONE_STRING)));
			libraryFundList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.eq(TForecastLibrary::getProvidentPayMonth, payMonth)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ZERO_STRING));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.eq(TForecastLibrary::getProvidentPayMonth, payMonth)
					.and(obj -> obj.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT)
							.or().eq(TForecastLibrary::getSalaryFundFlag, CommonConstants.ONE_STRING)));
			socialInfoList = socialFundInfoMapper.getSocialList(empIdCard, null);
			fundList = socialFundInfoMapper.getFundList(empIdCard, null);
		}
		if (Common.isEmpty(socialInfoList)
				&& Common.isEmpty(fundList)) {
			return R.failed("无需要重新生成的数据(无数据或数据已结算不可重新生成！)");
		}
		//先删除然后重新生成
		if (Common.isNotNull(librarySocialList)) {
			baseMapper.deleteBatchIds(librarySocialList);
		}
		if (Common.isNotNull(libraryFundList)) {
			baseMapper.deleteBatchIds(libraryFundList);
		}
		// 已存在的预估数据，采用比例
		HashMap<String, TForecastLibrary> socialHistoryMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundHistoryMap = new HashMap<>();
		// 已推送的预估明细Map
		HashMap<String, TForecastLibrary> socialPushMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundPushMap = new HashMap<>();
		// 组建基础Map
		this.getBaseMap(librarySocialList, librarySocialListTemp, libraryFundList, libraryFundListTemp
				, socialHistoryMap, fundHistoryMap, socialPushMap, fundPushMap);
		Map<String, TForecastLibrary> saveLibraryMap = new HashMap<>();
		boolean isReduceSocial = false;
		boolean isReduceFund = false;
		// 核心刷新
		R<String> coreR = this.doCore(payMonthList, socialInfoList, fundList, agentConfigHashMap, socialHistoryMap
				, fundHistoryMap, socialPushMap, fundPushMap, saveLibraryMap, isReduceSocial, isReduceFund, false);
		if (coreR != null) return coreR;
		boolean isSaveAndUpdate = false;
		for (TForecastLibrary library : saveLibraryMap.values()) {
			if (Common.isEmpty(library.getSocialId()) && Common.isEmpty(library.getProvidentId())) {
				continue;
			}
			if (Common.isNotNull(library.getId())) {
				library.setUpdateBy("305");
				long startTime = System.currentTimeMillis();
				baseMapper.updateForecastById(library);
				long times = System.currentTimeMillis() - startTime;
				log.info("更新一条预估耗时：" + times + "毫秒");
			} else {
				library.setCreateBy("305");
				library.setCreateName("定时生成");
				library.setCreateTime(LocalDateTime.now());
				baseMapper.insert(library);
			}
			isSaveAndUpdate = true;
		}

		List<TForecastLibrary> libraryFundInfoListSocial = new ArrayList<>();
		List<TForecastLibrary> libraryFundInfoListFund = new ArrayList<>();
		//社保收入
		Map<String,TSettleDomainSelectVo> mapSelectVo = this.getSelectVoMap();
		String redisKey = String.valueOf(UUID.randomUUID()).replaceAll("-", "") + "_incomePush";
		if (Common.isNotNull(socialFundInfo.getSocialId())
				&& CommonConstants.FOUR_STRING.equals(socialFundInfo.getSocialStatus())
				|| CommonConstants.THREE_STRING.equals(socialFundInfo.getSocialStatus())) {

			//获取所有的预估数据
			List<TForecastLibrary> librarySocialInfoList;
			librarySocialInfoList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getSettleDomainId, socialFundInfo.getSettleDomain())
					.in(TForecastLibrary::getSocialPayMonth, payMonthList));

			if (Common.isNotNull(librarySocialInfoList)) {
				for (TForecastLibrary library : librarySocialInfoList) {
					//办理成功生成收入
					createIncomeInfo(library,true, mapSelectVo,redisKey);
					if (CommonConstants.ZERO_INT == library.getDataPush()) {
						libraryFundInfoListSocial.add(library);
					}
				}
			}
		}

		//公积金收入
		if (Common.isNotNull(socialFundInfo.getFundId())
				&& CommonConstants.THREE_STRING.equals(socialFundInfo.getFundStatus())) {

			//获取所有的预估数据
			List<TForecastLibrary> libraryFundInfoList;
			libraryFundInfoList = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getSettleDomainId, socialFundInfo.getSettleDomain())
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList));

			if (Common.isNotNull(libraryFundInfoList)) {
				for (TForecastLibrary library : libraryFundInfoList) {
					//办理成功生成收入
					createIncomeInfo(library,true, mapSelectVo,redisKey);
					if (CommonConstants.ZERO_INT == library.getDataPush()) {
						libraryFundInfoListFund.add(library);
					}
				}
			}
		}
		//推送失败的数据重新推送
		if (Common.isNotNull(redisUtil.get(redisKey))) {
			List<TIncome> list = (List<TIncome>) redisUtil.get(redisKey);
			for (TIncome income:list) {
				doJointSocialTask.asynchronousEkpIncomeT(income);
			}
			redisUtil.remove(redisKey);
		}
		//推送社保明细
		if (Common.isNotNull(libraryFundInfoListSocial)) {
			pushForecastInfo(libraryFundInfoListSocial,true,mapSelectVo);
		}
		//推送公积金明细
		if (Common.isNotNull(libraryFundInfoListFund)) {
			pushForecastFundInfo(libraryFundInfoListFund,true,mapSelectVo);
		}
		if (isSaveAndUpdate) {
			return R.ok(null, "执行成功！");
		} else {
			return R.failed("执行失败！无需更新的数据！");
		}
	}

	@Override
	public int updateForecastSocialStatusToSettle(List<String> idList) {
		if (idList != null && !idList.isEmpty()) {
			return baseMapper.updateForecastSocialStatusByIdList(idList, CommonConstants.ONE_STRING);
		}
		return 0;
	}

	@Override
	public TPaymentVo selectTForecastBySalaryVo(TPaymentBySalaryVo tPaymentBySalaryVo) {
		List<TPaymentBySalaryVo> list = baseMapper.selectTForecastBySalaryVo(tPaymentBySalaryVo);
		TPaymentVo vo = new TPaymentVo();
		vo.setPaymentList(list);
		return vo;
	}

	@Override
	public int updateForecastSocialStatusToNoSettle(List<String> idList) {
		if (idList != null && !idList.isEmpty()) {
			return baseMapper.updateForecastSocialStatusByIdList(idList, CommonConstants.ZERO_STRING);
		}
		return 0;
	}

	@Override
	public int updateForecastFundStatusToSettle(List<String> idList) {
		if (idList != null && !idList.isEmpty()) {
			return baseMapper.updateForecastFundStatusByIdList(idList, CommonConstants.ONE_STRING);
		}
		return 0;
	}

	@Override
	public int updateForecastFundStatusToNoSettle(List<String> idList) {
		if (idList != null && !idList.isEmpty()) {
			return baseMapper.updateForecastFundStatusByIdList(idList, CommonConstants.ZERO_STRING);
		}
		return 0;
	}

	@Override
	public void updateForSocialAndFound(UpdateSocialFoundVo infoVo) {
		if (Common.isNotNull(infoVo)) {
			baseMapper.updateForSocialAndFound(infoVo);
		}
	}

	@Override
	public void createForecastInfo() {
		long count  = baseMapper.selectCount(Wrappers.<TForecastLibrary>query().lambda()
				.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
				.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT));
		if (count > 0) {
			Map<String, TSettleDomainSelectVo> selectVoMap = this.getSelectVoMap();
			//获取所有未推送的社保预估明细数据
			List<TForecastLibrary> unPushInfo = baseMapper.selectTForecastSocialInfoList();
			int i = (int) Math.ceil((double) count / CommonConstants.ONE_THOUSAND_INT);
			if (!unPushInfo.isEmpty()) {
				List<TForecastLibrary> pushList;
				int k = 0;
				for (int j = 0; j < i; j++) {
					synchronized (this) {
						if (j == i - 1) {
							pushList = unPushInfo.subList(k, unPushInfo.size());
						} else {
							pushList = unPushInfo.subList(k, k + 1000);
						}
						k = k + 1000;
						if (Common.isNotNull(pushList)) {
							//推送数据封装并推送
							initEkpPushSocialParam(pushList, true, selectVoMap);
						}
					}
				}
			}
		}
	}

	private Map<String, TSettleDomainSelectVo> getSelectVoMap() {
		R<TSettleDomainListVo> settleDomainR = archivesDaprUtil.selectAllSettleDomainSelectVos();
		Map<String,TSettleDomainSelectVo> mapSelectVo = null;
		if (Common.isNotNull(settleDomainR) && Common.isNotNull(settleDomainR.getData())){
			mapSelectVo = settleDomainR.getData().getMapSelectVo();
		}
		if (Common.isEmpty(mapSelectVo)){
			ServiceUtil.runTimeExceptionDiy(CommonConstants.SETTLE_DOMAIN_GET_ERROR);
		}
		return mapSelectVo;
	}

	@Override
	public void createForecastFundInfo() {
		long count = baseMapper.selectCount(Wrappers.<TForecastLibrary>query().lambda()
				.eq(TForecastLibrary::getDataPush, CommonConstants.ZERO_INT)
				.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT));
		if (count > 0) {
			Map<String, TSettleDomainSelectVo> selectVoMap = this.getSelectVoMap();
			//获取所有未推送的社保预估明细数据
			List<TForecastLibrary> unPushInfo = baseMapper.selectTForecastFundInfoList();
			int i = (int) Math.ceil((double) count / CommonConstants.ONE_THOUSAND_INT);
			if (!unPushInfo.isEmpty()) {
				List<TForecastLibrary> pushList;
				int k = 0;
				for (int j = 0; j < i; j++) {
					synchronized (this) {
						if (j == i - 1) {
							pushList = unPushInfo.subList(k, unPushInfo.size());
						} else {
							pushList = unPushInfo.subList(k, k + 1000);
						}
						k = k + 1000;
						if (Common.isNotNull(pushList)) {
							//推送数据封装并推送
							initEkpPushFundParam(pushList, true, selectVoMap);
						}
					}
				}
			}
		}
	}

	@Override
	public void pushForecastInfo(List<TForecastLibrary> library, boolean synFlag,
								 Map<String,TSettleDomainSelectVo> mapSelectVo) {
		if (Common.isNotNull(library)) {
			//推送数据封装并推送
			Map<String,TSettleDomainSelectVo> selectVoMap;
			if (Common.isNotNull(mapSelectVo)) {
				selectVoMap = mapSelectVo;
			} else {
				selectVoMap = this.getSelectVoMap();
			}
			int i = (int) Math.ceil((double) library.size() / CommonConstants.ONE_THOUSAND_INT);
			if (!library.isEmpty()) {
				List<TForecastLibrary> pushList;
				int k = 0;
				for (int j = 0; j < i; j++) {
					synchronized (this) {
						if (j == i - 1) {
							pushList = library.subList(k, library.size());
						} else {
							pushList = library.subList(k, k + 1000);
						}
						k = k + 1000;
						if (Common.isNotNull(pushList)) {
							//推送数据封装并推送
							initEkpPushSocialParam(pushList, synFlag, selectVoMap);
						}
					}
				}
			}
		}
	}

	@Override
	public void pushForecastFundInfo(List<TForecastLibrary> library,boolean synFlag,
									 Map<String,TSettleDomainSelectVo> mapSelectVo) {
		if (Common.isNotNull(library)) {
			Map<String,TSettleDomainSelectVo> selectVoMap;
			if (Common.isNotNull(mapSelectVo)) {
				selectVoMap = mapSelectVo;
			} else {
				selectVoMap = this.getSelectVoMap();
			}
			//推送数据封装并推送
			int i = (int) Math.ceil((double) library.size() / CommonConstants.ONE_THOUSAND_INT);
			if (!library.isEmpty()) {
				List<TForecastLibrary> pushList;
				int k = 0;
				for (int j = 0; j < i; j++) {
					synchronized (this) {
						if (j == i - 1) {
							pushList = library.subList(k, library.size());
						} else {
							pushList = library.subList(k, k + 1000);
						}
						k = k + 1000;
						if (Common.isNotNull(pushList)) {
							//推送数据封装并推送
							initEkpPushFundParam(pushList, synFlag, selectVoMap);
						}
					}
				}
			}
		}
	}

	public void initEkpPushSocialParam(List<TForecastLibrary> unPushInfo, boolean synFlag,
									   Map<String, TSettleDomainSelectVo> selectVoMap) {
		// synFlag=true 异步推送 synFlag=false 非异步推送 兼容批量办理处理 fxj
		if (synFlag) {
			doJointSocialTask.asynchronousEkpForecastSocial(unPushInfo, selectVoMap);
		} else {
			doJointSocialTask.asynchronousEkpForecastSocialAsso(unPushInfo, selectVoMap);
		}
	}

	public void createIncomeInfo(TForecastLibrary library,boolean synFlag,Map<String,TSettleDomainSelectVo> mapSelectVo,
								 String redisKey) {
		//获取项目信息
		TSettleDomain settleDomain = new TSettleDomain();
		if (Common.isNotNull(mapSelectVo)) {
			settleDomain = mapSelectVo.get(library.getDeptNo());
		}

		//判断是否存在当月的社保或公积金收入数据
		boolean isExist = false;
		String sourceType = "";
		if (Common.isNotNull(library.getProvidentId())) {
			sourceType = CommonConstants.TWO_STRING;
		} else if (Common.isNotNull(library.getSocialId())) {
			sourceType = CommonConstants.ONE_STRING;
		}

		TIncomeDetail incomeDetail = new TIncomeDetail();
		incomeDetail.setEmpIdcard(library.getEmpIdcard());
		if (CommonConstants.ONE_STRING.equals(sourceType)) {
			incomeDetail.setPayMonth(library.getSocialPayMonth());
		} else {
			incomeDetail.setPayMonth(library.getProvidentPayMonth());
		}
		incomeDetail.setDeptNo(library.getDeptNo());
		incomeDetail.setSourceType(sourceType);
		List<TIncomeDetail> detailList = detailService.getTIncomeDetailList(incomeDetail);
		if (Common.isNotNull(detailList)) {
			BigDecimal sumMoney = BigDecimal.ZERO;
			for (TIncomeDetail income : detailList) {
				sumMoney = BigDecimalUtils.safeAdd(income.getMoney(), sumMoney);
			}
			if (sumMoney.compareTo(BigDecimal.ZERO) > CommonConstants.ZERO_INT) {
				isExist = true;
			}
		}

		if (Common.isNotNull(settleDomain)) {
			// 含有社保，则计算收入
			if (Common.isNotNull(settleDomain.getManageServerItem()) && ((settleDomain.getManageServerItem().contains(CommonConstants.ONE_STRING)
					&& CommonConstants.ONE_STRING.equals(sourceType)) || (settleDomain.getManageServerItem().contains(CommonConstants.TWO_STRING)
					&& CommonConstants.TWO_STRING.equals(sourceType))) && CommonConstants.ZERO_STRING.equals(settleDomain.getManagementTag()) &&
					CommonConstants.ONE_STRING.equals(settleDomain.getMrSettleType()) && !isExist ) {
				//预估模式
				createIncomeInsurance(library, settleDomain, CommonConstants.ONE_STRING,
						settleDomain.getManagementFee().toString(), settleDomain.getManagementType(),
						settleDomain.getManagementFee(), sourceType, synFlag,redisKey);
			}
			if (Common.isNotNull(settleDomain.getRiskServerItem()) && ((settleDomain.getRiskServerItem().contains(CommonConstants.ONE_STRING)
					&& CommonConstants.ONE_STRING.equals(sourceType)) || (settleDomain.getRiskServerItem().contains(CommonConstants.TWO_STRING)
					&& CommonConstants.TWO_STRING.equals(sourceType))) && CommonConstants.ZERO_STRING.equals(settleDomain.getRiskFundTag()) &&
					CommonConstants.ONE_STRING.equals(settleDomain.getMrSettleType()) && !isExist) {
				//预估模式
				createIncomeInsurance(library, settleDomain, CommonConstants.TWO_STRING,
						settleDomain.getRiskFundFee().toString(), settleDomain.getRiskFundType(),
						settleDomain.getRiskFundFee(), sourceType, synFlag,redisKey);
			}
		}
	}

	public void initEkpPushFundParam(List<TForecastLibrary> unPushInfo, boolean synFlag,
									 Map<String, TSettleDomainSelectVo> selectVoMap) {
		if (synFlag) {
			doJointSocialTask.asynchronousEkpForecastFund(unPushInfo, selectVoMap);
		} else {
			doJointSocialTask.asynchronousEkpForecastFundAsso(unPushInfo, selectVoMap);
		}
	}

	public void createIncomeInsurance(TForecastLibrary library, TSettleDomain settleDomain, String feeType,
									  String charges, String feeMode, BigDecimal money, String sourceType
			,boolean synFlag, String redisKey) {
		//生成收入数据
		TIncomeDetail detail = new TIncomeDetail();
		detail.setCreateTime(DateUtil.getCurrentDateTime());
		detail.setRedisKey(redisKey);
		detail.setDeptName(settleDomain.getDepartName());
		detail.setDeptNo(settleDomain.getDepartNo());
		detail.setDeptId(settleDomain.getId());
		detail.setEmpIdcard(library.getEmpIdcard());
		detail.setEmpName(library.getEmpName());
		detail.setUnitNo(settleDomain.getCustomerNo());
		detail.setUnitId(settleDomain.getCustomerId());
		detail.setUnitName(settleDomain.getCustomerName());
		detail.setDataCreateMonth(DateUtil.addMonth(0));
		detail.setSourceId(library.getId());
		detail.setSourceType(sourceType);
		if (CommonConstants.ONE_STRING.equals(sourceType)) {
			detail.setCreateMonth(library.getSocialCreateMonth());
			detail.setPayMonth(library.getSocialPayMonth());
		} else if (CommonConstants.TWO_STRING.equals(sourceType)) {
			detail.setCreateMonth(library.getProvidentCreateMonth());
			detail.setPayMonth(library.getProvidentPayMonth());
		}
		detail.setMoney(money);
		detail.setFeeType(feeType);
		detail.setFeeMode(feeMode);
		detail.setCharges(charges);
		detail.setMrSettleType(settleDomain.getMrSettleType());
		detail.setRedData(CommonConstants.ZERO_STRING);
		detail.setId(CommonConstants.NULL);
		incomeService.saveDetail(detail,synFlag);
	}
}
