/*
 *    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 cn.hutool.core.util.ArrayUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.util.ListUtils;
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.admin.api.entity.SysArea;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.AreaVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.social.entity.SysBaseSetInfo;
import com.yifu.cloud.plus.v1.yifu.social.entity.SysHouseHoldInfo;
import com.yifu.cloud.plus.v1.yifu.social.entity.SysPayProportion;
import com.yifu.cloud.plus.v1.yifu.social.mapper.SysBaseSetInfoMapper;
import com.yifu.cloud.plus.v1.yifu.social.mapper.SysHouseHoldInfoMapper;
import com.yifu.cloud.plus.v1.yifu.social.service.SysBaseSetInfoService;
import com.yifu.cloud.plus.v1.yifu.social.service.SysPayProportionService;
import com.yifu.cloud.plus.v1.yifu.social.service.TForecastLibraryService;
import com.yifu.cloud.plus.v1.yifu.social.service.TSocialLogService;
import com.yifu.cloud.plus.v1.yifu.social.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 基数设置表
 *
 * @author hgw
 * @date 2022-07-11 18:21:23
 */
@Log4j2
@RequiredArgsConstructor
@Service
public class SysBaseSetInfoServiceImpl extends ServiceImpl<SysBaseSetInfoMapper, SysBaseSetInfo> implements SysBaseSetInfoService {

	private final TSocialLogService tSocialLogService;

	private final SysPayProportionService sysPayProportionService;

	private final SysHouseHoldInfoMapper sysHouseHoldInfoMapper;

	@Autowired
	private UpmsDaprUtils upmsDaprUtils;
	/**
	 * 基数设置表简单分页查询
	 *
	 * @param sysBaseSetInfo 基数设置表
	 * @return
	 */
	@Override
	public IPage<SysBaseSetInfo> getSysBaseSetInfoPage(Page<SysBaseSetInfo> page, SysBaseSetInfo sysBaseSetInfo) {
		return baseMapper.getSysBaseSetInfoPage(page, sysBaseSetInfo);
	}

	@Override
	public R<String> saveSysBase(SysBaseSetInfo sysBaseSetInfo) {
		YifuUser user = SecurityUtils.getUser();
		if (null == user) {
			return R.failed("获取用户登录信息失败！");
		}
		SysBaseSetInfo baseSetInfo = null;
		SysBaseSetInfo lastBase = null;
		if (null != sysBaseSetInfo.getTown()) {
			baseSetInfo = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getTown, sysBaseSetInfo.getTown())
					.and(obj -> obj
							.ge(SysBaseSetInfo::getApplyStartDate, sysBaseSetInfo.getApplyStartDate())
							.or()
							.ge(SysBaseSetInfo::getApplyEndDate, sysBaseSetInfo.getApplyStartDate()))
					.last(CommonConstants.LAST_ONE_SQL));

