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

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.EmployeeRegistrationLeaveInsurance;
import com.yifu.cloud.plus.v1.csp.entity.EmployeeRegistrationLeaveLog;
import com.yifu.cloud.plus.v1.yifu.insurances.constants.InsurancesConstants;
import com.yifu.cloud.plus.v1.csp.mapper.EmployeeRegistrationLeaveInsuranceMapper;
import com.yifu.cloud.plus.v1.csp.mapper.EmployeeRegistrationLeaveMapper;
import com.yifu.cloud.plus.v1.csp.mapper.EmployeeRegistrationMapper;
import com.yifu.cloud.plus.v1.csp.service.EmployeeRegistrationLeaveLogService;
import com.yifu.cloud.plus.v1.csp.service.EmployeeRegistrationLeaveService;
import com.yifu.cloud.plus.v1.csp.vo.*;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainRegistListVo;
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.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.ErrorMessage;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchListVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseServiceParamListVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.InsuranceDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.SocialDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.util.LocalDateUtil;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.HolidayListVO;
import com.yifu.cloud.plus.v1.yifu.social.vo.TDispatchReduceListVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.TDispatchReduceVo;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 自动化离职待办
 *
 * @author hgw
 * @date 2025-11-19 19:23:15
 */
@Log4j2
@Service
public class EmployeeRegistrationLeaveServiceImpl extends ServiceImpl<EmployeeRegistrationLeaveMapper, EmployeeRegistrationLeave> implements EmployeeRegistrationLeaveService {

	@Autowired
	private ArchivesDaprUtil archivesDaprUtil;
	@Autowired
	private SocialDaprUtils socialDaprUtils;
	@Autowired
	private InsuranceDaprUtil insuranceDaprUtil;
	@Autowired
	private EmployeeRegistrationMapper employeeRegistrationMapper;
	@Autowired
	private EmployeeRegistrationLeaveInsuranceMapper leaveInsuranceMapper;
	@Autowired
	private EmployeeRegistrationLeaveLogService leaveLogService;

