package com.yifu.cloud.plus.v1.csp.service.impl;

import cn.hutool.core.bean.BeanUtil;
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.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.csp.config.WxConfig;
import com.yifu.cloud.plus.v1.csp.constants.RegistConstants;
import com.yifu.cloud.plus.v1.csp.entity.EmployeeRegistration;
import com.yifu.cloud.plus.v1.csp.entity.EmployeeRegistrationLeave;
import com.yifu.cloud.plus.v1.csp.entity.TCspAttaInfo;
import com.yifu.cloud.plus.v1.csp.entity.TOperationLog;
import com.yifu.cloud.plus.v1.csp.mapper.EmployeeRegistrationMapper;
import com.yifu.cloud.plus.v1.csp.service.EmployeeRegistrationLeaveService;
import com.yifu.cloud.plus.v1.csp.service.EmployeeRegistrationService;
import com.yifu.cloud.plus.v1.csp.service.TAttaInfoService;
import com.yifu.cloud.plus.v1.csp.service.TOperationLogService;
import com.yifu.cloud.plus.v1.csp.utils.ContractTermCalculator;
import com.yifu.cloud.plus.v1.csp.vo.*;
import com.yifu.cloud.plus.v1.ekp.vo.EkpDeptContractInfoVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysUser;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.SysCspDeptVo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ClientNameConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.UserPermissionVo;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprArchivesProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.util.equator.HrEquator;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TEmployeeInsurancePre;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TInsuranceDetail;
import com.yifu.cloud.plus.v1.yifu.insurances.util.LocalDateUtil;
import com.yifu.cloud.plus.v1.yifu.insurances.util.ValidityUtil;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.TEmployeeInsurancePreVo;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.TEmployeeInsuranceSelectVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.SysBaseSetInfoVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.TEmployeeInsuranceWorkDayVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.THouseHoldLimitInnerVo;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * 入离职登记表
 *
 * @author huych
 * @date 2025-02-25 14:48:11
 */
