/*
 *    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 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.common.mybatis.base.BaseEntity;
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 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<TForecastLibrary> 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, TForecastLibrary.class).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 = noPageDiy(searchVo);
					if (Common.isNotNull(list)) {
						ExcelUtil<TForecastLibrary> util = new ExcelUtil<>(TForecastLibrary.class);
						for (TForecastLibrary 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);
			}
		}
	}

	@Override
	public List<TForecastLibrary> noPageDiy(TForecastLibrary searchVo) {
		LambdaQueryWrapper<TForecastLibrary> wrapper = buildQueryWrapper(searchVo);
		if (Common.isNotNull(searchVo.getIdList())) {
			wrapper.in(TForecastLibrary::getId, searchVo.getIdList());
		}
		if (searchVo.getLimitStart() >= 0 && searchVo.getLimitEnd() > 0) {
			wrapper.last(" limit " + searchVo.getLimitStart() + "," + searchVo.getLimitEnd());
		}
		wrapper.orderByDesc(BaseEntity::getCreateTime);
		return baseMapper.selectList(wrapper);
	}

	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<Boolean> 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 {
			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);
		}
		boolean flag;
		// 已推送的预估明细Map
		HashMap<String, TForecastLibrary> socialPushMap = new HashMap<>();
		HashMap<String, TForecastLibrary> fundPushMap = new HashMap<>();
		// Map的key
		String sfMapKey;
		if (Common.isNotNull(librarySocialListTemp)) {
			TForecastLibrary libraryOld;
			for (TForecastLibrary library : librarySocialListTemp) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getSocialPayMonth(), library.getSocialCreateMonth());
				libraryOld = socialPushMap.get(sfMapKey);
				if (libraryOld != null) {
					this.getChangeAddData(libraryOld, library);
				}
				socialPushMap.put(sfMapKey, library);
			}
		}
		if (Common.isNotNull(libraryFundListTemp)) {
			TForecastLibrary libraryOld;
			for (TForecastLibrary library : libraryFundListTemp) {
				sfMapKey = this.getMapKey(library.getEmpIdcard(), library.getSettleDomainId(), library.getProvidentPayMonth(), library.getProvidentCreateMonth());
				libraryOld = fundPushMap.get(sfMapKey);
				if (libraryOld != null) {
					this.getChangeAddData(libraryOld, library);
				}
				fundPushMap.put(sfMapKey, library);
			}
		}
		Map<String, TForecastLibrary> saveLibraryMap = new HashMap<>();
		TForecastLibrary tForecastLibrary;
		String createMonth;
		boolean isReduceSocial = false;
		boolean isReduceFund = false;
		for (String payMonth : payMonthList) {
			//封装社保预估数据
			if (Common.isNotNull(socialInfoList)) {
				for (TSocialFundInfo tSocialInfo : socialInfoList) {
					createMonth = ServiceUtil.initCreateMonth(tSocialInfo.getCreateTime(), payMonth);
					sfMapKey = this.getMapKey(tSocialInfo.getEmpIdcard(), tSocialInfo.getSettleDomain(), payMonth, createMonth);

					// 变更：已推送的，计算变更值
					tForecastLibrary = socialPushMap.get(sfMapKey);
					if (null != tForecastLibrary) {
						this.getChangeReduceData(tSocialInfo, tForecastLibrary);
					}
					//起缴月份在要生成的月份前不处理
					if (Integer.parseInt(payMonth) < DateUtil.formatDateInt(tSocialInfo.getSocialStartDate())) {
						continue;
					}
					flag = CommonConstants.ZERO_STRING.equals(tSocialInfo.getCanOverpay()) && (null == tSocialInfo.getOverpayNumber() || null == tSocialInfo.getHaveThisMonth() || null == tSocialInfo.getSocialStartDate());
					if (flag) {
						return R.failed("员工" + tSocialInfo.getEmpName() + ":" + tSocialInfo.getEmpIdcard() + SocialConstants.SOCIAL_SET_ERROR);
					}
					// 初始化社保
					initSocialLibary(payMonth, saveLibraryMap, tSocialInfo, isReduceFund, agentConfigHashMap, tForecastLibrary, sfMapKey);
				}
			}
			//封装公积金预估数据
			if (Common.isNotNull(fundList)) {
				for (TSocialFundInfo providentFund : fundList) {
					createMonth = ServiceUtil.initCreateMonth(providentFund.getCreateTime(), payMonth);
					sfMapKey = this.getMapKey(providentFund.getEmpIdcard(), providentFund.getSettleDomainFund(), payMonth, createMonth);
					// 变更：已推送的，计算变更值
					tForecastLibrary = fundPushMap.get(sfMapKey);
					if (null != tForecastLibrary) {
						this.getChangeReduceData(providentFund, tForecastLibrary);
					}
					//起缴月份在要生成的月份后不处理
					if (Integer.parseInt(payMonth) < DateUtil.formatDateInt(providentFund.getProvidentStart())) {
						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);
					}
					// 初始化公积金
					initFundLibary(payMonth, saveLibraryMap, providentFund, isReduceSocial, tForecastLibrary, sfMapKey);
				}
			}
		}
		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("执行失败！无需更新的数据！");
		}
	}

	private String getMapKey(String empIdcard, String settleDomainId
			, String socialPayMonth, String socialCreateMonth) {
		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);
		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.getPersonalUnemploymentFee(), library.getPersonalUnemploymentFee()));
		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 socialFund
	 * @param libraryOld
	 * @Description: 获取变更的部分
	 * @Author: hgw
	 * @Date: 2022/7/20 11:29
	 * @return: void
	 **/
	private void getChangeReduceData(TSocialFundInfo socialFund, TForecastLibrary libraryOld) {
		//单位社保
		libraryOld.setUnitPensionFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitPensionFee(), socialFund.getUnitPersionMoney()));
		libraryOld.setUnitMedicalFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitMedicalFee(), socialFund.getUnitMedicalMoney()));
		libraryOld.setUnitBirthFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitBirthFee(), socialFund.getUnitBirthMoney()));
		libraryOld.setUnitWorkInjuryFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitWorkInjuryFee(), socialFund.getUnitInjuryMoney()));
		libraryOld.setUnitUnemploymentFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitUnemploymentFee(), socialFund.getUnitUnemploymentMoney()));
		libraryOld.setUnitBitailmentFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitBitailmentFee(), socialFund.getUnitBigailmentMoney()));
		libraryOld.setUnitInterestFee(BigDecimalUtils.safeSubtract(libraryOld.getUnitInterestFee(), socialFund.getUnitInterestFee()));
		libraryOld.setUnitSocialSum(BigDecimalUtils.safeSubtract(libraryOld.getUnitSocialSum(), socialFund.getUnitSocialSum()));
		// 个人社保
		libraryOld.setPersonalPensionFee(BigDecimalUtils.safeSubtract(libraryOld.getPersonalPensionFee(), socialFund.getPersonalPersionMoney()));
		libraryOld.setPersonalMedicalFee(BigDecimalUtils.safeSubtract(libraryOld.getPersonalMedicalFee(), socialFund.getPersonalMedicalMoney()));
		libraryOld.setPersonalUnemploymentFee(BigDecimalUtils.safeSubtract(libraryOld.getPersonalUnemploymentFee(), socialFund.getPersonalUnemploymentMoney()));
		libraryOld.setPersonalInterestFee(BigDecimalUtils.safeSubtract(libraryOld.getPersonalUnemploymentFee(), socialFund.getPersonalUnemploymentMoney()));
		libraryOld.setPersonalBigailmentFee(BigDecimalUtils.safeSubtract(libraryOld.getPersonalBigailmentFee(), socialFund.getPersonalBigailmentMoney()));
		libraryOld.setPersonalSocialSum(BigDecimalUtils.safeSubtract(libraryOld.getPersonalSocialSum(), socialFund.getPersonalSocialSum()));
		// 单位公积金
		libraryOld.setUnitFundSum(BigDecimalUtils.safeSubtract(libraryOld.getUnitFundSum(), socialFund.getUnitFundSum()));
		// 个人公积金
		libraryOld.setPersonalFundSum(BigDecimalUtils.safeSubtract(libraryOld.getPersonalFundSum(), socialFund.getPersonalFundSum()));
	}


	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: 填充key的基本信息
	 * @Author: hgw
	 * @Date: 2022-7-19 15:30:45
	 * @return: void
	 **/
	private void getMapKey(StringBuilder mapKeyBuilder, String socialProvince, String socialCity, String socialTown) {
		if (Common.isNotNull(socialProvince)) {
			mapKeyBuilder.append(CommonConstants.DOWN_LINE_STRING).append(socialProvince);
		}
		if (Common.isNotNull(socialCity)) {
			mapKeyBuilder.append(CommonConstants.DOWN_LINE_STRING).append(socialCity);
		} else if (Common.isNotNull(socialProvince) && "12".equals(socialProvince)) {
			mapKeyBuilder.append(CommonConstants.DOWN_LINE_STRING).append("135");
		}
		if (Common.isNotNull(socialTown)) {
			mapKeyBuilder.append(CommonConstants.DOWN_LINE_STRING).append(socialTown);
		}
	}

	private void initSocialLibary(String payMonth, Map<String, TForecastLibrary> saveLibraryMap
			, TSocialFundInfo tSocialInfo, boolean isReduceFund, HashMap<String, TAgentConfig> agentConfigMap
			, TForecastLibrary lib, String sfMapKey) {
		if (null == lib) {
			lib = new TForecastLibrary();
		}
		lib.setDataType(CommonConstants.ZERO_INT);
		lib.setEmpId(tSocialInfo.getEmpId());
		lib.setEmpIdcard(tSocialInfo.getEmpIdcard());
		lib.setEmpName(tSocialInfo.getEmpName());
		lib.setEmpNo(tSocialInfo.getEmpNo());
		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());

		//判断是否允许补缴 是否可补缴 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);
		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;
	}

	@Override
	public TForecastLibrary initForecastLibrary(TForecastLibrary library
			, TSocialFundInfo socialInfo, TSocialFundInfo fund, Integer month, boolean isReduceFund
			, boolean isReduceSocial, HashMap<String, TAgentConfig> agentConfigMap) {
		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);
			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);
		}
		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) {
		initLibrayOfPersonal(library, socialInfo, sysBaseSetInfo);
		initLibraryOfUnit(library, socialInfo, sysBaseSetInfo);
	}

	private void initLibrayOfPersonal(TForecastLibrary library, TSocialFundInfo socialInfo
			, SysBaseSetInfo sysBaseSetInfo) {
		// 个人养老基数
		BigDecimal personalPersionBase = BigDecimal.ZERO;
		// 个人医疗基数
		BigDecimal personalMedicalBase = BigDecimal.ZERO;
		// 个人失业基数
		BigDecimal personalUnemploymentBase = BigDecimal.ZERO;
		// 个人养老比例
		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;
				personalPersionPro = sysBaseSetInfo.getPersonalPersionPro();
				personalMedicalPro = sysBaseSetInfo.getPersonalMedicalPro();
				personalUnemploymentPro = sysBaseSetInfo.getPersonalUnemploymentPro();
			} else {
				personalPersionBase = socialInfo.getPersonalPensionCardinal();
				personalMedicalBase = socialInfo.getPersonalMedicalCardinal();
				personalUnemploymentBase = socialInfo.getPersonalUnemploymentCardinal();

				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);

		library.setPersonalPensionBase(personalPersionBase);
		library.setPersonalMedicalBase(personalMedicalBase);
		library.setPersonalUnemploymentBase(personalUnemploymentBase);

		library.setPersonalPersionPro(personalPersionPro);
		library.setPersonalMedicalPro(personalMedicalPro);
		library.setPersonalUnemploymentPro(personalUnemploymentPro);

		library.setPersonalMedicalFee(personalMedicalMoney);
		library.setPersonalPensionFee(personalPersionMoney);
		library.setPersonalUnemploymentFee(personalUnemploymentMoney);
	}

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

		// 单位养老比例
		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;
				unitPersionPro = sysBaseSetInfo.getUnitPersionPro();
				unitMedicalPro = sysBaseSetInfo.getUnitMedicalPro();
				unitUnemploymentPro = sysBaseSetInfo.getUnitUnemploymentPro();
				unitInjuryPro = sysBaseSetInfo.getUnitInjuryPro();
				unitBirthPro = sysBaseSetInfo.getUnitBirthPro();
			} else {
				unitPersionBase = socialInfo.getUnitPensionCardinal();
				unitMedicalBase = socialInfo.getUnitMedicalCardinal();
				unitUnemploymentBase = socialInfo.getUnitUnemploymentCardinal();
				unitInjuryBase = socialInfo.getUnitWorkInjuryCardinal();
				unitBirthBase = socialInfo.getUnitBirthCardinal();

				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);

		library.setUnitPensionBase(unitPersionBase);
		library.setUnitMedicalBase(unitMedicalBase);
		library.setUnitUnemploymentBase(unitUnemploymentBase);
		library.setUnitInjuryBase(unitInjuryBase);
		library.setUnitBirthBase(unitBirthBase);

		library.setUnitPersionPro(unitPersionPro);
		library.setUnitMedicalPro(unitMedicalPro);
		library.setUnitUnemploymentPro(unitUnemploymentPro);
		library.setUnitInjuryPro(unitInjuryPro);
		library.setUnitBirthPro(unitBirthPro);

		library.setUnitPensionFee(unitPersionMoney);
		library.setUnitMedicalFee(unitMedicalMoney);
		library.setUnitUnemploymentFee(unitUnemploymentMoney);
		library.setUnitBirthFee(unitBirthMoney);
		library.setUnitWorkInjuryFee(unitInjuryMoney);
	}

	/**
	 * 按临时政策初始化个人预估数据
	 *
	 * @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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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, CommonConstants.TWO_BIG));
		} 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.getSocialStartDate().getYear())
					|| library.getSocialPayMonth().equals(DateUtil.formatDatePatten(socialInfo.getSocialStartDate(), null))) {
				//  大病取值方式：0按定值
				library.setUnitBitailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayCompany()));
				library.setPersonalBigailmentFee(BigDecimalUtils.isNullToZero(sysBaseSetInfo.getPayPersonal()));
				//第一次收取费用逻辑：新员工入职是否收费处理逻辑：先按第一次不收取费用 (只针对按年收)
				if (library.getSocialPayMonth().equals(DateUtil.formatDatePatten(socialInfo.getSocialStartDate(), null))
						&& CommonConstants.ONE_STRING.equals(socialInfo.getIsChargePersonal())) {
					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.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()));
			}
		}
	}

	/**
	 * 初始化公积金预估信息
	 *
	 * @param payMonth
	 * @param saveLibraryMap
	 * @param providentFund
	 * @param isReduceSocial
	 * @return
	 * @Author fxj
	 * @Date 2020-07-21
	 **/
	private void initFundLibary(String payMonth, Map<String, TForecastLibrary> saveLibraryMap
			, TSocialFundInfo providentFund, boolean isReduceSocial, TForecastLibrary lib, String mapKeyStr) {
		if (lib == null) {
			lib = new TForecastLibrary();
		}
		lib.setDataType(CommonConstants.ONE_INT);
		lib.setEmpId(providentFund.getEmpId());
		lib.setEmpIdcard(providentFund.getEmpIdcard());
		lib.setEmpName(providentFund.getEmpName());
		lib.setEmpNo(providentFund.getEmpNo());
		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());

		//判断是否允许补缴 是否可补缴 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);
		saveLibraryMap.put(mapKeyStr, lib);
	}

}