			lastBase = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getTown, sysBaseSetInfo.getTown())
					.isNull(SysBaseSetInfo::getApplyEndDate)
					.last(CommonConstants.LAST_ONE_SQL));
		}
		if (null != sysBaseSetInfo.getCity() && null == sysBaseSetInfo.getTown()) {
			baseSetInfo = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getCity, sysBaseSetInfo.getCity())
					.isNull(SysBaseSetInfo::getTown)
					.and(obj -> obj
							.ge(SysBaseSetInfo::getApplyStartDate, sysBaseSetInfo.getApplyStartDate())
							.or()
							.ge(SysBaseSetInfo::getApplyEndDate, sysBaseSetInfo.getApplyStartDate()))
					.last(CommonConstants.LAST_ONE_SQL));

			lastBase = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getCity, sysBaseSetInfo.getCity())
					.isNull(SysBaseSetInfo::getTown)
					.isNull(SysBaseSetInfo::getApplyEndDate)
					.last(CommonConstants.LAST_ONE_SQL));
		}
		if (null != sysBaseSetInfo.getProvince() && null == sysBaseSetInfo.getCity()) {
			baseSetInfo = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getProvince, sysBaseSetInfo.getProvince())
					.isNull(SysBaseSetInfo::getCity)
					.and(obj -> obj
							.ge(SysBaseSetInfo::getApplyStartDate, sysBaseSetInfo.getApplyStartDate())
							.or()
							.ge(SysBaseSetInfo::getApplyEndDate, sysBaseSetInfo.getApplyStartDate()))
					.last(CommonConstants.LAST_ONE_SQL));

			lastBase = this.getOne(Wrappers.<SysBaseSetInfo>query().lambda()
					.eq(SysBaseSetInfo::getBaseType, sysBaseSetInfo.getBaseType())
					.eq(SysBaseSetInfo::getDepartId, sysBaseSetInfo.getDepartId())
					.eq(SysBaseSetInfo::getProvince, sysBaseSetInfo.getProvince())
					.isNull(SysBaseSetInfo::getCity)
					.isNull(SysBaseSetInfo::getApplyEndDate)
					.last(CommonConstants.LAST_ONE_SQL));
		}
		if (null != baseSetInfo) {
			return R.failed("对应户、地市、有效期的基数配置已存在！");
		}

		// 将上一个无截止月的增加截止月（本次起始月的上一个月）
		if (lastBase != null) {
			lastBase.setApplyEndDate(DateUtil.addDayByDate(sysBaseSetInfo.getApplyStartDate(), -1));
			this.updateById(lastBase);
		}
		this.saveOrUpdateBaseAndFundPro(sysBaseSetInfo, null);
		return R.ok();
	}

	@Override
	public R<String> updateSysBase(SysBaseSetInfo sysBaseSetInfo) {
		YifuUser user = SecurityUtils.getUser();
		if (null == user) {
			return R.failed("获取用户登录信息失败！");
		}
		SysBaseSetInfo old = this.getById(sysBaseSetInfo.getId());
		if (old == null || Common.isEmpty(old.getId())) {
			return R.failed("根据id未找到基数配置！" + sysBaseSetInfo.getId());
		} else {
			List<SysPayProportion> payProportionList = sysPayProportionService.getSysPayProportionByBaseId(sysBaseSetInfo.getId());
			old.setFundProList(payProportionList);
		}
		// 2023-2-16 09:38:24 晨会上产品经理倩倩确认，编辑时，时间日期不可编辑。
		/*int count = baseMapper.getCountByEdit(sysBaseSetInfo)
		if count > CommonConstants.ZERO_INT)
			return R.failed("对应户、地市、有效期的基数配置已存在！")
		*/

		this.saveOrUpdateBaseAndFundPro(sysBaseSetInfo, old);
		int type = CommonConstants.ONE_INT;
		if (CommonConstants.ONE_STRING.equals(sysBaseSetInfo.getBaseType())) {
			type = CommonConstants.TWO_INT;
		}
		// 记录变更日志
		tSocialLogService.saveModificationRecord(type, old.getId(), old, sysBaseSetInfo);
		return R.ok();
	}

	/**
	 * @param sysBaseSetInfo
	 * @Description: 新增、编辑社保、公积金基数
	 * @Author: hgw
	 * @Date: 2022/7/12 14:33
	 * @return: void
	 **/
	private void saveOrUpdateBaseAndFundPro(SysBaseSetInfo sysBaseSetInfo, SysBaseSetInfo old) {
		if (Common.isNotNull(sysBaseSetInfo.getId())) {
			baseMapper.updateById(sysBaseSetInfo);
		} else {
			sysBaseSetInfo.setStatus(CommonConstants.ZERO_INT);
			sysBaseSetInfo.setDeleteFlag(CommonConstants.ZERO_STRING);
			sysBaseSetInfo.setIsNew(CommonConstants.ONE_STRING);
			baseMapper.insert(sysBaseSetInfo);
			// 测试用（同步社保公积金查询、预估库），后面可删除
			//tForecastLibraryService.updateForecastLibaryBySysBase(sysBaseSetInfo)
		}
		List<SysPayProportion> payProportionList = sysBaseSetInfo.getFundProList();
		Map<String, SysPayProportion> oldFundMap = new HashMap<>();
		if (old != null && Common.isNotNull(old.getFundProList())) {
			for (SysPayProportion payProportion : old.getFundProList()) {
				oldFundMap.put(payProportion.getId(), payProportion);
			}
		}
		if (Common.isNotNull(payProportionList)) {
			for (SysPayProportion payProportion : payProportionList) {
				if (Common.isNotNull(payProportion.getId())) {
					sysPayProportionService.updateById(payProportion);
					oldFundMap.remove(payProportion.getId());
				} else {
					payProportion.setSysBaseSetId(sysBaseSetInfo.getId());
					sysPayProportionService.save(payProportion);
				}
			}
			for (SysPayProportion payProportion : payProportionList) {
				payProportion.setCreateBy(null);
				payProportion.setCreateName(null);
				payProportion.setCreateTime(null);
				payProportion.setUpdateBy(null);
				payProportion.setUpdateTime(null);
			}
			if (!oldFundMap.isEmpty()) {
				for (SysPayProportion fund : oldFundMap.values()) {
					sysPayProportionService.removeById(fund);
				}
			}
		}
	}

	@Override
	public Map<String, SysBaseSetInfo> getSysBaseSetInfoMap(String baseType) {
		// 基数配置
		SysBaseSetInfo sysBaseSetInfo = new SysBaseSetInfo();
		sysBaseSetInfo.setBaseType(baseType);
		sysBaseSetInfo.setDeleteFlag(CommonConstants.STATUS_NORMAL);
		sysBaseSetInfo.setStatus(CommonConstants.ZERO_INT);
		sysBaseSetInfo.setApplyStartDate(new Date());
		// 查询符合条件的基数列表
		List<SysBaseSetInfo> sysBaseSetInfoList = baseMapper.getSysBaseSetInfoNoPage(sysBaseSetInfo);
		// 返回的map
		Map<String, SysBaseSetInfo> setInfoMap = new HashMap<>();
		if (sysBaseSetInfoList != null && !sysBaseSetInfoList.isEmpty()) {
			// map的键
			String key;
			for (SysBaseSetInfo setInfo : sysBaseSetInfoList) {
				/*key = setInfo.getDepartId() + CommonConstants.DOWN_LINE_STRING + setInfo.getProvince()
						+ CommonConstants.DOWN_LINE_STRING + setInfo.getCity();
				if (setInfo.getTown() != null) {
					key += CommonConstants.DOWN_LINE_STRING + setInfo.getTown();
				}*/
				setInfoMap.put(setInfo.getDepartName(), setInfo);
			}
		}
		return setInfoMap;
	}

	/**
	 * @Author fxj
	 * @Description 获取社保或公积金的户信息
	 * @Date 17:37 2025/11/4
	 * @Param
	 * @return
	**/
	private Map<String, SysHouseHoldInfo> getHouseHoldMap(String baseType) {
		// 基数配置
		SysHouseHoldInfo enity = new SysHouseHoldInfo();
		enity.setType(baseType);
		enity.setDelFlag(CommonConstants.STATUS_NORMAL);
		// 查询符合条件的基数列表
		List<SysHouseHoldInfo> list = sysHouseHoldInfoMapper.getSysHouseHoldNoPage(enity);
		// 返回的map
		Map<String, SysHouseHoldInfo> holdMap = new HashMap<>();
		if (list != null && !list.isEmpty()) {
			// map的键
			String key;
			for (SysHouseHoldInfo vo : list) {
				/*key = vo.getName() + CommonConstants.DOWN_LINE_STRING + vo.getProvince();
				if (vo.getCity() != null){
					key += CommonConstants.DOWN_LINE_STRING + vo.getCity();
				}
				if (vo.getTown() != null) {
					key += CommonConstants.DOWN_LINE_STRING + vo.getTown();
				}*/
				holdMap.put(vo.getName(), vo);
			}
		}
		return holdMap;
	}

	@Override
	public R<Boolean> updateByIdAsso(String id ,int status) {
		SysBaseSetInfo baseSetInfo = baseMapper.selectById(id);
		if (null == baseSetInfo){
			return R.failed("无对应ID的数据！");
		}
		if (CommonConstants.ZERO_INT == status){
			SysHouseHoldInfo holdInfo = sysHouseHoldInfoMapper.selectById(baseSetInfo.getDepartId());
			if (Common.isNotNull(holdInfo) && CommonConstants.ONE_STRING.equals(holdInfo.getDelFlag())){
				return R.failed("对应户已禁用，禁止启用基数！");
			}
		}
		baseSetInfo.setStatus(status);
		int res = baseMapper.updateById(baseSetInfo);
		if (res >= 0){
			return R.ok();
		}else {
			return R.failed(CommonConstants.RESULT_DATA_FAIL);
		}
	}

	/**
	 * 基数设置表批量导出社保基数
	 * @param searchVo 基数设置表
	 * @return
	 */
	@Override
	public void listSocialExport(HttpServletResponse response, SysBaseSetInfo searchVo){
		String fileName = "基数设置表批量导出社保基数" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<SysBaseSetSocialExportVo> list = baseMapper.noPageSocialDiy(searchVo);;
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName  , CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcel.write(out, SysBaseSetSocialExportVo.class).build();
			int index = 0;
			if (null != list  && list.size() >  CommonConstants.ZERO_INT){
				if (Common.isNotNull(list)){
					ExcelUtil<SysBaseSetSocialExportVo> util = new ExcelUtil<>(SysBaseSetSocialExportVo.class);
					for (SysBaseSetSocialExportVo vo:list){
						util.convertEntity(vo,null,null,null);
					}
				}
				if (Common.isNotNull(list)){
					WriteSheet writeSheet = EasyExcel.writerSheet("基数设置表"+index).build();
					excelWriter.write(list,writeSheet);
					index++;
				}
				if (Common.isNotNull(list)){
					list.clear();
				}
			}else {
				WriteSheet writeSheet = EasyExcel.writerSheet("基数设置表"+index).build();
				excelWriter.write(list,writeSheet);
			}
			if (Common.isNotNull(list)){
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		}catch (Exception e){
			log.error("执行异常" ,e);
		}finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	/**
	 * 基数设置表批量导出社保基数
	 * @param searchVo 基数设置表
	 * @return
	 */
	@Override
	public void listFundExport(HttpServletResponse response, SysBaseSetInfo searchVo){
		String fileName = "基数设置表批量导出公积金基数" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<SysBaseSetFundExportVo> list = baseMapper.noPageFundDiy(searchVo);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName  , CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			//EasyExcel.write(out, TEmpBadRecord.class).sheet("不良记录").doWrite(list);
			ExcelWriter excelWriter = EasyExcel.write(out, SysBaseSetFundExportVo.class).build();
			int index = 0;
			if (null != list  && list.size() >  CommonConstants.ZERO_INT){
				if (Common.isNotNull(list)){
					ExcelUtil<SysBaseSetFundExportVo> util = new ExcelUtil<>(SysBaseSetFundExportVo.class);
					for (SysBaseSetFundExportVo vo:list){
						util.convertEntity(vo,null,null,null);
					}
				}
				if (Common.isNotNull(list)){
					WriteSheet writeSheet = EasyExcel.writerSheet("基数设置表"+index).build();
					excelWriter.write(list,writeSheet);
					index++;
				}
				if (Common.isNotNull(list)){
					list.clear();
				}
			}else {
				WriteSheet writeSheet = EasyExcel.writerSheet("基数设置表"+index).build();
				excelWriter.write(list,writeSheet);
			}
			if (Common.isNotNull(list)){
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		}catch (Exception e){
			log.error("执行异常" ,e);
		}finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	public List<SysBaseSetInfo> noPageDiy(SysBaseSetInfoSearchVo searchVo) {
		LambdaQueryWrapper<SysBaseSetInfo> wrapper = buildQueryWrapper(searchVo);
		List<String> idList = Common.getList(searchVo.getIds());
		if (Common.isNotNull(idList)){
			wrapper.in(SysBaseSetInfo::getId,idList);
		}
		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(SysBaseSetInfoSearchVo searchVo) {
		LambdaQueryWrapper<SysBaseSetInfo> wrapper = buildQueryWrapper(searchVo);
		List<String> idList = Common.getList(searchVo.getIds());
		if (Common.isNotNull(idList)){
			wrapper.in(SysBaseSetInfo::getId,idList);
		}
		return baseMapper.selectCount(wrapper);
	}

	private LambdaQueryWrapper buildQueryWrapper(SysBaseSetInfoSearchVo entity){
		LambdaQueryWrapper<SysBaseSetInfo> wrapper = Wrappers.lambdaQuery();
		if (ArrayUtil.isNotEmpty(entity.getCreateTimes())) {
			wrapper.ge(SysBaseSetInfo::getCreateTime, entity.getCreateTimes()[0])
					.le(SysBaseSetInfo::getCreateTime,
							entity.getCreateTimes()[1]);
		}
		if (Common.isNotNull(entity.getCreateName())){
			wrapper.eq(SysBaseSetInfo::getCreateName,entity.getCreateName());
		}
		return wrapper;
	}

	@Override
	public R<List<ErrorMessage>> importFundDiy(InputStream inputStream) {
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<SysBaseSetFundInsertVo> util1 = new ExcelUtil<>(SysBaseSetFundInsertVo.class);;
		// 写法2：
		// 匿名内部类 不用额外写一个DemoDataListener
		// 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
		try {
			EasyExcel.read(inputStream, SysBaseSetFundInsertVo.class, new ReadListener<SysBaseSetFundInsertVo>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT;
				/**
				 *临时存储
				 */
				private List<SysBaseSetFundInsertVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

				@Override
				public void invoke(SysBaseSetFundInsertVo data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex+1);
					ErrorMessage errorMessage = util1.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)){
						errorMessageList.add(errorMessage);
					}else {
						cachedDataList.add(data);
					}
					if (cachedDataList.size() >= BATCH_COUNT) {
						saveData();
						// 存储完成清理 list
						cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
					}
				}
				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					saveData();
				}

				/**
				 * 加上存储数据库
				 */
				private void saveData() {
					log.info("{}条数据，开始存储数据库！", cachedDataList.size());
					importSysBaseSetFund(cachedDataList,errorMessageList);
					log.info("存储数据库成功！");
				}
			}).sheet().doRead();
		}catch (Exception e){
			log.error(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR,e);
			return R.failed(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR);
		}
		return  R.ok(errorMessageList);
	}

	@Override
	public R<List<ErrorMessage>> importSocialDiy(InputStream inputStream) {
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<SysBaseSetSocialInsertVo> util1 = new ExcelUtil<>(SysBaseSetSocialInsertVo.class);;
		// 写法2：
		// 匿名内部类 不用额外写一个DemoDataListener
		// 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
		try {
			EasyExcel.read(inputStream, SysBaseSetSocialInsertVo.class, new ReadListener<SysBaseSetSocialInsertVo>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT;
				/**
				 *临时存储
				 */
				private List<SysBaseSetSocialInsertVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

				@Override
				public void invoke(SysBaseSetSocialInsertVo data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex+1);
					ErrorMessage errorMessage = util1.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)){
						errorMessageList.add(errorMessage);
					}else {
						cachedDataList.add(data);
					}
					if (cachedDataList.size() >= BATCH_COUNT) {
						saveData();
						// 存储完成清理 list
						cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
					}
				}
				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					saveData();
				}

				/**
				 * 加上存储数据库
				 */
				private void saveData() {
					log.info("{}条数据，开始存储数据库！", cachedDataList.size());
					importSysBaseSetSocial(cachedDataList,errorMessageList);
					log.info("存储数据库成功！");
				}
			}).sheet().doRead();
		}catch (Exception e){
			log.error(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR,e);
			return R.failed(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR);
		}
		return  R.ok(errorMessageList);
	}
	private void importSysBaseSetSocial(List<SysBaseSetSocialInsertVo> excelVOList, List<ErrorMessage> errorMessageList) {
		// 区域数据初始化
		HashMap<String, String> areaMap = new HashMap<>();
		HashMap<String, Integer> areaMap2 = new HashMap<>();
		R<AreaVo> areaListR = upmsDaprUtils.getAreaListR();
		if (Common.isNotNull(areaListR)) {
			AreaVo areaList = areaListR.getData();
			if (null != areaList && !areaList.getSysAreaList().isEmpty()) {
				for (SysArea area : areaList.getSysAreaList()) {
					areaMap.put(Integer.toString(area.getId()), area.getAreaName());
					areaMap2.put(area.getAreaName() + CommonConstants.DOWN_LINE_STRING + (
							null == area.getParentId() ? "null" : (0 == area.getParentId() ? "null" : Integer.toString(
									area.getParentId()))), area.getId());
				}
			}
		}
		// 个性化校验逻辑
		ErrorMessage errorMsg;
		//获取已有数据有效使用周期含当前时间的数据
		Map<String, SysBaseSetInfo> socialSetInfoMap = this.getSysBaseSetInfoMap(CommonConstants.ZERO_STRING);
		//获取已有数据有效状态的户配置
		Map<String, SysHouseHoldInfo> holdMap = this.getHouseHoldMap(CommonConstants.ZERO_STRING);
		// 执行数据插入操作 组装
		SysBaseSetInfo  temp = null;
		//社保缴纳地
		String[] areaArray = null;
		//社保插入数据
		SysBaseSetSocialInsertVo excel = null;
		SysBaseSetInfo infoVo = null;
		//起始月月份
		Date dateFormat = null;
		//执行月月份
		Date dateUse = null;
		SysHouseHoldInfo hold = null;
		//补缴险种
		String insurancePension = null;
		for (int i = 0; i < excelVOList.size(); i++) {
			infoVo = new SysBaseSetInfo();
			excel = excelVOList.get(i);
			hold = holdMap.get(excel.getDepartName());
			if (Common.isEmpty(hold)){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"社保户”"+excel.getDepartName()+"“在户配置中未找到，请先到“社保公积金-配置中心-户配置”中确认是否存在该户");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setDepartName(excel.getDepartName());
			//社保缴纳地解析
			areaArray = excel.getProvinceStr().split(CommonConstants.CENTER_SPLIT_LINE_STRING);
			infoVo = initAddress(areaArray, areaMap2, infoVo);
			//比较hold对象中的省市县 与 infoVo对象中的省市县 是否一致，考虑为空的情况，不一致提示
			if (!Objects.equals(hold.getTown(), null==infoVo.getTown()?null:infoVo.getTown().toString())
					|| !Objects.equals(hold.getCity(), null==infoVo.getCity()?null:infoVo.getCity().toString())
					|| !Objects.equals(hold.getProvince(), null==infoVo.getProvince()?null:infoVo.getProvince().toString())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"社保户”"+excel.getDepartName()+"“的社保缴纳地与户配置中该户的社保缴纳地不一致，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			//校验适用其实月份及执行月月份 是否符合规则 2025-10
			if (!Common.validateFormatYearMonth(excel.getApplyStartDate())
					|| !Common.validateFormatYearMonth(excel.getDoMonth())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份或执行月月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//适用起始月份
			dateFormat = DateUtil.stringToDate2(excel.getApplyStartDate()+"-01", DateUtil.ISO_EXPANDED_DATE_FORMAT);
			if (null != dateFormat){
				infoVo.setApplyStartDate(dateFormat);
			}else {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			if (!Objects.equals(DateUtil.getYearAndMonth(dateFormat,0),DateUtil.getYearAndMonth(LocalDateTime.now(),0))
					&&  !Objects.equals(DateUtil.getYearAndMonth(dateFormat,0) , DateUtil.getYearAndMonth(LocalDateTime.now(),1))) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份只可填写“"
						+DateUtil.getYearAndMonth(new Date(),0,CommonConstants.CENTER_SPLIT_LINE_STRING) +"”或“"
						+DateUtil.getYearAndMonth(new Date(),1,CommonConstants.CENTER_SPLIT_LINE_STRING)
						+"”，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			temp = socialSetInfoMap.get(excel.getDepartName());
			// 如果已经存在使用周期内，然后判断新增的起始月份是否大于已有的起始月份，然后已有的截止月赋值为新的起始月的上月月底最后一天
			if (Common.isNotNull(temp)){
				if (temp.getApplyStartDate().getTime() >= dateFormat.getTime()){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"请检查数据，使用起始月份不能小于已存在的使用起始月份");
					errorMessageList.add(errorMsg);
					continue;
				}
				temp.setApplyEndDate(DateUtil.addDayByDate(dateFormat,-1));
			}
			//执行月份校验
			dateUse = DateUtil.stringToDate2(excel.getDoMonth()+"-01", DateUtil.ISO_EXPANDED_DATE_FORMAT);
			if (null != dateUse){
				infoVo.setDoMonth(DateUtil.getYearAndMonth(dateFormat,0));
			}else {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"执行月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//执行月份不能大于使用起始月份
			if (dateUse.after(dateFormat)){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"执行月份只能填写“"
						+DateUtil.getYearAndMonth(dateFormat,0,CommonConstants.CENTER_SPLIT_LINE_STRING)
						+"”及之前的月份，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//是否同一基数上下限
			if (!CommonConstants.ZERO_STRING.equals(excel.getIsSameBase()) && !CommonConstants.ONE_STRING.equals(excel.getIsSameBase())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"是否同一基数上下限只可填写“是”或“否”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setIsSameBase(excel.getIsSameBase());
			//是否同一基数为是时，赋值工伤、医疗、生育、失业、大病对应单位及个人基数上下限
			if (CommonConstants.ZERO_STRING.equals(excel.getIsSameBase())){
				infoVo.setUpPersion(excel.getUpPersion());
				infoVo.setLowerPersion(excel.getLowerPersion());
				infoVo.setUpInjury(excel.getUpPersion());
				infoVo.setLowerInjury(excel.getLowerPersion());
				infoVo.setUpMedical(excel.getUpPersion());
				infoVo.setLowerMedical(excel.getLowerPersion());
				infoVo.setUpBirth(excel.getUpPersion());
				infoVo.setLowerBirth(excel.getLowerPersion());
				infoVo.setUpUnemployment(excel.getUpPersion());
				infoVo.setLowerUnemployment(excel.getLowerPersion());
				infoVo.setUpperLimit(excel.getUpPersion());
				infoVo.setLowerLimit(excel.getLowerPersion());
				//如果不是按比例后面要清空
				excel.setUpBig(excel.getUpPersion());
				excel.setLowerBig(excel.getLowerPersion());
			}else if (CommonConstants.ONE_STRING.equals(excel.getIsSameBase())){
				//工伤、医疗、生育、失业 必填
				if (Common.isEmpty(excel.getUpInjury()) || Common.isEmpty(excel.getLowerInjury())
						|| Common.isEmpty(excel.getUpMedical()) || Common.isEmpty(excel.getLowerMedical())
						|| Common.isEmpty(excel.getUpBirth()) || Common.isEmpty(excel.getLowerBirth())
						|| Common.isEmpty(excel.getUpUnemployment()) || Common.isEmpty(excel.getLowerUnemployment())){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"是否同一基数上下限为否时，工伤、失业、医疗、生育上下限必填");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setUpPersion(excel.getUpPersion());
				infoVo.setLowerPersion(excel.getLowerPersion());
				infoVo.setUpInjury(excel.getUpInjury());
				infoVo.setLowerInjury(excel.getLowerInjury());
				infoVo.setUpMedical(excel.getUpMedical());
				infoVo.setLowerMedical(excel.getLowerMedical());
				infoVo.setUpBirth(excel.getUpBirth());
				infoVo.setLowerBirth(excel.getLowerBirth());
				infoVo.setUpUnemployment(excel.getUpUnemployment());
				infoVo.setLowerUnemployment(excel.getLowerUnemployment());

				excel.setUpBig(excel.getUpBig());
				excel.setLowerBig(excel.getLowerBig());

			}
			//大病是否收取
			if (!CommonConstants.ZERO_STRING.equals(excel.getIsIllness()) && !CommonConstants.ONE_STRING.equals(excel.getIsIllness())){
				if (!CommonConstants.ZERO_STRING.equals(excel.getIsIllness())){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取只可填写“是”或“否”，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
			}
			infoVo.setIsIllness(excel.getIsIllness());
			//大病是否收费为是
			if (CommonConstants.ZERO_STRING.equals(excel.getIsIllness())){
				infoVo.setIsIllness(excel.getIsIllness());
				//大病缴纳周期必填且只可是按年或按月
				if (!CommonConstants.ZERO_STRING.equals(excel.getCollectType()) && !CommonConstants.ONE_STRING.equals(excel.getCollectType())){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期必填且只可填写“按年”或“按月”，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setCollectType(excel.getCollectType());
				//大病缴纳周期按年
				if (CommonConstants.ZERO_STRING.equals(excel.getCollectType())){
					//大病缴纳周期按年  收费模式必填且只可填写“立即收费”或“次年起手”
					if (!CommonConstants.ZERO_STRING.equals(excel.getCollectTypeSub()) && !CommonConstants.ONE_STRING.equals(excel.getCollectTypeSub())){
						errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期按年时，收费模式必填且只可填写“立即收费”或“次年起收”，请修改后重新提交");
						errorMessageList.add(errorMsg);
						continue;
					}
					infoVo.setIsChargePersonal(excel.getCollectTypeSub());
					//大病缴纳周期为“按年”的，该字段必填，只可以填写一月~十二月中的任意一月
					if (!Common.getSet(CommonConstants.ONE_STRING, CommonConstants.TWO_STRING, CommonConstants.THREE_STRING,
									CommonConstants.FOUR_STRING, CommonConstants.FIVE_STRING, CommonConstants.SIX_STRING,
									CommonConstants.SEVEN_STRING, CommonConstants.EIGHT_STRING, CommonConstants.NINE_STRING,
									CommonConstants.TEN_STRING, CommonConstants.ELEVEN_STRING, CommonConstants.TWELVE_STRING)
							.contains(excel.getCollectMoth())) {
						errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期为“按年”的，缴纳月份字段必填，只可以填写一月~十二月中的任意一月，请修改后重新提交");
						errorMessageList.add(errorMsg);
						continue;
					}
					infoVo.setCollectMoth(Integer.parseInt(excel.getCollectMoth()));
				}
				//大病缴纳周期按月
				if (CommonConstants.ONE_STRING.equals(excel.getCollectType())){
					if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getValueType())){
						errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期为“按月”的，缴纳方式字段必填，只可填写“按定值”或“按比例”，请修改后重新提交");
						errorMessageList.add(errorMsg);
						continue;
					}
					infoVo.setValueType(excel.getValueType());
					//大病是否收取为是 大病缴纳周期为按月缴纳方式
					if (CommonConstants.ONE_STRING.equals(excel.getValueType())){
						//大病缴纳周期为按月缴纳方式为按比例需要填写金额 无值提示
						if (null == excel.getUpBig()
								|| null == excel.getLowerBig()
								|| excel.getLowerBig().compareTo(BigDecimal.ZERO) < 0
								|| excel.getUpBig().compareTo(BigDecimal.ZERO) < 0){
							errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期为“按月”的，单位或个人大病基数上下限字段必填，仅填写正确基数即可，请修改后重新提交");
							errorMessageList.add(errorMsg);
							continue;
						}
						infoVo.setUpBig(excel.getUpPersion());
						infoVo.setLowerBig(excel.getLowerPersion());
						//大病缴纳周期为按月缴纳方式为按比例需要填写比例无值提示
						if (null == excel.getPayCompanyPro()
								|| null == excel.getPayPersonalPro()
								|| excel.getPayPersonalPro().compareTo(BigDecimal.ZERO) < 0
								|| excel.getPayPersonalPro().compareTo(BigDecimal.ZERO) < 0){
							errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期为“按月”的，单位或个人大病比例字段必填，仅填写正确比例即可，请修改后重新提交");
							errorMessageList.add(errorMsg);
							continue;
						}
						infoVo.setPayCompanyPro(excel.getPayCompanyPro());
						infoVo.setPayPersonalPro(excel.getPayPersonalPro());
					}
				}
				//大病缴纳周期为“按年”的，或大病缴纳周期为“按月”，缴纳方式为“按定值”的，该字段必填，仅填写金额即可
				if (CommonConstants.ZERO_STRING.equals(excel.getCollectType())
						|| (CommonConstants.ONE_STRING.equals(excel.getCollectType())
						&& CommonConstants.ZERO_STRING.equals(excel.getValueType()))){
					if (null == excel.getChargeCompany()
							|| null == excel.getChargePersonal()
							|| excel.getChargePersonal().compareTo(BigDecimal.ZERO) < 0
							|| excel.getChargeCompany().compareTo(BigDecimal.ZERO) < 0){
						errorMsg = new ErrorMessage(excel.getRowIndex(),"大病是否收取为是时，大病缴纳周期为“按年”或大病缴纳周期为“按月”且缴纳方式为“按定值”时，单位或个人大病金额字段必填，仅填写正确金额即可，请修改后重新提交");
						errorMessageList.add(errorMsg);
						continue;
					}
					infoVo.setPayCompany(excel.getChargeCompany());
					infoVo.setPayPersonal(excel.getChargePersonal());
				}

			}
			//是否可补缴  只可以填写是或否，必填
			if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getCanOverpay())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"是否可补缴必填，只可填写“是”或“否”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setCanOverpay(excel.getCanOverpay());
			//是否可补缴为是时补缴险种必填
			if (CommonConstants.ZERO_STRING.equals(excel.getCanOverpay())) {
				if (!Common.isNotNull(excel.getInsurancePension())) {
					errorMsg = new ErrorMessage(excel.getRowIndex(), "是否可补缴为是时补缴险种必填，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				insurancePension = excel.getInsurancePension();
				// 可补交险种：养老、医疗、失业、工伤、生育、大病
				if (insurancePension.indexOf("养老") >= 0) {
					infoVo.setInsurancePension(CommonConstants.ZERO_STRING);
				}
				if (insurancePension.indexOf("医疗") >= 0) {
					infoVo.setInsuranceMedical(CommonConstants.ZERO_STRING);
				}
				if (insurancePension.indexOf("失业") >= 0) {
					infoVo.setInsuranceUnemployment(CommonConstants.ZERO_STRING);
				}
				if (insurancePension.indexOf("工伤") >= 0) {
					infoVo.setInsuranceInjury(CommonConstants.ZERO_STRING);
				}
				if (insurancePension.indexOf("生育") >= 0) {
					infoVo.setInsuranceBirth(CommonConstants.ZERO_STRING);
				}
				if (insurancePension.indexOf("大病") >= 0) {
					infoVo.setInsuranceBigailment(CommonConstants.ZERO_STRING);
				}
				insurancePension = insurancePension.replace("养老", "")
						.replace("医疗", "")
						.replace("失业", "")
						.replace("工伤", "")
						.replace("生育", "")
						.replace("大病", "")
						.replace(" ", "")
						.replace(",", "");
				if (insurancePension.length() > 0) {
					errorMsg = new ErrorMessage(excel.getRowIndex(), "补缴险种填写错误，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				//最大补缴期限  若是否可补缴为“是”，必填，只可填写一个月~十二个月中的任意一个月
				if (!Common.getSet(CommonConstants.ONE_STRING, CommonConstants.TWO_STRING, CommonConstants.THREE_STRING,
						CommonConstants.FOUR_STRING, CommonConstants.FIVE_STRING, CommonConstants.SIX_STRING,
						CommonConstants.SEVEN_STRING, CommonConstants.EIGHT_STRING, CommonConstants.NINE_STRING,
						CommonConstants.TEN_STRING, CommonConstants.ELEVEN_STRING, CommonConstants.TWELVE_STRING)
						.contains(excel.getOverpayNumber())){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"最大补缴期限必填，只可填写“一个月”~“十二个月”中的任意一个月，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setOverpayNumber(Integer.parseInt(excel.getOverpayNumber()));
				//是否含起缴当月 必填
				if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getHaveThisMonth())) {
					errorMsg = new ErrorMessage(excel.getRowIndex(),"是否含起缴当月必填，只可填写“是”或“否”，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setHaveThisMonth(excel.getHaveThisMonth());
				// 补缴基数 若是否可补缴为“是”，必填,只可填写“最新基数”或“当期基数”
				if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getInsuranceIsLatestCardinality())) {
					errorMsg = new ErrorMessage(excel.getRowIndex(),"补缴基数必填，只可填写“最新基数”或“当期基数”，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setInsuranceIsLatestCardinality(excel.getInsuranceIsLatestCardinality());
				// 补缴政策 必填
				if (Common.isEmpty(excel.getPayPolicy())) {
					errorMsg = new ErrorMessage(excel.getRowIndex(),"补缴政策必填，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setPayPolicy(excel.getPayPolicy());
			}
			infoVo.setUnitPersionPro(excel.getUnitPersionPro());
			infoVo.setUnitInjuryPro(excel.getUnitInjuryPro());
			infoVo.setUnitMedicalPro(excel.getUnitMedicalPro());
			infoVo.setUnitBirthPro(excel.getUnitBirthPro());
			infoVo.setUnitUnemploymentPro(excel.getUnitUnemploymentPro());
			infoVo.setPayCompanyPro(excel.getPayCompanyPro());

			infoVo.setPersonalUnemploymentPro(excel.getPersonalUnemploymentPro());
			infoVo.setPersonalMedicalPro(excel.getPersonalMedicalPro());
			infoVo.setPersonalPersionPro(excel.getPersonalPersionPro());
			infoVo.setPayPersonalPro(excel.getPayPersonalPro());
			//单位及个人比例合计
			infoVo.setUnitProSum(BigDecimalUtils.safeAdd(infoVo.getUnitInjuryPro(),
					infoVo.getUnitMedicalPro(),
					infoVo.getUnitBirthPro(),
					infoVo.getUnitUnemploymentPro(),
					infoVo.getUnitPersionPro()));
			infoVo.setPersonalProSum(BigDecimalUtils.safeAdd(infoVo.getPersonalPersionPro(),
					infoVo.getPersonalUnemploymentPro(),
					infoVo.getPersonalMedicalPro()));
			//只有大病是否收费为是 且 缴纳方式为按比例才计算合计比例
			if (CommonConstants.ZERO_STRING.equals(excel.getIsIllness()) && CommonConstants.ONE_STRING.equals(excel.getValueType())){
				infoVo.setUnitProSum(BigDecimalUtils.safeAdd(infoVo.getUnitProSum(), infoVo.getPayCompanyPro()));
				infoVo.setPersonalProSum(BigDecimalUtils.safeAdd(infoVo.getPersonalProSum(),infoVo.getPayPersonalPro()));
			}
			infoVo.setStatus(CommonConstants.ZERO_INT);
			infoVo.setBaseType(CommonConstants.ZERO_STRING);
			// 插入并更新历史数据
			try {
				insertSocialExcel(infoVo,socialSetInfoMap,temp);
			}catch (Exception e){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"数据保存失败，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			errorMessageList.add(new ErrorMessage(excel.getRowIndex(),CommonConstants.SAVE_SUCCESS));
		}
	}
	/**
	 * 插入excel bad record
	 */
	private void insertSocialExcel(SysBaseSetInfo insert ,Map<String, SysBaseSetInfo> socialSetInfoMap,SysBaseSetInfo  old) {
		if (null != old && null != old.getId()){
			this.updateById(old);
		}
		this.save(insert);
		socialSetInfoMap.put(insert.getDepartName(),insert);
	}


	private void importSysBaseSetFund(List<SysBaseSetFundInsertVo> excelVOList, List<ErrorMessage> errorMessageList) {
		// 区域数据初始化
		HashMap<String, String> areaMap = new HashMap<>();
		HashMap<String, Integer> areaMap2 = new HashMap<>();
		R<AreaVo> areaListR = upmsDaprUtils.getAreaListR();
		if (Common.isNotNull(areaListR)) {
			AreaVo areaList = areaListR.getData();
			if (null != areaList && !areaList.getSysAreaList().isEmpty()) {
				for (SysArea area : areaList.getSysAreaList()) {
					areaMap.put(Integer.toString(area.getId()), area.getAreaName());
					areaMap2.put(area.getAreaName() + CommonConstants.DOWN_LINE_STRING + (
							null == area.getParentId() ? "null" : (0 == area.getParentId() ? "null" : Integer.toString(
									area.getParentId()))), area.getId());
				}
			}
		}
		// 个性化校验逻辑
		ErrorMessage errorMsg;
		//获取已有数据有效使用周期含当前时间的数据
		Map<String, SysBaseSetInfo> fundSetInfoMap = this.getSysBaseSetInfoMap(CommonConstants.ONE_STRING);
		//获取已有数据有效状态的户配置
		Map<String, SysHouseHoldInfo> holdMap = this.getHouseHoldMap(CommonConstants.ONE_STRING);
		// 执行数据插入操作 组装
		SysBaseSetInfo  temp = null;
		//社保缴纳地
		String[] areaArray = null;
		//社保插入数据
		SysBaseSetFundInsertVo excel = null;
		SysBaseSetInfo infoVo = null;
		//起始月月份
		Date dateFormat = null;
		//执行月月份
		Date dateUse = null;
		SysHouseHoldInfo hold = null;
		//公积金比例
		List<SysPayProportion> fundProList;
		SysPayProportion fundPro = null;
		String[] split = null;
		String[] splitSub = null;
		// 执行数据插入操作 组装
		for (int i = 0; i < excelVOList.size(); i++) {
			 excel = excelVOList.get(i);
			infoVo = new SysBaseSetInfo();
			hold = holdMap.get(excel.getDepartName());
			if (Common.isEmpty(hold)){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"公积金户”"+excel.getDepartName()+"“在户配置中未找到，请先到“社保公积金-配置中心-户配置”中确认是否存在该户");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setDepartName(excel.getDepartName());
			//公积金类型
			if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getFundPayType())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"公积金类型必填，只可填写“省直”或“市直”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			//缴纳地解析
			areaArray = excel.getProvinceStr().split(CommonConstants.CENTER_SPLIT_LINE_STRING);
			infoVo = initAddress(areaArray, areaMap2, infoVo);
			//比较hold对象中的省市县 与 infoVo对象中的省市县 是否一致，考虑为空的情况，不一致提示
			if (!Objects.equals(hold.getTown(), null==infoVo.getTown()?null:infoVo.getTown().toString())
					|| !Objects.equals(hold.getCity(), null==infoVo.getCity()?null:infoVo.getCity().toString())
					|| !Objects.equals(hold.getProvince(), null==infoVo.getProvince()?null:infoVo.getProvince().toString())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"公积金户”"+excel.getDepartName()+"“的社保缴纳地与户配置中该户的社保缴纳地不一致，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			//校验适用其实月份及执行月月份 是否符合规则 2025-10
			if (!Common.validateFormatYearMonth(excel.getApplyStartDate())
					|| !Common.validateFormatYearMonth(excel.getDoMonth())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份或执行月月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//适用起始月份
			dateFormat = DateUtil.stringToDate2(excel.getApplyStartDate()+"-01", DateUtil.ISO_EXPANDED_DATE_FORMAT);
			if (null != dateFormat){
				infoVo.setApplyStartDate(dateFormat);
			}else {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			if (!Objects.equals(DateUtil.getYearAndMonth(dateFormat,0),DateUtil.getYearAndMonth(LocalDateTime.now(),0))
					&&  !Objects.equals(DateUtil.getYearAndMonth(dateFormat,0) , DateUtil.getYearAndMonth(LocalDateTime.now(),1))){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"适用起始月份只可填写“"
						+DateUtil.getYearAndMonth(new Date(),0,CommonConstants.CENTER_SPLIT_LINE_STRING) +"”或“"
						+DateUtil.getYearAndMonth(new Date(),1,CommonConstants.CENTER_SPLIT_LINE_STRING)
						+"”，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			temp = fundSetInfoMap.get(excel.getDepartName());
			// 如果已经存在使用周期内，然后判断新增的起始月份是否大于已有的起始月份，然后已有的截止月赋值为新的起始月的上月月底最后一天
			if (Common.isNotNull(temp)){
				if (temp.getApplyStartDate().getTime() >= dateFormat.getTime()){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"请检查数据，使用起始月份不能小于已存在的使用起始月份");
					errorMessageList.add(errorMsg);
					continue;
				}
				temp.setApplyEndDate(DateUtil.addDayByDate(dateFormat,-1));
			}
			//执行月份校验
			dateUse = DateUtil.stringToDate2(excel.getDoMonth()+"-01", DateUtil.ISO_EXPANDED_DATE_FORMAT);
			if (null != dateUse){
				infoVo.setDoMonth(DateUtil.getYearAndMonth(dateFormat,0));
			}else {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"执行月份格式错误，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//执行月份不能大于使用起始月份
			if (dateUse.after(dateFormat)){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"执行月份只可填写“"
						+DateUtil.getYearAndMonth(dateFormat,0,CommonConstants.CENTER_SPLIT_LINE_STRING)
						+"”及之前的月份，请修改后重新提交。");
				errorMessageList.add(errorMsg);
				continue;
			}
			//基数上下限赋值
			infoVo.setLowerLimit(excel.getLowerLimit());
			infoVo.setUpperLimit(excel.getUpperLimit());
			infoVo.setFundPayLowerLimit(excel.getLowerLimit());
			infoVo.setFundPayUpperLimit(excel.getUpperLimit());
			//单边小数点
			if (!Common.getSet(CommonConstants.ONE_STRING, CommonConstants.TWO_STRING,
					CommonConstants.THREE_STRING, CommonConstants.FOUR_STRING,
					CommonConstants.FIVE_STRING, CommonConstants.SIX_STRING)
					.contains(excel.getFundPayPoint())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"单边小数点必填，只可填写“四舍五入取整或元以下舍去或见角进元或保留两位小数或保留一位小数或见分进元”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setFundPayPoint(Integer.parseInt(excel.getFundPayPoint()));
			//单位公积金比例，个人公积金比例 :需要校验格式 为 10,10;12,13
			if (!Common.isNotNull(excel.getHousingFundPro())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"单位公积金比例，个人公积金比例必填，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			// 校验 单位公积金比例，个人公积金比例格式：10,10;12,13
			if (!Common.validateFormat(excel.getHousingFundPro())){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"单位公积金比例，个人公积金比例格式错误，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			split = excel.getHousingFundPro().split(CommonConstants.SEMICOLON_STRING);
			fundProList = new ArrayList<>();
			for (String var : split) {
				fundPro = new SysPayProportion();
				splitSub = var.split(CommonConstants.COMMA_STRING);
				if (null != splitSub && splitSub.length == 2){
					fundPro.setCompanyPro(Double.valueOf(splitSub[0]));
					fundPro.setPersonalPro(Double.valueOf(splitSub[1]));
				}
				fundProList.add(fundPro);
			}
			//是否可补缴  只可以填写是或否，必填
			if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getCanOverpay())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"是否可补缴必填，只可填写“是”或“否”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			//是否可补缴为是时补缴险种必填
			if (CommonConstants.ZERO_STRING.equals(excel.getCanOverpay())) {
				//最大补缴期限  若是否可补缴为“是”，必填，只可填写一个月~十二个月中的任意一个月
				if (!Common.getSet(CommonConstants.ONE_STRING, CommonConstants.TWO_STRING, CommonConstants.THREE_STRING,
								CommonConstants.FOUR_STRING, CommonConstants.FIVE_STRING, CommonConstants.SIX_STRING,
								CommonConstants.SEVEN_STRING, CommonConstants.EIGHT_STRING, CommonConstants.NINE_STRING,
								CommonConstants.TEN_STRING, CommonConstants.ELEVEN_STRING, CommonConstants.TWELVE_STRING)
						.contains(excel.getOverpayNumber())){
					errorMsg = new ErrorMessage(excel.getRowIndex(),"最大补缴期限必填，只可填写“一个月”~“十二个月”中的任意一个月，请修改后重新提交");
					errorMessageList.add(errorMsg);
					continue;
				}
				infoVo.setOverpayNumber(Integer.parseInt(excel.getOverpayNumber()));
			}
			//是否含起缴当月
			//是否含起缴当月 必填
			if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getHaveThisMonth())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"是否含起缴当月必填，只可填写“是”或“否”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setHaveThisMonth(excel.getHaveThisMonth());
			// 补缴基数 若是否可补缴为“是”，必填,只可填写“最新基数”或“当期基数”
			if (!Common.getSet(CommonConstants.ZERO_STRING, CommonConstants.ONE_STRING).contains(excel.getInsuranceIsLatestCardinality())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"补缴基数必填，只可填写“最新基数”或“当期基数”，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			// 补缴政策 必填
			if (Common.isEmpty(excel.getPayPolicy())) {
				errorMsg = new ErrorMessage(excel.getRowIndex(),"补缴政策必填，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}
			infoVo.setPayPolicy(excel.getPayPolicy());
			infoVo.setInsuranceIsLatestCardinality(excel.getInsuranceIsLatestCardinality());
			infoVo.setCanOverpay(excel.getCanOverpay());
			infoVo.setStatus(CommonConstants.ZERO_INT);
			infoVo.setBaseType(CommonConstants.ONE_STRING);

			// 插入
			try {
				insertFundExcel(temp,infoVo,fundProList);
			}catch (Exception e){
				errorMsg = new ErrorMessage(excel.getRowIndex(),"数据保存失败，请修改后重新提交");
				errorMessageList.add(errorMsg);
				continue;
			}

			errorMessageList.add(new ErrorMessage(excel.getRowIndex(),CommonConstants.SAVE_SUCCESS));
		}
	}
	/**
	 * 插入excel bad record
	 */
	private void insertFundExcel(SysBaseSetInfo old,SysBaseSetInfo insert,List<SysPayProportion> fundProList) {
		if (Common.isNotNull(old) && Common.isNotNull(old.getId()));{
			baseMapper.updateById( old);
		}
		baseMapper.insert(insert);
		if (Common.isNotNull(fundProList)){
			for (SysPayProportion fundPro : fundProList) {
				fundPro.setSysBaseSetId(insert.getId());
				sysPayProportionService.save(fundPro);
			}
		}
	}

	/**
	 * 转换缴纳地址为省市县ID
	 **/
	private SysBaseSetInfo initAddress(String[] areaArray, HashMap<String, Integer> areaMap2, SysBaseSetInfo s) {
		if (null == areaArray || null == areaMap2 || null == s) {
			return s;
		}
		Integer temp;
		if (areaArray.length >= CommonConstants.TWO_INT) {
			temp = areaMap2.get(areaArray[0] + CommonConstants.DOWN_LINE_STRING + "null");
			if (Common.isNotNull(temp)) {
				s.setProvince(temp);
			}
			temp = areaMap2.get(areaArray[1] + CommonConstants.DOWN_LINE_STRING + (null == s.getProvince()
					? "null" : s.getProvince()));
			if (Common.isNotNull(temp)) {
				s.setCity(temp);
			}
			if (areaArray.length >= CommonConstants.THREE_INT) {
				temp = areaMap2.get(areaArray[2] + CommonConstants.DOWN_LINE_STRING + (null == s.getCity()
						? "null" : s.getCity()));
				if (Common.isNotNull(temp)) {
					s.setTown(temp);
				}
			}
		}
		return s;
	}
}