	/**
	 * 自动化离职待办简单分页查询
	 *
	 * @param employeeRegistrationLeave 自动化离职待办
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistrationLeaveTableVo> getEmployeeRegistrationLeaveTablePage(Page<EmployeeRegistrationLeaveTableVo> page, EmployeeRegistrationLeaveSearchVo employeeRegistrationLeave) {
		initSearchVo(employeeRegistrationLeave);
		return baseMapper.getEmployeeRegistrationLeaveTablePage(page, employeeRegistrationLeave);
	}

	@Override
	public List<EmployeeRegistrationLeaveTableVo> getEmployeeRegistrationLeaveTablePage2000(EmployeeRegistrationLeaveSearchVo employeeRegistrationLeave) {
		initSearchVo(employeeRegistrationLeave);
		return baseMapper.getEmployeeRegistrationLeaveTablePage2000(employeeRegistrationLeave);
	}

	@Override
	public long getRegistrationLeaveCount(EmployeeRegistrationLeaveSearchVo searchVo) {
		initSearchVo(searchVo);
		return baseMapper.getEmployeeRegistrationLeaveTableCount(searchVo);
	}

	@Override
	public IPage<EmployeeRegistrationLeaveTableVo> getEmployeeRegistrationLeaveConfirmTablePage(Page<EmployeeRegistrationLeaveTableVo> page, EmployeeRegistrationLeaveSearchVo employeeRegistrationLeave) {
		initSearchVo(employeeRegistrationLeave);
		return baseMapper.getEmployeeRegistrationLeaveConfirmTablePage(page, employeeRegistrationLeave);
	}

	/**
	 * @Description: 前端客服的权限
	 * @Author: hgw
	 * @Date: 2025/11/20 10:37
	 * @return: void
	 **/
	private void initSearchVo(EmployeeRegistrationLeaveSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		boolean isSsc = this.haveRole(user);
		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().isEmpty()) {
				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);
				}
			}
		}
	}

	private boolean haveRole(YifuUser user) {
		List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
		for (Long role : roleList) {
			if (role == CommonConstants.CS_ROLE_ID) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 自动化离职待办批量导出
	 *
	 * @param searchVo 自动化离职待办
	 * @return
	 */
	@Override
	public void exportTable(HttpServletResponse response, EmployeeRegistrationLeaveSearchVo searchVo) {
		String fileName = "自动化离职待处理批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationLeaveExportVo> list = new ArrayList<>();
		//获取要导出的列表
		if (Common.isNotNull(searchVo.getIds())) {
			searchVo.setIdList(Common.getList(searchVo.getIds()));
		}
		//权限赋值
		initSearchVo(searchVo);
		long count = baseMapper.getEmployeeRegistrationLeaveTableCount(searchVo);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcelFactory.write(out, EmployeeRegistrationLeaveExportVo.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.getEmployeeRegistrationLeaveTableList(searchVo);
					if (Common.isNotNull(list)) {
						WriteSheet writeSheet = EasyExcelFactory.writerSheet("自动化离职待处理" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcelFactory.writerSheet("自动化离职待处理" + index).build();
				excelWriter.write(list, writeSheet);
			}
			if (Common.isNotNull(list)) {
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		} catch (Exception e) {
			log.error("执行异常", e);
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	@Override
	public void exportConfirmTable(HttpServletResponse response, EmployeeRegistrationLeaveSearchVo searchVo) {
		String fileName = "自动化离职确认批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationLeaveConfirmExportVo> list = new ArrayList<>();
		long count = baseMapper.getEmployeeRegistrationLeaveConfirmTableCount(searchVo);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcelFactory.write(out, EmployeeRegistrationLeaveConfirmExportVo.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.getEmployeeRegistrationLeaveConfirmTableList(searchVo);
					if (Common.isNotNull(list)) {
						WriteSheet writeSheet = EasyExcelFactory.writerSheet("自动化离职确认" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcelFactory.writerSheet("自动化离职确认" + index).build();
				excelWriter.write(list, writeSheet);
			}
			if (Common.isNotNull(list)) {
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		} catch (Exception e) {
			log.error("执行异常", e);
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	@Override
	public void saveLeaveInfo(EmployeeRegistration registration) {

		EmployeeRegistrationLeave leave = new EmployeeRegistrationLeave();
		leave.setId(registration.getId());
		leave.setLeaveStatus(CommonConstants.ZERO_STRING);

		// 设置执行状态为“未执行”
		leave.setDoStatus(CommonConstants.ZERO_STRING);

		// 1社保2公积金3商险4合同5项目档案6人员档案
		StringBuilder doType = new StringBuilder();

		BaseSearchVO paramVo = new BaseSearchVO();
		paramVo.setEmpIdCard(registration.getEmpIdcard());
		paramVo.setDeptNo(registration.getDeptNo());
		// 设置社保减员状态
		String socialId = "";
		String socialStatusOld = "";
		String fundId = "";
		String fundStatusOld = "";
		BaseSearchVO returnVo;
		R<BaseSearchVO> returnR = socialDaprUtils.getSocialAndFundStatus(paramVo);
		if (null != returnR && Common.isNotNull(returnR.getData())) {
			returnVo = returnR.getData();
			if (Common.isNotNull(returnVo.getResultIdOne())) {
				socialId = returnVo.getResultIdOne();
				socialStatusOld = returnVo.getResultIdOneStatus();
			}
			if (Common.isNotNull(returnVo.getResultIdTwo())) {
				fundId = returnVo.getResultIdTwo();
				fundStatusOld = returnVo.getResultIdTwoStatus();
			}
		}
		if (Common.isNotNull(socialId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.ONE_STRING);
			leave.setDoStatusSocial(CommonConstants.ZERO_STRING);
			leave.setSocialDispatchIdOld(socialId);
			leave.setSocialStatusOld(socialStatusOld);
		} else {
			leave.setDoStatusSocial(CommonConstants.ONE_STRING);
		}

		// 设置公积金减员状态
		if (Common.isNotNull(fundId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.TWO_STRING);
			leave.setDoStatusFund(CommonConstants.ZERO_STRING);
			leave.setFundDispatchIdOld(fundId);
			leave.setFundStatusOld(fundStatusOld);
		} else {
			leave.setDoStatusFund(CommonConstants.ONE_STRING);
		}

		// 设置商险退保状态
		String insuranceId = "";
		String insuranceStatusOld = "";
		returnR = insuranceDaprUtil.getInsurancesStatus(paramVo);
		if (null != returnR && Common.isNotNull(returnR.getData())) {
			returnVo = returnR.getData();
			if (Common.isNotNull(returnVo.getResultIdOne())) {
				insuranceId = returnVo.getResultIdOne();
				insuranceStatusOld = returnVo.getResultIdOneStatus();
			}
		}
		if (Common.isNotNull(insuranceId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.THREE_STRING);
			leave.setDoStatusInsurance(CommonConstants.ZERO_STRING);
			leave.setInsuranceIdOld(insuranceId);
			leave.setInsuranceStatusOld(insuranceStatusOld);
			String[] insuranceArr = insuranceId.split(CommonConstants.COMMA_STRING);
			EmployeeRegistrationLeaveInsurance sub;
			// 保存前，先删除，防止错误数据，导致状态判断失败
			leaveInsuranceMapper.deleteLeaveInsurance(leave.getId());
			for (String subId : insuranceArr) {
				sub = new EmployeeRegistrationLeaveInsurance();
				sub.setLeaveId(leave.getId());
				sub.setInsuranceId(subId);
				sub.setDoStatusInsurance(CommonConstants.ZERO_STRING);
				leaveInsuranceMapper.insert(sub);
			}
		} else {
			leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
		}
		// 设置合同终止状态
		String contractId = "";
		String contractStatusOld = "";
		String empProjectId = "";
		String empProjectStatusOld = "";
		String empId = "";
		String empStatusOld = "";
		// 是否多项目0否1是
		String isMultipleDept = CommonConstants.ZERO_STRING;
		returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
		if (null != returnR && Common.isNotNull(returnR.getData())) {
			returnVo = returnR.getData();
			if (Common.isNotNull(returnVo.getResultIdOne())) {
				empId = returnVo.getResultIdOne();
				empStatusOld = returnVo.getResultIdOneStatus();
			}
			if (Common.isNotNull(returnVo.getResultIdTwo())) {
				empProjectId = returnVo.getResultIdTwo();
				empProjectStatusOld = returnVo.getResultIdTwoStatus();
			}
			if (Common.isNotNull(returnVo.getResultIdThree())) {
				contractId = returnVo.getResultIdThree();
				contractStatusOld = returnVo.getResultIdThreeStatus();
			}
			if (Common.isNotNull(returnVo.getResultIdFour())) {
				isMultipleDept = returnVo.getResultIdFour();
			}
		}
		if (Common.isNotNull(contractId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.FOUR_STRING);
			leave.setDoStatusContract(CommonConstants.ZERO_STRING);
			leave.setContractIdOld(contractId);
			leave.setContractStatusOld(contractStatusOld);
		} else {
			leave.setDoStatusContract(CommonConstants.ONE_STRING);
		}

		leave.setIsMultipleDept(isMultipleDept);
		if (Common.isNotNull(empProjectId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.FIVE_STRING);
			leave.setDoStatusProject(CommonConstants.ZERO_STRING);
			leave.setEmpProjectIdOld(empProjectId);
			leave.setEmpProjectStatusOld(empProjectStatusOld);
		} else {
			leave.setDoStatusProject(CommonConstants.ONE_STRING);
		}
		if (Common.isNotNull(empId)) {
			if (Common.isNotNull(doType) && doType.length() > CommonConstants.ZERO_INT) {
				doType.append(",");
			}
			doType.append(CommonConstants.SIX_STRING);
			leave.setDoStatusEmp(CommonConstants.ZERO_STRING);
			leave.setEmpIdOld(empId);
			leave.setEmpStatusOld(empStatusOld);
		} else {
			leave.setDoStatusEmp(CommonConstants.ONE_STRING);
		}

		leave.setLeaveReasonName(RegistConstants.BASE_REASON_TYPE_NAME);
		leave.setLeaveReasonId(RegistConstants.BASE_REASON_TYPE);


		// 设置需处理项（1社保2公积金3商险4合同5项目档案6人员档案）
		leave.setDoType(doType.toString());
		// 设置联动端口（固定值：人员离职）
		leave.setLinkPort(RegistConstants.BASE_LINK_PORT);
		this.saveOrUpdate(leave);
	}

	@Override
	public EmployeeRegistrationLeave initLeaveInfo(String id) {
		EmployeeRegistration registration = employeeRegistrationMapper.selectById(id);
		EmployeeRegistrationLeave leave = this.getById(id);
		if (registration == null || leave == null) {
			return leave;
		}
		//获取假日信息
		Map<String, Integer> holidayMap = getHolidayMap();
		// 停缴社保日期
		if (Common.isNotNull(leave.getSocialDispatchIdOld()) && Common.isEmpty(leave.getSocialReduceDate())) {
			leave.setSocialReduceDate(DateUtil.addMonth(CommonConstants.ONE_INT));
		}
		// 停缴公积金日期
		if (Common.isNotNull(leave.getFundDispatchIdOld()) && Common.isEmpty(leave.getFundReduceDate())) {
			leave.setFundReduceDate(DateUtil.addMonth(CommonConstants.ONE_INT));
		}

		// 获取下个工作日，且大于等于今天，如果大于15点20，换下个工作日
		if (Common.isNotNull(leave.getSocialDispatchIdOld()) && Common.isEmpty(leave.getSocialExpectedTime())) {
			leave.setSocialExpectedTime(calculateNextWorkDays(holidayMap));
		}
		// 获取下个工作日，且大于等于今天，如果大于15点20，换下个工作日
		if (Common.isNotNull(leave.getFundDispatchIdOld()) && Common.isEmpty(leave.getFundExpectedTime())) {
			leave.setFundExpectedTime(calculateNextWorkDays(holidayMap));
		}

		// 设置商险退保状态
		initInsurance(registration, leave, holidayMap);
		// 设置合同终止状态
		if (Common.isNotNull(leave.getContractIdOld()) && Common.isEmpty(leave.getContractExpectedTime())) {
			leave.setContractExpectedTime(calculateNextWorkDays(holidayMap));
		}
		return leave;
	}

	// 初始化商险
	private void initInsurance(EmployeeRegistration registration, EmployeeRegistrationLeave leave, Map<String, Integer> holidayMap) {
		if (Common.isNotNull(leave.getInsuranceIdOld()) && Common.isNotNull(registration.getJoinLeaveDate()) && Common.isEmpty(leave.getInsuranceExpectedTime())) {
			// 获取下个工作日，且大于等于今天，如果大于15点20，换下个工作日
			leave.setInsuranceExpectedTime(calculateNextWorkDaysByDate(dateToLocalDate(registration.getJoinLeaveDate()), holidayMap));
			leave.setInsuranceExpectedTimeNext(leave.getInsuranceExpectedTime().plusDays(CommonConstants.ONE_INT));
		}
	}

	@Override
	public BatchSureLeaveVo initBatchSureInfo() {
		BatchSureLeaveVo vo = new BatchSureLeaveVo();

		//获取假日信息
		//获取假日信息
		Map<String, Integer> holidayMap = getHolidayMap();
		// 商险是否处理：0否1是
		vo.setDoTypeInsurance(CommonConstants.ONE_STRING);
		// 停缴社保日期
		vo.setSocialReduceDate(DateUtil.addMonth(CommonConstants.ONE_INT));
		// 停缴公积金日期
		vo.setFundReduceDate(DateUtil.addMonth(CommonConstants.ONE_INT));
		vo.setLeaveReasonId(RegistConstants.BASE_REASON_TYPE);
		vo.setLeaveReasonName(RegistConstants.BASE_REASON_TYPE_NAME);
		// 获取下个工作日，且大于等于今天，如果大于15点20，换下个工作日
		vo.setSocialExpectedTimeAndFund(calculateNextWorkDays(holidayMap));
		// 设置合同终止
		vo.setContractExpectedTime(calculateNextWorkDays(holidayMap));
		return vo;
	}

	private LocalDate dateToLocalDate(Date joinLeaveDate) {
		return joinLeaveDate.toInstant()
				.atZone(ZoneId.systemDefault())
				.toLocalDate();
	}

	// 获取下一个工作日：先比较与今天谁大，用大的，如果非工作日，或大于15点20，取下个工作日，否则用大的
	private LocalDateTime calculateNextWorkDaysByDate(LocalDate joinLeaveDate, Map<String, Integer> holidayMap) {
		// 获取下一个工作日：先比较与今天谁大，用大的，如果非工作日，或大于15点20，取下个工作日，否则用大的
		// 今天
		LocalDate today = LocalDate.now();
		LocalDateTime todayTime = LocalDateTime.now();
		// 创建今天的15点20时间
		LocalDateTime targetTime = LocalDateTime.now().withHour(15).withMinute(20).withSecond(0).withNano(0);
		// 判断是否大于15点20，大于则取明天
		if (todayTime.isAfter(targetTime)) {
			today = today.plusDays(1);
		}
		if (joinLeaveDate.isBefore(today)) {
			// 如果B小于今天，则B为今天
			joinLeaveDate = today;
		}
		// 如果今天是工作日，则为今天
		if (this.isWorkday(joinLeaveDate, holidayMap)) {
			return joinLeaveDate.atTime(15, 20, 0);
		} else {
			// 今天非工作日，顺延到工作日
			return getNextWorkday(joinLeaveDate, holidayMap).atTime(15, 20, 0);
		}
	}

	private LocalDateTime calculateNextWorkDays(Map<String, Integer> holidayMap) {
		// 获取下一个工作日：先比较与今天谁大，用大的，如果非工作日，或大于15点20，取下个工作日，否则用大的
		// 今天
		LocalDate today = LocalDate.now();
		LocalDateTime todayTime = LocalDateTime.now();
		// 创建今天的15点20时间
		LocalDateTime targetTime = LocalDateTime.now().withHour(15).withMinute(20).withSecond(0).withNano(0);
		// 判断是否大于15点20，大于则取明天
		if (todayTime.isAfter(targetTime)) {
			today = today.plusDays(1);
		}
		// 如果今天是工作日，则为今天
		if (this.isWorkday(today, holidayMap)) {
			return today.atTime(15, 20, 0);
		} else {
			// 今天非工作日，顺延到工作日
			return getNextWorkday(today, holidayMap).atTime(15, 20, 0);
		}
	}

	// 获取下一个工作日
	public LocalDate getNextWorkday(LocalDate date, Map<String, Integer> holidayMap) {
		LocalDate result = date.plusDays(CommonConstants.ONE_INT);
		int i=100;
		while (i>0 && !this.isWorkday(result, holidayMap)) {
			result = result.plusDays(CommonConstants.ONE_INT);
			i--;
		}
		return result;
	}

	/**
	 * 判断是否为工作日,true是，false否
	 */
	public boolean isWorkday(LocalDate date, Map<String, Integer> holidayMap) {
		String days = LocalDateUtil.getDateSrt(date, LocalDateUtil.NORM_DATE_PATTERN);
		return holidayMap.get(days) == null;
	}


	// 手动关闭：
	// 需处理项：1社保2公积金3商险4合同 6人员档案
	// doTypeWu 3商险6人员档案
	// doTypeYi 1社保2公积金3商险4合同
	@Override
	public R<String> doClose(String id, String remark, String doTypeWu, String doTypeYi) {
		YifuUser user = SecurityUtils.getUser();
		if (user == null) {
			return R.failed("请登录");
		}
		EmployeeRegistrationLeave leave = this.getById(id);
		EmployeeRegistration registration = employeeRegistrationMapper.selectById(id);
		if (Common.isEmpty(doTypeWu) && Common.isEmpty(doTypeYi)) {
			return R.failed("请选择处理项");
		}
		if (Common.isNotNull(remark) && remark.length()>200) {
			return R.failed("无需处理原因超过200字！");
		}
		if (leave != null) {
			BaseSearchVO returnVo;
			BaseSearchVO paramVo = new BaseSearchVO();
			paramVo.setEmpIdCard(registration.getEmpIdcard());
			paramVo.setDeptNo(registration.getDeptNo());

			StringBuilder errorInfo = new StringBuilder();
			StringBuilder logInfo = new StringBuilder("手动关闭：");
			if (Common.isNotNull(doTypeWu)) {
				logInfo.append("无需处理标记：");
				if (doTypeWu.contains(CommonConstants.THREE_STRING)) {
					logInfo.append("商险;");
					if (CommonConstants.TWO_STRING.equals(leave.getDoStatusInsurance())
							|| CommonConstants.THREE_STRING.equals(leave.getDoStatusInsurance())
							|| CommonConstants.NINE_STRING.equals(leave.getDoStatusInsurance())) {
						leave.setInsuranceId(leave.getInsuranceIdOld());
						leave.setCloseRemarkInsurance(remark);
						leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
					} else {
						errorInfo.append("商险状态已处理，不可手动关闭！");
					}
				}
				if (doTypeWu.contains(CommonConstants.SIX_STRING)) {
					logInfo.append("人员档案;");
					if (CommonConstants.TWO_STRING.equals(leave.getDoStatusEmp())
							|| CommonConstants.NINE_STRING.equals(leave.getDoStatusEmp())) {
						leave.setEmpId(leave.getEmpIdOld());
						leave.setCloseRemarkEmp(remark);
						leave.setDoStatusEmp(CommonConstants.ONE_STRING);

						String isMultipleDept = CommonConstants.ZERO_STRING;
						R<BaseSearchVO> returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
						if (null != returnR && Common.isNotNull(returnR.getData())) {
							returnVo = returnR.getData();
							if (Common.isNotNull(returnVo.getResultIdFour())) {
								isMultipleDept = returnVo.getResultIdFour();
							}
						}
						if (CommonConstants.ZERO_STRING.equals(isMultipleDept)) {
							errorInfo.append("人员当下非多项目，不可无需处理！");
						}
					} else {
						errorInfo.append("人员状态已处理，不可手动关闭！");
					}

				}
			}
			if (Common.isNotNull(doTypeYi)) {
				String closeRemark = "已在其他入口处理";
				logInfo.append("已在其他入口处理：");
				String socialDispatchId = "";
				String fundDispatchId = "";
				R<BaseSearchVO> returnR = socialDaprUtils.getSocialAndFundStatusByClose(paramVo);
				if (null != returnR && Common.isNotNull(returnR.getData())) {
					returnVo = returnR.getData();
					if (Common.isNotNull(returnVo.getResultIdOne())) {
						socialDispatchId = returnVo.getResultIdOne();
					}
					if (Common.isNotNull(returnVo.getResultIdTwo())) {
						fundDispatchId = returnVo.getResultIdTwo();
					}
				}

				if (doTypeYi.contains(CommonConstants.ONE_STRING)) {
					logInfo.append("社保;");
					if (!CommonConstants.ONE_STRING.equals(leave.getDoStatusSocial())
							&& !CommonConstants.EIGHT_STRING.equals(leave.getDoStatusSocial())) {
						if (Common.isEmpty(socialDispatchId)) {
							errorInfo.append("社保未派减完结！");
						} else {
							leave.setSocialId(socialDispatchId);
							leave.setDoStatusSocial(CommonConstants.ONE_STRING);
							leave.setCloseRemarkSocial(closeRemark);
						}
					} else {
						errorInfo.append("社保状态已完结，不可处理！");
					}
				}
				if (doTypeYi.contains(CommonConstants.TWO_STRING)) {
					logInfo.append("公积金;");
					if (!CommonConstants.ONE_STRING.equals(leave.getDoStatusFund())
							&& !CommonConstants.EIGHT_STRING.equals(leave.getDoStatusFund())) {
						if (Common.isEmpty(fundDispatchId)) {
							errorInfo.append("公积金未派减完结！");
						} else {
							leave.setFundId(fundDispatchId);
							leave.setDoStatusFund(CommonConstants.ONE_STRING);
							leave.setCloseRemarkFund(closeRemark);
						}
					} else {
						errorInfo.append("公积金状态已完结，不可处理！");
					}
				}
				if (doTypeYi.contains(CommonConstants.THREE_STRING)) {
					logInfo.append("商险;");
					String insuranceId = "";
					returnR = insuranceDaprUtil.getInsurancesStatusByClose(paramVo);
					if (null != returnR && Common.isNotNull(returnR.getData())) {
						returnVo = returnR.getData();
						if (Common.isNotNull(returnVo.getResultIdOne())) {
							insuranceId = returnVo.getResultIdOne();
						}
					}
					if (!CommonConstants.ONE_STRING.equals(leave.getDoStatusInsurance())
							&& !CommonConstants.EIGHT_STRING.equals(leave.getDoStatusInsurance())) {
						// 这个反着查的，有未减完的，表示不可以关闭它，只能忽略它
						if (Common.isNotNull(insuranceId)) {
							errorInfo.append("商险未派减完结！");
						} else {
							leave.setInsuranceId(leave.getInsuranceIdOld());
							leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
							leave.setCloseRemarkInsurance(closeRemark);
						}
					} else {
						errorInfo.append("商险状态已完结，不可处理！");
					}
				}
				if (doTypeYi.contains(CommonConstants.FOUR_STRING)) {
					logInfo.append("合同;");
					String contractId = "";
					String contractIdEnd = "";
					returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
					if (null != returnR && Common.isNotNull(returnR.getData())) {
						returnVo = returnR.getData();
						if (Common.isNotNull(returnVo.getResultIdThree())) {
							contractId = returnVo.getResultIdThree();
						}
						if (Common.isNotNull(returnVo.getResultIdFourStatus())) {
							contractIdEnd = returnVo.getResultIdFourStatus();
						}
					}
					if (!CommonConstants.ONE_STRING.equals(leave.getDoStatusContract())
							&& !CommonConstants.EIGHT_STRING.equals(leave.getDoStatusContract())) {
						if (Common.isNotNull(contractId)) {
							errorInfo.append("存在可用的合同！");
						} else {
							if (Common.isNotNull(contractIdEnd)) {
								leave.setContractId(contractIdEnd);
								leave.setDoStatusContract(CommonConstants.ONE_STRING);
								leave.setCloseRemarkContract(closeRemark);
							} else {
								// errorInfo.append("未找到终止的合同！")
								// 社保派减，同步减合同，是没有终止的合同的，而是在合同本身改状态
								leave.setContractId(leave.getContractIdOld());
								leave.setDoStatusContract(CommonConstants.ONE_STRING);
								leave.setCloseRemarkContract(closeRemark);
							}
						}
					} else {
						errorInfo.append("合同状态已完结，不可处理！");
					}
				}
			}

			if (errorInfo.length() > 0) {
				return R.failed(errorInfo.toString());
			} else {
				this.judgeStatus(leave);
				this.updateById(leave);
				EmployeeRegistrationLeaveLog leaveLog = new EmployeeRegistrationLeaveLog();
				leaveLog.setLeaveId(leave.getId());
				leaveLog.setCreateName(user.getNickname());
				leaveLog.setCreateTime(LocalDateTime.now());
				leaveLog.setContent(logInfo.toString());
				leaveLogService.save(leaveLog);
				return R.ok();
			}
		} else {
			return R.failed("未找到该数据");
		}

	}

	// 判断状态
	private void judgeStatus(EmployeeRegistrationLeave leave) {
		// 收集所有分项状态
		String[] statusArray = {
				leave.getDoStatusContract(),
				leave.getDoStatusSocial(),
				leave.getDoStatusFund(),
				leave.getDoStatusInsurance(),
				leave.getDoStatusProject(),
				leave.getDoStatusEmp()
		};

		// 统计状态
		int total = 0;
		int initialCount = 0;
		int successCount = 0;
		int failedCount = 0;
		int noNeedCount = 0;

		for (String status : statusArray) {
			if (status == null) continue;

			total++;
			if ("1".equals(status)) {
				noNeedCount++;
			} else if ("0".equals(status) ||"2".equals(status) || status.isEmpty()) {
				initialCount++;
			} else if (status.endsWith("8")) {
				successCount++;
			} else if (status.endsWith("3") || status.endsWith("9") || status.endsWith("10")) {
				failedCount++;
			}
		}

		// 有效状态数量（排除无需处理的）
		int validCount = total - noNeedCount;

		String doStatus;
		if (validCount == 0) {
			doStatus = "6"; // 全部无需处理
		} else if (initialCount == validCount) {
			doStatus = "1"; // 未执行
		} else if (successCount == validCount) {
			doStatus = "5"; // 全部成功
		} else if (failedCount == validCount) {
			doStatus = "4"; // 全部失败
		} else if (successCount > 0 && failedCount > 0) {
			doStatus = "3"; // 部分成功
		} else {
			doStatus = "2"; // 执行中
		}

		leave.setDoStatus(doStatus);
		setLeaveStatusByDoStatus(leave);
	}

	/**
	 * 根据执行结果更新离职处理状态
	 * 规则：
	 * - 执行结果为"执行中(2)、部分成功(3)、全部失败(4)"，离职处理状态为"处理中(2)"
	 * - 执行结果为"全部成功(5)"，离职处理状态为"已处理(3)"
	 * - 其他情况保持原有离职处理状态不变（避免覆盖待确认、待处理状态）
	 */
	private void setLeaveStatusByDoStatus(EmployeeRegistrationLeave leave) {
		switch (leave.getDoStatus()) {
			case "2": // 执行中
			case "3": // 部分成功
			case "4": // 全部失败
				leave.setLeaveStatus("2"); // 处理中
				break;
			case "5": // 全部成功
				leave.setLeaveStatus("3"); // 已处理
				break;
			case "6": // 无需处理
				leave.setLeaveStatus("3"); // 已处理
				break;
			// case "1": // 未执行 - 保持原有状态（可能是待处理）
			// case "6": // 无需处理 - 保持原有状态
			// default:   // 其他情况保持原有状态不变
		}
	}

	@Override
	public R<String> doSure(EmployeeRegistrationLeave leave) {
		YifuUser user = SecurityUtils.getUser();
		if (user == null) {
			return R.failed("请登录");
		}
		if (leave != null && Common.isNotNull(leave.getId())) {
			EmployeeRegistrationLeave leaveOld = this.getById(leave.getId());
			EmployeeRegistration registrationOld = employeeRegistrationMapper.selectById(leave.getId());
			if (leaveOld != null && Common.isNotNull(leaveOld.getId()) && registrationOld != null
					&& Common.isNotNull(registrationOld.getEmpIdcard()) && Common.isNotNull(registrationOld.getDeptNo())) {
				if (CommonConstants.ZERO_STRING.equals(leaveOld.getLeaveStatus())) {
					if (Common.isNotNull(leave.getDoType())) {
						if (leave.getDoType().contains(CommonConstants.THREE_STRING)) {
							leave.setDoStatusInsurance(CommonConstants.TWO_STRING);
						} else {
							leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
						}
						// 停缴社保日期
						if (Common.isNotNull(leave.getSocialDispatchIdOld())) {
							leave.setDoStatusSocial(CommonConstants.TWO_STRING);
						}
						// 停缴公积金日期
						if (Common.isNotNull(leave.getFundDispatchIdOld())) {
							leave.setDoStatusFund(CommonConstants.TWO_STRING);
						}
						// 设置合同终止状态
						if (Common.isNotNull(leave.getContractIdOld())) {
							leave.setDoStatusContract(CommonConstants.TWO_STRING);
						}
						if (Common.isNotNull(leave.getEmpProjectIdOld())) {
							leave.setDoStatusProject(CommonConstants.TWO_STRING);
						}
						if (Common.isNotNull(leave.getEmpIdOld())) {
							leave.setDoStatusEmp(CommonConstants.TWO_STRING);
						}
					}
					this.judgeStatus(leave);
					leave.setLeaveStatus(CommonConstants.ONE_STRING);
					leave.setConfirmUser(user.getNickname());
					leave.setConfirmTime(LocalDateTime.now());
					this.updateById(leave);
					
					// 离职待办确认后，更新为商险续签待办为已离职
					BaseSearchVO paramVo = new BaseSearchVO();
					paramVo.setEmpIdCard(registrationOld.getEmpIdcard());
					paramVo.setDeptNo(registrationOld.getDeptNo());
					insuranceDaprUtil.updateInsurancePreRenewToIsLeave(paramVo);
					
					// 离职确认后，对该人员在该项目下的已投保未过期且有效的商险数据进行打标“可替换”
					updateInsuranceReplaceTagBySingle(registrationOld.getEmpIdcard(), registrationOld.getDeptNo(), user.getNickname(),user.getId());
					return R.ok();
				} else {
					return R.failed("状态不是待确认");
				}
			} else {
				return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
			}
		} else {
			return R.failed("请传参ID");
		}
	}

	@Override
	public R<String> doSureBatch(BatchSureLeaveVo vo) {
		YifuUser user = SecurityUtils.getUser();
		if (user == null) {
			return R.failed("请登录");
		}
		List<String> ids = vo.getIds();
		if (Common.isEmpty(ids)) {
			return R.failed(CommonConstants.PARAM_IS_NOT_ERROR);
		}
		//获取假日信息
		Map<String, Integer> holidayMap = getHolidayMap();
		if (holidayMap == null) {
			return R.failed("未获取到假日信息，请检查社保服务！");
		}
		// 先查再更新
		List<EmployeeRegistrationLeave> alertList = baseMapper.selectLeaveListBySure(ids);
		List<EmployeeRegistration> registrationList = employeeRegistrationMapper.selectRegistrationListBySure(ids);
		if (alertList != null && !alertList.isEmpty() && registrationList != null && !registrationList.isEmpty()) {
			List<EmployeeRegistrationLeave> successList = new ArrayList<>();
			Map<String, EmployeeRegistrationLeave> alertMap = new HashMap<>();
			Map<String, EmployeeRegistration> registrationMap = new HashMap<>();
			for (EmployeeRegistrationLeave alert : alertList) {
				alertMap.put(alert.getId(), alert);
			}
			for (EmployeeRegistration registration : registrationList) {
				registrationMap.put(registration.getId(), registration);
			}
			EmployeeRegistrationLeave leave;
			EmployeeRegistration registration;
			int successNum = 0;

			// 离职待办确认后，更新为商险续签待办为已离职
			List<BaseSearchVO> paramVoList = new ArrayList<>();
			BaseSearchVO paramVo;

			for (String id : ids) {
				leave = alertMap.get(id);
				registration = registrationMap.get(id);
				if (registration != null && leave != null && CommonConstants.ZERO_STRING.equals(leave.getLeaveStatus())) {
					// 初始化信息
					if (Common.isNotNull(leave.getDoType())) {
						leave.setLeaveReasonId(vo.getLeaveReasonId());
						leave.setLeaveReasonName(vo.getLeaveReasonName());
						if (leave.getDoType().contains(CommonConstants.THREE_STRING)) {
							// 要处理商险初始值
							if (Common.isNotNull(vo.getDoTypeInsurance()) && CommonConstants.ONE_STRING.equals(vo.getDoTypeInsurance())) {
								// 初始化商险
								initInsurance(registration, leave, holidayMap);
								leave.setDoStatusInsurance(CommonConstants.TWO_STRING);
							} else {
								this.removeInsuranceToDoType(leave);
								leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
							}
						}
						// 停缴社保日期
						if (Common.isNotNull(leave.getSocialDispatchIdOld())) {
							leave.setSocialReduceDate(vo.getSocialReduceDate());
							leave.setSocialTrustRemark(vo.getSocialTrustRemarkAndFund());
							leave.setSocialExpectedTime(vo.getSocialExpectedTimeAndFund());
							leave.setDoStatusSocial(CommonConstants.TWO_STRING);
						}
						// 停缴公积金日期
						if (Common.isNotNull(leave.getFundDispatchIdOld())) {
							leave.setFundReduceDate(vo.getFundReduceDate());
							leave.setFundTrustRemark(vo.getSocialTrustRemarkAndFund());
							leave.setFundExpectedTime(vo.getSocialExpectedTimeAndFund());
							leave.setDoStatusFund(CommonConstants.TWO_STRING);
						}
						// 设置合同终止状态
						if (Common.isNotNull(leave.getContractIdOld())) {
							leave.setContractExpectedTime(vo.getContractExpectedTime());
							leave.setDoStatusContract(CommonConstants.TWO_STRING);
						}
						if (Common.isNotNull(leave.getEmpProjectIdOld())) {
							leave.setDoStatusProject(CommonConstants.TWO_STRING);
						}
						if (Common.isNotNull(leave.getEmpIdOld())) {
							leave.setDoStatusEmp(CommonConstants.TWO_STRING);
						}
					}
					paramVo = new BaseSearchVO();
					paramVo.setEmpIdCard(registration.getEmpIdcard());
					paramVo.setDeptNo(registration.getDeptNo());
					paramVoList.add(paramVo);
					this.judgeStatus(leave);
					leave.setLeaveStatus(CommonConstants.ONE_STRING);
					leave.setConfirmUser(user.getNickname());
					leave.setConfirmTime(LocalDateTime.now());
					successList.add(leave);
					successNum++;
				}
			}
			if (successNum == CommonConstants.ZERO_INT) {
				return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
			} else {
				this.updateBatchById(successList);
				// 离职待办确认后，更新为商险续签待办为已离职
				if (!paramVoList.isEmpty()) {
					BaseSearchListVO baseSearchListVO = new BaseSearchListVO();
					baseSearchListVO.setListParam(paramVoList);
					insuranceDaprUtil.updateInsurancePreRenewToIsLeaveList(baseSearchListVO);
					
					// 离职确认后，对该人员在该项目下的已投保未过期且有效的商险数据进行打标“可替换”
					updateInsuranceReplaceTagByBatch(paramVoList, user.getNickname(),user.getId());
				}
				return R.ok();
			}
		} else {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
	}

	private Map<String, Integer> getHolidayMap() {
		R<HolidayListVO> holidayListR = socialDaprUtils.getOneMonthDay();
		Map<String, Integer> holidayMap = null;
		if (null != holidayListR && Common.isNotNull(holidayListR.getData()) && Common.isNotNull(holidayListR.getData().getWorkDayMap())) {
			holidayMap = holidayListR.getData().getHolidayMap();
		}
		return holidayMap;
	}

	/**
	 * @Description: 单个离职确认后更新商险替换标签为“可替换”
	 * @Author: fxj
	 * @Date: 2026-03-19
	 * @param empIdcard: 身份证号
	 * @param deptNo: 项目编码
	 * @param operator: 操作人员
	 * @return: void
	 **/
	private void updateInsuranceReplaceTagBySingle(String empIdcard, String deptNo, String operator,String operatorId) {
		List<BaseSearchVO> paramVoList = new ArrayList<>();
		BaseSearchVO paramVo = new BaseSearchVO();
		paramVo.setEmpIdCard(empIdcard);
		paramVo.setDeptNo(deptNo);
		paramVoList.add(paramVo);
		updateInsuranceReplaceTagByBatch(paramVoList, operator,operatorId);
	}

	/**
	 * @Description: 批量离职确认后更新商险替换标签为“可替换”（调用商险服务接口）
	 * @Author: fxj
	 * @Date: 2026-03-19
	 * @param paramVoList: 查询参数列表（身份证 + 项目编码）
	 * @param operator: 操作人员
	 * @return: void
	 **/
	private void updateInsuranceReplaceTagByBatch(List<BaseSearchVO> paramVoList, String operator,String operatorId) {
		if (Common.isEmpty(paramVoList)) {
			log.warn("批量更新商险替换标签失败，参数列表为空");
			return;
		}
		
		try {
			// 调用商险服务批量更新替换标签和说明
			insuranceDaprUtil.batchUpdateInsuranceReplaceTagByParamList(paramVoList, operator, operatorId, "离职确认操作");
		} catch (Exception e) {
			log.warn("批量更新商险替换标签异常，参数列表大小：{}", paramVoList.size(), e);
		}
	}

	// 去除浮动的商险
	private void removeInsuranceToDoType(EmployeeRegistrationLeave alert) {
		if (alert.getDoType().contains(",3")) {
			alert.setDoType(alert.getDoType().replace(",3", ""));
		} else if (alert.getDoType().contains("3,")) {
			alert.setDoType(alert.getDoType().replace("3,", ""));
		} else if (CommonConstants.THREE_STRING.equals(alert.getDoType())) {
			alert.setDoType("");
		}
	}


	// @param isExit: 1仅发起日期为今日及之前的事项 0立即发起（全量）
	//	 * @param doType: 需处理项：1社保2公积金3商险4合同5项目档案6人员档案
	@Override
	public void autoDoLeave() {
		List<EmployeeRegistrationLeave> leaveList = baseMapper.selectLeaveListByDispatch(null);
		List<EmployeeRegistrationLeave> saveLeaveList = new ArrayList<>();
		String customerUsernameNew;

		YifuUser user;
		String userName = "自动化自动-";
		Set<String> dbAuthsSet = new HashSet<>();
		Collection<? extends GrantedAuthority> authorities = AuthorityUtils
				.createAuthorityList(dbAuthsSet.toArray(new String[0]));
		for (int i=0; i<leaveList.size(); i++) {
			saveLeaveList.add(leaveList.get(i));
			customerUsernameNew = leaveList.get(i).getCustomerUsernameNew();
			if (i == leaveList.size()-1 || Common.isEmpty(customerUsernameNew)
					|| !customerUsernameNew.equals(leaveList.get(i+1).getCustomerUsernameNew())) {
				user = getNewYifuUser(authorities, userName + customerUsernameNew);
				batchDoLeaveCore(saveLeaveList, CommonConstants.ONE_STRING, null, user);
				saveLeaveList = new ArrayList<>();
			}
		}
	}

	// @param isExit: 1仅发起日期为今日及之前的事项 0立即发起（全量）
	//	 * @param doType: 需处理项：1社保2公积金3商险4合同5项目档案6人员档案
	@Override
	public R<List<EmployeeRegistrationLeave>> batchDoLeave(List<String> idList, String isExit, String doType) {
		List<EmployeeRegistrationLeave> leaveList = baseMapper.selectLeaveListByDispatch(idList);
		YifuUser user = SecurityUtils.getUser();
		String userName = "自动化手动-";
		Set<String> dbAuthsSet = new HashSet<>();
		Collection<? extends GrantedAuthority> authorities = AuthorityUtils
				.createAuthorityList(dbAuthsSet.toArray(new String[0]));
		user = getNewYifuUser(authorities, userName + user.getNickname());
		return batchDoLeaveCore(leaveList, isExit, doType, user);
	}

	private YifuUser getNewYifuUser(Collection<? extends GrantedAuthority> authorities, String userName) {

		return new YifuUser("1", 1L, "", userName,
				userName, "0", SecurityConstants.BCRYPT + "123456",
				"12345678911", true, true, true,
				true,
				"1", authorities, "1",
				null, null,
				null, null);
	}

	// @param isExit: 1仅发起日期为今日及之前的事项 0立即发起（全量）
	//	 * @param doType: 需处理项：1社保2公积金3商险4合同5项目档案6人员档案
	private R<List<EmployeeRegistrationLeave>> batchDoLeaveCore(List<EmployeeRegistrationLeave> leaveList, String isExit
			, String doType, YifuUser user) {
		if (Common.isEmpty(leaveList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		String userName = user.getNickname();
		List<TDispatchReduceVo> socialOldList = new ArrayList<>();
		TDispatchReduceVo vo;
		List<TDispatchReduceVo> fundOldList = new ArrayList<>();
		List<String> insuranceOldList = new ArrayList<>();
		// 今天的最后时间，用于发起今日及之前的事项
		LocalDateTime nowTime = LocalDateTime.now().with(LocalTime.MAX);

		// 减少合同需要的传参
		List<BaseSearchVO> listParamContract = new ArrayList<>();
		List<BaseSearchVO> listParamProject = new ArrayList<>();
		List<BaseSearchVO> listParamEmp = new ArrayList<>();
		BaseSearchVO searchVo;
		// 离职待办与商险的映射
		Map<String, List<String>> leaveInsuranceMap = new HashMap<>();
		// 单一离职待办里的商险
		List<String> insuranceList;
		String[] insuranceArr;
		String errorMessage;

		// 1社保2公积金3商险4合同5项目档案6人员档案
		List<EmployeeRegistrationLeaveLog> logList = new ArrayList<>();
		EmployeeRegistrationLeaveLog leaveLog;
		String preContent = "立即发起全部日期的事项：";
		if (Common.isNotNull(isExit) && isExit.equals(CommonConstants.ONE_STRING)) {
			preContent = "立即发起今日及之前的事项：";
		}
		StringBuilder logSubType;
		for (EmployeeRegistrationLeave leave : leaveList) {
			//日志
			leaveLog = new EmployeeRegistrationLeaveLog();
			leaveLog.setLeaveId(leave.getId());
			leaveLog.setCreateName(user.getNickname());
			leaveLog.setCreateTime(LocalDateTime.now());
			leaveLog.setContent(preContent);
			logSubType = new StringBuilder();

			if (judgeToUpdateSocial(isExit, doType, nowTime, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.ONE_INT]).append(CommonConstants.DUNHAO_STRING);
				leave.setFailSocialUser(userName);
				vo = new TDispatchReduceVo();
				vo.setLeaveId(leave.getId());
				vo.setEmpName(leave.getEmployeeName());
				vo.setEmpIdcard(leave.getEmpIdcard());
				vo.setDepartNo(leave.getDeptNo());
				vo.setSocialReduceDate(leave.getSocialReduceDate());
				vo.setReasonType(leave.getLeaveReasonId());
				vo.setTrustRemark(leave.getSocialTrustRemark());
				vo.setChangeContractAndEmployee(CommonConstants.ONE_STRING);
				if (Common.isNotNull(leave.getJoinLeaveDate())) {
					try {
						vo.setLeaveDate(DateUtil.parseDate(leave.getJoinLeaveDate(), DateUtil.ISO_EXPANDED_DATE_FORMAT));
					} catch (Exception e) {
					}
				}
				socialOldList.add(vo);
			}
			if (judgeToUpdateFund(isExit, doType, nowTime, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.TWO_INT]).append(CommonConstants.DUNHAO_STRING);
				leave.setFailFundUser(userName);
				vo = new TDispatchReduceVo();
				vo.setLeaveId(leave.getId());
				vo.setEmpName(leave.getEmployeeName());
				vo.setEmpIdcard(leave.getEmpIdcard());
				vo.setDepartNo(leave.getDeptNo());
				vo.setFundReduceDate(leave.getFundReduceDate());
				vo.setReasonType(leave.getLeaveReasonId());
				vo.setTrustRemark(leave.getFundTrustRemark());
				vo.setChangeContractAndEmployee(CommonConstants.ONE_STRING);
				if (Common.isNotNull(leave.getJoinLeaveDate())) {
					try {
						vo.setLeaveDate(DateUtil.parseDate(leave.getJoinLeaveDate(), DateUtil.ISO_EXPANDED_DATE_FORMAT));
					} catch (Exception e) {
					}
				}
				fundOldList.add(vo);
			}
			if (judgeToUpdateInsurance(isExit, doType, nowTime, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.THREE_INT]).append(CommonConstants.DUNHAO_STRING);
				insuranceArr = leave.getInsuranceIdOld().split(",");
				insuranceList = new ArrayList<>();
				for (String id : insuranceArr) {
					insuranceList.add(id);
					insuranceOldList.add(id);
				}
				leaveInsuranceMap.put(leave.getId(), insuranceList);
			}
			if (judgeToUpdateContract(isExit, doType, nowTime, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.FOUR_INT]).append(CommonConstants.DUNHAO_STRING);
				leave.setFailContractUser(userName);
				searchVo = new BaseSearchVO();
				searchVo.setSearchKey(leave.getContractIdOld());
				searchVo.setResultIdOne(leave.getId());
				searchVo.setResultIdTwo(leave.getJoinLeaveDate());
				if (Common.isNotNull(leave.getLeaveReasonName())) {
					searchVo.setResultIdThree(leave.getLeaveReasonName());
				} else {
					searchVo.setResultIdThree(RegistConstants.BASE_REASON_TYPE_NAME);
				}
				listParamContract.add(searchVo);

			}
			if (judgeToUpdateProject(doType, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.FIVE_INT]).append(CommonConstants.DUNHAO_STRING);
				leave.setFailEmpUser(userName);
				searchVo = new BaseSearchVO();
				searchVo.setSearchKey(leave.getEmpProjectIdOld());
				searchVo.setEmpName(leave.getEmployeeName());
				searchVo.setEmpIdCard(leave.getEmpIdcard());
				searchVo.setDeptNo(leave.getDeptNo());
				searchVo.setResultIdOne(leave.getId());
				if (Common.isNotNull(leave.getLeaveReasonName())) {
					searchVo.setResultIdThree(leave.getLeaveReasonId());
				} else {
					searchVo.setResultIdThree(RegistConstants.BASE_REASON_TYPE);
				}
				listParamProject.add(searchVo);
			}
			if (judgeToUpdateEmp(doType, leave) ) {
				logSubType.append(RegistConstants.DO_TYPE_ARR[CommonConstants.SIX_INT]).append(CommonConstants.DUNHAO_STRING);
				leave.setFailEmpProjectUser(userName);
				searchVo = new BaseSearchVO();
				searchVo.setSearchKey(leave.getEmpProjectIdOld());
				searchVo.setEmpName(leave.getEmployeeName());
				searchVo.setEmpIdCard(leave.getEmpIdcard());
				searchVo.setResultIdOne(leave.getId());
				if (Common.isNotNull(leave.getLeaveReasonName())) {
					searchVo.setResultIdThree(leave.getLeaveReasonName());
				} else {
					searchVo.setResultIdThree(RegistConstants.BASE_REASON_TYPE_NAME);
				}
				listParamEmp.add(searchVo);
			}
			if (logSubType.length() > 0) {
				logSubType.setLength(logSubType.length() - 1); // 长度减1，去掉最后一个
				leaveLog.setContent(preContent + logSubType);
				logList.add(leaveLog);
			}
		}

		//组装返回给前端
		List<ErrorMessage> socialParamList ;
		List<ErrorMessage> fundParamList ;
		List<ErrorMessage> insuranceParamList ;
		List<ErrorMessage> contractParamList ;
		List<ErrorMessage> projectParamList ;
		List<ErrorMessage> empParamList ;
		String closeRemark = "已在其他入口处理";
		BaseSearchVO returnVo;
		BaseSearchVO paramVo;
		R<BaseSearchVO> returnR;
		// 社保-完成
		if (!socialOldList.isEmpty()) {
			TDispatchReduceListVo paramListVo = new TDispatchReduceListVo();
			paramListVo.setUserId(user.getId());
			paramListVo.setUserName(user.getNickname());
			paramListVo.setListParam(socialOldList);
			R<BaseSearchListVO> listR = socialDaprUtils.leaveToReduceSocialAndFund(paramListVo);
			// 成功+失败
			if (Common.isNotNull(listR) && Common.isNotNull(listR.getData())
					&& Common.isNotNull(listR.getData().getErrorMessageList())
					&& !listR.getData().getErrorMessageList().isEmpty()) {
				socialParamList = listR.getData().getErrorMessageList();
				Map<String, String> errorMap = new HashMap<>();
				// 存放成功的新ID
				Map<String, String> successMap = new HashMap<>();
				for (ErrorMessage message : socialParamList) {
					if (CommonConstants.SAVE_SUCCESS.equals(message.getMessage())) {
						successMap.put(message.getKey(), message.getName());
					} else {
						errorMap.put(message.getKey(), message.getMessage());
					}
				}
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateSocial(isExit, doType, nowTime, leave) ) {
						// 成功
						if (successMap.get(leave.getId()) != null) {
							leave.setSocialId(successMap.get(leave.getId()));
							leave.setDoStatusSocial(CommonConstants.FOUR_STRING);
						} else if (errorMap.get(leave.getId()) != null) {
							// 失败
							errorMessage = errorMap.get(leave.getId());
							if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
								errorMessage = errorMessage.substring(0, 300);
							}
							leave.setFailSocialRemark(errorMessage);
							leave.setFailSocialTime(LocalDateTime.now());
							leave.setDoStatusSocial(CommonConstants.THREE_STRING);
						}
					}
					// 1社保:加一重保险：失败的再查一下是否已完结，变为无需处理
					if (CommonConstants.THREE_STRING.equals(leave.getDoStatusSocial())) {
						paramVo = new BaseSearchVO();
						paramVo.setEmpIdCard(leave.getEmpIdcard());
						paramVo.setDeptNo(leave.getDeptNo());
						returnR = socialDaprUtils.getSocialAndFundStatusByClose(paramVo);
						if (null != returnR && Common.isNotNull(returnR.getData())) {
							returnVo = returnR.getData();
							if (Common.isNotNull(returnVo.getResultIdOne())) {
								leave.setSocialId(returnVo.getResultIdOne());
								leave.setDoStatusSocial(CommonConstants.ONE_STRING);
								leave.setCloseRemarkSocial(closeRemark);
							}
						}
					}
				}
			}
		}
		// 公积金-完成
		if (!fundOldList.isEmpty()) {
			TDispatchReduceListVo paramListVo = new TDispatchReduceListVo();
			paramListVo.setUserId(user.getId());
			paramListVo.setUserName(user.getNickname());
			paramListVo.setListParam(fundOldList);
			R<BaseSearchListVO> listR = socialDaprUtils.leaveToReduceSocialAndFund(paramListVo);
			// 成功+失败
			if (Common.isNotNull(listR) && Common.isNotNull(listR.getData())
					&& Common.isNotNull(listR.getData().getErrorMessageList())
					&& !listR.getData().getErrorMessageList().isEmpty()) {
				fundParamList = listR.getData().getErrorMessageList();
				Map<String, String> errorMap = new HashMap<>();
				// 存放成功的新ID
				Map<String, String> successMap = new HashMap<>();
				for (ErrorMessage message : fundParamList) {
					if (CommonConstants.SAVE_SUCCESS.equals(message.getMessage())) {
						successMap.put(message.getKey(), message.getName());
					} else {
						errorMap.put(message.getKey(), message.getMessage());
					}
				}
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateFund(isExit, doType, nowTime, leave) ) {
						// 成功
						if (successMap.get(leave.getId()) != null) {
							leave.setFundId(successMap.get(leave.getId()));
							leave.setDoStatusFund(CommonConstants.FOUR_STRING);
						} else if (errorMap.get(leave.getId()) != null) {
							// 失败
							errorMessage = errorMap.get(leave.getId());
							if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
								errorMessage = errorMessage.substring(0, 300);
							}
							leave.setFailFundRemark(errorMessage);
							leave.setFailFundTime(LocalDateTime.now());
							leave.setDoStatusFund(CommonConstants.THREE_STRING);
						}
					}
					// 2公积金:加一重保险：失败的再查一下是否已完结，变为无需处理
					if (CommonConstants.THREE_STRING.equals(leave.getDoStatusFund())) {
						paramVo = new BaseSearchVO();
						paramVo.setEmpIdCard(leave.getEmpIdcard());
						paramVo.setDeptNo(leave.getDeptNo());
						returnR = socialDaprUtils.getSocialAndFundStatusByClose(paramVo);
						if (null != returnR && Common.isNotNull(returnR.getData())) {
							returnVo = returnR.getData();
							if (Common.isNotNull(returnVo.getResultIdTwo())) {
								leave.setFundId(returnVo.getResultIdTwo());
								leave.setDoStatusFund(CommonConstants.ONE_STRING);
								leave.setCloseRemarkFund(closeRemark);
							}
						}
					}
				}
			}
		}
		// 商险-完成
		if (!insuranceOldList.isEmpty()) {
			// 查找是 2待派单3发起失败9减员退回 的再去办
			List<String> toDoList = leaveInsuranceMapper.getLeaveInsuranceListByIdAndStatus(insuranceOldList);
			if (toDoList != null && !toDoList.isEmpty()) {
				BaseSearchListVO paramVoInsurance = new BaseSearchListVO();
				paramVoInsurance.setUserId(user.getId());
				paramVoInsurance.setUserName(user.getNickname());
				paramVoInsurance.setListStringParam(toDoList);
				R<BaseSearchListVO> listR = insuranceDaprUtil.leaveToReduceInsurance(paramVoInsurance);
				if (Common.isNotNull(listR) && Common.isNotNull(listR.getData())) {
					// 部分失败
					if (!listR.getData().getErrorMessageList().isEmpty()) {
						insuranceParamList = listR.getData().getErrorMessageList();
						// 商险id与错误原因
						Map<String, String> errorMap = new HashMap<>();
						for (ErrorMessage message : insuranceParamList) {
							if (Common.isNotNull(message.getName())) {
								errorMap.put(message.getName(), message.getMessage());
							}
						}
						StringBuilder errorMsg;
						// 错误的商险派单
						List<String> errorList = new ArrayList<>();
						List<String> successList = new ArrayList<>();
						String insuranceIdTemp;
						for (EmployeeRegistrationLeave leave : leaveList) {
							if (judgeToUpdateInsurance(isExit, doType, nowTime, leave) ) {
								errorMsg = new StringBuilder();
								leave.setInsuranceId(leave.getInsuranceIdOld());
								insuranceList = leaveInsuranceMap.get(leave.getId());
								if (insuranceList != null) {
									// 处理每一条商险
									for (String insuranceId : insuranceList) {
										if (errorMap.get(insuranceId) != null) {
											errorMsg.append(errorMap.get(insuranceId)).append(CommonConstants.SEMICOLON_STRING);
											errorList.add(insuranceId);
										} else {
											successList.add(insuranceId);
										}
									}
									if (errorMsg.length() > CommonConstants.ZERO_INT) {
										leave.setFailInsuranceUser(userName);
										errorMessage = errorMsg.toString();
										if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
											errorMessage = errorMessage.substring(0, 300);
										}
										leave.setFailInsuranceRemark(errorMessage);
										leave.setFailInsuranceTime(LocalDateTime.now());
										leave.setDoStatusInsurance(CommonConstants.THREE_STRING);
									} else {
										// 待减员
										leave.setDoStatusInsurance(CommonConstants.FOUR_STRING);
									}
								}
							}

							// 3商险:加一重保险：失败的再查一下是否已完结，变为无需处理
							if (CommonConstants.THREE_STRING.equals(leave.getDoStatusInsurance())) {
								paramVo = new BaseSearchVO();
								paramVo.setEmpIdCard(leave.getEmpIdcard());
								paramVo.setDeptNo(leave.getDeptNo());
								insuranceIdTemp = "";
								returnR = insuranceDaprUtil.getInsurancesStatusByClose(paramVo);
								if (null != returnR && Common.isNotNull(returnR.getData())) {
									returnVo = returnR.getData();
									if (Common.isNotNull(returnVo.getResultIdOne())) {
										insuranceIdTemp = returnVo.getResultIdOne();
									}
								}
								// 这个反着查的，有未减完的，表示不可以关闭它，只能忽略它
								if (Common.isEmpty(insuranceIdTemp)) {
									leave.setInsuranceId(leave.getInsuranceIdOld());
									leave.setDoStatusInsurance(CommonConstants.ONE_STRING);
									leave.setCloseRemarkInsurance(closeRemark);
								}
							}
						}
						// 批量处理商险明细表的状态为失败：
						if (!errorList.isEmpty()) {
							// 可以再将【3商险:加一重保险】里无需处理的部分摘出来，改为无需处理，也可以不变，不影响总状态
							leaveInsuranceMapper.updateLeaveInsuranceListByIdAndStatus(CommonConstants.THREE_STRING, errorList);
						}
						if (!successList.isEmpty()) {
							leaveInsuranceMapper.updateLeaveInsuranceListByIdAndStatus(CommonConstants.FOUR_STRING, successList);
						}
					} else {
						// 全部成功
						for (EmployeeRegistrationLeave leave : leaveList) {
							if (judgeToUpdateInsurance(isExit, doType, nowTime, leave) ) {
								leave.setInsuranceId(leave.getInsuranceIdOld());
								// 待办理
								leave.setDoStatusInsurance(CommonConstants.FOUR_STRING);
							}
						}
						leaveInsuranceMapper.updateLeaveInsuranceListByIdAndStatus(CommonConstants.FOUR_STRING, insuranceOldList);
					}
				}
			}
		}
		// 合同-完成
		if (!listParamContract.isEmpty()) {
			BaseSearchListVO paramVoContract = new BaseSearchListVO();
			paramVoContract.setUserId(user.getId());
			paramVoContract.setUserName(user.getNickname());
			paramVoContract.setListParam(listParamContract);
			R<BaseSearchListVO> listR = archivesDaprUtil.leaveToReduceContract(paramVoContract);
			// 成功+失败
			if (Common.isNotNull(listR) && Common.isNotNull(listR.getData())
					&& Common.isNotNull(listR.getData().getErrorMessageList())
					&& !listR.getData().getErrorMessageList().isEmpty()) {
				contractParamList = listR.getData().getErrorMessageList();
				Map<String, String> errorMap = new HashMap<>();
				// 存放成功的新ID
				Map<String, String> successMap = new HashMap<>();
				Map<String, String> successAndAuditMap = new HashMap<>();
				for (ErrorMessage message : contractParamList) {
					if (CommonConstants.SAVE_SUCCESS.equals(message.getMessage())) {
						successMap.put(message.getKey(), message.getName());
					} else if (CommonConstants.SAVE_AND_UPDATE.equals(message.getMessage())) {
						successAndAuditMap.put(message.getKey(), message.getName());
					} else {
						errorMap.put(message.getKey(), message.getMessage());
					}
				}
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateContract(isExit, doType, nowTime, leave) ) {
						// 成功
						if (successMap.get(leave.getId()) != null) {
							leave.setContractId(successMap.get(leave.getId()));
							leave.setDoStatusContract(CommonConstants.FOUR_STRING);
						} else if (successAndAuditMap.get(leave.getId()) != null) {
							leave.setContractId(successAndAuditMap.get(leave.getId()));
							leave.setDoStatusContract(CommonConstants.EIGHT_STRING);
						} else if (errorMap.get(leave.getId()) != null) {
							// 失败
							errorMessage = errorMap.get(leave.getId());
							if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
								errorMessage = errorMessage.substring(0, 300);
							}
							leave.setFailContractRemark(errorMessage);
							leave.setFailContractTime(LocalDateTime.now());
							leave.setDoStatusContract(CommonConstants.THREE_STRING);
						}
					}
				}
			}
		}

		// 4合同:加一重保险：失败的再查一下是否已完结，变为无需处理
		String contractId = "";
		String contractIdEnd = "";
		for (EmployeeRegistrationLeave leave : leaveList) {
			// 判断了不等于 空、无需处理、完成，再去查合同
			if (judgeToQueryContract(isExit, doType, nowTime, leave) ) {
				contractId = "";
				contractIdEnd = "";
				paramVo = new BaseSearchVO();
				paramVo.setEmpIdCard(leave.getEmpIdcard());
				paramVo.setDeptNo(leave.getDeptNo());
				returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
				if (null != returnR && Common.isNotNull(returnR.getData())) {
					returnVo = returnR.getData();
					if (Common.isNotNull(returnVo.getResultIdThree())) {
						contractId = returnVo.getResultIdThree();
					}
					if (Common.isNotNull(returnVo.getResultIdFourStatus())) {
						contractIdEnd = returnVo.getResultIdFourStatus();
					}
				}
				if (Common.isEmpty(contractId)) {
					if (Common.isNotNull(contractIdEnd)) {
						leave.setContractId(contractIdEnd);
					} else {
						// errorInfo.append("未找到终止的合同！")
						// 社保派减，同步减合同，是没有终止的合同的，而是在合同本身改状态
						leave.setContractId(leave.getContractIdOld());
					}
					leave.setDoStatusContract(CommonConstants.ONE_STRING);
					leave.setCloseRemarkContract(closeRemark);
				}
			}
		}
		// 项目-完成
		if (!listParamProject.isEmpty()) {
			projectParamList = new ArrayList<>();
			List<BaseSearchVO> tempProject;
			BaseSearchListVO paramVoProject;
			for (BaseSearchVO proVo : listParamProject) {
				tempProject = new ArrayList<>();
				tempProject.add(proVo);
				paramVoProject = new BaseSearchListVO();
				paramVoProject.setUserId(user.getId());
				paramVoProject.setUserName(user.getNickname());
				paramVoProject.setListParam(tempProject);
				R<BaseSearchListVO> listR = archivesDaprUtil.leaveToReduceProject(paramVoProject);
				if (Common.isNotNull(listR) && Common.isNotNull(listR.getData()) && !listR.getData().getErrorMessageList().isEmpty()) {
					projectParamList.addAll(listR.getData().getErrorMessageList());
				}
			}
			if (!projectParamList.isEmpty()) {
				Map<String, String> errorMap = new HashMap<>();
				for (ErrorMessage message : projectParamList) {
					errorMap.put(message.getKey(), message.getMessage());
				}
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateProject(doType, leave)) {
						if (errorMap.get(leave.getId()) != null) {
							errorMessage = errorMap.get(leave.getId());
							if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
								errorMessage = errorMessage.substring(0, 300);
							}
							leave.setFailEmpProjectRemark(errorMessage);
							leave.setFailEmpProjectTime(LocalDateTime.now());
							leave.setDoStatusProject(CommonConstants.NINE_STRING);
						} else {
							leave.setEmpProjectId(leave.getEmpProjectIdOld());
							leave.setDoStatusProject(CommonConstants.EIGHT_STRING);
						}
					}

					// 5项目档案:加一重保险：失败的再查一下是否已完结，变为无需处理
					if (CommonConstants.NINE_STRING.equals(leave.getDoStatusProject())) {
						paramVo = new BaseSearchVO();
						paramVo.setEmpIdCard(leave.getEmpIdcard());
						paramVo.setDeptNo(leave.getDeptNo());
						returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
						if (null != returnR && Common.isNotNull(returnR.getData())) {
							returnVo = returnR.getData();
							if (Common.isEmpty(returnVo.getResultIdTwo())) {
								leave.setEmpProjectId(leave.getEmpProjectIdOld());
								leave.setCloseRemarkEmpProject(closeRemark);
								leave.setDoStatusProject(CommonConstants.ONE_STRING);
							}
						}
					}
				}
			} else {
				// 全部成功
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateProject(doType, leave)) {
						leave.setEmpProjectId(leave.getEmpProjectIdOld());
						leave.setDoStatusProject(CommonConstants.EIGHT_STRING);
					}
				}
			}
		}
		// 员工-完成
		if (!listParamEmp.isEmpty()) {

			empParamList = new ArrayList<>();
			List<BaseSearchVO> tempEmp;
			BaseSearchListVO paramVoEmp;
			for (BaseSearchVO empVo : listParamEmp) {

				tempEmp = new ArrayList<>();
				tempEmp.add(empVo);
				paramVoEmp = new BaseSearchListVO();
				paramVoEmp.setUserId(user.getId());
				paramVoEmp.setUserName(user.getNickname());
				paramVoEmp.setListParam(tempEmp);
				R<BaseSearchListVO> listR = archivesDaprUtil.leaveToReduceEmp(paramVoEmp);
				if (Common.isNotNull(listR) && Common.isNotNull(listR.getData()) && !listR.getData().getErrorMessageList().isEmpty()) {
					empParamList.addAll(listR.getData().getErrorMessageList());
				}
			}
			if (!empParamList.isEmpty()) {
				Map<String, String> errorMap = new HashMap<>();
				for (ErrorMessage message : empParamList) {
					errorMap.put(message.getKey(), message.getMessage());
				}
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateEmp(doType, leave)) {
						if (errorMap.get(leave.getId()) != null) {
							errorMessage = errorMap.get(leave.getId());
							if (Common.isNotNull(errorMessage) && errorMessage.length() > 300) {
								errorMessage = errorMessage.substring(0, 300);
							}
							leave.setFailEmpRemark(errorMessage);
							leave.setFailEmpTime(LocalDateTime.now());
							leave.setDoStatusEmp(CommonConstants.NINE_STRING);
						} else {
							leave.setEmpId(leave.getEmpIdOld());
							leave.setDoStatusEmp(CommonConstants.EIGHT_STRING);
						}
					}
					// 6人员档案:加一重保险：失败的再查一下是否已完结，变为无需处理
					if (CommonConstants.NINE_STRING.equals(leave.getDoStatusEmp())) {
						paramVo = new BaseSearchVO();
						paramVo.setEmpIdCard(leave.getEmpIdcard());
						paramVo.setDeptNo(leave.getDeptNo());
						returnR = archivesDaprUtil.getEmpAndContractStatus(paramVo);
						if (null != returnR && Common.isNotNull(returnR.getData())) {
							returnVo = returnR.getData();
							if (Common.isEmpty(returnVo.getResultIdOne())) {
								leave.setEmpId(leave.getEmpIdOld());
								leave.setCloseRemarkEmp(closeRemark);
								leave.setDoStatusEmp(CommonConstants.ONE_STRING);
							}
						}
					}
				}
			} else {
				// 全部成功
				for (EmployeeRegistrationLeave leave : leaveList) {
					if (judgeToUpdateEmp(doType, leave)) {
						leave.setEmpId(leave.getEmpIdOld());
						leave.setDoStatusEmp(CommonConstants.EIGHT_STRING);
					}
				}
			}
		}


		// 是否返回前端错误信息
		boolean isReturn = false;
		// 最终更新总状态
		for (EmployeeRegistrationLeave leave : leaveList) {
			judgeStatus(leave);
			if (!isReturn && (Common.isNotNull(leave.getDoStatusSocial()) && CommonConstants.THREE_STRING.equals(leave.getDoStatusSocial()))
						|| (Common.isNotNull(leave.getDoStatusFund()) && CommonConstants.THREE_STRING.equals(leave.getDoStatusFund()))
						|| (Common.isNotNull(leave.getDoStatusContract()) && CommonConstants.THREE_STRING.equals(leave.getDoStatusContract()))
						|| (Common.isNotNull(leave.getDoStatusInsurance()) && CommonConstants.THREE_STRING.equals(leave.getDoStatusInsurance()))
						|| (Common.isNotNull(leave.getDoStatusProject()) && CommonConstants.NINE_STRING.equals(leave.getDoStatusProject()))
						|| (Common.isNotNull(leave.getDoStatusEmp()) && CommonConstants.NINE_STRING.equals(leave.getDoStatusEmp()))
				) {
				isReturn = true;
			}
		}
		if (logList != null && !logList.isEmpty()) {
			leaveLogService.saveBatch(logList);
		}
		this.updateBatchById(leaveList);
		if (isReturn) {
			return R.failed(leaveList, "发起失败！");
		} else {
			return R.ok();
		}
	}

	private boolean judgeToUpdateEmp(String doType, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.SIX_STRING))
				&& Common.isNotNull(leave.getEmpIdOld())
				&& Common.isNotNull(leave.getDoStatusEmp())
				&& (leave.getDoStatusEmp().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusEmp().equals(CommonConstants.NINE_STRING)
		);
	}

	private boolean judgeToUpdateProject(String doType, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.FIVE_STRING))
				&& Common.isNotNull(leave.getEmpProjectIdOld())
				&& Common.isNotNull(leave.getDoStatusProject())
				&& (leave.getDoStatusProject().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusProject().equals(CommonConstants.NINE_STRING)
		);
	}

	// 判断是否要发起
	private boolean judgeToUpdateContract(String isExit, String doType, LocalDateTime nowTime, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.FOUR_STRING))
				&& Common.isNotNull(leave.getContractIdOld()) && (CommonConstants.ZERO_STRING.equals(isExit)
				|| (CommonConstants.ONE_STRING.equals(isExit) && Common.isNotNull(leave.getContractExpectedTime()) && leave.getContractExpectedTime().isBefore(nowTime)))
				&& Common.isNotNull(leave.getDoStatusContract())
				&& (leave.getDoStatusContract().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusContract().equals(CommonConstants.THREE_STRING)
				|| leave.getDoStatusContract().equals(CommonConstants.TEN_STRING)
		);
	}

	// 判断是否要关闭为无需处理
	private boolean judgeToQueryContract(String isExit, String doType, LocalDateTime nowTime, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.FOUR_STRING))
				&& Common.isNotNull(leave.getContractIdOld()) && (CommonConstants.ZERO_STRING.equals(isExit)
				|| (CommonConstants.ONE_STRING.equals(isExit) && Common.isNotNull(leave.getContractExpectedTime()) && leave.getContractExpectedTime().isBefore(nowTime)))
				&& Common.isNotNull(leave.getDoStatusContract())
				&& !leave.getDoStatusContract().equals(CommonConstants.ZERO_STRING)
				&& !leave.getDoStatusContract().equals(CommonConstants.ONE_STRING)
				&& !leave.getDoStatusContract().equals(CommonConstants.EIGHT_STRING);
	}

	private boolean judgeToUpdateSocial(String isExit, String doType, LocalDateTime nowTime, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.ONE_STRING))
				&& Common.isNotNull(leave.getSocialDispatchIdOld()) && (CommonConstants.ZERO_STRING.equals(isExit)
				|| (CommonConstants.ONE_STRING.equals(isExit) && Common.isNotNull(leave.getSocialExpectedTime()) && leave.getSocialExpectedTime().isBefore(nowTime)))
				&& Common.isNotNull(leave.getDoStatusSocial())
				&& (leave.getDoStatusSocial().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusSocial().equals(CommonConstants.THREE_STRING)
				|| leave.getDoStatusSocial().equals(CommonConstants.SIX_STRING)
				|| leave.getDoStatusSocial().equals(CommonConstants.NINE_STRING)
				|| leave.getDoStatusSocial().equals(CommonConstants.TEN_STRING)
		);
	}

	private boolean judgeToUpdateFund(String isExit, String doType, LocalDateTime nowTime, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.TWO_STRING))
				&& Common.isNotNull(leave.getFundDispatchIdOld()) && (CommonConstants.ZERO_STRING.equals(isExit)
				|| (CommonConstants.ONE_STRING.equals(isExit) && Common.isNotNull(leave.getFundExpectedTime()) && leave.getFundExpectedTime().isBefore(nowTime)))
				&& Common.isNotNull(leave.getDoStatusFund())
				&& (leave.getDoStatusFund().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusFund().equals(CommonConstants.THREE_STRING)
				|| leave.getDoStatusFund().equals(CommonConstants.NINE_STRING)
				|| leave.getDoStatusFund().equals(CommonConstants.TEN_STRING)
		);
	}

	// 派单时，判断是否需要办理此条商险
	private boolean judgeToUpdateInsurance(String isExit, String doType, LocalDateTime nowTime, EmployeeRegistrationLeave leave) {
		return (Common.isEmpty(doType) || doType.contains(CommonConstants.THREE_STRING))
				&& Common.isNotNull(leave.getInsuranceIdOld()) && (CommonConstants.ZERO_STRING.equals(isExit)
				|| (CommonConstants.ONE_STRING.equals(isExit) && Common.isNotNull(leave.getInsuranceExpectedTime()) && leave.getInsuranceExpectedTime().isBefore(nowTime)))
				&& Common.isNotNull(leave.getDoStatusInsurance())
				&& (leave.getDoStatusInsurance().equals(CommonConstants.TWO_STRING)
				|| leave.getDoStatusInsurance().equals(CommonConstants.THREE_STRING)
				|| leave.getDoStatusInsurance().equals(CommonConstants.NINE_STRING)
		);
	}

	@Override
	public void reduceHandleToLeave(BaseServiceParamListVO vo) {
		if (vo == null) {
			return;
		}
		String doType = vo.getDoType();
		String doStatus = vo.getDoStatus();
		// 0：失败；1：成功（失败要记录信息）
		String isSuccess = vo.getIsSuccess();
		String userName = vo.getUserName();
		// 最终成功，才更新执行详情
		boolean canUpdateFail = false;
		if (Common.isNotNull(isSuccess) && CommonConstants.ZERO_STRING.equals(isSuccess)) {
			canUpdateFail = true;
		}
		String doRemark = vo.getRemark();
		if (Common.isNotNull(doRemark) && doRemark.length()>50) {
			doRemark = doRemark.substring(0,50);
		}
		List<String> idList = vo.getListParam();
		if (idList != null && !idList.isEmpty() && Common.isNotNull(doType)) {
			// 需处理项：1社保2公积金3商险4合同5项目档案6人员档案
			List<EmployeeRegistrationLeave> leaveList;
			Map<String, Integer> insuranceMap = new HashMap<>();
			if (CommonConstants.THREE_STRING.equals(doType)) {
				leaveList = baseMapper.selectLeaveListByHandleAndInsuranceType(idList);
				for (String id:idList) {
					insuranceMap.put(id, CommonConstants.ONE_INT);
				}
			} else {
				leaveList = baseMapper.selectLeaveListByHandleAndType(idList, doType);
			}
			if (leaveList != null && !leaveList.isEmpty()) {
				List<EmployeeRegistrationLeaveInsurance> insuranceList;
				String minStatus;
				String currentStatus;
				for (EmployeeRegistrationLeave leave : leaveList) {
					// 处理社保
					if (CommonConstants.ONE_STRING.equals(doType)) {
						leave.setDoStatusSocial(doStatus);
						if (canUpdateFail) {
							leave.setFailSocialUser(userName);
							leave.setFailSocialTime(LocalDateTime.now());
							leave.setFailSocialRemark(doRemark);
						}
					}
					if (CommonConstants.TWO_STRING.equals(doType)) {
						leave.setDoStatusFund(doStatus);
						if (canUpdateFail) {
							leave.setFailFundUser(userName);
							leave.setFailFundTime(LocalDateTime.now());
							leave.setFailFundRemark(doRemark);
						}
					}
					if (CommonConstants.THREE_STRING.equals(doType)) {
						insuranceList = leaveInsuranceMapper.getLeaveInsuranceList(leave.getId(), null);
						minStatus = null;
						for (EmployeeRegistrationLeaveInsurance insurance : insuranceList) {
							if (insuranceMap.get(insurance.getInsuranceId()) != null) {
								insurance.setDoStatusInsurance(doStatus);
								leaveInsuranceMapper.updateById(insurance);
							}
							if (Common.isNotNull(insurance.getDoStatusInsurance())) {
								currentStatus = insurance.getDoStatusInsurance();
								if (Common.isEmpty(minStatus)) {
									minStatus = currentStatus;
								} else {
									minStatus = compareInsuranceStatus(minStatus, currentStatus);
								}
							}
						}
						if (canUpdateFail) {
							leave.setFailInsuranceUser(userName);
							leave.setFailInsuranceTime(LocalDateTime.now());
							leave.setFailInsuranceRemark(doRemark);
						}
						leave.setDoStatusInsurance(minStatus);
					}
					if (CommonConstants.FOUR_STRING.equals(doType)) {
						leave.setDoStatusContract(doStatus);
						if (canUpdateFail) {
							leave.setFailContractUser(userName);
							leave.setFailContractTime(LocalDateTime.now());
							leave.setFailContractRemark(doRemark);
						}
					}
					if (CommonConstants.FIVE_STRING.equals(doType)) {
						leave.setDoStatusProject(doStatus);
						if (canUpdateFail) {
							leave.setFailEmpProjectUser(userName);
							leave.setFailEmpProjectTime(LocalDateTime.now());
							leave.setFailEmpProjectRemark(doRemark);
						}
					}
					if (CommonConstants.SIX_STRING.equals(doType)) {
						leave.setDoStatusEmp(doStatus);
						if (canUpdateFail) {
							leave.setFailEmpUser(userName);
							leave.setFailEmpTime(LocalDateTime.now());
							leave.setFailEmpRemark(doRemark);
						}
					}
					judgeStatus( leave);
				}
				this.updateBatchById(leaveList);
			}
		}
	}

	/**
	 * 比较两个保险状态，返回较小的那个
	 * 特殊规则：8是最大的
	 * // 2待派单3发起失败4待减员5待办理6减员中8减员成功9减员退回
	 */
	private String compareInsuranceStatus(String status1, String status2) {
		// 如果其中一个状态是8，返回另一个状态
		if (CommonConstants.EIGHT_STRING.equals(status1)) {
			return status2;
		}
		if (CommonConstants.EIGHT_STRING.equals(status2)) {
			return status1;
		}
		// 其他情况正常比较数字大小
		try {
			return String.valueOf(Math.min(Integer.parseInt(status1), Integer.parseInt(status2)));
		} catch (Exception e) {
			return status1;
		}
	}

}