@Log4j2
@Service
@AllArgsConstructor
@EnableConfigurationProperties(DaprArchivesProperties.class)
public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistrationMapper, EmployeeRegistration> implements EmployeeRegistrationService {

	private final DaprArchivesProperties archivesProperties;

	@Autowired
	private ArchivesDaprUtil archivesDaprUtil;

	@Autowired
	private SocialDaprUtils socialDaprUtils;

	@Autowired
	private WxConfig wxConfig;

	@Autowired
	private UpmsDaprUtils upmsDaprUtils;

	@Autowired
	private EkpDaprUtils ekpDaprUtils;

	@Autowired
	private InsuranceDaprUtil insuranceDaprUtil;

	@Autowired
	private OSSUtil ossUtil;

	@Autowired
	private final CheckDaprUtil checkDaprUtil;

	private final TAttaInfoService tAttaInfoService;

	private final TOperationLogService logService;
	private final EmployeeRegistrationLeaveService employeeRegistrationLeaveService;

	@Autowired
	private ContractTermCalculator calculator = new ContractTermCalculator();

	// 社保/公积金派单信息比较时忽略的字段
	private static final List<String> SOCIAL_IGNORE_FIELD = new ArrayList<>();
	static {
		SOCIAL_IGNORE_FIELD.add("joinLeaveDate");
		SOCIAL_IGNORE_FIELD.add("createTime");
		SOCIAL_IGNORE_FIELD.add("empName");
		SOCIAL_IGNORE_FIELD.add("phone");
		SOCIAL_IGNORE_FIELD.add("employeeName");
		SOCIAL_IGNORE_FIELD.add("empIdcard");
		SOCIAL_IGNORE_FIELD.add("deptNo");
		SOCIAL_IGNORE_FIELD.add("deptName");
		SOCIAL_IGNORE_FIELD.add("deptId");
		SOCIAL_IGNORE_FIELD.add("customerUsername");
		SOCIAL_IGNORE_FIELD.add("customerUserLoginname");
		SOCIAL_IGNORE_FIELD.add("position");
		SOCIAL_IGNORE_FIELD.add("contractId");
		SOCIAL_IGNORE_FIELD.add("errorBackInfo");
		SOCIAL_IGNORE_FIELD.add("errorInfo");
		SOCIAL_IGNORE_FIELD.add("errorTime");
		SOCIAL_IGNORE_FIELD.add("socialFundId");
		SOCIAL_IGNORE_FIELD.add("dispatcherId");
		SOCIAL_IGNORE_FIELD.add("contractStatus");
		SOCIAL_IGNORE_FIELD.add("typeSub");
		SOCIAL_IGNORE_FIELD.add("registerId");
		SOCIAL_IGNORE_FIELD.add("createBy");
		SOCIAL_IGNORE_FIELD.add("createName");
		SOCIAL_IGNORE_FIELD.add("updateBy");
		SOCIAL_IGNORE_FIELD.add("id");
		SOCIAL_IGNORE_FIELD.add("expectedCollectionType");
		SOCIAL_IGNORE_FIELD.add("upperLimit");
		SOCIAL_IGNORE_FIELD.add("lowerLimit");
		SOCIAL_IGNORE_FIELD.add("fundUpdateFlag");
		SOCIAL_IGNORE_FIELD.add("processStatus");
		SOCIAL_IGNORE_FIELD.add("isLeave");
		SOCIAL_IGNORE_FIELD.add("isRefuse");
		SOCIAL_IGNORE_FIELD.add("configId");
	}

	// 档案信息比较时忽略的字段
	private static final List<String> PRE_IGNORE_FIELD = new ArrayList<>();
	static {
		PRE_IGNORE_FIELD.add("createTime");
		PRE_IGNORE_FIELD.add("deptId");
		PRE_IGNORE_FIELD.add("dataSource");
		PRE_IGNORE_FIELD.add("createBy");
		PRE_IGNORE_FIELD.add("createName");
		PRE_IGNORE_FIELD.add("updateBy");
		PRE_IGNORE_FIELD.add("fundUpdateFlag");
		PRE_IGNORE_FIELD.add("socialUpdateFlag");
		PRE_IGNORE_FIELD.add("contractUpdateFlag");
		PRE_IGNORE_FIELD.add("isLeave");
		PRE_IGNORE_FIELD.add("isRefuse");
		PRE_IGNORE_FIELD.add("configId");
	}

	// 合同信息比较时忽略的字段
	private static final List<String> CONTRACT_IGNORE_FIELD = new ArrayList<>();
	static {
		CONTRACT_IGNORE_FIELD.add("joinLeaveDate");
		CONTRACT_IGNORE_FIELD.add("createTime");
		CONTRACT_IGNORE_FIELD.add("empPhone");
		CONTRACT_IGNORE_FIELD.add("employeeName");
		CONTRACT_IGNORE_FIELD.add("empIdcard");
		CONTRACT_IGNORE_FIELD.add("deptNo");
		CONTRACT_IGNORE_FIELD.add("deptName");
		CONTRACT_IGNORE_FIELD.add("deptId");
		CONTRACT_IGNORE_FIELD.add("changeTypeReason");
		CONTRACT_IGNORE_FIELD.add("changeTypeUser");
		CONTRACT_IGNORE_FIELD.add("changeTypeTime");
		CONTRACT_IGNORE_FIELD.add("dataSource");
		CONTRACT_IGNORE_FIELD.add("contractId");
		CONTRACT_IGNORE_FIELD.add("registerId");
		CONTRACT_IGNORE_FIELD.add("createBy");
		CONTRACT_IGNORE_FIELD.add("createName");
		CONTRACT_IGNORE_FIELD.add("updateBy");
		CONTRACT_IGNORE_FIELD.add("id");
		CONTRACT_IGNORE_FIELD.add("timeoutElecSign");
		CONTRACT_IGNORE_FIELD.add("internshipPeriodNum");
		CONTRACT_IGNORE_FIELD.add("tryPeriodNum");
		CONTRACT_IGNORE_FIELD.add("fundUpdateFlag");
		CONTRACT_IGNORE_FIELD.add("isLeave");
		CONTRACT_IGNORE_FIELD.add("isRefuse");
		CONTRACT_IGNORE_FIELD.add("configId");
	}

	// 商险明细比较时忽略的字段
	private static final List<String> INSURANCE_IGNORE_FIELD = new ArrayList<>();
	static {
		INSURANCE_IGNORE_FIELD.add("joinLeaveDate");
		INSURANCE_IGNORE_FIELD.add("createTime");
		INSURANCE_IGNORE_FIELD.add("modelType");
		INSURANCE_IGNORE_FIELD.add("empPhone");
		INSURANCE_IGNORE_FIELD.add("employeeName");
		INSURANCE_IGNORE_FIELD.add("empIdcard");
		INSURANCE_IGNORE_FIELD.add("deptNo");
		INSURANCE_IGNORE_FIELD.add("deptName");
		INSURANCE_IGNORE_FIELD.add("deptId");
		INSURANCE_IGNORE_FIELD.add("customerUsername");
		INSURANCE_IGNORE_FIELD.add("customerUserLoginname");
		INSURANCE_IGNORE_FIELD.add("dataSource");
		INSURANCE_IGNORE_FIELD.add("position");
		INSURANCE_IGNORE_FIELD.add("createBy");
		INSURANCE_IGNORE_FIELD.add("createName");
		INSURANCE_IGNORE_FIELD.add("updateBy");
		INSURANCE_IGNORE_FIELD.add("isAddress");
		INSURANCE_IGNORE_FIELD.add("fundUpdateFlag");
		INSURANCE_IGNORE_FIELD.add("socialUpdateFlag");
		INSURANCE_IGNORE_FIELD.add("contractUpdateFlag");
		INSURANCE_IGNORE_FIELD.add("isLeave");
		INSURANCE_IGNORE_FIELD.add("isRefuse");
		INSURANCE_IGNORE_FIELD.add("configId");
	}

	/**
	 * 入离职登记表简单分页查询
	 *
	 * @param employeeRegistration 入离职登记表
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistration> getEmployeeRegistrationPage(Page<EmployeeRegistration> page, EmployeeRegistrationSearchVo employeeRegistration) {
		getDtpeAuth(employeeRegistration);
		return baseMapper.getEmployeeRegistrationPage(page, employeeRegistration);
	}

	/**
	 * hr入离职登记表代办列表简单分页查询
	 *
	 * @param employeeRegistration 入离职登记表
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistration> getHrEmployeeRegistrationPage(Page<EmployeeRegistration> page, EmployeeRegistrationSearchVo employeeRegistration) {
		YifuUser user = SecurityUtils.getUser();
		// 全服管理者
		long roleId = 1839501715787390978L;
		boolean isSsc = this.haveRole(user, roleId);
		if (isSsc) {
			employeeRegistration.setCustomerUserLoginname(null);
		}
		return baseMapper.getEmployeeRegistrationPage(page, employeeRegistration);
	}

	/**
	 * 作业自动化-入离职登记列表简单分页查询
	 *
	 * @param employeeRegistration 入离职登记表
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistration> getHrAutoEmployeeRegistrationPage(Page<EmployeeRegistration> page, EmployeeRegistrationSearchVo employeeRegistration) {
		employeeRegistration.setCustomerUserLoginname(null);
		// 项目权限赋值
		employeeRegistration.setType(CommonConstants.TWO_STRING);
		initSearchVo(employeeRegistration);
		return baseMapper.getEmployeeRegistrationPage(page, employeeRegistration);
	}

	/**
	 * 入职待确认简单分页查询表简单分页查询
	 *
	 * @param employeeRegistration 入离职登记表
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistration> getHrConfirmEmployeeRegistrationPage(Page<EmployeeRegistration> page, EmployeeRegistrationSearchVo employeeRegistration) {
		//权限和条件赋值
		initSearchVo(employeeRegistration);
		if (Common.isEmpty(employeeRegistration.getStatusList())) {
			employeeRegistration.setStatusList(CommonConstants.processPreStatus);
		}
		employeeRegistration.setTypeList(CommonConstants.processPreStatus);
		return baseMapper.getEmployeeRegistrationPage(page, employeeRegistration);
	}

	@Override
	public List<EmployeeRegistration> getHrConfirmIdcardList(EmployeeRegistrationSearchVo searchVo) {
		//权限和条件赋值
		initSearchVo(searchVo);
		if (Common.isEmpty(searchVo.getStatusList())) {
			searchVo.setStatusList(CommonConstants.processPreStatus);
		}
		searchVo.setTypeList(CommonConstants.processPreStatus);
		return baseMapper.getHrConfirmIdcardList(searchVo);
	}

	/**
	 * 入离职登记表批量导出
	 *
	 * @param searchVo 入离职登记表
	 * @return
	 */
	@Override
	public void listExport(HttpServletResponse response, EmployeeRegistrationSearchVo searchVo) {
		String fileName = "入离职登记表批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationExportVo> list = new ArrayList<>();
		getDtpeAuth(searchVo);
		long count = baseMapper.selectExportCount(searchVo);
		try (ServletOutputStream 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, EmployeeRegistrationExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.selectExportList(searchVo);
					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);
		}
	}

	/**
	 * 入离职代办表批量导出
	 *
	 * @param searchVo 入离职登记表
	 */
	@Override
	public void listHrExport(HttpServletResponse response, EmployeeRegistrationSearchVo searchVo) {
		// 1.9.8: 前端客服去掉指定人查询
		YifuUser user = SecurityUtils.getUser();
		long roleId = 1839501715787390978L;
		boolean isSsc = this.haveRole(user, roleId);
		if (isSsc) {
			searchVo.setCustomerUserLoginname(null);
		}

		String fileName = "入离职待办任务表批量导出" + DateUtil.getThisTime() + ".xlsx";

		//获取要导出的列表
		List<EmployeeRegistrationHrExportVo> list = new ArrayList<>();
		long count = baseMapper.selectExportCount(searchVo);
		try (ServletOutputStream 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, EmployeeRegistrationHrExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.selectHrExportList(searchVo);
					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);
		}
	}

	/**
	 * 作业自动化-入离职登记导出
	 *
	 * @param searchVo 入离职登记表
	 * @since 1.9.8
	 * @author chenyuxi
	 */
	@Override
	public void hrRegistrationExport(HttpServletResponse response, EmployeeRegistrationSearchVo searchVo) {
		// 1.9.8: 前端客服去掉指定人查询
		searchVo.setCustomerUserLoginname(null);
		// 1.9.8: 项目权限赋值
		searchVo.setType(CommonConstants.TWO_STRING);
		initSearchVo(searchVo);

		String fileName = "入离职登记批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationHrAutoExportVo> list = new ArrayList<>();
		long count = baseMapper.selectExportCount(searchVo);
		try (ServletOutputStream 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, EmployeeRegistrationHrAutoExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.selectHrAutoExportList(searchVo);
					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);
		}

	}

	/**
	 * 入职待确认批量导出
	 * @param searchVo 入职待确认
	 * @return
	 */
	@Override
	public void hrConfirmExport(HttpServletResponse response, EmployeeRegistrationSearchVo searchVo) {
		String fileName = "入职待确认批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationHrPreExportVo> list = new ArrayList<>();
		//前端客服的所有项目权限赋值
		initSearchVo(searchVo);
		//待办列表只查看未处理的数据
		if (Common.isEmpty(searchVo.getStatusList())) {
			searchVo.setStatusList(CommonConstants.processPreStatus);
		}
		searchVo.setTypeList(CommonConstants.processPreStatus);
		long count = baseMapper.selectExportCount(searchVo);
		try (ServletOutputStream 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, EmployeeRegistrationHrPreExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.selectHrPreExportList(searchVo);
					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);
		}
	}

	@Override
	public R<List<ErrorMessage>> importDiy(InputStream inputStream, String deptId, String dataSource) {

		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<EmployeeRegistrationVo> util1 = new ExcelUtil<>(EmployeeRegistrationVo.class);
		YifuUser user = SecurityUtils.getUser();
		//获取项目信息
		R<TSettleDomainSelectVo> domainR = archivesDaprUtil.getSettleDomainSelectVoById(deptId);

		if (null == domainR || null == domainR.getData()) {
			errorMessageList.add(new ErrorMessage(-1, "访问员工基础服务异常："));
			return R.ok(errorMessageList);
		}
		TSettleDomainSelectVo selectVo = domainR.getData();

		// 1.9.8：获取项目配置的字典值
		List<String> postConfigList = new ArrayList<>();
		R<SysAutoDictItemVo> domainDictR = archivesDaprUtil.getDictListByDeptNo(deptId);
		if (Common.isNotNull(domainDictR) && Common.isNotNull(domainDictR.getData()) && Common.isNotNull(domainDictR.getData().getSysAutoDictItemList())) {
			List<SysAutoDictItem> dictItemList = domainDictR.getData().getSysAutoDictItemList();
			for(SysAutoDictItem sysAutoDictItem : dictItemList){
				if("post_type".equals(sysAutoDictItem.getType())){
					postConfigList.add(sysAutoDictItem.getLabel());
				}
			}
		}

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

				@Override
				public void invoke(EmployeeRegistrationVo 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)) {
						errorMessage.setData(data);
						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());
					importEmployeeRegistration(cachedDataList, errorMessageList, user, selectVo, postConfigList, dataSource);
					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 importEmployeeRegistration(List<EmployeeRegistrationVo> excelVOList,
											List<ErrorMessage> errorMessageList, YifuUser user, TSettleDomainSelectVo selectVo,
											List<String> postConfigList, String dataSource) {
		// 1.9.8新增来源区分
		// 没有来源默认是：1客户端
		if(Common.isEmpty(dataSource)){
			dataSource = CommonConstants.ONE_STRING;
		}

		Map<String, String> exitMap = new HashMap<>();
		EmployeeRegistrationVo excel;
		int inNum = 0;
		int outNum = 0;
		List<EmployeeRegistration> insertList = new ArrayList<>();
		for (int i = 0; i < excelVOList.size(); i++) {
			excel = excelVOList.get(i);
			// 插入
			EmployeeRegistration insert = new EmployeeRegistration();
			BeanUtil.copyProperties(excel, insert);
			//表数据验重
			//表内数据重复 员工姓名、员工身份证号码、反馈类型
			StringBuilder errorTemp = new StringBuilder();
			errorTemp.append(excel.getEmployeeName());
			errorTemp.append("_");
			errorTemp.append(excel.getEmpIdcard());
			errorTemp.append("_");
			errorTemp.append(excel.getFeedbackType());
			if (null == exitMap.get(errorTemp.toString())) {
				exitMap.put(errorTemp.toString(), "1");
			} else {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(), RegistConstants.IMPORT_EXIT_CHECK, excel));
				continue;
			}
			insert.setDeptNo(selectVo.getDepartNo());
			// 1.9.8：新增校验
			if(CommonConstants.TWO_STRING.equals(dataSource) 
					&& Common.isNotNull(postConfigList) 
					&& !postConfigList.contains(insert.getPosition())){
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "岗位不在项目配置的岗位配置项里", excel));
				continue;
			}

			String error = registCheck(insert);
			if (null != error) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(), error, excel));
				continue;
			}
			// 1.9.8：新增赋值
			insert.setDataSource(dataSource);
			initRegistInfo(insert, user, selectVo);
			insertList.add(insert);
			//新增记录,新增操作记录
			baseMapper.insert(insert);
			if (Common.isNotNull(insert.getFeedbackType()) && CommonConstants.TWO_STRING.equals(insert.getFeedbackType())) {
				// 生成离职待办
				employeeRegistrationLeaveService.saveLeaveInfo(insert);
			}
			if (CommonConstants.ONE_STRING.equals(insert.getFeedbackType())) {
				inNum++;
			} else {
				outNum++;
			}
			logService.saveLog(insert.getId(), CommonConstants.ZERO_STRING, RegistConstants.MESSAGE_REGIST, LocalDateTime.now(),
					insert.getRegistorUsername(), null);
		}
		if (!Common.isEmpty(insertList)) {
			insertList.clear();
			//发送企业微信待办
			EmployeeRegistration msgRegistration = new EmployeeRegistration();
			msgRegistration.setInNum(inNum);
			msgRegistration.setOutNum(outNum);
			msgRegistration.setCustomerUserLoginname(selectVo.getCsLoginName());
			msgRegistration.setDeptName(selectVo.getDepartName());
			msgRegistration.setDeptNo(selectVo.getDepartNo());
			//企业微信消息提醒
			sendMessageToWx(msgRegistration, CommonConstants.THREE_STRING);
		}

	}

	/**
	 * 入职待确认表确认接收
	 *
	 * @param preVo 确认接受vo
	 * @return
	 */
	@Override
	public R confirmReceive(EmployeeRegistrationPreVo preVo) {
		YifuUser user = SecurityUtils.getUser();
		if (Common.isEmpty(preVo)) {
			return R.failed(CommonConstants.PARAM_IS_NOT_ERROR);
		}
		EmployeeRegistration registration = baseMapper.selectById(preVo.getId());
		if (Common.isEmpty(registration) || (Common.isNotNull(registration) &&
				!CommonConstants.ONE_STRING.equals(registration.getProcessStatus()))) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		//错误信息
		StringBuilder errorTemp = new StringBuilder();
		if (preVo.getServerItem().contains("商险") && !preVo.getEmployeeInsurancePreVos().isEmpty()
				&& Common.isNotNull(preVo.getInsuranceIsBuy())
				&& preVo.getInsuranceIsBuy().equals(CommonConstants.ONE_STRING)) {
//			List<TEmployeeAutoRegistCheckVo> errorList = new ArrayList<>();
			TEmployeeAutoRegistCheckVo checkVo;
			String key;
			// 判断重复性MAP
			Map<String, Integer> keyMap = new HashMap<>();
			for (TEmployeeInsurancePreVo insurancePreVo : preVo.getEmployeeInsurancePreVos()) {
				// 1：重复性判断
				key = this.getFiveKey(insurancePreVo);
				if (keyMap.get(key) == null) {
					keyMap.put(key, CommonConstants.ONE_INT);
				} else {
					errorTemp.append("保险公司、险种、购买标准、保单起/止日期不可同时重复;");
//					return R.other(CommonConstants.TWO_INT,null,"保险公司、险种、购买标准、保单起/止日期不可同时重复！");
				}
				insurancePreVo.setEmpIdcard(registration.getEmpIdcard());
				insurancePreVo.setDeptNo(registration.getDeptNo());
				//商险是否存在判断
				checkVo = checkInsuranceExit(insurancePreVo,registration);
				if (null != checkVo) {
					errorTemp.append("保单开始日期：" + DateUtil.dateToString(insurancePreVo.getPolicyStart(), "yyyy-MM-dd")
							+ ",保单结束日期：" + DateUtil.dateToString(insurancePreVo.getPolicyEnd(), "yyyy-MM-dd")
							+ "这条数据存在流程中/已完结的商险数据;");
//					errorList.add(checkVo);
				} else {
					if (Common.isEmpty(insurancePreVo.getProcessStatus())) {
						insurancePreVo.setProcessStatus(CommonConstants.ZERO_STRING);
					}
				}
			}
//			if (!errorList.isEmpty()) {
//				return R.other(CommonConstants.TWO_INT,null,errorList);
//			}
		}
		//1.9.12合同自动化校验逻辑
		TEmployeeAutoRegistCheckVo cardVo = new TEmployeeAutoRegistCheckVo();
		cardVo.setEmpIdcard(registration.getEmpIdcard());
		cardVo.setDeptNo(registration.getDeptNo());
		R<Boolean> flag = archivesDaprUtil.selectExitEmpCopntract(cardVo);
		if (preVo.getServerItem().contains("合同") && null != preVo.getEmployeeContractPreVos()) {
			TEmployeeContractPreVo employeeContractPreVo = preVo.getEmployeeContractPreVos();
			//根据身份证号码和项目编号查询合同
			//是否已签署为是需要判断合同是否在用或者流程中
			if (CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getContractFlag()) &&
					(Common.isEmpty(flag) || Boolean.TRUE.equals(!flag.getData()))) {
				errorTemp.append("未找到流程中或者在用的合同;");
//				return R.other(CommonConstants.TWO_INT,null,"未找到流程中或者在用的合同！");
			}
			//是否已签署为否需要判断是否在用或者流程中的合同
			if (CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractFlag()) &&
					Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
				errorTemp.append("该项目下存在在途/有效的合同数据，请【是否已签署合同】是否调整为【是】;");
//				return R.other(CommonConstants.TWO_INT,null,"该项目下存在在途/有效的合同数据，请“是否已签署合同”是否调整为“是”");
			}
		}

		if (preVo.getServerItem().contains("商险") && Common.isNotNull(preVo.getInsuranceIsBuy())
				&& preVo.getInsuranceIsBuy().equals(CommonConstants.ZERO_STRING)
				&& !preVo.getExitInsuranceInfoList().isEmpty()) {
			//判断带出的流程中或者已完结的商险数据是否准确
			//商险是否存在判断
			preVo.setEmpIdcard(registration.getEmpIdcard());
			preVo.getExitInsuranceInfoList().forEach(e -> e.setCreateTime(null));
			boolean isTrue = checkInsuranceIsProcess(preVo);
			if (isTrue) {
				errorTemp.append("带出的商险已购买数据状态或条数发生变更，请重新确认;");
//				return R.other(CommonConstants.TWO_INT,null,"带出的商险已购买数据状态或条数发生变更，请重新确认接收！");
			}
		}

		//合同签署状态赋值
		if (null != preVo.getDispatchInfoPreVo()) {
			if (Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
				preVo.getDispatchInfoPreVo().setContractStatus(CommonConstants.ZERO_STRING);
			} else {
				preVo.getDispatchInfoPreVo().setContractStatus(CommonConstants.ONE_STRING);
			}
		}
		THouseHoldLimitInnerVo socialLimitVo = null;
		//1.9.16社保自动化校验逻辑
		if (preVo.getServerItem().contains("社保")) {
			//根据身份证号码和项目编号查询合同
			R<Boolean> socialFlag = socialDaprUtils.selectExitEmpSocial(cardVo);
			//是否已签署为是需要判断合同是否在用或者流程中
			if (CommonConstants.ZERO_STRING.equals(preVo.getSocialIsBuy()) &&
					(Common.isEmpty(socialFlag) || Boolean.TRUE.equals(!socialFlag.getData()))) {
				errorTemp.append("未找到流程中或者在用的社保信息;");
//				return R.other(CommonConstants.TWO_INT,null,"未找到流程中或者在用的社保信息！");
			}
			//是否已签署为否需要判断是否在用或者流程中的合同
			if (CommonConstants.ONE_STRING.equals(preVo.getSocialIsBuy()) &&
					Common.isNotNull(socialFlag) && Boolean.TRUE.equals(socialFlag.getData())) {
				errorTemp.append("该人员存在在途/有效的社保数据，请将【是否已参保】调整为【是】;");
//				return R.other(CommonConstants.TWO_INT,null,"该人员存在在途/有效的社保数据，请将“是否已参保”调整为“是”");
			}
			if (null != preVo.getDispatchInfoPreVo()
					&& Common.isNotNull(preVo.getDispatchInfoPreVo().getIsAutoDis())
					&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoPreVo().getIsAutoDis())
					&& null == preVo.getDispatchInfoPreVo().getExpectedCollectionTime()
					&& null == preVo.getDispatchInfoPreVo().getExpectedConfirmTime()) {
				BaseSearchVO paramVo = new BaseSearchVO();
				paramVo.setName(preVo.getDispatchInfoPreVo().getSocialHouseholdName());
				paramVo.setType(CommonConstants.ZERO_STRING);
				R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
				socialLimitVo =  null== resultR?null:resultR.getData();
				if (null == socialLimitVo){
					errorTemp.append("请及时配置户("+paramVo.getName()+")截止日配置信息");
				}
			}
		}
		THouseHoldLimitInnerVo fundLimitVo = null;
		// 公积金自动化校验逻辑 1.9.17 FXJ
		if (preVo.getServerItem().contains("公积金") && null != preVo.getDispatchInfoFundPreVo()) {
			//根据身份证号码和项目编号查询公积金
			flag = socialDaprUtils.selectExitEmpFund(cardVo);
			//是否已签署为是需要判断是否在用或者流程中的公积金
			if (CommonConstants.ZERO_STRING.equals(preVo.getFundIsBuy()) &&
					(Common.isEmpty(flag) || Boolean.TRUE.equals(!flag.getData()))) {
				errorTemp.append("未找到流程中或者在用的公积金信息;");
//				return R.other(CommonConstants.THREE_INT,null,"未找到流程中或者在用的公积金信息！");
			}
			// 是否已签署为否需要判断是否在用或者流程中的公积金
			if (CommonConstants.ONE_STRING.equals(preVo.getFundIsBuy()) &&
					Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
				errorTemp.append("该人员存在在途/有效的公积金数据，请将【是否已参保】调整为【是】;");
//				return R.other(CommonConstants.THREE_INT,null,"该人员存在在途/有效的公积金数据，请将'是否已参保'调整为'是'");
			}
			if (null != preVo.getDispatchInfoFundPreVo()
					&& Common.isNotNull(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
					&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
					&& null == preVo.getDispatchInfoFundPreVo().getExpectedCollectionTime()
					&& null == preVo.getDispatchInfoFundPreVo().getExpectedConfirmTime()) {
				BaseSearchVO paramVo = new BaseSearchVO();
				paramVo.setName(preVo.getDispatchInfoFundPreVo().getProvidentHouseholdName());
				paramVo.setType(CommonConstants.ONE_STRING);
				R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
				fundLimitVo =  null== resultR?null:resultR.getData();
				if (null == fundLimitVo){
					errorTemp.append("请及时配置户("+paramVo.getName()+")截止日配置信息");
				}
			}

		}
		if (preVo.getServerItem().contains("合同") && null != preVo.getEmployeeContractPreVos() &&
				Common.isNotNull(preVo.getEmployeeContractPreVos().getContractFlag()) &&
				CommonConstants.ONE_STRING.equals(preVo.getEmployeeContractPreVos().getContractFlag())) {
			//生成合同待购买数据
			String error = null;
			try {
				error = initContractPreInfo(registration, preVo.getEmployeeContractPreVos(), user);
			} catch (ParseException e) {
				errorTemp.append("初始化合同待购买数据异常："+error);
			}
			if (error != null){
				errorTemp.append(error);
			}
		}
		//错误信息全量返回
		if (errorTemp.length() > 0) {
			return R.other(CommonConstants.TWO_INT,null,errorTemp.toString());
		}
		//点击“接收确认”的时候，监测到该人员该项目下已有在项的档案时，再次提醒：该人员已在项，
		//状态将更新成“已处理”；处理记录中，针对此情况，记录真实的进项时间，备注：先于登记入项
		EmpProjectStatusVo vo = new EmpProjectStatusVo();
		vo.setEmpIdcard(registration.getEmpIdcard());
		vo.setDeptNo(registration.getDeptNo());
		EmpProjectStatusVo exit = getEmpProjectStatus(vo);
		if (Common.isNotNull(exit)) {
			EmployeeRegistrationReceiveVo receiveVo = new EmployeeRegistrationReceiveVo();
			receiveVo.setId(registration.getId());
			receiveVo.setEmployeeName(registration.getEmployeeName());
			receiveVo.setEmpIdcard(registration.getEmpIdcard());
			receiveVo.setReason(RegistConstants.BEFORE_IN_PROJECT);
			receiveVo.setEmpProjectId(exit.getEmpProjectId());
			receiveVo.setProjectCreateTime(exit.getProjectTime());
			receiveVo.setPreVo(preVo);
			return R.ok(receiveVo);
		}
		registration.setProcessStatus(CommonConstants.ZERO_STRING);
		baseMapper.updateById(registration);
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
				user.getNickname(), null);
		try {
			//生成档案待建档数据
			initRegistPreInfo(registration, preVo, user, CommonConstants.ZERO_STRING);
			R<String> domainR = archivesDaprUtil.saveRegistPreInfo(preVo);
			if (Common.isNotNull(domainR) && Common.isNotNull(domainR.getData())) {
				//是否存在商险为是时生成入职确认信息商险明细数据
				if (preVo.getServerItem().contains("商险") && Common.isNotNull(preVo.getInsuranceIsBuy())
						&& preVo.getInsuranceIsBuy().equals(CommonConstants.ZERO_STRING)
						&& !preVo.getExitInsuranceInfoList().isEmpty()) {
					preVo.getExitInsuranceInfoList().forEach(insurancePreVo -> insurancePreVo.setRegisterId(domainR.getData()));
					//生成入职确认信息商险明细数据
					insuranceDaprUtil.saveInsurancePreInfo(preVo);
				} else if (preVo.getServerItem().contains("商险")
						&& preVo.getInsuranceIsBuy().equals(CommonConstants.ONE_STRING)
						&& !preVo.getEmployeeInsurancePreVos().isEmpty()) {
					//生成商险待购买的数据
					for (TEmployeeInsurancePreVo insurancePreVo : preVo.getEmployeeInsurancePreVos()) {
						initInsruancePreInfo(registration, insurancePreVo, user, domainR.getData());
					}
					insuranceDaprUtil.saveInsurancePreInfo(preVo);
				}
				if (preVo.getServerItem().contains("合同") && null != preVo.getEmployeeContractPreVos() &&
						Common.isNotNull(preVo.getEmployeeContractPreVos().getContractFlag()) &&
						CommonConstants.ONE_STRING.equals(preVo.getEmployeeContractPreVos().getContractFlag())) {
					//生成合同待购买数据
					//initContractPreInfo(registration, preVo.getEmployeeContractPreVos(), user, domainR.getData());
					// 设置员工注册ID
					preVo.getEmployeeContractPreVos().setRegisterId(domainR.getData());
					archivesDaprUtil.saveContractPreInfo(preVo.getEmployeeContractPreVos());
				}
				//服务类型包含社保购买时
				if (preVo.getServerItem().contains("社保") && (null != preVo.getExitSocialInfoList()
						|| null != preVo.getDispatchInfoPreVo())) {
					if (null != preVo.getExitSocialInfoList() && !preVo.getExitSocialInfoList().isEmpty()) {
						preVo.getExitSocialInfoList().forEach(socialPreDetailVo -> socialPreDetailVo.setRegisterId(domainR.getData()));
					}
					//生成社保待购买或者已购买数据
					if (null != preVo.getDispatchInfoPreVo()) {
						 initSocialPreInfo(registration, preVo.getDispatchInfoPreVo(), user, domainR.getData(),socialLimitVo);
					}
					socialDaprUtils.saveSocialPreInfo(preVo);
				}
				//服务类型包含公积金购买时
				if (preVo.getServerItem().contains("公积金") && (null != preVo.getExitFundInfoList()
						|| null != preVo.getDispatchInfoFundPreVo())) {
					if (null != preVo.getExitFundInfoList() && !preVo.getExitFundInfoList().isEmpty()) {
						preVo.getExitFundInfoList().forEach(fundPreDetailVo -> fundPreDetailVo.setRegisterId(domainR.getData()));
					}
					if (null != preVo.getDispatchInfoFundPreVo()) {
						initFundPreInfo(registration, preVo.getDispatchInfoFundPreVo(), user, domainR.getData(),fundLimitVo);
					}
					socialDaprUtils.saveFundPreInfo(preVo);
				}
			}
			//确认接收时增加 档案、商险、合同、社保、公积金的变更日志 （具体产生哪些日志按服务事项（serverItem）来生成），参考 tEmployeePreLogService.saveModifyAndUpdateInsurance的实现，只处理日志
			saveConfirmReceiveLog(domainR.getData(), preVo, user);
		} catch (Exception e) {
			log.error("自动化办理执行异常", e);
		}
		return R.ok();
	}

	private void initFundPreInfo(EmployeeRegistration registration,
								 TDispatchInfoPreVo preVo, YifuUser user, String id,
								 THouseHoldLimitInnerVo limitInfo) throws ParseException  {
		preVo.setRegisterId(id);
		preVo.setCustomerUsername(registration.getCustomerUsernameNew());
		preVo.setCustomerUserLoginName(null != registration.getCustomerUserLoginNameNew()
				? registration.getCustomerUserLoginNameNew() : registration.getCustomerUserLoginname());
		preVo.setDeptName(registration.getDeptName());
		preVo.setDeptId(registration.getDeptId());
		preVo.setJoinLeaveDate(registration.getJoinLeaveDate());
		preVo.setDeptNo(registration.getDeptNo());
		preVo.setEmpName(registration.getEmployeeName());
		preVo.setPhone(registration.getEmpPhone());
		preVo.setPosition(registration.getPosition());
		preVo.setEmpIdcard(registration.getEmpIdcard());
		preVo.setCreateBy(user.getId());
		preVo.setCreateName(user.getNickname());
		preVo.setUpdateBy(user.getId());
		preVo.setTypeSub(CommonConstants.ONE_STRING);
		preVo.setProcessStatus(CommonConstants.ZERO_STRING);
		preVo.setDispatchItem("公积金");
		//如果公积金起缴日期为空需要初始化--只有批量确认时才会走到这里
		initFundStartDate(preVo);
		//如果自动触发派增为是，计算派单发起时间和派单确认时间
		if (Common.isNotNull(preVo.getIsAutoDis()) && CommonConstants.ZERO_STRING.equals(preVo.getIsAutoDis())
				&& null == preVo.getExpectedCollectionTime()
				&& null == preVo.getExpectedConfirmTime()) {
			initExpectedCollectionTime(preVo.getProvidentHouseholdName(), preVo.getFundStartDate(), preVo,limitInfo);
		}
	}

	/**
	 * @Author fxj
	 * @Description 初始化预计派单发起时间、预计派单确认时间
	 * @Date 17:06 2025/12/12
	**/
	private void initExpectedCollectionTime(String houseName, Date startDate,
											TDispatchInfoPreVo preVo2,
											THouseHoldLimitInnerVo innerVo) throws ParseException {
		//获取当前月是否可办理状态：获取办理截止日往前最近的工昨日，当前日及截止日前(含截止日)有工作日就是可办理
		if (null == innerVo){
			return;
		}
		boolean canBeHandle = innerVo.getCanBeHandle();
		LocalTime currentTime = LocalTime.now();
		LocalTime thresholdTime = LocalTime.of(15, 20);
		boolean isBeforeThreshold = currentTime.isBefore(thresholdTime) || currentTime.equals(thresholdTime);

		// 时间格式常量
		String collectionTimeFormat = " 15:20";
		String confirmTimeFormat = " 09:00";

		//获取次月1号日期
		Date nextMonthFirstDay = DateUtil.addMonthByDate(DateUtil.formatDateByPatten(new Date(), DateUtil.ISO_EXPANDED_DATE_FORMAT), 1);
		nextMonthFirstDay = DateUtil.setDayByDate(nextMonthFirstDay, 1);

		//获取起缴月份1号
		Date startDateFirstDay = DateUtil.addDayByDate(DateUtil.formatDateByPatten(startDate, DateUtil.ISO_EXPANDED_DATE_FORMAT), 0);
		startDateFirstDay = DateUtil.setDayByDate(startDateFirstDay, 1);

		//获取起缴月-1日期
		Date startDatePrevMonth = DateUtil.addMonthByDate(startDateFirstDay, -1);

		//获取次日
		Date tomorrow = DateUtil.getDateByDayNum(1);
		//1.起缴月份为当月及之前的月份
		if (DateUtil.isCurrentOrBeforeMonth(startDate)){
			if (canBeHandle){
				//发起时间不看工作日
				if (isBeforeThreshold) {
					Date today = new Date();
					preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
							today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
					preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
							today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				} else {
					preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
							tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
					preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
							tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				}
			} else {
				preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
						nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
						nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
			}
		}
		//2.起缴月份为次月
		else if (DateUtil.isNextMonth(startDate)){
			//当月办次月生效
			if (CommonConstants.ONE_STRING.equals(innerVo.getAddHandleRule())){
				if (canBeHandle){
					if (isBeforeThreshold){
						Date today = new Date();
						preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
								today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
						preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
								today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
					}else {
						preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
								tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
						preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
								tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
					}
				} else {
					preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
							nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
					preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
							nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				}
				//当月办当月生效
			} else if (CommonConstants.ZERO_STRING.equals(innerVo.getAddHandleRule())){
				preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
						nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
						nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
			}
		}
		//3.起缴月份为次月之后的月份
		else if (DateUtil.isNextNextMonthOrAfter(startDate)){
			//当月办次月生效
			if (CommonConstants.ONE_STRING.equals(innerVo.getAddHandleRule())){
				preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
						startDatePrevMonth, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
				preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
						startDatePrevMonth, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
			} else if (CommonConstants.ZERO_STRING.equals(innerVo.getAddHandleRule())){
				preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
						startDateFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));

					preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
							startDateFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
			}
		}
	}

	private void initFundStartDate(TDispatchInfoPreVo preVo) {
		if (null != preVo.getJoinLeaveDate()) {
			TEmployeeContractDateVo initDate = new TEmployeeContractDateVo();
			//先计算起缴日期 接收方式 0项目配置   自定义必须填写起缴日期
			//0 入职日期  1 入职满个月 2 入职满2个月 3 入职满3个月 4 入职满4个月 5 入职满5个月 6 入职满6个月 7 入职满7个月
			//8 入职满8个月 9 入职满9个月 10 入职满10个月 11 入职满11个月 12 入职满12个月
			initDate.setMonthAfter(Integer.parseInt(preVo.getFundDateType()));
			initDate.setYearAfter(0);
			initDate.setRegistDate(preVo.getJoinLeaveDate());
			Date date = this.addYearsMonthsKeepFirstDay(initDate);
			preVo.setFundStartDate(date);
		}
	}

	/**
	 * 初始化合同预信息
	 * 该方法用于将员工注册信息转换并填充到合同预信息对象中，以便后续的合同签订流程使用
	 * @param registration          员工注册信息对象，包含员工的基本注册信息
	 * @param employeeContractPreVo 员工合同预信息对象，将被填充数据以用于合同签订流程
	 * @param user                  当前用户信息，用于记录合同预信息的创建和更新者
	 * @throws ParseException 日期解析异常，当日期格式不符合预期时抛出
	 */
	private String initContractPreInfo(EmployeeRegistration registration, TEmployeeContractPreVo employeeContractPreVo,
									 YifuUser user) throws ParseException {
		employeeContractPreVo.setProcessStatus(CommonConstants.ZERO_STRING);
		employeeContractPreVo.setSituation("正常签订");
		// 设置客户用户名
		employeeContractPreVo.setCustomerUsername(registration.getCustomerUsernameNew());
		// 设置客户用户登录名
		employeeContractPreVo.setCustomerUserLoginname(null != registration.getCustomerUserLoginNameNew()
				? registration.getCustomerUserLoginNameNew() : registration.getCustomerUserLoginname());
		// 设置部门名称
		employeeContractPreVo.setDeptName(registration.getDeptName());
		// 设置部门ID
		employeeContractPreVo.setDeptId(registration.getDeptId());
		// 设置数据源
		employeeContractPreVo.setDataSource(registration.getDataSource());
		// 设置职位
		employeeContractPreVo.setPosition(registration.getPosition());
		// 设置入职或离职日期
		employeeContractPreVo.setJoinLeaveDate(registration.getJoinLeaveDate());
		// 设置部门编号
		employeeContractPreVo.setDeptNo(registration.getDeptNo());
		// 设置员工联系电话
		employeeContractPreVo.setEmpPhone(registration.getEmpPhone());
		// 设置员工姓名
		employeeContractPreVo.setEmployeeName(registration.getEmployeeName());
		// 设置员工身份证号
		employeeContractPreVo.setEmpIdcard(registration.getEmpIdcard());
		// 设置创建者ID
		employeeContractPreVo.setCreateBy(user.getId());
		// 设置创建者
		employeeContractPreVo.setCreateName(user.getNickname());
		// 设置更新者ID
		employeeContractPreVo.setUpdateBy(user.getId());
		//是否撤销签署
		employeeContractPreVo.setSignFlag(CommonConstants.ONE_STRING);
		employeeContractPreVo.setRevokeReason(CommonConstants.EMPTY_STRING);
		//预计确认提醒时间、预计合同发起时间日期赋值
		R<TEmployeeInsuranceWorkDayVo> dataR;
		if (Common.isNotNull(employeeContractPreVo.getRegistType())
				&& Common.isEmpty(employeeContractPreVo.getExpectedCollectionTime())
				&& Common.isEmpty(employeeContractPreVo.getExpectedConfirmTime())) {
			TEmployeeInsuranceWorkDayVo dayVo = new TEmployeeInsuranceWorkDayVo();
			dayVo.setType(CommonConstants.TWO_STRING);
			dayVo.setRegistDate(registration.getJoinLeaveDate());
			dayVo.setRegistType(Integer.parseInt(employeeContractPreVo.getRegistType()));
			dataR = socialDaprUtils.getContractAfterWorkDay(dayVo);
			if (Common.isNotNull(dataR) && Common.isNotNull(dataR.getData())
					&& Common.isNotNull(dataR.getData().getRegistDate())) {
				employeeContractPreVo.setExpectedCollectionTime(dataR.getData().getRegistDate());
				employeeContractPreVo.setExpectedConfirmTime(dataR.getData().getRegistDate());
			} else {
				employeeContractPreVo.setExpectedCollectionTime(registration.getJoinLeaveDate());
				employeeContractPreVo.setExpectedConfirmTime(registration.getJoinLeaveDate());
			}
		}
		TEmployeeContractDateVo vo = new TEmployeeContractDateVo();
		//合同开始日期、合同截止日期
		if (Common.isEmpty(employeeContractPreVo.getContractStart())
				&& Common.isEmpty(employeeContractPreVo.getContractEnd())
				&& Common.isEmpty(employeeContractPreVo.getContractDurationYear())
				&& Common.isEmpty(employeeContractPreVo.getContractDurationMonth())
				&& Common.isNotNull(employeeContractPreVo.getContractEndType())
				&& CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractEndType())) {
			employeeContractPreVo.setContractStart(employeeContractPreVo.getJoinLeaveDate());
			EkpDeptContractInfoVo infoVo = new EkpDeptContractInfoVo();
			infoVo.setDeptNo(registration.getDeptNo());
			R<EkpDeptContractInfoVo> info = ekpDaprUtils.selectContractInfoByDetptNo(infoVo);
			if (Common.isNotNull(info) && Common.isNotNull(info.getData())) {
				EkpDeptContractInfoVo returnVo = info.getData();
				employeeContractPreVo.setContractEnd(null != returnVo.getContractEndTime() ?
						DateUtil.stringToDate(returnVo.getContractEndTime()) : null);
			} else {
				employeeContractPreVo.setContractEnd(null);
			}
		}
		//合同年限推算
		if (Common.isEmpty(employeeContractPreVo.getContractStart())
				&& Common.isEmpty(employeeContractPreVo.getContractEnd())
				&& (Common.isNotNull(employeeContractPreVo.getContractDurationYear())
				|| Common.isNotNull(employeeContractPreVo.getContractDurationMonth()))
				&& Common.isNotNull(employeeContractPreVo.getContractEndType())
				&& CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getContractEndType())) {
			employeeContractPreVo.setContractStart(employeeContractPreVo.getJoinLeaveDate());
			vo.setMonthAfter(Integer.parseInt(Common.isEmpty(employeeContractPreVo.getContractDurationMonth()) ? "0":employeeContractPreVo.getContractDurationMonth()));
			vo.setYearAfter(Integer.parseInt(Common.isEmpty(employeeContractPreVo.getContractDurationYear()) ? "0":employeeContractPreVo.getContractDurationYear()));
			vo.setRegistDate(employeeContractPreVo.getContractStart());
			employeeContractPreVo.setContractEnd(this.addYearsMonths(vo));
		}
		//合同开始日期
		if (Common.isEmpty(employeeContractPreVo.getContractStart())
				&& Common.isEmpty(employeeContractPreVo.getContractDurationYear())
				&& Common.isEmpty(employeeContractPreVo.getContractDurationMonth())) {
			employeeContractPreVo.setContractStart(employeeContractPreVo.getJoinLeaveDate());
		}
		//试用期开始日期、试用期截止日期
		if (Common.isEmpty(employeeContractPreVo.getTryPeriodStart())
				&& Common.isNotNull(employeeContractPreVo.getTryPeriodNum())
				&& CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getSignType())) {
			employeeContractPreVo.setTryPeriodStart(employeeContractPreVo.getJoinLeaveDate());
			vo.setMonthAfter(Integer.parseInt(employeeContractPreVo.getTryPeriodNum()));
			vo.setYearAfter(0);
			vo.setRegistDate(employeeContractPreVo.getTryPeriodStart());
			employeeContractPreVo.setTryPeriodEnd(this.addYearsMonths(vo));
		}
		//派遣开始日期、派遣结束日期
		if (Common.isEmpty(employeeContractPreVo.getDispatchPeriodStart())
				&& (Common.isNotNull(employeeContractPreVo.getDispatchPeriodYear())
				|| Common.isNotNull(employeeContractPreVo.getDispatchPeriodMonth()))) {
			employeeContractPreVo.setDispatchPeriodStart(employeeContractPreVo.getJoinLeaveDate());
			vo.setMonthAfter(Integer.parseInt(Common.isEmpty(employeeContractPreVo.getDispatchPeriodMonth()) ? "0":employeeContractPreVo.getDispatchPeriodMonth()));
			vo.setYearAfter(Integer.parseInt(Common.isEmpty(employeeContractPreVo.getDispatchPeriodYear()) ? "0":employeeContractPreVo.getDispatchPeriodYear()));
			vo.setRegistDate(employeeContractPreVo.getDispatchPeriodStart());
			employeeContractPreVo.setDispatchPeriodEnd(this.addYearsMonths(vo));
		}
		//实习开始日期、实习结束日期赋值合同开始、截止日期
		if (Common.isNotNull(employeeContractPreVo.getInternshipPeriodStart())) {
			employeeContractPreVo.setContractStart(employeeContractPreVo.getInternshipPeriodStart());
		}
		if (Common.isNotNull(employeeContractPreVo.getInternshipPeriodEnd())) {
			employeeContractPreVo.setContractEnd(employeeContractPreVo.getInternshipPeriodEnd());
		}
		//实习开始日期、实习结束日期
		if (Common.isEmpty(employeeContractPreVo.getInternshipPeriodStart())
				&& Common.isNotNull(employeeContractPreVo.getInternshipPeriodNum())) {
			employeeContractPreVo.setInternshipPeriodStart(employeeContractPreVo.getJoinLeaveDate());
			employeeContractPreVo.setContractStart(employeeContractPreVo.getJoinLeaveDate());
			vo.setMonthAfter(Integer.parseInt(employeeContractPreVo.getInternshipPeriodNum()));
			vo.setYearAfter(0);
			vo.setRegistDate(employeeContractPreVo.getInternshipPeriodStart());
			employeeContractPreVo.setInternshipPeriodEnd(this.addYearsMonths(vo));
			employeeContractPreVo.setContractEnd(employeeContractPreVo.getInternshipPeriodEnd());
		}
		//合同岗位名称
		if (CommonConstants.ONE_STRING.equals(employeeContractPreVo.getPostType())
				&& Common.isEmpty(employeeContractPreVo.getPost())) {
			employeeContractPreVo.setPost(registration.getPosition());
		}
		// 预计提醒时间、预计合同发起时间
		if (Common.isNotNull(employeeContractPreVo.getExpectedCollectionTime()) &&
				Common.isNotNull(employeeContractPreVo.getExpectedConfirmTime())) {
			employeeContractPreVo.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
					employeeContractPreVo.getExpectedCollectionTime(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " 15:20", DateUtil.DATETIME_PATTERN_MINUTE));
			employeeContractPreVo.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
					employeeContractPreVo.getExpectedConfirmTime(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " 9:00", DateUtil.DATETIME_PATTERN_MINUTE));
		}
		//指定日期 或 与商务合同一致 计算合同年限
		if (CommonConstants.THREE_STRING.equals(employeeContractPreVo.getContractEndType())
				||CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractEndType())){
			//处理合同年限
			ContractTermCalculator.ContractTerm term = calculator.calculateTerm(
					DateUtil.formatDatePatten(employeeContractPreVo.getContractStart(),DateUtil.ISO_EXPANDED_DATE_FORMAT),
					DateUtil.formatDatePatten(employeeContractPreVo.getContractEnd(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
			if (term != null){
				employeeContractPreVo.setContractDurationYear(Integer.toString(term.getYears()));
				employeeContractPreVo.setContractDurationMonth(Integer.toString(term.getMonths()));
			}else {
				employeeContractPreVo.setContractDurationYear(CommonConstants.ZERO_STRING);
				employeeContractPreVo.setContractDurationMonth(CommonConstants.ZERO_STRING);
			}
		}
		// 校验合同有效期：合同截止日期不得早于合同开始日期
		if (Common.isNotNull(employeeContractPreVo.getContractStart())
				&& Common.isNotNull(employeeContractPreVo.getContractEnd())) {
			if (!employeeContractPreVo.getContractEnd().after(employeeContractPreVo.getContractStart())) {
				return "合同截止日期需大于合同开始日期";

			}
		}
		//劳务派遣合同相关校验
		List<String> allErrorMessages = new ArrayList<>();
		if (CommonConstants.TWENTY_STRING.equals(employeeContractPreVo.getContractType())
		|| "劳务派遣合同".equals(employeeContractPreVo.getContractType())) {

			if (Common.isNotNull(employeeContractPreVo.getContractDurationYear())
					&& Common.isNotNull(employeeContractPreVo.getContractDurationMonth())
					&& CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getSignType())
					&& CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractTerm())) {
				// 校验劳务派遣的派遣年限必须为两年
				final int REQUIRED_SERVICE_YEARS = 2;
				int dispatchYears = 0;
				try {
					dispatchYears = Integer.parseInt(employeeContractPreVo.getContractDurationYear().trim());
				} catch (NumberFormatException e) {
					return "合同年限格式不正确";
				}

				// 将派遣月份转换为年的小数部分（例如：6 个月=0.5 年）
				int dispatchMonths = 0;
				try {
					dispatchMonths = Integer.parseInt(employeeContractPreVo.getContractDurationMonth().trim());
				} catch (NumberFormatException e) {
					return "合同月份格式不正确";
				}

				// 计算总派遣年限（年 + 月/12）
				double totalDispatchYears = dispatchYears + (dispatchMonths / 12.0);

				if (totalDispatchYears < REQUIRED_SERVICE_YEARS) {
					////电子签 且 是劳务派遣合同 且 签订期限为固定期限的 合同年前置的合同不能小于 2 年，请检查";
					return "劳务派遣合同的合同年限不能小于 2 年，请检查";
				}

				// 合同开始时间、合同截止时间应与派遣的合同开始时间、合同截止时间一致
				if (Common.isNotNull(employeeContractPreVo.getContractStart())
						&& Common.isNotNull(employeeContractPreVo.getDispatchPeriodStart())
						&& !employeeContractPreVo.getContractStart().equals(employeeContractPreVo.getDispatchPeriodStart())) {
					allErrorMessages.add("合同开始日期与派遣开始日期不一致");
				}
				if (Common.isNotNull(employeeContractPreVo.getContractEnd())
						&& Common.isNotNull(employeeContractPreVo.getDispatchPeriodEnd())
						&& !employeeContractPreVo.getContractEnd().equals(employeeContractPreVo.getDispatchPeriodEnd())) {
					allErrorMessages.add("合同截止日期与派遣截止日期不一致");
				}
				//固定期限时 劳务派遣合同需要校验 标准合同的年限和劳务派遣合同的年限一致
				if ("劳务派遣合同".equals(employeeContractPreVo.getContractType())
						&& CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractTerm())){
					if (!employeeContractPreVo.getContractDurationYear().equals(employeeContractPreVo.getDispatchPeriodYear())
							|| !employeeContractPreVo.getContractDurationMonth().equals(employeeContractPreVo.getDispatchPeriodMonth())){
						allErrorMessages.add("合同的年限同派遣的期限不一致");
					}
				}
			}

		}
		if (Common.isNotNull(employeeContractPreVo.getDispatchPeriodStart())
				&& Common.isNotNull(employeeContractPreVo.getDispatchPeriodEnd())) {
			if (employeeContractPreVo.getDispatchPeriodEnd().before(employeeContractPreVo.getDispatchPeriodStart())) {
				return "派遣结束日期需大于等于派遣开始日期";
			}
		}

		//合同类型为 标准合同或劳务派遣合同时且试用期不为空时，无固定期限 时试用期不能大于6个月，提示“无固定期限时试用期不得超过6个月”
		// 固定期限时 合同截止日期类型为合同年限推算或同商务合同一致或指定日期时 按1.“合同年限不满一年的，试用期不得超过1个月"
		//2."合同年限1年以上不满3年的，试用期不得超过2个月" 3."合同年限3年以上的，试用期不得超过6个月" 限制
		// 合同类型为劳务派遣合同或标准合同时，校验试用期合法性
		if ("劳务派遣合同".equals(employeeContractPreVo.getContractType())
				|| "标准合同".equals(employeeContractPreVo.getContractType())) {

			// 检查必要字段是否为空 关键字段不为空才校验
			boolean flag = CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractTerm())
					&& !Common.isEmpty(employeeContractPreVo.getTryPeriodNum())
					&& CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getTryPeriodType());
			if (!flag){
				flag = CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractTerm())
						&& !Common.isEmpty(employeeContractPreVo.getTryPeriodNum())
						&& !"0".equals(employeeContractPreVo.getTryPeriodNum())
						&& (CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractEndType())
						|| CommonConstants.THREE_STRING.equals(employeeContractPreVo.getContractEndType()));
			}
			if (flag) {
				// 安全解析试用期月数
				int tryPeriodMonths = 0;
				try {
					tryPeriodMonths = Integer.parseInt(employeeContractPreVo.getTryPeriodNum().trim());
				} catch (NumberFormatException e) {
					return "试用期月份格式不正确";
				}

				// 无固定期限合同校验（contractTerm = "2"）
				if (CommonConstants.TWO_STRING.equals(employeeContractPreVo.getContractTerm())) {
					if (tryPeriodMonths > 6) {
						return "无固定期限时试用期不得超过 6 个月";
					}
				}
				// 固定期限合同校验（contractTerm = "1"）
				else if (CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractTerm())) {
					// 仅对特定合同截止日期类型进行校验
					if (CommonConstants.ZERO_STRING.equals(employeeContractPreVo.getContractEndType())
							|| CommonConstants.ONE_STRING.equals(employeeContractPreVo.getContractEndType())
							|| CommonConstants.THREE_STRING.equals(employeeContractPreVo.getContractEndType())) {

						// 安全解析合同年限
						int contractYears = 0;
						int contractMonths = 0;

						if (Common.isNotNull(employeeContractPreVo.getContractDurationYear())) {
							try {
								contractYears = Integer.parseInt(employeeContractPreVo.getContractDurationYear().trim());
							} catch (NumberFormatException e) {
								contractYears = 0;
							}
						}

						if (Common.isNotNull(employeeContractPreVo.getContractDurationMonth())) {
							try {
								contractMonths = Integer.parseInt(employeeContractPreVo.getContractDurationMonth().trim());
							} catch (NumberFormatException e) {
								contractMonths = 0;
							}
						}

						// 计算合同总月数
						int totalContractMonths = contractYears * 12 + contractMonths;

						// 根据合同期限分段校验试用期（劳动合同法第 19 条规定）
						if (totalContractMonths < 12) {
							// 合同期限不满 1 年，试用期不得超过 1 个月
							if (tryPeriodMonths > 1) {
								return "固定期限时合同年限不满一年的，试用期不得超过 1 个月";
							}
						} else if (totalContractMonths >= 12 && totalContractMonths < 36) {
							// 合同期限 1 年以上不满 3 年，试用期不得超过 2 个月
							if (tryPeriodMonths > 2) {
								return "固定期限时合同年限 1 年以上不满 3 年的，试用期不得超过 2 个月";
							}
						} else {
							// 合同期限 3 年以上，试用期不得超过 6 个月
							if (tryPeriodMonths > 6) {
								return "固定期限时合同年限 3 年以上的，试用期不得超过 6 个月";
							}
						}
					}
				}
			}

		}


		// 如果有错误信息,根据具体错误项动态生成提示
		if (!allErrorMessages.isEmpty()) {
			// 筛选出需要组合提示的错误项
			List<String> contractDispatchErrors = new ArrayList<>();
			for (String errorMsg : allErrorMessages) {
				if (errorMsg.contains("合同的年限同派遣的期限不一致")
						|| errorMsg.contains("合同开始日期与派遣开始日期不一致")
						|| errorMsg.contains("合同截止日期与派遣截止日期不一致")) {
					contractDispatchErrors.add(errorMsg);
				}
			}
					
			// 如果存在合同与派遣相关的错误,生成组合提示
			if (!contractDispatchErrors.isEmpty()) {
				List<String> contractItems = new ArrayList<>();
				List<String> dispatchItems = new ArrayList<>();
						
				for (String error : contractDispatchErrors) {
					if (error.contains("年限")) {
						contractItems.add("年限");
						dispatchItems.add("期限");
					}
					if (error.contains("开始日期")) {
						contractItems.add("开始日期");
						dispatchItems.add("开始日期");
					}
					if (error.contains("截止日期")) {
						contractItems.add("截止日期");
						dispatchItems.add("截止日期");
					}
				}
						
				String contractStr = String.join("、", contractItems);
				String dispatchStr = String.join("、", dispatchItems);
				return "派遣的" + dispatchStr + "同合同的" + contractStr + "不一致,请调整!";
			}
		}

		return null;
	}

	/**
	 * 入职待确认表确认接收
	 *
	 * @param preVo 确认接受vo
	 * @return
	 */
	@Override
	public R batchConfirmReceive(EmployeeRegistrationPreVo preVo) {
		if (Common.isEmpty(preVo)) {
			return R.failed(CommonConstants.PARAM_IS_NOT_ERROR);
		}
		//查询该项目该前端客服下所有待接收的入职登记
		//前端客服的所有项目权限赋值
		EmployeeRegistrationSearchVo searchVo = new EmployeeRegistrationSearchVo();
		initSearchVo(searchVo);
		List<String> statusList = new ArrayList<>();
		statusList.add(CommonConstants.ONE_STRING);
		searchVo.setStatusList(statusList);
		searchVo.setTypeList(CommonConstants.processPreStatus);
		searchVo.setDeptNo(preVo.getDeptNo());
		if (Common.isNotNull(preVo.getIdcardList())) {
			searchVo.setIdcardList(preVo.getIdcardList());
		}
		List<EmployeeRegistration> registrationList = baseMapper.getEmployeeRegistrationList(searchVo);
		YifuUser user = SecurityUtils.getUser();
		if (Common.isEmpty(registrationList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		//商险存在校验
		List<TEmployeeAutoRegistCheckVo> errorList = new ArrayList<>();
		TEmployeeAutoRegistCheckVo checkVo;

		List<EmployeeRegistrationReceiveVo> receiveVoList = new ArrayList<>();
		R<TEmployeeInsuranceWorkDayVo> dataR;
		R<Boolean> flag;
		TEmployeeAutoRegistCheckVo exitCheckVo;
		R<SysBaseSetInfoVo> resR;
		SysBaseSetInfoVo setInfo;
		for (EmployeeRegistration registration:registrationList) {
			exitCheckVo = new TEmployeeAutoRegistCheckVo();
			exitCheckVo.setEmployeeName(registration.getEmployeeName());
			exitCheckVo.setEmpIdcard(registration.getEmpIdcard());
			exitCheckVo.setDeptName(registration.getDeptName());
			exitCheckVo.setDeptNo(registration.getDeptNo());
			if (preVo.getServerItem().contains("商险") && !preVo.getEmployeeInsurancePreVos().isEmpty()) {
				//批量的商险是否已购买默认为否
				if (Common.isEmpty(preVo.getInsuranceIsBuy())) {
					preVo.setInsuranceIsBuy(CommonConstants.ONE_STRING);
				}
				TEmployeeInsurancePreVo insurancePreVo = preVo.getEmployeeInsurancePreVos().get(0);
				insurancePreVo.setEmpIdcard(registration.getEmpIdcard());
				insurancePreVo.setDeptNo(registration.getDeptNo());
				//日期赋值
				TEmployeeInsuranceWorkDayVo dayVo = new TEmployeeInsuranceWorkDayVo();
				dayVo.setType(CommonConstants.TWO_STRING);
				dayVo.setRegistDate(registration.getJoinLeaveDate());
				if (insurancePreVo.getBuyType() ==1) {
					dayVo.setAddOrBatch(CommonConstants.ONE_STRING);
				}
				dataR = socialDaprUtils.getBeforeOrAfterWorkDay(dayVo);
				if (Common.isNotNull(dataR) && Common.isNotNull(dataR.getData())
						&& Common.isNotNull(dataR.getData().getRegistDate())
						&& Common.isNotNull(dataR.getData().getPriDisDate())) {
					insurancePreVo.setExpectedCollectionTime(dataR.getData().getPriDisDate());
					insurancePreVo.setPolicyEffect(dataR.getData().getRegistDate());
					if (Common.isEmpty(insurancePreVo.getPolicyStart())) {
						insurancePreVo.setPolicyStart(dataR.getData().getRegistDate());
					}
				} else {
					insurancePreVo.setExpectedCollectionTime(registration.getJoinLeaveDate());
					insurancePreVo.setPolicyEffect(registration.getJoinLeaveDate());
					insurancePreVo.setPolicyStart(registration.getJoinLeaveDate());
				}
				//入职日期需要小于保单截止日期
				if ((DateUtil.dateToString(registration.getJoinLeaveDate(),DateUtil.ISO_EXPANDED_DATE_FORMAT).
						compareTo(DateUtil.dateToString(insurancePreVo.getPolicyEnd(),DateUtil.ISO_EXPANDED_DATE_FORMAT)) > 0)
						|| (DateUtil.dateToString(insurancePreVo.getPolicyStart(),DateUtil.ISO_EXPANDED_DATE_FORMAT).
						compareTo(DateUtil.dateToString(insurancePreVo.getPolicyEnd(),DateUtil.ISO_EXPANDED_DATE_FORMAT)) > 0)) {
					exitCheckVo.setType("商险");
					exitCheckVo.setErrorMsg("入职日期需要小于等于保单截止日期/保单开始日期需小于等于保单截止日期");
					errorList.add(exitCheckVo);
					continue;
				}
				//商险是否存在判断
				checkVo = checkInsuranceExit(insurancePreVo, registration);
				if (null != checkVo) {
					errorList.add(checkVo);
					continue;
				} else {
					if (Common.isEmpty(insurancePreVo.getProcessStatus())) {
						insurancePreVo.setProcessStatus(CommonConstants.ZERO_STRING);
					}
				}
			}
			//1.9.12合同自动化校验逻辑
			//根据身份证号码和项目编号查询合同
			TEmployeeAutoRegistCheckVo cardVo = new TEmployeeAutoRegistCheckVo();
			cardVo.setEmpIdcard(registration.getEmpIdcard());
			cardVo.setDeptNo(registration.getDeptNo());
			flag = archivesDaprUtil.selectExitEmpCopntract(cardVo);
			if (preVo.getServerItem().contains("合同") && null != preVo.getEmployeeContractPreVos()) {
				//是否已签署为否需要判断是否在用或者流程中的合同
				if (Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
					exitCheckVo.setType("合同");
					exitCheckVo.setErrorMsg("该项目下存在在途/有效的合同数据");
					errorList.add(exitCheckVo);
					continue;
				}
			}
			//合同签署状态赋值
			if (null != preVo.getDispatchInfoPreVo()) {
				if (Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
					preVo.getDispatchInfoPreVo().setContractStatus(CommonConstants.ZERO_STRING);
				} else {
					preVo.getDispatchInfoPreVo().setContractStatus(CommonConstants.ONE_STRING);
				}
			}
			THouseHoldLimitInnerVo socialLimitVo = null;
			//1.9.16社保自动化校验逻辑
			if (preVo.getServerItem().contains("社保") && null != preVo.getDispatchInfoPreVo()) {
				//根据身份证号码和项目编号查询合同
				flag = socialDaprUtils.selectExitEmpSocial(cardVo);
				//是否已签署为否需要判断是否在用或者流程中的合同
				if (Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
					exitCheckVo.setType("社保");
					exitCheckVo.setErrorMsg("该人员存在在途/有效的社保数据");
					errorList.add(exitCheckVo);
					continue;
				}
				if (null != preVo.getDispatchInfoPreVo()
						&& Common.isNotNull(preVo.getDispatchInfoPreVo().getIsAutoDis())
						&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoPreVo().getIsAutoDis())
						&& null == preVo.getDispatchInfoPreVo().getExpectedCollectionTime()
						&& null == preVo.getDispatchInfoPreVo().getExpectedConfirmTime()) {
					BaseSearchVO paramVo = new BaseSearchVO();
					paramVo.setName(preVo.getDispatchInfoPreVo().getSocialHouseholdName());
					paramVo.setType(CommonConstants.ZERO_STRING);
					R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
					socialLimitVo =  null== resultR?null:resultR.getData();
					if (null == socialLimitVo){
						exitCheckVo.setType("社保");
						exitCheckVo.setErrorMsg("请及时配置户("+paramVo.getName()+")截止日配置信息");
						errorList.add(exitCheckVo);
						continue;
					}
				}
			}
			THouseHoldLimitInnerVo fundLimitVo = null;
			// 公积金自动化校验逻辑
			if (preVo.getServerItem().contains("公积金") && null != preVo.getDispatchInfoFundPreVo()) {
				//根据身份证号码和项目编号查询公积金
				flag = socialDaprUtils.selectExitEmpFund(cardVo);
				//是否已签署为是需要判断是否在用或者流程中的公积金
				if (CommonConstants.ZERO_STRING.equals(preVo.getFundIsBuy()) &&
						(Common.isEmpty(flag) || Boolean.TRUE.equals(!flag.getData()))) {
					exitCheckVo.setType("公积金");
					exitCheckVo.setErrorMsg("未找到流程中或者在用的公积金信息");
					errorList.add(exitCheckVo);
					continue;
				}
				//是否已签署为否需要判断是否在用或者流程中的公积金
				if (CommonConstants.ONE_STRING.equals(preVo.getFundIsBuy()) &&
						Common.isNotNull(flag) && Boolean.TRUE.equals(flag.getData())) {
					exitCheckVo.setType("公积金");
					exitCheckVo.setErrorMsg("该人员存在在途/有效的公积金数据");
					errorList.add(exitCheckVo);
					continue;
				}
				if (null != preVo.getDispatchInfoFundPreVo()
						&& Common.isNotNull(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
						&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
						&& null == preVo.getDispatchInfoFundPreVo().getExpectedCollectionTime()
						&& null == preVo.getDispatchInfoFundPreVo().getExpectedConfirmTime()) {
					BaseSearchVO paramVo = new BaseSearchVO();
					paramVo.setName(preVo.getDispatchInfoFundPreVo().getProvidentHouseholdName());
					paramVo.setType(CommonConstants.ONE_STRING);
					R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
					fundLimitVo =  null== resultR?null:resultR.getData();
					if (null == fundLimitVo){
						exitCheckVo.setType("公积金");
						exitCheckVo.setErrorMsg("请及时配置户("+paramVo.getName()+")截止日配置信息");
						errorList.add(exitCheckVo);
						continue;
					}
				}
				//判断公积金基数 是否小于 公积金户配置的最低基数
			}
			TEmployeeContractPreVo employeeContractPreVo = new TEmployeeContractPreVo();
			if (preVo.getServerItem().contains("合同") && Common.isNotNull(preVo.getEmployeeContractPreVos())) {
				BeanUtils.copyProperties(preVo.getEmployeeContractPreVos(),employeeContractPreVo);
				//生成合同待购买数据
				String errorStr  = null;
				try {
					errorStr = initContractPreInfo(registration, employeeContractPreVo, user);
				} catch (ParseException e) {
					exitCheckVo.setType("合同");
					exitCheckVo.setErrorMsg("合同初始化异常："+e.getMessage());
					errorList.add(exitCheckVo);
					continue;
				}
				if (null != errorStr){
					exitCheckVo.setType("合同");
					exitCheckVo.setErrorMsg(errorStr);
					errorList.add(exitCheckVo);
					continue;
				}
			}
			//点击“接收确认”的时候，监测到该人员该项目下已有在项的档案时，再次提醒：该人员已在项，
			//状态将更新成“已处理”；处理记录中，针对此情况，记录真实的进项时间，备注：先于登记入项
			EmpProjectStatusVo vo = new EmpProjectStatusVo();
			vo.setEmpIdcard(registration.getEmpIdcard());
			vo.setDeptNo(registration.getDeptNo());
			EmpProjectStatusVo exit = getEmpProjectStatus(vo);
			if (Common.isNotNull(exit)) {
				EmployeeRegistrationReceiveVo receiveVo = new EmployeeRegistrationReceiveVo();
				receiveVo.setId(registration.getId());
				receiveVo.setEmployeeName(registration.getEmployeeName());
				receiveVo.setEmpIdcard(registration.getEmpIdcard());
				receiveVo.setReason(RegistConstants.BEFORE_IN_PROJECT);
				receiveVo.setEmpProjectId(exit.getEmpProjectId());
				receiveVo.setProjectCreateTime(exit.getProjectTime());
				receiveVo.setPreVo(preVo);
				receiveVoList.add(receiveVo);
				continue;
			}
			registration.setProcessStatus(CommonConstants.ZERO_STRING);
			baseMapper.updateById(registration);
			logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
					user.getNickname(), null);
			try {
				//生成档案待建档数据
				initRegistPreInfo(registration, preVo, user, CommonConstants.ZERO_STRING);
				R<String> domainR = archivesDaprUtil.saveRegistPreInfo(preVo);
				if (Common.isNotNull(domainR) && Common.isNotNull(domainR.getData())) {
					if (preVo.getServerItem().contains("商险") && !preVo.getEmployeeInsurancePreVos().isEmpty()) {
						//生成商险待购买的数据
						TEmployeeInsurancePreVo insurancePreVo = preVo.getEmployeeInsurancePreVos().get(0);
						initInsruancePreInfo(registration, insurancePreVo, user, domainR.getData());
						insuranceDaprUtil.saveInsurancePreInfo(preVo);
					}
					if (preVo.getServerItem().contains("合同") && Common.isNotNull(employeeContractPreVo)) {
						employeeContractPreVo.setRegisterId(domainR.getData());
						archivesDaprUtil.saveContractPreInfo(employeeContractPreVo);
					}
					//服务类型包含社保购买时
					if (preVo.getServerItem().contains("社保") && (null != preVo.getExitSocialInfoList()
							|| null != preVo.getDispatchInfoPreVo())) {
						//生成社保待购买或者已购买数据
						if (null != preVo.getDispatchInfoPreVo()) {
							initSocialPreInfo(registration, preVo.getDispatchInfoPreVo(), user, domainR.getData(),socialLimitVo);
						}
						socialDaprUtils.saveSocialPreInfo(preVo);
					}
					//服务类型包含公积金购买时
					if (preVo.getServerItem().contains("公积金") && (null != preVo.getExitFundInfoList()
							|| null != preVo.getDispatchInfoFundPreVo())) {
						if (null != preVo.getExitFundInfoList() && !preVo.getExitFundInfoList().isEmpty()) {
							preVo.getExitFundInfoList().forEach(fundPreDetailVo -> fundPreDetailVo.setRegisterId(domainR.getData()));
						}
						if (null != preVo.getDispatchInfoFundPreVo()) {
							initFundPreInfo(registration, preVo.getDispatchInfoFundPreVo(), user, domainR.getData(),fundLimitVo);
						}
						socialDaprUtils.saveFundPreInfo(preVo);
					}
					//确认接收时增加 档案、商险、合同、社保、公积金的变更日志 （具体产生哪些日志按服务事项（serverItem）来生成），参考 tEmployeePreLogService.saveModifyAndUpdateInsurance的实现，只处理日志
					saveConfirmReceiveLog(domainR.getData(), preVo, user);
				}
			}catch (Exception e) {
				log.error("执行异常", e);
			}
		}
		EmployeeRegistrationBatchErrorVo batchErrorVo = new EmployeeRegistrationBatchErrorVo();
		batchErrorVo.setRegistrationReceiveVoList(receiveVoList);
		batchErrorVo.setErrorList(errorList);
		if (!errorList.isEmpty()) {
			return R.other(CommonConstants.TWO_INT, null, batchErrorVo);
		}
		if (!receiveVoList.isEmpty() && Common.isNotNull(receiveVoList)) {
			return R.ok(receiveVoList);
		}
		return R.ok();
	}

	@Override
	public R registAdd(EmployeeRegistration registration) {
		//提交校验内容：
		//1、身份证号位数、手机号码位数及格式，就职岗位下拉选择“内勤、揽投员、其他”
		//2、按照类型、按照身份证号、按照项目进行去重校验
		String errorInfo = registCheck(registration);
		if (null != errorInfo) {
			return R.failed(errorInfo);
		} else {
			// 1.9.8: 没有来源默认是：1客户端
			if(Common.isEmpty(registration.getDataSource())){
				registration.setDataSource(CommonConstants.ONE_STRING);
			}
			// 1.9.8: 赋值【最新的客服名称】
			registration.setCustomerUsernameNew(registration.getCustomerUsername());
			registration.setCustomerUserLoginNameNew(registration.getCustomerUserLoginname());
			baseMapper.insert(registration);
			if (Common.isNotNull(registration.getFeedbackType()) && CommonConstants.TWO_STRING.equals(registration.getFeedbackType())) {
				// 生成离职待办
				employeeRegistrationLeaveService.saveLeaveInfo(registration);
			}
			//更新附件
			updateFileId(registration);
		}
		//企业微信消息提醒
		if (registration.getFeedbackType().equals(CommonConstants.ONE_STRING)) {
			sendMessageToWxSingle(registration);
		} else {
			sendMessageToWx(registration, registration.getFeedbackType());
		}
		//操作记录
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.MESSAGE_REGIST, LocalDateTime.now(),
				registration.getRegistorUsername(), null);
		return R.ok();
	}

	@Override
	public R confirmSubmit(EmployeeRegistration registration) {
		YifuUser user = SecurityUtils.getUser();
		EmployeeRegistration registrationNow = baseMapper.selectById(registration.getId());
		if (Common.isEmpty(registrationNow) || !CommonConstants.ONE_STRING.equals(registrationNow.getProcessStatus())) {
			return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
		}
		//点击“接收确认”的时候，监测到该人员该项目下已有在项的档案时，再次提醒：该人员已在项，
		//状态将更新成“已处理”；处理记录中，针对此情况，记录真实的进项时间，备注：先于登记入项
		EmpProjectStatusVo vo = new EmpProjectStatusVo();
		vo.setEmpIdcard(registrationNow.getEmpIdcard());
		vo.setDeptNo(registrationNow.getDeptNo());
		EmpProjectStatusVo exit;
		if (CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType())) {
			exit = getEmpProjectStatus(vo);
		} else {
			exit = getOutEmpProjectStatus(vo);
		}
		if (Common.isNotNull(exit)) {
			return R.ok(exit);
		}
		registrationNow.setProcessStatus(CommonConstants.ZERO_STRING);
		baseMapper.updateById(registrationNow);
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
				user.getNickname(), null);
		return R.ok();
	}

	@Override
	public R updateRegist(EmployeeRegistration registration) {
		YifuUser user = SecurityUtils.getUser();
		EmployeeRegistration registrationNow = baseMapper.selectById(registration.getId());
		if (Common.isEmpty(registrationNow) || !CommonConstants.ONE_STRING.equals(registrationNow.getProcessStatus())) {
			return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
		}
		registrationNow.setProcessStatus(CommonConstants.TWO_STRING);
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
				user.getNickname(), null);
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.MESSAGE_FINISH, registration.getProjectCreateTime(),
				user.getNickname(), CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType())
						? RegistConstants.BEFORE_IN_PROJECT : RegistConstants.BEFORE_OUT_PROJECT);
		SysCspDeptVo vo = new SysCspDeptVo();
		if (CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType())) {
			if (Common.isNotNull(registrationNow.getEmpDeptid())) {
				vo.setDepartName(registrationNow.getEmpDeptname());
				vo.setDepartId(Long.valueOf(registrationNow.getEmpDeptid()));
				vo.setProjectId(registrationNow.getEmpProjectId());
				archivesDaprUtil.saveOrDeleteDeptRelation(vo);
			}
		} else {
			vo.setProjectId(registration.getEmpProjectId());
			archivesDaprUtil.saveOrDeleteDeptRelation(vo);
		}
		baseMapper.updateById(registrationNow);
		return R.ok();
	}

	@Override
	public R updateEmpRegistInfo(EmployeeRegistration registration) {
		EmployeeRegistration registrationNow = baseMapper.selectById(registration.getId());
		if (Common.isEmpty(registrationNow) ) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		//入职状态校验
		if (CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType()) &&
				CommonConstants.ZERO_STRING.equals(registrationNow.getProcessStatus())) {
			return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
		}
		//离职状态校验
		if (CommonConstants.TWO_STRING.equals(registrationNow.getFeedbackType())) {
			EmployeeRegistrationLeave registrationLeave = employeeRegistrationLeaveService.getById(registration.getId());
			if (Common.isNotNull(registrationLeave) && !CommonConstants.ZERO_STRING.equals(registrationLeave.getLeaveStatus())) {
				return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
			}
		}

		//手机号和身份证验证
		if (Common.isNotNull(registration.getEmpPhone())
				&& !registration.getEmpPhone().equals(registrationNow.getEmpPhone())) {
			if (!ValidityUtil.validateEmpPhone(registration.getEmpPhone())) {
				return R.failed(RegistConstants.PHONE_FORMAT_ERROR);
			}
			//姓名、身份证+手机号真实性校验
			R<Boolean> checkRes = checkDaprUtil.checkIdCardAndMobile(registration.getEmployeeName(),
					registration.getEmpIdcard(),registration.getEmpPhone());
			if (Common.isEmpty(checkRes) || checkRes.getCode() != CommonConstants.SUCCESS){
				return R.failed(checkRes.getMsg());
			}
		}
		//更新入离职日期和手机号
		if (Common.isNotNull(registration.getJoinLeaveDate())) {
			registrationNow.setJoinLeaveDate(registration.getJoinLeaveDate());
		}
		if (Common.isNotNull(registration.getEmpPhone())) {
			registrationNow.setEmpPhone(registration.getEmpPhone());
		}
		baseMapper.updateById(registrationNow);
		return R.ok();
	}

	@Override
	public R batchUpdatePreById(List<EmployeeRegistrationReceiveVo> employeeRegistList) {
		YifuUser user = SecurityUtils.getUser();
		EmployeeRegistration registrationNow;
		for (EmployeeRegistrationReceiveVo vo : employeeRegistList) {
			registrationNow = baseMapper.selectById(vo.getId());
			if (Common.isEmpty(registrationNow) || !CommonConstants.ONE_STRING.equals(registrationNow.getProcessStatus())) {
				return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
			}
			registrationNow.setProcessStatus(CommonConstants.TWO_STRING);
			logService.saveLog(registrationNow.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
					user.getNickname(), null);
			logService.saveLog(registrationNow.getId(), CommonConstants.ZERO_STRING, RegistConstants.MESSAGE_FINISH, vo.getProjectCreateTime(),
					user.getNickname(), CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType())
							? RegistConstants.BEFORE_IN_PROJECT : RegistConstants.BEFORE_OUT_PROJECT);
			SysCspDeptVo deptVo = new SysCspDeptVo();
			if (CommonConstants.ONE_STRING.equals(registrationNow.getFeedbackType())) {
				if (Common.isNotNull(registrationNow.getEmpDeptid())) {
					deptVo.setDepartName(registrationNow.getEmpDeptname());
					deptVo.setDepartId(Long.valueOf(registrationNow.getEmpDeptid()));
					deptVo.setProjectId(vo.getEmpProjectId());
					archivesDaprUtil.saveOrDeleteDeptRelation(deptVo);
				}
				//生成入职确认信息
				try {
					EmployeeRegistrationPreVo preVo = vo.getPreVo();
					initRegistPreInfo(registrationNow, preVo, user, CommonConstants.FOUR_STRING);
					R<String> domainR = archivesDaprUtil.saveRegistPreInfo(preVo);
					if (Common.isNotNull(domainR) && Common.isNotNull(domainR.getData())){
						//是否存在商险为是时生成入职确认信息商险明细数据
						if (preVo.getServerItem().contains("商险") && Common.isNotNull(preVo.getInsuranceIsBuy())
								&& preVo.getInsuranceIsBuy().equals(CommonConstants.ZERO_STRING)
								&& !preVo.getExitInsuranceInfoList().isEmpty()) {
							preVo.getExitInsuranceInfoList().forEach(e -> e.setCreateTime(null));
							preVo.getExitInsuranceInfoList().forEach(insurancePreVo -> insurancePreVo.setRegisterId(domainR.getData()));
							//生成入职确认信息商险明细数据
							insuranceDaprUtil.saveInsurancePreInfo(preVo);
						} else if (preVo.getServerItem().contains("商险") && !preVo.getEmployeeInsurancePreVos().isEmpty()) {
							//生成商险待购买的数据
							for (TEmployeeInsurancePreVo insurancePreVo : preVo.getEmployeeInsurancePreVos()) {
								initInsruancePreInfo(registrationNow, insurancePreVo, user, domainR.getData());
							}
							insuranceDaprUtil.saveInsurancePreInfo(preVo);
						}
						TEmployeeContractPreVo employeeContractPreVo = preVo.getEmployeeContractPreVos();
						if (preVo.getServerItem().contains("合同") && null != preVo.getEmployeeContractPreVos() &&
								((Common.isNotNull(preVo.getEmployeeContractPreVos().getContractFlag()) &&
								CommonConstants.ONE_STRING.equals(preVo.getEmployeeContractPreVos().getContractFlag())) ||
										Common.isEmpty(preVo.getEmployeeContractPreVos().getContractFlag()))) {
							//生成合同待购买数据
							String errorStr = initContractPreInfo(registrationNow, employeeContractPreVo, user);
							if (null != errorStr){
								throw new RuntimeException(errorStr);
							}
							employeeContractPreVo.setRegisterId(domainR.getData());
							archivesDaprUtil.saveContractPreInfo(employeeContractPreVo);
						}
						//服务类型包含社保购买时
						if (preVo.getServerItem().contains("社保") && (null != preVo.getExitSocialInfoList()
								|| null != preVo.getDispatchInfoPreVo())) {
							if (null != preVo.getExitSocialInfoList() && !preVo.getExitSocialInfoList().isEmpty()) {
								preVo.getExitSocialInfoList().forEach(socialPreDetailVo -> socialPreDetailVo.setRegisterId(domainR.getData()));
							}
							//生成社保待购买或者已购买数据
							if (null != preVo.getDispatchInfoPreVo()) {
								THouseHoldLimitInnerVo socialLimitVo =  null;
								if (Common.isNotNull(preVo.getDispatchInfoPreVo().getIsAutoDis())
										&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoPreVo().getIsAutoDis())
										&& null == preVo.getDispatchInfoPreVo().getExpectedCollectionTime()
										&& null == preVo.getDispatchInfoPreVo().getExpectedConfirmTime()) {
									BaseSearchVO paramVo = new BaseSearchVO();
									paramVo.setName(preVo.getDispatchInfoPreVo().getSocialHouseholdName());
									paramVo.setType(CommonConstants.ZERO_STRING);
									R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
									socialLimitVo =  null== resultR?null:resultR.getData();
									if (null == socialLimitVo){
										throw new RuntimeException("请及时配置户("+paramVo.getName()+")截止日配置信息");
									}
								}
								initSocialPreInfo(registrationNow, preVo.getDispatchInfoPreVo(), user, domainR.getData(),socialLimitVo);
							}
							socialDaprUtils.saveSocialPreInfo(preVo);
						}
						//服务类型包含公积金购买时
						if (preVo.getServerItem().contains("公积金") && (null != preVo.getExitFundInfoList()
								|| null != preVo.getDispatchInfoFundPreVo())) {
							if (null != preVo.getExitFundInfoList() && !preVo.getExitFundInfoList().isEmpty()) {
								preVo.getExitFundInfoList().forEach(fundPreDetailVo -> fundPreDetailVo.setRegisterId(domainR.getData()));
							}
							//生成公积金待购买或者已购买数据
							if (null != preVo.getDispatchInfoFundPreVo()) {
								THouseHoldLimitInnerVo fundLimitVo =  null;
								if (Common.isNotNull(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
										&& CommonConstants.ZERO_STRING.equals(preVo.getDispatchInfoFundPreVo().getIsAutoDis())
										&& null == preVo.getDispatchInfoFundPreVo().getExpectedCollectionTime()
										&& null == preVo.getDispatchInfoFundPreVo().getExpectedConfirmTime()) {
									BaseSearchVO paramVo = new BaseSearchVO();
									paramVo.setName(preVo.getDispatchInfoFundPreVo().getProvidentHouseholdName());
									paramVo.setType(CommonConstants.ONE_STRING);
									R<THouseHoldLimitInnerVo> resultR = socialDaprUtils.getWorkDayByDeadLineDay(paramVo);
									fundLimitVo =  null== resultR?null:resultR.getData();
									if (null == fundLimitVo){
										throw new RuntimeException("请及时配置户("+paramVo.getName()+")截止日配置信息");
									}
								}
								initFundPreInfo(registrationNow, preVo.getDispatchInfoFundPreVo(), user, domainR.getData(),fundLimitVo);
							}
							socialDaprUtils.saveFundPreInfo(preVo);
						}
					}
				}catch (Exception e) {
					log.error("执行异常", e);
				}
			} else {
				deptVo.setProjectId(vo.getEmpProjectId());
				archivesDaprUtil.saveOrDeleteDeptRelation(deptVo);
			}
			baseMapper.updateById(registrationNow);
		}
		return R.ok();
	}

	@Override
	public Boolean updateRegistByPreInfo(EmployeeRegistrationUpdateVo updateVo) {
		EmployeeRegistration registration = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
				.eq(EmployeeRegistration::getDeptNo, updateVo.getDeptNo())
				.eq(EmployeeRegistration::getEmpIdcard, updateVo.getEmpIdcard())
				.in(EmployeeRegistration::getProcessStatus, CommonConstants.processStatus)
				.last(CommonConstants.LAST_ONE_SQL));
		if (Common.isNotNull(registration)) {
			registration.setProcessStatus(CommonConstants.THREE_STRING);
			baseMapper.updateById(registration);
			//新增拒绝入职操作记录
			logService.saveInnerLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.BACK_RECEIVE, LocalDateTime.now(),
					updateVo.getEmployeeName(), updateVo.getReason(),updateVo.getEmployeeId());
		}
		return true;
	}

	@Override
	public Boolean updateRegistCustomerUserInfo(EmployeeRegistrationCustomerUserUpdateVo updateVo) {
		LambdaUpdateWrapper<EmployeeRegistration> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(EmployeeRegistration::getDeptNo,updateVo.getDeptNo())
				.eq(EmployeeRegistration::getFeedbackType, CommonConstants.ONE_STRING)
				.set(EmployeeRegistration::getCustomerUsernameNew, updateVo.getCustomerUserName())
				.set(EmployeeRegistration::getCustomerUserLoginNameNew, updateVo.getCustomerUserLoginName());
		this.update(updateWrapper);
		return true;
	}

	@Override
	public long getRegisterPreCount(EmployeeRegistrationSearchVo employeeRegistration) {
		//权限和条件赋值
		initSearchVo(employeeRegistration);
		employeeRegistration.setStatusList(CommonConstants.processPreStatus);
		employeeRegistration.setTypeList(CommonConstants.processPreStatus);
		return baseMapper.selectExportCount(employeeRegistration);
	}

	//单个新增、导入校验
	private String registCheck(EmployeeRegistration registration) {
		//定义判别用户身份证号的正则表达式（要么是15位，要么是18位，最后一位可以为字母）
		Pattern idNumPattern = compile("(\\d{14}[0-9a-zA-Z])|(\\d{17}[0-9a-zA-Z])");
		//通过Pattern获得Matcher
		Matcher idNumMatcher = idNumPattern.matcher(registration.getEmpIdcard());
		if (!idNumMatcher.matches()) {
			return RegistConstants.IDCARD_FORMAT_ERROR;
		}
		if (!ValidityUtil.validateEmpPhone(registration.getEmpPhone())) {
			return RegistConstants.PHONE_FORMAT_ERROR;
		}
		//姓名、身份证+手机号真实性校验
		R<Boolean> checkRes = checkDaprUtil.checkIdCardAndMobile(registration.getEmployeeName(),
				registration.getEmpIdcard(),registration.getEmpPhone());
		if (Common.isEmpty(checkRes) || checkRes.getCode() != CommonConstants.SUCCESS){
			return checkRes.getMsg();
		}
		EmployeeRegistration exit = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
				.eq(EmployeeRegistration::getEmpIdcard, registration.getEmpIdcard())
				.eq(EmployeeRegistration::getDeptNo, registration.getDeptNo())
				.eq(EmployeeRegistration::getFeedbackType, registration.getFeedbackType())
				.in(EmployeeRegistration::getProcessStatus, CommonConstants.processStatus)
				.last(CommonConstants.LAST_ONE_SQL));
		if (Common.isNotNull(exit)) {
			return RegistConstants.REGIST_SAME_CHECK;
		}
		//针对入职的判断是否存在流程中的合同待签订数据
		if (CommonConstants.ONE_STRING.equals(registration.getFeedbackType())) {
			EmpProjectStatusVo vo = new EmpProjectStatusVo();
			vo.setEmpIdcard(registration.getEmpIdcard());
			vo.setDeptNo(registration.getDeptNo());
			if (Boolean.TRUE.equals(checkContractPreIsExit(vo))) {
				return RegistConstants.EMP_CONTRACT_EXIT_CHECK;
			}
		}
		//针对离职的判断人员项目档案状态是否正常
		if (CommonConstants.TWO_STRING.equals(registration.getFeedbackType())) {
			EmpProjectStatusVo vo = new EmpProjectStatusVo();
			vo.setEmpIdcard(registration.getEmpIdcard());
			vo.setDeptNo(registration.getDeptNo());
			EmpProjectStatusVo exitVo = getEmpProjectStatus(vo);
			if (Common.isEmpty(exitVo)) {
				return RegistConstants.EMP_PROJECT_EXIT_CHECK;
			}
		}
		if (Common.isNotNull(registration.getEmpIdcard()) && Common.isNotNull(registration.getDeptNo())) {
			int count = baseMapper.getEmployeeRegistrationLeavingCount(registration.getEmpIdcard(), registration.getDeptNo());
			if (count > 0) {
				return RegistConstants.HAVE_LEAVING;
			}
		} else {
			return RegistConstants.NO_ID_DEPT;
		}
		return null;
	}

	//获取人员档案信息
	private EmpProjectStatusVo getEmpProjectStatus(EmpProjectStatusVo vo) {
		//找到不在项人员的身份证信息
		R<EmpProjectStatusVo> sdr = HttpDaprUtil.invokeMethodPost(archivesProperties.getAppUrl(), archivesProperties.getAppId()
				, "/temployeeproject/inner/getEmpProjectStatus", vo, EmpProjectStatusVo.class, SecurityConstants.FROM_IN);
		if (sdr != null && sdr.getData() != null) {
			vo = sdr.getData();
			return vo;
		} else {
			return null;
		}
	}

	//判断是否存在流程中的合同待签订数据
	private Boolean checkContractPreIsExit(EmpProjectStatusVo vo) {
		//找到不在项人员的身份证信息
		R<Boolean> sdr = HttpDaprUtil.invokeMethodPost(archivesProperties.getAppUrl(), archivesProperties.getAppId()
				, "/temployeecontractpre/inner/checkContractPreIsExit", vo, Boolean.class, SecurityConstants.FROM_IN);
		if (sdr != null && sdr.getData() != null) {
			return sdr.getData();
		} else {
			return false;
		}
	}

	//获取减项人员档案信息
	private EmpProjectStatusVo getOutEmpProjectStatus(EmpProjectStatusVo vo) {
		//找到不在项人员的身份证信息
		R<EmpProjectStatusVo> sdr = HttpDaprUtil.invokeMethodPost(archivesProperties.getAppUrl(), archivesProperties.getAppId()
				, "/temployeeproject/inner/getOutEmpProjectStatus", vo, EmpProjectStatusVo.class, SecurityConstants.FROM_IN);
		if (sdr != null && sdr.getData() != null) {
			vo = sdr.getData();
			return vo;
		} else {
			return null;
		}
	}

	//数据初始化
	private void initRegistInfo(EmployeeRegistration insert, YifuUser user, TSettleDomainSelectVo selectVo) {
		SysCspDeptVo vo = new SysCspDeptVo();
		vo.setUserId(user.getId());
		vo.setProjectId(selectVo.getId());
		// 1.9.8: 从客服端导入，入职部门默认为空
		if(CommonConstants.ONE_STRING.equals(insert.getDataSource())){
			R<SysCspDeptVo> booleanR = upmsDaprUtils.selectCspDeptByUserDeptId(vo);
			if (Common.isNotNull(booleanR) && Common.isNotNull(booleanR.getData())
					&& Common.isNotNull(booleanR.getData().getDepartId()) && Common.isNotNull(booleanR.getData().getDepartName())) {
				vo = booleanR.getData();
				insert.setRegistorDeptname(vo.getDepartName());
				insert.setRegistorDeptid(vo.getDepartId().toString());
				insert.setEmpDeptid(vo.getDepartId().toString());
				insert.setEmpDeptname(vo.getDepartName());
			} else {
				insert.setRegistorDeptname(user.getDeptName());
				insert.setRegistorDeptid(user.getDeptId().toString());
				insert.setEmpDeptid(user.getDeptId().toString());
				insert.setEmpDeptname(user.getDeptName());
			}
		}

		insert.setRegistorUsername(user.getNickname());
		insert.setRegistorPhone(user.getPhone());
		insert.setCustomerPhone(selectVo.getCsPhone());
		insert.setCustomerUsername(selectVo.getCsName());
		insert.setCustomerUserLoginname(selectVo.getCsLoginName());
		insert.setDeptName(selectVo.getDepartName());
		insert.setDeptId(selectVo.getId());

		// 1.9.8: 新增字段
		insert.setCustomerUsernameNew(selectVo.getCsName());
		insert.setCustomerUserLoginNameNew(selectVo.getCsLoginName());
	}

	//发送企业微信待办
	private void sendMessageToWx(EmployeeRegistration registration, String type) {
		//获取前端客服
		SysUser user;
		if (Common.isEmpty(registration.getCustomerUserLoginname())) {
			return;
		}
		R<SysUser> res = upmsDaprUtils.getSimpleUserByLoginName(registration.getCustomerUserLoginname());
		if (Common.isNotNull(res) && Common.isNotNull(res.getData())) {
			user = res.getData();
		} else {
			return;
		}
		StringBuilder sendUser = null;
		if (Common.isNotKong(user.getWxMessage())) {
			sendUser = new StringBuilder(user.getWxMessage());
		}
		if (sendUser != null) {
			RestTemplate restTemplate = new RestTemplate();
			Map<String, Object> requestMap = new HashMap<>();
			Map<String, Object> textcard = new HashMap<>();
			String authUrl = String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "66" + registration.getId());
			StringBuilder description = new StringBuilder();
			String title = "";
			if (CommonConstants.ONE_STRING.equals(type) || CommonConstants.TWO_STRING.equals(type)) {
				title = CommonConstants.ONE_STRING.equals(type) ? "人员入职提醒：" : "人员离职提醒：";
				description.append(CommonConstants.ONE_STRING.equals(type) ? "入职日期：" : "离职日期：")
						.append(DateUtil.dateToString(registration.getJoinLeaveDate(), DateUtil.ISO_EXPANDED_DATE_FORMAT)).append("<br>");
				description.append("项目名称：").append(registration.getDeptName()).append("<br>");
				description.append("项目编码：").append(registration.getDeptNo()).append("<br>");
				description.append("员工姓名：").append(registration.getEmployeeName()).append("<br>");
				description.append("身份证号：").append(registration.getEmpIdcard()).append("<br>");
				description.append("手机号码：").append(registration.getEmpPhone()).append("<br>");
			} else {
				title = "人员批量入离职提醒";
				description.append("项目名称：").append(registration.getDeptName()).append("<br>");
				description.append("项目编码：").append(registration.getDeptNo()).append("<br>");
				description.append("入职人数：").append(registration.getInNum()).append("<br>");
				description.append("离职人数：").append(registration.getOutNum()).append("<br>");
			}
			textcard.put("title", title);
			textcard.put("url", authUrl);
			textcard.put("description", description.toString());
			requestMap.put("touser", sendUser);
			requestMap.put("agentid", wxConfig.getAgentid());
			requestMap.put("msgtype", "textcard");
			requestMap.put("textcard", textcard);
			// 必须加上header说明
			if (!wxConfig.sendTextCard(restTemplate, requestMap)) {
				wxConfig.sendTextCard(restTemplate, requestMap);
			}
			//企业微信发送记录
			logService.saveLog(user.getUserId(), CommonConstants.ZERO_STRING, "企业微信消息提醒", LocalDateTime.now(),
					registration.getRegistorUsername(), "提醒人：" + user.getNickname());
		}
	}

	//发送企业微信待办
	private void sendMessageToWxSingle(EmployeeRegistration registration) {
		//获取前端客服
		SysUser user;
		if (Common.isEmpty(registration.getCustomerUserLoginname())) {
			return;
		}
		R<SysUser> res = upmsDaprUtils.getSimpleUserByLoginName(registration.getCustomerUserLoginname());
		if (Common.isNotNull(res) && Common.isNotNull(res.getData())) {
			user = res.getData();
		} else {
			return;
		}
		StringBuilder sendUser = null;
		if (Common.isNotKong(user.getWxMessage())) {
			sendUser = new StringBuilder(user.getWxMessage());
		}
		if (sendUser != null) {
			RestTemplate restTemplate = new RestTemplate();
			Map<String, Object> requestMap = new HashMap<>();
			Map<String, Object> textcard = new HashMap<>();
			String authUrl = String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "64" + registration.getId());
			StringBuilder description = new StringBuilder();
			String title = "作业自动化--人员入职通知";
			description.append("新入职人员:")
					.append(registration.getEmployeeName())
					.append("_")
					.append(registration.getEmpIdcard())
					.append("_")
					.append(registration.getEmpPhone())
					.append("<br>");
			description.append("请及时处理").append("<br>");
			textcard.put("title", title);
			textcard.put("url", authUrl);
			textcard.put("description", description.toString());
			requestMap.put("touser", sendUser);
			requestMap.put("agentid", wxConfig.getAgentid());
			requestMap.put("msgtype", "textcard");
			requestMap.put("textcard", textcard);
			// 必须加上header说明
			if (!wxConfig.sendTextCard(restTemplate, requestMap)) {
				wxConfig.sendTextCard(restTemplate, requestMap);
			}
			//企业微信发送记录
			logService.saveLog(user.getUserId(), CommonConstants.ZERO_STRING, "企业微信消息提醒", LocalDateTime.now(),
					registration.getRegistorUsername(), "提醒人：" + user.getNickname());
		}
	}

	/**
	 * @param searchCspVo 身份证与类型
	 * @Description: 获取已接收的入离职申请，同步所属部门到项目档案里
	 * @Author: hgw
	 * @Date: 2025/3/3 16:57
	 * @return: com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeProjectBelongDept
	 **/
	@Override
	public TEmployeeProjectBelongDept getZeroRegistrationAndUpdateTwo(TEmployeeProjectBelongDeptSearchCspVo searchCspVo) {
		List<TEmployeeProjectBelongDept> belongDeptList = baseMapper.getZeroRegistrationByIdCard(searchCspVo);
		if (belongDeptList != null && !belongDeptList.isEmpty()) {
			// 1：加日志
			if (doSaveLogBatch(searchCspVo, belongDeptList)) return null;
			// 更新为已处理
			baseMapper.updateTwoRegistrationByIdCard(searchCspVo);
			return belongDeptList.get(0);
		} else {
			return null;
		}
	}

	/**
	 * 根据ID获取员工注册的详细信息
	 * 此方法首先通过ID从数据库中获取员工注册信息，然后查询与该员工相关的附件信息，
	 * 并为每个附件生成可访问的URL，最后将这些信息一起封装返回
	 * @Author: huych
	 * @param id 员工注册信息的唯一标识符
	 * @return 返回一个封装了员工注册详细信息的结果对象，包括附件信息
	 */
	@Override
	public R<EmployeeRegistration> getDetailInfoById(String id) {
	    // 根据ID从数据库中获取员工注册信息
	    EmployeeRegistration employeeRegistration = baseMapper.selectById(id);
	    // 如果员工注册信息为空，则返回失败结果
	    if (Common.isEmpty(employeeRegistration)) {
	        return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
	    }
	    // 查询与员工相关的附件信息
	    List<TCspAttaInfo> attaInfo = tAttaInfoService.list(Wrappers.<TCspAttaInfo>query().lambda().eq(TCspAttaInfo::getDomainId, id));
	    // 如果附件信息非空，则为每个附件生成可访问的URL，并将其添加到员工注册信息中
	    if (attaInfo != null && !attaInfo.isEmpty()) {
	        URL url;
	        for (TCspAttaInfo a: attaInfo) {
	            url = ossUtil.getObjectUrl(null, a.getAttaSrc());
	            a.setAttaUrl(url.toString());
	        }
	        employeeRegistration.setAttaInfoList(attaInfo);
	    }
	    // 返回封装了员工注册详细信息的成功结果
	    return R.ok(employeeRegistration);
	}

	@Override
	public Date addYearsMonths(TEmployeeContractDateVo vo) {
		if (vo == null || vo.getRegistDate() == null) return null;

		// 转换为LocalDate（自动处理时区）
		LocalDate localDate = vo.getRegistDate().toInstant()
				.atZone(ZoneId.systemDefault())
				.toLocalDate();
		// 添加年数和月数
		if (vo.getMonthAfter() ==0 && vo.getYearAfter() ==0) {
			// 转回Date类型
			return Date.from(localDate.atStartOfDay()
					.atZone(ZoneId.systemDefault())
					.toInstant());
		} else {
			localDate = localDate
					.plusYears(vo.getYearAfter())
					.plusMonths(vo.getMonthAfter())
					.minusDays(1);
			// 转回 Date 类型
			return Date.from(localDate.atStartOfDay()
					.atZone(ZoneId.systemDefault())
					.toInstant());
		}
	}
	
	/**
	 * @Description: 添加年数和月数，如果结果为月份 1 号则不减 1 天
	 * @Author: system
	 * @Date: 2026/03/19
	 * @param: vo - 包含注册日期、年数、月数的对象
	 * @return: java.util.Date
	 **/
	public Date addYearsMonthsKeepFirstDay(TEmployeeContractDateVo vo) {
		if (vo == null || vo.getRegistDate() == null) return null;
	
		// 转换为 LocalDate（自动处理时区）
		LocalDate localDate = vo.getRegistDate().toInstant()
				.atZone(ZoneId.systemDefault())
				.toLocalDate();
		// 添加年数和月数
		if (vo.getMonthAfter() == 0 && vo.getYearAfter() == 0) {
			// 转回 Date 类型
			return Date.from(localDate.atStartOfDay()
					.atZone(ZoneId.systemDefault())
					.toInstant());
		} else {
			// 先计算加年加月后的日期
			localDate = localDate
					.plusYears(vo.getYearAfter())
					.plusMonths(vo.getMonthAfter());
				
			// 如果计算后的日期不是月份 1 号，则减 1 天；如果是 1 号则保持不变
			if (localDate.getDayOfMonth() != 1) {
				localDate = localDate.minusDays(1);
			}
				
			// 转回 Date 类型
			return Date.from(localDate.atStartOfDay()
					.atZone(ZoneId.systemDefault())
					.toInstant());
		}
	}

	@Override
	public EkpDeptContractInfoVo selectContractInfoByDetptNo(EkpDeptContractInfoVo vo) {
		if (Common.isNotNull(vo) && Common.isNotNull(vo.getDeptNo())) {
			R<EkpDeptContractInfoVo> info = ekpDaprUtils.selectContractInfoByDetptNo(vo);
			if (Common.isNotNull(info) && Common.isNotNull(info.getData())) {
				return info.getData();
			}
		}
		return null;
	}

	/**
	 * @Description: 批量处理日志
	 * @Author: hgw
	 * @Date: 2025/3/4 10:41
	 * @return: boolean
	 **/
	private boolean doSaveLogBatch(TEmployeeProjectBelongDeptSearchCspVo searchCspVo, List<TEmployeeProjectBelongDept> belongDeptList) {
		TOperationLog log;
		List<TOperationLog> logList = new ArrayList<>();
		String title = "已处理";
		for (TEmployeeProjectBelongDept belongDept : belongDeptList) {
			log = new TOperationLog();
			log.setMainId(belongDept.getId());
			log.setType(CommonConstants.ZERO_STRING);
			log.setTitle(title);
			log.setOperationName(searchCspVo.getEmpCreateAndLeaveUser());
			log.setOperationTime(searchCspVo.getEmpCreateAndLeaveTime());
			if (searchCspVo.getEmpCreateAndLeaveTime() != null && belongDept.getLogCreateTime() != null
					&& searchCspVo.getEmpCreateAndLeaveTime().isBefore(belongDept.getLogCreateTime())) {
				if (CommonConstants.ONE_STRING.equals(searchCspVo.getFeedbackType())) {
					log.setRemark("入职登记前已增员");
				} else {
					log.setRemark("离职登记前已减员");
				}
			}
			log.setCreateBy(searchCspVo.getUserId());
			log.setCreateName(searchCspVo.getUserName());
			log.setCreateTime(LocalDateTime.now());
			logList.add(log);
		}
		if (!logList.isEmpty()) {
			logService.saveBatch(logList);
		}
		return false;
	}

	/**
	 * @Description: 获取部门权限
	 * @Author: huych
	 * @Date: 2025/3/4 10:41
	 * @return:
	 **/
	private void getDtpeAuth(EmployeeRegistrationSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		if (null != user && Common.isNotNull(user.getId())) {
			List<UserPermissionVo> cspPermList = user.getCspPermMap();
			if (Common.isNotNull(cspPermList)) {
				// 获取用户在当前项目下的权限
				UserPermissionVo authority = null;
				for (UserPermissionVo userPermissionVo : cspPermList) {
					if (searchVo.getDeptNo().equals(userPermissionVo.getProjectNo())) {
						authority = userPermissionVo;
					}
				}
				if (Common.isNotNull(authority) && !authority.isHaveAll()) {
					if (Common.isNotNull(authority.getDepartIdSet())) {
						searchVo.setDepartIdSet(authority.getDepartIdSet());
					} else {
						searchVo.setId(CommonConstants.ONE_STRING_NEGATE);
					}
				}
			}
		}
	}

	/**
	 * @Description: 获取前端客服的所有项目权限
	 * @Author: huych
	 * @Date: 2025/3/13 17:02
	 * @return:
	 **/
	public void initSearchVo(EmployeeRegistrationSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		long roleId = 1839501715787390978L;
		boolean isSsc = this.haveRole(user, roleId);
		if (isSsc || CommonConstants.ZERO_STRING.equals(user.getSystemFlag())) {
			searchVo.setAuthSql(null);
			return;
		}
		if (Common.isNotNull(searchVo.getType()) && CommonConstants.ONE_STRING.equals(searchVo.getType())) {
			searchVo.setAuthSql(null);
			//获取项目信息
			R<TSettleDomainRegistListVo> domainR = archivesDaprUtil.getAllDeptByCustomerLoginName(user.getUsername());
			if (null != domainR && null != domainR.getData() && null != domainR.getData().getDeptNos() && domainR.getData().getDeptNos().size() > 0) {
				searchVo.setDeptNoList(domainR.getData().getDeptNos());
			} else {
				domainR = archivesDaprUtil.getAllDeptByCustomerLoginName(user.getUsername());
				if (null != domainR && null != domainR.getData() && null != domainR.getData().getDeptNos() && !domainR.getData().getDeptNos().isEmpty()) {
					searchVo.setDeptNoList(domainR.getData().getDeptNos());
				} else {
					searchVo.setId(CommonConstants.ONE_STRING_NEGATE);
				}
			}
		}
	}

	public boolean haveRole(YifuUser user, long roleId) {
		List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
		for (Long role : roleList) {
			if (role == roleId) {
				return true;
			}
		}
		return false;
	}

	//入职待建档数据初始化
	private void initRegistPreInfo(EmployeeRegistration registration,EmployeeRegistrationPreVo preVo,
								   YifuUser user,String status) throws ParseException {
		preVo.setId(registration.getId());
		preVo.setCustomerUsername(registration.getCustomerUsernameNew());
		preVo.setCustomerUserLoginname(null != registration.getCustomerUserLoginNameNew()
				? registration.getCustomerUserLoginNameNew() : registration.getCustomerUserLoginname());
		preVo.setDeptName(registration.getDeptName());
		preVo.setDeptId(registration.getDeptId());
		preVo.setDataSource(registration.getDataSource());
		preVo.setPosition(registration.getPosition());
		preVo.setJoinLeaveDate(registration.getJoinLeaveDate());
		preVo.setConfirmTime(DateUtil.getCurrentDateTime());
		preVo.setDeptNo(registration.getDeptNo());
		preVo.setConfirmUser(user.getNickname());
		preVo.setCustomerUsernameNew(registration.getCustomerUsernameNew());
		preVo.setEmpPhone(registration.getEmpPhone());
		preVo.setEmployeeName(registration.getEmployeeName());
		preVo.setEmpIdcard(registration.getEmpIdcard());
		preVo.setCreateBy(user.getId());
		preVo.setCreateName(user.getNickname());
		preVo.setUpdateBy(user.getId());
		preVo.setProcessStatus(status);
		// 预计收集时间为空且配置的推送时间不为空 计算预计收集时间
		if (null == preVo.getExpectedCollectionTime() && Common.isNotNull(preVo.getPushDate())) {
			String pushType = preVo.getPushType();
			try {
				// 推送日期类型：0 入职日期
				if (CommonConstants.ZERO_STRING.equals(pushType)) {
					preVo.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
							registration.getJoinLeaveDate(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " " + preVo.getPushDate(),
							DateUtil.DATETIME_PATTERN_MINUTE));
				}
				// 推送日期类型：1 入职前第 3 个工作日--含入职日期；2 入职前第 5 个工作日--含入职日期
				else if ((CommonConstants.ONE_STRING.equals(pushType) || CommonConstants.TWO_STRING.equals(pushType))
						&& registration.getJoinLeaveDate() != null) {
					int workDaysBefore = CommonConstants.ONE_STRING.equals(pushType) ? 3 : 5;
					LocalDate tempDate = parseContractEndDate(registration.getJoinLeaveDate());
					tempDate = calculateReminderWorkDaysBefore(tempDate, workDaysBefore, 0);
					Date temp  = DateUtil.getDateByLocalDate(tempDate);
					preVo.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
							temp, DateUtil.ISO_EXPANDED_DATE_FORMAT) + " " + preVo.getPushDate(),
							DateUtil.DATETIME_PATTERN_MINUTE));
				}
			} catch (Exception e){
				throw new RuntimeException("预期收款日期计算失败");
			}
		}

		//附件赋值
		List<TCspAttaInfo> attaInfoList = tAttaInfoService.list(Wrappers.<TCspAttaInfo>query().lambda().eq(TCspAttaInfo::getDomainId, registration.getId()));
		if (attaInfoList != null && !attaInfoList.isEmpty()) {
			List<TAttaInfoSaveVo> attaInfos = new ArrayList<>();
			for (TCspAttaInfo cspAttaInfo : attaInfoList) {
				TAttaInfoSaveVo attaInfo = new TAttaInfoSaveVo();
				BeanUtils.copyProperties(cspAttaInfo,attaInfo);
				if (CommonConstants.ONE_STRING.equals(cspAttaInfo.getRelationType())) {
					attaInfo.setRelationType("31");
				} else if (CommonConstants.TWO_STRING.equals(cspAttaInfo.getRelationType())) {
					attaInfo.setRelationType("32");
				}
				attaInfo.setDomainId(preVo.getId());
				attaInfos.add(attaInfo);
			}
			preVo.setAttaList(attaInfos);
		}

	}

	//商险待购买数据初始化
	private void initInsruancePreInfo(EmployeeRegistration registration,TEmployeeInsurancePreVo preVo,
									  YifuUser user,String id) throws ParseException {
		preVo.setRegisterId(id);
		preVo.setCustomerUsername(registration.getCustomerUsernameNew());
		preVo.setCustomerUserLoginname(null != registration.getCustomerUserLoginNameNew()
				? registration.getCustomerUserLoginNameNew() : registration.getCustomerUserLoginname());
		preVo.setDeptName(registration.getDeptName());
		preVo.setDeptId(registration.getDeptId());
		preVo.setDataSource(registration.getDataSource());
		preVo.setPosition(registration.getPosition());
		preVo.setJoinLeaveDate(registration.getJoinLeaveDate());
		preVo.setDeptNo(registration.getDeptNo());
		preVo.setEmpPhone(registration.getEmpPhone());
		preVo.setEmployeeName(registration.getEmployeeName());
		preVo.setEmpIdcard(registration.getEmpIdcard());
		preVo.setCreateBy(user.getId());
		preVo.setCreateName(user.getNickname());
		preVo.setUpdateBy(user.getId());
		preVo.setRegistTime(LocalDateTimeUtils.convertLDTToDate(registration.getCreateTime()));
		preVo.setRegistUser(registration.getCreateName());

		//预计派单日期
//		if (Common.isEmpty(preVo.getExpectedCollectionTime()) && Common.isNotNull(preVo.getPolicyStartType()) && CommonConstants.ONE_STRING.equals(preVo.getPolicyStartType())) {
//			//新增选择保单开始日期类型= 默认等于入职日期
//			TEmployeeInsuranceWorkDayVo dayVo = new TEmployeeInsuranceWorkDayVo();
//			dayVo.setType(CommonConstants.TWO_STRING);
//			dayVo.setRegistDate(preVo.getJoinLeaveDate());
//			R<TEmployeeInsuranceWorkDayVo> dataR = socialDaprUtils.getBeforeOrAfterWorkDay(dayVo);
//			if (Common.isNotNull(dataR) && Common.isNotNull(dataR.getData())
//					&& Common.isNotNull(dataR.getData().getRegistDate())
//					&& Common.isNotNull(dataR.getData().getPriDisDate())) {
//				preVo.setExpectedCollectionTime(dataR.getData().getPriDisDate());
//				preVo.setPolicyEffect(dataR.getData().getRegistDate());
//				preVo.setPolicyStart(dataR.getData().getRegistDate());
//			} else {
//				preVo.setExpectedCollectionTime(preVo.getJoinLeaveDate());
//				preVo.setPolicyEffect(preVo.getJoinLeaveDate());
//				preVo.setPolicyStart(preVo.getJoinLeaveDate());
//			}
//		}
		preVo.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
				preVo.getExpectedCollectionTime(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " 15:20", DateUtil.DATETIME_PATTERN_MINUTE));
	}

	//社保待购买数据初始化
	private void initSocialPreInfo(EmployeeRegistration registration, TDispatchInfoPreVo preVo,
								   YifuUser user, String id,THouseHoldLimitInnerVo limitInfo) throws ParseException {
		preVo.setRegisterId(id);
		preVo.setCustomerUsername(registration.getCustomerUsernameNew());
		preVo.setCustomerUserLoginName(null != registration.getCustomerUserLoginNameNew()
				? registration.getCustomerUserLoginNameNew() : registration.getCustomerUserLoginname());
		preVo.setDeptName(registration.getDeptName());
		preVo.setDeptId(registration.getDeptId());
		preVo.setJoinLeaveDate(registration.getJoinLeaveDate());
		preVo.setDeptNo(registration.getDeptNo());
		preVo.setEmpName(registration.getEmployeeName());
		preVo.setPhone(registration.getEmpPhone());
		preVo.setPosition(registration.getPosition());
		preVo.setEmpIdcard(registration.getEmpIdcard());
		preVo.setCreateBy(user.getId());
		preVo.setCreateName(user.getNickname());
		preVo.setUpdateBy(user.getId());
		preVo.setTypeSub(CommonConstants.ZERO_STRING);
		preVo.setProcessStatus(CommonConstants.ZERO_STRING);
		preVo.setDispatchItem("养老、医疗、生育、失业、工伤、大病");

		if (CommonConstants.ZERO_STRING.equals(preVo.getIsCreateDate())) {
			//原社保起缴日期类型为 0 入职日期 新：0 入职日期  1 入职满1个月 2 入职满2个月 3 入职满3个月 4 入职满4个月 5 入职满5个月
			// 6 入职满6个月 7 入职满7个月 8 入职满8个月 9 入职满9个月 10 入职满10个月 11 入职满11个月 12 入职满12个月
			if (!Common.isEmpty(preVo.getJoinLeaveDate())) {
				if (Common.isNotNull(preVo.getSocialDateType())){
					TEmployeeContractDateVo vo = new TEmployeeContractDateVo();
					vo.setMonthAfter(Integer.parseInt(preVo.getSocialDateType()));
					vo.setYearAfter(0);
					vo.setRegistDate(registration.getJoinLeaveDate());
					Date date = this.addYearsMonthsKeepFirstDay(vo);
					preVo.setSocialStartDate(date);
				}else {
					preVo.setSocialStartDate(registration.getJoinLeaveDate());
				}
			}
			preVo.setBigailmentStart(preVo.getSocialStartDate());
			preVo.setPensionStart(preVo.getSocialStartDate());
			preVo.setMedicalStart(preVo.getSocialStartDate());
			preVo.setBirthStart(preVo.getSocialStartDate());
			preVo.setWorkInjuryStart(preVo.getSocialStartDate());
			preVo.setUnemployStart(preVo.getSocialStartDate());
			preVo.setSocialStartDate(preVo.getSocialStartDate());
		}
		//如果自动触发派增为是，计算派单发起时间和派单确认时间,因为前端可以修改，所以只有没有值的时候才后端结算
		if (Common.isNotNull(preVo.getIsAutoDis()) && CommonConstants.ZERO_STRING.equals(preVo.getIsAutoDis())
				&& null == preVo.getExpectedCollectionTime()
				&& null == preVo.getExpectedConfirmTime()) {
			//获取当前月是否可办理状态：获取办理截止日往前最近的工昨日，当前日及截止日前(含截止日)有工作日就是可办理
			initExpectedCollectionTime(preVo.getSocialHouseholdName(), preVo.getSocialStartDate(), preVo,limitInfo);
		}
	}

	//商险状态是否正常判断
	private boolean checkInsuranceIsProcess(EmployeeRegistrationPreVo preVo) {
		R<Boolean> flag = insuranceDaprUtil.checkExitInsuanceIsProcess(preVo);
		//是否已签署为是需要判断合同是否在用或者流程中
		return Common.isEmpty(flag) || Boolean.TRUE.equals(!flag.getData());
	}

	//商险是否存在判断
	private TEmployeeAutoRegistCheckVo checkInsuranceExit(TEmployeeInsurancePreVo preVo,EmployeeRegistration registration) {
		//查询入职确认信息数据
		TEmployeeAutoRegistCheckVo exitCheckVo = new TEmployeeAutoRegistCheckVo();
		boolean erorFlag = false;
		R<TEmployeeInsuranceSelectVo> dataR = insuranceDaprUtil.selectInsurancePreInfoList(preVo);
		//查询商险数据
		TInsuranceDetail insuranceDetail= null;
		R<TEmployeeInsuranceSelectVo> dataInsurR = insuranceDaprUtil.selectInsuranceInfo(preVo);
		if (Common.isNotNull(dataInsurR) && Common.isNotNull(dataInsurR.getData())&& Common.isNotNull(dataInsurR.getData().getInsuranceDetail())) {
			insuranceDetail = dataInsurR.getData().getInsuranceDetail();
		}
		//二次确认接收场景
		if (Common.isNotNull(dataR) && Common.isNotNull(dataR.getData().getInsurancePreList())
				&& !dataR.getData().getInsurancePreList().isEmpty()) {
			//已存在该身份证的商险入职确认信息
			List<TEmployeeInsurancePre> list = dataR.getData().getInsurancePreList();
			for (TEmployeeInsurancePre pre : list) {
				//项目不同
				if (!preVo.getDeptNo().equals(pre.getDeptNo()) && (pre.getProcessStatus().equals(CommonConstants.ZERO_STRING) ||
						pre.getProcessStatus().equals(CommonConstants.ONE_STRING) ||
						pre.getProcessStatus().equals(CommonConstants.TWO_STRING))) {
					erorFlag = true;
					break;
				}
				//项目相同
				if (null != insuranceDetail && preVo.getDeptNo().equals(insuranceDetail.getDeptNo()) &&
						insuranceDetail.getBuyHandleStatus() != CommonConstants.FIVE_INT &&
						insuranceDetail.getBuyHandleStatus() != CommonConstants.FOUR_INT) {
					erorFlag = true;
					break;
				}
				if (null != insuranceDetail && !preVo.getDeptNo().equals(insuranceDetail.getDeptNo())
						&& insuranceDetail.getBuyHandleStatus() != CommonConstants.FIVE_INT) {
					erorFlag = true;
					break;
				}
			}
		} else {
			//第一次确认接收场景
			if (Common.isNotNull(insuranceDetail)) {
				//项目不同
				if (!preVo.getDeptNo().equals(insuranceDetail.getDeptNo()) && (
						insuranceDetail.getBuyHandleStatus() == CommonConstants.ONE_INT ||
						insuranceDetail.getBuyHandleStatus() == CommonConstants.SIX_INT ||
						insuranceDetail.getBuyHandleStatus() == CommonConstants.TWO_INT ||
						insuranceDetail.getBuyHandleStatus() == CommonConstants.THREE_INT)) {
					erorFlag = true;
				}
				//项目相同带回状态
				if (preVo.getDeptNo().equals(insuranceDetail.getDeptNo()) && insuranceDetail.getBuyHandleStatus() != CommonConstants.FIVE_INT) {
					if (insuranceDetail.getBuyHandleStatus() == CommonConstants.ONE_INT) {
						preVo.setProcessStatus(CommonConstants.THREE_STRING);
					} else if (insuranceDetail.getBuyHandleStatus() == CommonConstants.TWO_INT) {
						preVo.setProcessStatus(CommonConstants.FOUR_STRING);
					} else if (insuranceDetail.getBuyHandleStatus() == CommonConstants.THREE_INT) {
						preVo.setProcessStatus(CommonConstants.SIX_STRING);
					} else if (insuranceDetail.getBuyHandleStatus() == CommonConstants.FOUR_INT) {
						preVo.setProcessStatus(CommonConstants.FIVE_STRING);
					} else if (insuranceDetail.getBuyHandleStatus() == CommonConstants.SIX_INT) {
						preVo.setProcessStatus(CommonConstants.SEVEN_STRING);
					}
					//是否地市自购
					preVo.setIsAddress(insuranceDetail.getIsAdress());
					preVo.setInsurancesId(insuranceDetail.getId());
				}
			}
		}
		//组装错误信息
		if (erorFlag) {
			exitCheckVo.setEmployeeName(registration.getEmployeeName());
			exitCheckVo.setEmpIdcard(registration.getEmpIdcard());
			exitCheckVo.setDeptName(registration.getDeptName());
			exitCheckVo.setDeptNo(registration.getDeptNo());
			exitCheckVo.setType("商险");
			exitCheckVo.setErrorMsg("存在流程中/已完结的商险数据");
		} else {
			return null;
		}
		return exitCheckVo;
	}

	/**
	 * @param insurancePreVo
	 * @Description: 获取5个字段构成的关键字
	 * @Author: hgw
	 * @Date: 2025/4/9 11:23
	 * @return: java.lang.String
	 **/
	private String getFiveKey(TEmployeeInsurancePreVo insurancePreVo) {
		// 1：重复性判断
		return isNullToEmpty(insurancePreVo.getBuyStandard()) + CommonConstants.DOWN_LINE_STRING
				+ isNullToEmpty(insurancePreVo.getInsuranceTypeName()) + CommonConstants.DOWN_LINE_STRING
				+ isNullToEmpty(insurancePreVo.getInsuranceCompanyName()) + CommonConstants.DOWN_LINE_STRING
				+ isNullToEmpty(insurancePreVo.getPolicyStart()) + CommonConstants.DOWN_LINE_STRING + isNullToEmpty(insurancePreVo.getPolicyEnd());
	}

	/**
	 * @param str
	 * @Description: 空转化为空字符
	 * @Author: hgw
	 * @Date: 2025/4/9 11:29
	 * @return: java.lang.String
	 **/
	private String isNullToEmpty(Object str) {
		return null == str ? "" : str.toString();
	}

	/**
	 * 更新附件的ID
	 * 当员工注册时，此方法会更新附件信息表中相关记录的ID
	 * 首先，它会将所有与当前员工注册记录关联的附件的ID清空
	 * 然后，对于员工注册记录中的每个附件ID，它会更新附件信息表中对应记录的ID为当前员工的注册ID
	 * @Author: huych
	 * @param registration 员工注册对象，包含附件ID列表
	 */
	private void updateFileId(EmployeeRegistration registration) {
		// 创建更新条件构造器
		LambdaUpdateWrapper<TCspAttaInfo> updateWrapper = new LambdaUpdateWrapper<>();
		// 设置更新条件和新值
		updateWrapper.eq(TCspAttaInfo::getDomainId, registration.getId())
				.set(TCspAttaInfo::getDomainId, CommonConstants.EMPTY_STRING);
		// 执行更新操作，清空附件的域名ID
		tAttaInfoService.update(updateWrapper);
	    // 检查附件ID列表是否不为空
	    if (Common.isNotNull(registration.getAttaIdList()) && !registration.getAttaIdList().isEmpty()) {
	        // 遍历员工注册记录中的附件ID列表
			TCspAttaInfo atta;
	        for (String id : registration.getAttaIdList()) {
	            // 根据ID获取附件信息
	            atta = tAttaInfoService.getById(id);
	            // 更新附件的域名ID为当前员工的注册ID
				if (Common.isNotNull(atta)) {
					atta.setDomainId(registration.getId());
					// 保存更新后的附件信息
					tAttaInfoService.updateById(atta);
				}
	        }
	    }
	}
	/**
	 * @Author fxj
	 * @Description 拒绝入职--入职待确认列表
	 * @Date 20:14 2026/1/22
	 * @Param
	 * @return
	**/
	@Override
	public R refuseOffer(EmployeeRegistration registration) {
		YifuUser user = SecurityUtils.getUser();
		EmployeeRegistration registrationNow = baseMapper.selectById(registration.getId());
		if (Common.isEmpty(registrationNow)) {
			return R.failed(RegistConstants.NO_DATA_TO_HANDLE);
		}
		if (!CommonConstants.ONE_STRING.equals(registrationNow.getProcessStatus())){
			return R.failed("状态非未处理状态，请刷新确认后操作！");
		}
		registrationNow.setProcessStatus(CommonConstants.THREE_STRING);
		logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.BACK_RECEIVE, LocalDateTime.now(),
				user.getNickname(), registration.getLeaveReason());
		baseMapper.updateById(registrationNow);
		return R.ok();
	}

	@Override
	public R<List<ErrorMessage>> importDiyNew(InputStream inputStream) {
		// 验证输入参数
		if (inputStream == null) {
			return R.failed("导入文件流不能为空");
		}
	
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<EmployeeRegistrationNewVo> excelUtil = new ExcelUtil<>(EmployeeRegistrationNewVo.class);
		YifuUser user = SecurityUtils.getUser();
	
		// 获取当前登录人拥有的项目权限--非管理员获取
		List<String> deptNos = new ArrayList<>();
		if (Common.isNotNull(user) && !CommonConstants.ZERO_STRING.equals(user.getSystemFlag())) {
			R<TSettleDomainListVo> haveDomainR = archivesDaprUtil.getSettleDomainIdsByUserId(user.getId());
			if (null == haveDomainR || null == haveDomainR.getData()) {
				return R.failed("未获取到客服项目权限！");
			}
			TSettleDomainListVo haveDomain = haveDomainR.getData();
			// 添加空值检查，避免 NPE
			if (haveDomain.getDeptNos() != null) {
				deptNos = haveDomain.getDeptNos();
			}
		}
	
		// 临时存储已查询的项目信息
		Map<String, TSettleDomainSelectVo> domainMap = new HashMap<>(16);
	
		// 存储项目对应的岗位配置信息
		Map<String, List<String>> postConfigMap = new HashMap<>(16);
			
		// 验证重复存储（修正拼写错误：exitMap -> existMap）
		Map<String, String> existMap = new HashMap<>(16);
	
		// 写法 2：
		// 匿名内部类 不用额外写一个 DemoDataListener
		// 这里 需要指定读用哪个 class 去读，然后读取第一个 sheet 文件流会自动关闭
		try {
			List<String> finalDeptNos = deptNos;
			EasyExcel.read(inputStream, EmployeeRegistrationNewVo.class, new ReadListener<EmployeeRegistrationNewVo>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT1;
				/**
				 * 临时存储
				 */
				private List<EmployeeRegistrationNewVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
	
				@Override
				public void invoke(EmployeeRegistrationNewVo data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex + 1);
					ErrorMessage errorMessage = excelUtil.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)) {
						errorMessage.setData(data);
						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());
					importEmployeeRegistrationNew(cachedDataList, errorMessageList, user, domainMap, postConfigMap, finalDeptNos, existMap);
					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 importEmployeeRegistrationNew(List<EmployeeRegistrationNewVo> excelVOList,
											   List<ErrorMessage> errorMessageList, YifuUser user,
											   Map<String, TSettleDomainSelectVo> domainMap,
											   Map<String,List<String>> postConfigMap,
											   List<String> deptNos,
											   Map<String, String> exitMap ) {
		//来源为 MVP 端专用
		String dataSource = CommonConstants.TWO_STRING;
		//判断当前用户是否为管理员
		boolean isAdmin = Common.isNotNull(user) && CommonConstants.ZERO_STRING.equals(user.getSystemFlag());
		int inNum = 0;
		int outNum = 0;
		List<EmployeeRegistration> insertList = new ArrayList<>();
		TSettleDomainSelectVo selectVo = null;
		R<SysAutoDictItemVo> domainDictR= null;
		List<String> postConfigList  = null;
		//定义判别用户身份证号的正则表达式（要么是15位，要么是18位，最后一位可以为字母）
		Pattern idNumPattern = compile("(\\d{14}[0-9a-zA-Z])|(\\d{17}[0-9a-zA-Z])");
		//该人员入职/离职数据已登记，请勿重复操作
		EmployeeRegistration exit;
		StringBuilder errorTempBuilder;
		EmployeeRegistration insert;
		for (EmployeeRegistrationNewVo excel : excelVOList) {
			selectVo = domainMap.get(excel.getDeptNo());
			//统一校验（整合所有错误信息一起返回）
			List<String> errorList = new ArrayList<>();
			if (null == selectVo){
				//获取项目信息
				R<TSettleDomainSelectVo> domainR = archivesDaprUtil.getSettleDomainSelectVoById(excel.getDeptNo());
				if (null == domainR || !CommonConstants.SUCCESS.equals(domainR.getCode())) {
					String errorMsg = Optional.ofNullable(domainR)
							.map(R::getMsg)
							.orElse("未知错误");
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
									"访问员工基础服务异常：" + errorMsg, excel));
					continue;
				}
				if (null == domainR.getData()){
					errorList.add("未查询到具体项目信息");
					selectVo = null;
				} else {
					selectVo = domainR.getData();
					domainMap.put(excel.getDeptNo(), selectVo);
				}
			}
			//判断项目是否可用 (务状态：0 正常 1 停止服务 2 冻结)
			if (null != selectVo && !CommonConstants.ZERO_STRING.equals(selectVo.getStopFlag())) {
				errorList.add("项目不可用！");
			}
			//非管理员判断是否有项目权限
			if (!isAdmin){
				if (!deptNos.contains(excel.getDeptNo())){
					errorList.add("无项目权限！");
				}
			}

			//获取项目配置的字典值
			postConfigList = postConfigMap.get(excel.getDeptNo());
			if (null == postConfigList) {
				postConfigList = new ArrayList<>();
				domainDictR = archivesDaprUtil.getDictListByDeptNo(excel.getDeptNo());

				// 校验响应数据完整性
				if (Common.isNotNull(domainDictR)
						&& Common.isNotNull(domainDictR.getData())
						&& Common.isNotNull(domainDictR.getData().getSysAutoDictItemList())) {

					List<SysAutoDictItem> dictItemList = domainDictR.getData().getSysAutoDictItemList();

					// 筛选并收集岗位类型标签
					dictItemList.stream()
							.filter(Objects::nonNull)
							.filter(item -> "post_type".equals(item.getType()))
							.map(SysAutoDictItem::getLabel)
							.filter(Objects::nonNull)
							.forEach(postConfigList::add);

					// 仅当获取到有效数据时才缓存
					if (!postConfigList.isEmpty()) {
						postConfigMap.put(excel.getDeptNo(), postConfigList);
					}
				}
			}

			// 插入
			insert = new EmployeeRegistration();
			BeanUtil.copyProperties(excel, insert);
			//表数据验重
			//表内数据重复 员工姓名、员工身份证号码、反馈类型、项目编码
			errorTempBuilder = new StringBuilder();
			errorTempBuilder.append(Common.isNullToString(excel.getDeptNo()))
					.append("_")
					.append(Common.isNullToString(excel.getEmployeeName()))
					.append("_")
					.append(Common.isNullToString(excel.getEmpIdcard()))
					.append("_")
					.append(Common.isNullToString(excel.getFeedbackType()));
			String duplicateKey = errorTempBuilder.toString();
			//修正拼写错误：exitMap -> existMap
			if (null == exitMap.get(duplicateKey)) {
				exitMap.put(duplicateKey, "1");
			} else {
				errorList.add(RegistConstants.IMPORT_EXIT_CHECK);
			}
			if (null != selectVo){
				insert.setDeptNo(selectVo.getDepartNo());
			}

			
			//岗位配置校验（离职时不需要验证岗位，入职时需要校验）
			if(CommonConstants.TWO_STRING.equals(dataSource)
					&& CommonConstants.ONE_STRING.equals(insert.getFeedbackType())
					&& Common.isNotNull(postConfigList)
					&& !postConfigList.contains(insert.getPosition())){
				errorList.add("岗位不在项目配置的岗位配置项里");
			}

			//通过Pattern获得Matcher
			String empIdcard = insert.getEmpIdcard();
			boolean isIdCardValid = true;
			if (Common.isEmpty(empIdcard)) {
				isIdCardValid = false;
				errorList.add(RegistConstants.IDCARD_FORMAT_ERROR);
			} else {
				Matcher idNumMatcher = idNumPattern.matcher(empIdcard);
				if (!idNumMatcher.matches()) {
					isIdCardValid = false;
					errorList.add(RegistConstants.IDCARD_FORMAT_ERROR);
				}
			}
			
			boolean isPhoneValid = true;
			if (!ValidityUtil.validateEmpPhone(insert.getEmpPhone())) {
				isPhoneValid = false;
				errorList.add(RegistConstants.PHONE_FORMAT_ERROR);
			}
			
			//姓名、身份证+手机号真实性校验（前置条件：手机号码和身份证正常）
			if (isIdCardValid && isPhoneValid) {
				R<Boolean> checkRes = checkDaprUtil.checkIdCardAndMobile(insert.getEmployeeName(),
						insert.getEmpIdcard(),insert.getEmpPhone());
				if (Common.isEmpty(checkRes) || checkRes.getCode() != CommonConstants.SUCCESS){
					errorList.add(Common.isNotNull(checkRes) ? checkRes.getMsg() : "姓名、身份证+手机号真实性校验失败");
				}
			}
			
			//该人员入职/离职数据已登记，请勿重复操作
			exit = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
					.eq(EmployeeRegistration::getEmpIdcard, insert.getEmpIdcard())
					.eq(EmployeeRegistration::getDeptNo, insert.getDeptNo())
					.eq(EmployeeRegistration::getFeedbackType, insert.getFeedbackType())
					.in(EmployeeRegistration::getProcessStatus, CommonConstants.processStatus)
					.last(CommonConstants.LAST_ONE_SQL));
			if (Common.isNotNull(exit)) {
				errorList.add(RegistConstants.REGIST_SAME_CHECK);
			}
			
			//针对入职的判断是否存在流程中的合同待签订数据
			if (CommonConstants.ONE_STRING.equals(insert.getFeedbackType())) {
				EmpProjectStatusVo vo = new EmpProjectStatusVo();
				vo.setEmpIdcard(insert.getEmpIdcard());
				vo.setDeptNo(insert.getDeptNo());
				if (Boolean.TRUE.equals(checkContractPreIsExit(vo))) {
					errorList.add(RegistConstants.EMP_CONTRACT_EXIT_CHECK);
				}
			}
			
			//针对离职的判断人员项目档案状态是否正常（前置条件：项目存在）
			if (CommonConstants.TWO_STRING.equals(insert.getFeedbackType()) && Common.isNotNull(selectVo)) {
				EmpProjectStatusVo vo = new EmpProjectStatusVo();
				vo.setEmpIdcard(insert.getEmpIdcard());
				vo.setDeptNo(insert.getDeptNo());
				EmpProjectStatusVo exitVo = getEmpProjectStatus(vo);
				if (Common.isEmpty(exitVo)) {
					errorList.add(RegistConstants.EMP_PROJECT_EXIT_CHECK);
				}
			}
			
			//检查自动化离职未处理完毕的信息（前置条件：项目存在）
			if (Common.isNotNull(insert.getEmpIdcard()) && Common.isNotNull(insert.getDeptNo()) && Common.isNotNull(selectVo)) {
				int count = baseMapper.getEmployeeRegistrationLeavingCount(insert.getEmpIdcard(), insert.getDeptNo());
				if (count > 0) {
					errorList.add(RegistConstants.HAVE_LEAVING);
				}
			}
			
			//如果有错误，整合后返回
			if (!errorList.isEmpty()) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(), String.join(";", errorList), excel));
				continue;
			}
			// 1.9.8：新增赋值
			insert.setDataSource(dataSource);
			initRegistInfo(insert, user, selectVo);
			insertList.add(insert);
			//新增记录,新增操作记录
			baseMapper.insert(insert);
			if (Common.isNotNull(insert.getFeedbackType()) && CommonConstants.TWO_STRING.equals(insert.getFeedbackType())) {
				// 生成离职待办
				employeeRegistrationLeaveService.saveLeaveInfo(insert);
			}
			if (CommonConstants.ONE_STRING.equals(insert.getFeedbackType())) {
				inNum++;
			} else {
				outNum++;
			}
			logService.saveLog(insert.getId(), CommonConstants.ZERO_STRING, RegistConstants.MESSAGE_REGIST, LocalDateTime.now(),
					insert.getRegistorUsername(), null);
		}
		if (!Common.isEmpty(insertList)) {
			insertList.clear();
			//发送企业微信待办
			if (Common.isNotNull(selectVo)) {
				EmployeeRegistration msgRegistration = new EmployeeRegistration();
				msgRegistration.setInNum(inNum);
				msgRegistration.setOutNum(outNum);
				msgRegistration.setCustomerUserLoginname(selectVo.getCsLoginName());
				msgRegistration.setDeptName(selectVo.getDepartName());
				msgRegistration.setDeptNo(selectVo.getDepartNo());
				//企业微信消息提醒
				sendMessageToWx(msgRegistration, CommonConstants.THREE_STRING);
			}
		}

	}

	/**
	 * 解析合同结束日期
	 */
	private LocalDate parseContractEndDate(Date contractEnd) {
		try {
			return LocalDateUtil.parseLocalDate(DateUtil.dateToString(contractEnd, DateUtil.ISO_EXPANDED_DATE_FORMAT));
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * @Author fxj
	 * @Description 往前找指定个工作日 含当前日期  --- 不好提炼为工具类
	 * @param type 0 往前  1  往后
	 * @Date 19:24 2026/2/26
	 * @return
	 **/
	private LocalDate calculateReminderWorkDaysBefore(LocalDate lastDay,int count,int type) {
		LocalDate currentDate = lastDay;
		int workDayCount = 0;
		// 往前找3个工作日
		while (workDayCount < count) {
			// 检查当前日期是否为工作日
			if (isWorkDay(currentDate)) {
				workDayCount++;
			}
			if (workDayCount == count){
				return currentDate;
			}
			// 往前一天
			currentDate = currentDate.minusDays(0==type?1:-1);
		}
		return currentDate;
	}
	/**
	 * 判断指定日期是否为工作日
	 * @param date 要检查的日期
	 * @return true-工作日，false-非工作日
	 */
	private boolean isWorkDay(LocalDate date) {
		TEmployeeInsuranceWorkDayVo workDayVo = new TEmployeeInsuranceWorkDayVo();
		workDayVo.setRegistDate(LocalDateTimeUtils.convertLDToDate(date));

		// 使用 THolidayInfoService 的 checkIsWorkDay 方法判断是否为假期
		// 如果是假期则不是工作日，否则是工作日
		R<Boolean> res = socialDaprUtils.checkIsWorkDay(workDayVo);
		// 添加空值检查，避免 NPE，并提高代码可读性
		if (res == null || res.getData() == null) {
			log.warn("checkIsWorkDay 返回结果为空，默认视为非工作日");
			return false;
		}
		// res.getData() 为 true 表示是假期（非工作日），为 false 表示是工作日
		return !res.getData();
	}

	/**
	 * @Description: 确认接收时保存变更日志（只有新增，old对象为空）
	 * @Author: system
	 * @Date: 2026-04-16
	 * @param empPreId 入职确认信息ID
	 * @param preVo 入职确认信息VO
	 * @param user 当前用户
	 **/
	private void saveConfirmReceiveLog(String empPreId, EmployeeRegistrationPreVo preVo, YifuUser user) {
		try {
			if (Common.isEmpty(empPreId) || Common.isEmpty(preVo)) {
				return;
			}

			String logId = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
			List<TEmployeePreLogDetail> detailList = new ArrayList<>();
			StringBuilder diffTitleBuilder = new StringBuilder();

			// 1. 档案信息日志（type=1）
			TEmployeePreLogDetail archiveDetail = new TEmployeePreLogDetail();
			archiveDetail.setModelType(CommonConstants.ONE_STRING); // 1新增
			archiveDetail.setType(CommonConstants.ONE_STRING); // 1档案
			archiveDetail.setPreId(empPreId);
			archiveDetail.setPreLogId(logId);
			archiveDetail.setOldInfo(null); // old对象为空
			archiveDetail.setNewInfo(JSON.toJSONString(preVo));
			archiveDetail.setDifferenceInfo(null);
			archiveDetail.setCreateBy(user.getId());
			archiveDetail.setCreateName(user.getNickname());
			detailList.add(archiveDetail);
			diffTitleBuilder.append("档案信息");

			// 2. 商险信息日志（type=2）
			if (preVo.getServerItem() != null && preVo.getServerItem().contains("商险")) {
				if (diffTitleBuilder.length() > 0) {
					diffTitleBuilder.append("、");
				}
				diffTitleBuilder.append("商险信息");

				// 是否已购买商险
				if (Common.isNotNull(preVo.getInsuranceIsBuy())) {
					TEmployeePreLogDetail insuranceBuyDetail = new TEmployeePreLogDetail();
					insuranceBuyDetail.setModelType(CommonConstants.ONE_STRING);
					insuranceBuyDetail.setType(CommonConstants.TWO_STRING); // 2商险
					insuranceBuyDetail.setPreId(empPreId);
					insuranceBuyDetail.setPreLogId(logId);
					insuranceBuyDetail.setOldInfo(null);
					Map<String, Object> newInfo = new HashMap<>();
					newInfo.put("insuranceIsBuy", preVo.getInsuranceIsBuy());
					insuranceBuyDetail.setNewInfo(JSON.toJSONString(newInfo));
					insuranceBuyDetail.setDifferenceInfo("insuranceIsBuy");
					insuranceBuyDetail.setCreateBy(user.getId());
					insuranceBuyDetail.setCreateName(user.getNickname());
					detailList.add(insuranceBuyDetail);
				}

				// 商险明细
				if (Common.isNotNull(preVo.getEmployeeInsurancePreVos()) && !preVo.getEmployeeInsurancePreVos().isEmpty()) {
					for (TEmployeeInsurancePreVo insurancePre : preVo.getEmployeeInsurancePreVos()) {
						TEmployeePreLogDetail insuranceDetail = new TEmployeePreLogDetail();
						insuranceDetail.setModelType(CommonConstants.ONE_STRING);
						insuranceDetail.setType(CommonConstants.TWO_STRING);
						insuranceDetail.setPreId(empPreId);
						insuranceDetail.setPreLogId(logId);
						insuranceDetail.setOldInfo(null);
						insuranceDetail.setNewInfo(JSON.toJSONString(insurancePre));
						// 使用 HrEquator 比较差异字段（新增时 old 为空，传入空对象）
						insuranceDetail.setDifferenceInfo(null);
						insuranceDetail.setCreateBy(user.getId());
						insuranceDetail.setCreateName(user.getNickname());
						detailList.add(insuranceDetail);
					}
				}
			}

			// 3. 合同信息日志（type=3）
			if (preVo.getServerItem() != null && preVo.getServerItem().contains("合同") 
					&& Common.isNotNull(preVo.getEmployeeContractPreVos())) {
				if (diffTitleBuilder.length() > 0) {
					diffTitleBuilder.append("、");
				}
				diffTitleBuilder.append("合同信息");

				TEmployeePreLogDetail contractDetail = new TEmployeePreLogDetail();
				contractDetail.setModelType(CommonConstants.ONE_STRING);
				contractDetail.setType(CommonConstants.THREE_STRING); // 3合同
				contractDetail.setPreId(empPreId);
				contractDetail.setPreLogId(logId);
				contractDetail.setOldInfo(null);
				contractDetail.setNewInfo(JSON.toJSONString(preVo.getEmployeeContractPreVos()));
				contractDetail.setDifferenceInfo(null);
				contractDetail.setCreateBy(user.getId());
				contractDetail.setCreateName(user.getNickname());
				detailList.add(contractDetail);
			}

			// 4. 社保信息日志（type=4）
			if (preVo.getServerItem() != null && preVo.getServerItem().contains("社保")) {
				if (diffTitleBuilder.length() > 0) {
					diffTitleBuilder.append("、");
				}
				diffTitleBuilder.append("社保信息");

				// 是否已参保
				if (Common.isNotNull(preVo.getSocialIsBuy())) {
					TEmployeePreLogDetail socialBuyDetail = new TEmployeePreLogDetail();
					socialBuyDetail.setModelType(CommonConstants.ONE_STRING);
					socialBuyDetail.setType(CommonConstants.FOUR_STRING); // 4社保
					socialBuyDetail.setPreId(empPreId);
					socialBuyDetail.setPreLogId(logId);
					socialBuyDetail.setOldInfo(null);
					Map<String, Object> newInfo = new HashMap<>();
					newInfo.put("socialIsBuy", preVo.getSocialIsBuy());
					socialBuyDetail.setNewInfo(JSON.toJSONString(newInfo));
					socialBuyDetail.setDifferenceInfo("socialIsBuy");
					socialBuyDetail.setCreateBy(user.getId());
					socialBuyDetail.setCreateName(user.getNickname());
					detailList.add(socialBuyDetail);
				}

				// 社保派单信息
				if (Common.isNotNull(preVo.getDispatchInfoPreVo())) {
					TEmployeePreLogDetail socialDetail = new TEmployeePreLogDetail();
					socialDetail.setModelType(CommonConstants.ONE_STRING);
					socialDetail.setType(CommonConstants.FOUR_STRING);
					socialDetail.setPreId(empPreId);
					socialDetail.setPreLogId(logId);
					socialDetail.setOldInfo(null);
					socialDetail.setNewInfo(JSON.toJSONString(preVo.getDispatchInfoPreVo()));
					socialDetail.setDifferenceInfo(null);
					socialDetail.setCreateBy(user.getId());
					socialDetail.setCreateName(user.getNickname());
					detailList.add(socialDetail);
				}
			}

			// 5. 公积金信息日志（type=5）
			if (preVo.getServerItem() != null && preVo.getServerItem().contains("公积金")) {
				if (diffTitleBuilder.length() > 0) {
					diffTitleBuilder.append("、");
				}
				diffTitleBuilder.append("公积金信息");

				// 是否已参保
				if (Common.isNotNull(preVo.getFundIsBuy())) {
					TEmployeePreLogDetail fundBuyDetail = new TEmployeePreLogDetail();
					fundBuyDetail.setModelType(CommonConstants.ONE_STRING);
					fundBuyDetail.setType(CommonConstants.FIVE_STRING); // 5公积金
					fundBuyDetail.setPreId(empPreId);
					fundBuyDetail.setPreLogId(logId);
					fundBuyDetail.setOldInfo(null);
					Map<String, Object> newInfo = new HashMap<>();
					newInfo.put("fundIsBuy", preVo.getFundIsBuy());
					fundBuyDetail.setNewInfo(JSON.toJSONString(newInfo));
					fundBuyDetail.setDifferenceInfo("fundIsBuy");
					fundBuyDetail.setCreateBy(user.getId());
					fundBuyDetail.setCreateName(user.getNickname());
					detailList.add(fundBuyDetail);
				}

				// 公积金派单信息
				if (Common.isNotNull(preVo.getDispatchInfoFundPreVo())) {
					TEmployeePreLogDetail fundDetail = new TEmployeePreLogDetail();
					fundDetail.setModelType(CommonConstants.ONE_STRING);
					fundDetail.setType(CommonConstants.FIVE_STRING);
					fundDetail.setPreId(empPreId);
					fundDetail.setPreLogId(logId);
					fundDetail.setOldInfo(null);
					fundDetail.setNewInfo(JSON.toJSONString(preVo.getDispatchInfoFundPreVo()));
					fundDetail.setDifferenceInfo(null);
					fundDetail.setCreateBy(user.getId());
					fundDetail.setCreateName(user.getNickname());
					detailList.add(fundDetail);
				}
			}

			// 保存日志主表和明细
			if (!detailList.isEmpty()) {
				TEmployeePreLog empPreLog = new TEmployeePreLog();
				empPreLog.setId(logId);
				empPreLog.setPreId(empPreId);
				empPreLog.setDiffTitle(diffTitleBuilder.toString());
				if (Common.isNotNull(user)) {
					empPreLog.setCreateBy(user.getId());
					empPreLog.setCreateName(user.getNickname());
				}

				// 通过Dapr调用档案服务保存日志
				archivesDaprUtil.savePreLogBatch(Collections.singletonList(empPreLog));

				// 保存日志明细
				archivesDaprUtil.savePreLogDetailBatch(detailList);
			}
		} catch (Exception e) {
			log.error("保存确认接收日志异常", e);
		}
	}
}
