/*
 *    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.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.social.constants.SocialConstants;
import com.yifu.cloud.plus.v1.yifu.social.entity.SysBaseSetInfo;
import com.yifu.cloud.plus.v1.yifu.social.entity.TAgentConfig;
import com.yifu.cloud.plus.v1.yifu.social.entity.TForecastLibrary;
import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFundInfo;
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.util.ServiceUtil;
import com.yifu.cloud.plus.v1.yifu.social.vo.TForecastLibraryExportVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
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.*;

/**
 * 预估费用
 *
 * @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;

	/**
	 * 预估费用简单分页查询
	 *
	 * @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() + ".xlsx";
		//获取要导出的列表
		List<TForecastLibraryExportVo> list = new ArrayList<>();
		long count = noPageCountDiy(searchVo);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType("multipart/form-data");
			response.setCharacterEncoding("utf-8");
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			//EasyExcel.write(out, TEmpBadRecord.class).sheet("预估费用").doWrite(list)
			ExcelWriter excelWriter = EasyExcel.write(out, TForecastLibraryExportVo.class).includeColumnFiledNames(searchVo.getExportFields()).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; ) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = exportLibrary(searchVo);
					if (Common.isNotNull(list)) {
						ExcelUtil<TForecastLibraryExportVo> util = new ExcelUtil<>(TForecastLibraryExportVo.class);
						for (TForecastLibraryExportVo vo : list) {
							util.convertEntity(vo, null, null, null);
						}
					}
					if (Common.isNotNull(list)) {
						WriteSheet writeSheet = EasyExcel.writerSheet("预估费用" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
					i = i + CommonConstants.EXCEL_EXPORT_LIMIT;
					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 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) {
		//定义未推送的按条件查询得到的预估数据
		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));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));

			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));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.in(TForecastLibrary::getSettleDomainId, settleDomainIdList)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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);
		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())) {
				baseMapper.updateById(library);
			} else {
				library.setCreateTime(LocalDateTime.now());
				baseMapper.insert(library);
			}
			isSaveAndUpdate = true;
		}
		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);
					}
				}
			}
		}
	}

	private void initSocialLibary(String diffType, String payMonth, Map<String, TForecastLibrary> saveLibraryMap
			, TSocialFundInfo tSocialInfo, boolean isReduceFund, HashMap<String, TAgentConfig> agentConfigMap
			, String sfMapKey, TForecastLibrary historyLibrary) {
		TForecastLibrary lib = new TForecastLibrary();
		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);
		saveLibraryMap.put(sfMapKey, lib);
	}

	/**
	 * @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;
	}

	// historyLibrary_历史比例（暂时未用到）
	private TForecastLibrary initForecastLibrary(TForecastLibrary library
			, TSocialFundInfo socialInfo, TSocialFundInfo fund, Integer month, boolean isReduceFund
			, boolean isReduceSocial, HashMap<String, TAgentConfig> agentConfigMap, TForecastLibrary historyLibrary) {
		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);

			// 基数配置
			SysBaseSetInfo sysBaseSetInfo = this.getSysBaseSetInfo(CommonConstants.ZERO_STRING, socialInfo.getSocialHousehold()
					, library.getSocialPayMonth(), socialInfo.getSocialProvince(), socialInfo.getSocialCity(), socialInfo.getSocialTown());
			// 初始化大病：
			this.initLibraryBigMoneyBySocial(library, socialInfo, sysBaseSetInfo);

			initUnitAndPersonalLibrary(library, socialInfo, sysBaseSetInfo, historyLibrary);
			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 baseType  0.社保 1.公积金
	 * @param household （社保、公积金）户
	 * @param payMonth
	 * @param province
	 * @param city
	 * @param town
	 * @Description: 查找基数配置
	 * @Author: hgw
	 * @Date: 2021/1/4 15:58
	 * @return: com.yifu.cloud.v1.hrms.api.entity.SysBaseSetInfo
	 **/
	private SysBaseSetInfo getSysBaseSetInfo(String baseType, String household, String payMonth, String province, String city, String town) {
		// 基数配置
		SysBaseSetInfo sysBaseSetInfo = new SysBaseSetInfo();
		sysBaseSetInfo.setBaseType(baseType);
		sysBaseSetInfo.setDeleteFlag(CommonConstants.ZERO_STRING);
		sysBaseSetInfo.setStatus(CommonConstants.ZERO_INT);
		sysBaseSetInfo.setDepartId(household);

		if (Common.isNotNull(payMonth)
				&& payMonth.length() > 5) {
			// 社保缴纳月
			String payMonthStr = payMonth.substring(0, 4).concat("-").concat(payMonth.substring(4, 6)).concat("-01 00:00:00");
			sysBaseSetInfo.setApplyStartDate(DateUtil.stringToDateByPatten(payMonthStr, DateUtil.DATETIME_PATTERN_SECOND));
		} else {
			sysBaseSetInfo.setApplyStartDate(new Date());
		}
		sysBaseSetInfo.setProvince(Integer.parseInt(province));
		if (city != null) {
			sysBaseSetInfo.setCity(Integer.parseInt(city));
		} else {
			sysBaseSetInfo.setCity(-1);
		}
		if (town != null) {
			sysBaseSetInfo.setTown(Integer.parseInt(town));
		} else {
			sysBaseSetInfo.setTown(-1);
		}
		// 查询符合条件的基数列表
		List<SysBaseSetInfo> sysBaseSetInfoList = sysBaseSetInfoMapper.getSysBaseSetInfoNoPage(sysBaseSetInfo);
		if (sysBaseSetInfoList != null && !sysBaseSetInfoList.isEmpty()) {
			sysBaseSetInfo = sysBaseSetInfoList.get(0);
		} else {
			// 如果没找到配置，取最新的一条：
			sysBaseSetInfo.setApplyStartDate(null);
			sysBaseSetInfoList = sysBaseSetInfoMapper.getSysBaseSetInfoNoPage(sysBaseSetInfo);
			if (sysBaseSetInfoList != null && !sysBaseSetInfoList.isEmpty()) {
				sysBaseSetInfo = sysBaseSetInfoList.get(0);
			}
		}
		return sysBaseSetInfo;
	}

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

	private void initLibrayOfPersonal(TForecastLibrary library, TSocialFundInfo socialInfo
			, SysBaseSetInfo sysBaseSetInfo, TForecastLibrary historyLibrary) {
		// 个人养老基数
		BigDecimal personalPersionBase;
		// 个人医疗基数
		BigDecimal personalMedicalBase;
		// 个人失业基数
		BigDecimal personalUnemploymentBase;
		// 个人养老比例
		BigDecimal personalPersionPro = BigDecimal.ZERO;
		// 个人医疗比例
		BigDecimal personalMedicalPro = BigDecimal.ZERO;
		// 个人失业比例
		BigDecimal personalUnemploymentPro = BigDecimal.ZERO;
		// 个人养老金额
		BigDecimal personalPersionMoney;
		// 个人医疗金额
		BigDecimal personalMedicalMoney;
		// 个人失业金额
		BigDecimal personalUnemploymentMoney;
		// 存储基数（最低或最高）
		BigDecimal baseLimit;
		if (socialInfo != null) {
			if (Common.isNotNull(socialInfo.getPaymentType()) && !CommonConstants.ONE_STRING.equals(socialInfo.getPaymentType())) {
				if (CommonConstants.ZERO_STRING.equals(socialInfo.getPaymentType())) {
					baseLimit = sysBaseSetInfo.getLowerLimit();
				} else {
					baseLimit = sysBaseSetInfo.getUpperLimit();
				}
				personalPersionBase = baseLimit;
				personalMedicalBase = baseLimit;
				personalUnemploymentBase = baseLimit;
			} else {
				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 (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
			, SysBaseSetInfo sysBaseSetInfo, TForecastLibrary historyLibrary) {
		// 单位养老基数
		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;

		// 存储基数（最低或最高）
		BigDecimal baseLimit;
		if (socialInfo != null) {
			// 需要从基数配置取数据：
			if (Common.isNotNull(socialInfo.getPaymentType()) && !CommonConstants.ONE_STRING.equals(socialInfo.getPaymentType())) {
				if (CommonConstants.ZERO_STRING.equals(socialInfo.getPaymentType())) {
					baseLimit = sysBaseSetInfo.getLowerLimit();
				} else {
					baseLimit = sysBaseSetInfo.getUpperLimit();
				}
				unitPersionBase = baseLimit;
				unitMedicalBase = baseLimit;
				unitUnemploymentBase = baseLimit;
				unitInjuryBase = baseLimit;
				unitBirthBase = baseLimit;
			} else {
				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 (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 sysBaseSetInfo 基数配置
	 * @Description: 直接计算单位大病
	 * @Author: hgw
	 * @Date: 2020/12/2 14:31
	 * @return: void
	 **/
	private void setBigMoneyBySelfForUnit(TForecastLibrary library, TSocialFundInfo socialInfo, SysBaseSetInfo sysBaseSetInfo) {
		if (socialInfo.getUnitBigailmentMoney() != null) {
			library.setUnitBitailmentFee(socialInfo.getUnitBigailmentMoney());
		} else if (socialInfo.getUnitBigailmentCardinal() != null && sysBaseSetInfo.getPayCompanyPro() != null) {
			library.setUnitBitailmentFee(BigDecimalUtils.safeMultiply(
					socialInfo.getUnitBigailmentCardinal(),
					sysBaseSetInfo.getPayCompanyPro(),
					CommonConstants.ONE_OF_PERCENT));
		}
	}

	/**
	 * @param library        预估主表
	 * @param socialInfo     社保
	 * @param sysBaseSetInfo 基数配置
	 * @Description: 直接计算个人大病
	 * @Author: hgw
	 * @Date: 2020/12/2 14:31
	 * @return: void
	 **/
	private void setBigMoneyBySelfForPerson(TForecastLibrary library, TSocialFundInfo socialInfo, SysBaseSetInfo sysBaseSetInfo) {
		if (socialInfo.getPersonalBigailmentMoney() != null) {
			library.setPersonalBigailmentFee(socialInfo.getPersonalBigailmentMoney());
		} else if (socialInfo.getPersonalBigailmentCardinal() != null && sysBaseSetInfo.getPayPersonalPro() != null) {
			library.setPersonalBigailmentFee(BigDecimalUtils.safeMultiply(
					socialInfo.getPersonalBigailmentCardinal(),
					sysBaseSetInfo.getPayPersonalPro(),
					CommonConstants.ONE_OF_PERCENT));
		}
	}

	/**
	 * @param library        预估库
	 * @param socialInfo     社保
	 * @param sysBaseSetInfo 基数配置
	 * @param paymentType    0最低缴纳、1自定义、2最高缴纳
	 * @Description: 塞大病金额
	 * @Author: hgw
	 * @Date: 2020/11/25 15:51
	 * @return: void
	 **/
	private void setBigMoney(TForecastLibrary library, TSocialFundInfo socialInfo, SysBaseSetInfo sysBaseSetInfo
			, String paymentType) {
		if (CommonConstants.ZERO_STRING.equals(sysBaseSetInfo.getCollectType())) {
			if ((null != sysBaseSetInfo.getCollectMoth()
					&& Integer.parseInt(library.getSocialPayMonth().substring(4, 6)) == sysBaseSetInfo.getCollectMoth()
					&& Integer.parseInt(library.getSocialPayMonth().substring(0, 4)) != socialInfo.getBigailmentStart().getYear())
					|| library.getSocialPayMonth().equals(DateUtil.formatDatePatten(socialInfo.getBigailmentStart(), null))) {
				//  大病取值方式：0按定值
				library.setUnitBitailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayCompany()));
				library.setPersonalBigailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayPersonal()));
				//第一次收取费用逻辑：新员工入职是否收费处理逻辑：先按第一次不收取费用 (只针对按年收)
				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(sysBaseSetInfo.getCollectType())) {
			// 存储基数（最低或最高）
			BigDecimal baseLimit = sysBaseSetInfo.getLowerLimit();
			if (CommonConstants.TWO_STRING.equals(paymentType)) {
				baseLimit = sysBaseSetInfo.getUpperLimit();
			}
			//  大病取值方式：1 按比例   按派单的基数和比例来
			if (CommonConstants.ONE_STRING.equals(sysBaseSetInfo.getValueType())) {
				library.setUnitBigailmentBase(baseLimit);
				library.setUnitBigailmentPro(sysBaseSetInfo.getPayCompanyPro());
				library.setPersonalBigailmentBase(baseLimit);
				library.setPersonalBigailmentPro(sysBaseSetInfo.getPayPersonalPro());
				library.setPersonalBigailmentFee(BigDecimalUtils.safeMultiply(
						baseLimit,
						sysBaseSetInfo.getPayPersonalPro(),
						CommonConstants.ONE_OF_PERCENT));
				library.setUnitBitailmentFee(BigDecimalUtils.safeMultiply(
						baseLimit,
						sysBaseSetInfo.getPayCompanyPro(),
						CommonConstants.ONE_OF_PERCENT));
			} else {
				// 大病取值方式：0按定值
				library.setUnitBitailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayCompany()));
				library.setPersonalBigailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayPersonal()));
			}
		}
	}

	private void changeFundInfoByBase(TSocialFundInfo socialFund, SysBaseSetInfo socialSet) {
		if (Common.isNotNull(socialSet) && socialFund.getUnitFundSum() != null) {
			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())));
			}
		}
	}

	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());
			// 比例初始化
			// 按最低
			if (CommonConstants.ZERO_STRING.equals(social.getPaymentType())) {
				this.setBaseInfo(social, socialSet.getLowerLimit());
			} else if (CommonConstants.TWO_STRING.equals(social.getPaymentType())) {
				//按最高
				this.setBaseInfo(social, socialSet.getUpperLimit());
			} else if (CommonConstants.ONE_STRING.equals(social.getPaymentType())) {
				//自定义
				// 五险
				if (social.getUnitPensionCardinal() != null) {
					if (social.getUnitPensionCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setPersonalPensionCardinal(socialSet.getLowerLimit());
						social.setUnitPensionCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitPensionCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setPersonalPensionCardinal(socialSet.getUpperLimit());
						social.setUnitPensionCardinal(socialSet.getUpperLimit());
					}
					if (social.getUnitMedicalCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setPersonalMedicalCardinal(socialSet.getLowerLimit());
						social.setUnitMedicalCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitMedicalCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setPersonalMedicalCardinal(socialSet.getUpperLimit());
						social.setUnitMedicalCardinal(socialSet.getUpperLimit());
					}
					if (social.getUnitUnemploymentCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setPersonalUnemploymentCardinal(socialSet.getLowerLimit());
						social.setUnitUnemploymentCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitUnemploymentCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setPersonalUnemploymentCardinal(socialSet.getUpperLimit());
						social.setUnitUnemploymentCardinal(socialSet.getUpperLimit());
					}
					if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getUpperLimit());
					}
					if (social.getUnitBirthCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setUnitBirthCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitBirthCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setUnitBirthCardinal(socialSet.getUpperLimit());
					}
					if (social.getUnitBigailmentCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setPersonalBigailmentCardinal(socialSet.getLowerLimit());
						social.setUnitBigailmentCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitBigailmentCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setPersonalBigailmentCardinal(socialSet.getUpperLimit());
						social.setUnitBigailmentCardinal(socialSet.getUpperLimit());
					}
				} else if (social.getUnitWorkInjuryCardinal() != null) {
					// 兼职工伤
					if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getLowerLimit()) < CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getLowerLimit());
					} else if (social.getUnitWorkInjuryCardinal().compareTo(socialSet.getUpperLimit()) > CommonConstants.ZERO_INT) {
						social.setUnitWorkInjuryCardinal(socialSet.getUpperLimit());
					}
				}
			}
			// 比例与金额
			this.setProAndMoney(social, socialSet);
		}
	}

	/**
	 * 初始化公积金预估信息
	 *
	 * @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) {
		TForecastLibrary lib = new TForecastLibrary();
		lib.setDataPush(CommonConstants.ZERO_INT);
		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);
		saveLibraryMap.put(mapKeyStr, lib);
	}

	/**
	 * @param social
	 * @param limitBase
	 * @Description: 塞基数
	 * @Author: hgw
	 * @Date: 2022/7/27 14:55
	 * @return: void
	 **/
	private void setBaseInfo(TSocialFundInfo social, BigDecimal limitBase) {
		if (social.getUnitPensionCardinal() != null) {
			// 基数
			social.setPersonalPensionCardinal(limitBase);
			social.setPersonalMedicalCardinal(limitBase);
			social.setPersonalUnemploymentCardinal(limitBase);
			social.setPersonalBigailmentCardinal(limitBase);
			social.setUnitPensionCardinal(limitBase);
			social.setUnitMedicalCardinal(limitBase);
			social.setUnitUnemploymentCardinal(limitBase);
			social.setUnitWorkInjuryCardinal(limitBase);
			social.setUnitBigailmentCardinal(limitBase);
			social.setUnitBirthCardinal(limitBase);

		} else if (social.getUnitWorkInjuryCardinal() != null) {
			social.setUnitWorkInjuryCardinal(limitBase);
		}
	}

	/**
	 * @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.ZERO_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.ONE_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_INT));
		} else {
			sysBaseSetInfoList.add(newSysBaseSetInfo);
		}
		if (sysBaseSetInfoList != null && !sysBaseSetInfoList.isEmpty()) {
			Map<String, TSocialFundInfo> socialFundInfoMap = new HashMap<>();
			List<TSocialFundInfo> socialFundInfoList;
			for (SysBaseSetInfo sysBaseSetInfo : sysBaseSetInfoList) {
				// 社保
				if (CommonConstants.ZERO_STRING.equals(sysBaseSetInfo.getBaseType())) {
					socialFundInfoList = socialFundInfoMapper.selectList(Wrappers.<TSocialFundInfo>query().lambda()
							.eq(TSocialFundInfo::getSocialHousehold, sysBaseSetInfo.getDepartId()));
					for (TSocialFundInfo socialFundInfo : socialFundInfoList) {
						this.changeSocialInfoByBase(socialFundInfo, 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()));
					for (TSocialFundInfo socialFundInfo : socialFundInfoList) {
						this.changeFundInfoByBase(socialFundInfo, sysBaseSetInfo);
						socialFundInfoMap.put(socialFundInfo.getId(), socialFundInfo);
					}
				}
			}
			for (TSocialFundInfo socialFundInfo : socialFundInfoMap.values()) {
				this.updateForecastLibaryCore(socialFundInfo, null);
				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(socialFundInfo, doMonth);
	}

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

	/**
	 * @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) {
		String empIdCard = socialFundInfo.getEmpIdcard();
		if (Common.isNotNull(empIdCard)) {
			Date minStartDate = this.getMinSocialDate(socialFundInfo);
			BigDecimal zero = BigDecimal.ZERO;
			// 查询已经生成的预估数据
			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);
							}
						} else {
							if (DateUtil.formatDateInt(minStartDate) <= Integer.parseInt(library.getSocialPayMonth())) {
								this.calculateSocialType(zero, library);
							}
						}
					}
				}
			}

			// 公积金
			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);
							}
						} else {
							if (DateUtil.formatDateInt(minStartDate) <= Integer.parseInt(library.getProvidentPayMonth())) {
								this.calculateFundType(zero, library);
							}
						}
					}
				}
			}
		}
		return R.ok();
	}

	private void calculateSocialType(BigDecimal zero, TForecastLibrary library) {
		if (library.getDataPush() == CommonConstants.ONE_INT) {
			// 加负数
			TForecastLibrary negateLib = new TForecastLibrary();
			BeanUtil.copyProperties(library, negateLib);
			negateLib.setId(null);
			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);
		} else {
			// 删除
			baseMapper.deleteById(library.getId());
		}
	}

	private void calculateFundType(BigDecimal zero, TForecastLibrary library) {
		if (library.getDataPush() == CommonConstants.ONE_INT) {
			// 加负数
			TForecastLibrary negateLib = new TForecastLibrary();
			BeanUtil.copyProperties(library, negateLib);
			negateLib.setId(null);
			// 单位公积金
			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);
		} else {
			// 删除
			baseMapper.deleteById(library.getId());
		}
	}

	/**
	 * @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(TSocialFundInfo socialFundInfo, String doMonth) {
		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<>();
		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);
		}
		//查询出所有对应条件的预估数、社保数据、公积金数据据用于重新生成
		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));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.in(TForecastLibrary::getSocialPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.in(TForecastLibrary::getProvidentPayMonth, payMonthList)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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);
		}
		// 新基数，老比例，存放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);
		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())) {
				baseMapper.updateById(library);
			} else {
				library.setCreateTime(LocalDateTime.now());
				baseMapper.insert(library);
			}
			isSaveAndUpdate = true;
		}
		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) {
		// 预估历史，存储基数
		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.getMinDate(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 (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);
						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 (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);
						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));
			librarySocialListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ZERO_INT)
					.eq(TForecastLibrary::getSocialPayMonth, payMonth)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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));
			libraryFundListTemp = baseMapper.selectList(Wrappers.<TForecastLibrary>query().lambda()
					.eq(TForecastLibrary::getEmpIdcard, empIdCard)
					.eq(TForecastLibrary::getDataType, CommonConstants.ONE_INT)
					.eq(TForecastLibrary::getProvidentPayMonth, payMonth)
					.eq(TForecastLibrary::getDataPush, CommonConstants.ONE_INT));
			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);
		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())) {
				baseMapper.updateById(library);
			} else {
				library.setCreateTime(LocalDateTime.now());
				baseMapper.insert(library);
			}
			isSaveAndUpdate = true;
		}
		if (isSaveAndUpdate) {
			return R.ok(null, "执行成功！");
		} else {
			return R.failed("执行失败！无需更新的数据！");
		}
	}

}
