package com.engine.salary.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.api.browser.bean.SearchConditionGroup;
import com.api.browser.bean.SearchConditionItem;
import com.api.browser.bean.SearchConditionOption;
import com.api.browser.util.ConditionFactory;
import com.api.browser.util.ConditionType;
import com.cloudstore.dev.api.util.Util_DataCache;
import com.cloudstore.eccom.pc.table.WeaTable;
import com.cloudstore.eccom.pc.table.WeaTableCheckboxpopedom;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.cloudstore.eccom.result.WeaResultMsg;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.cmd.siarchives.SIArchivesTipsCmd;
import com.engine.salary.common.SalaryContext;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.siarchives.bo.InsuranceArchivesBO;
import com.engine.salary.entity.siarchives.bo.InsuranceArchivesBaseInfoBO;
import com.engine.salary.entity.siarchives.dto.*;
import com.engine.salary.entity.siarchives.param.*;
import com.engine.salary.entity.siarchives.po.*;
import com.engine.salary.entity.sicategory.po.ICategoryPO;
import com.engine.salary.entity.sischeme.po.InsuranceSchemeDetailPO;
import com.engine.salary.entity.sischeme.po.InsuranceSchemePO;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO;
import com.engine.salary.entity.taxagent.po.TaxAgentEmpChangePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.datacollection.DataCollectionEmployeeTypeEnum;
import com.engine.salary.enums.salaryaccounting.EmployeeTypeEnum;
import com.engine.salary.enums.siaccount.EmployeeStatusEnum;
import com.engine.salary.enums.sicategory.*;
import com.engine.salary.enums.taxagent.TaxAgentEmpChangeModuleEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.datacollection.EmployMapper;
import com.engine.salary.mapper.siarchives.*;
import com.engine.salary.mapper.sicategory.ICategoryMapper;
import com.engine.salary.mapper.sischeme.InsuranceSchemeDetailMapper;
import com.engine.salary.mapper.sischeme.InsuranceSchemeMapper;
import com.engine.salary.mapper.taxagent.TaxAgentMapper;
import com.engine.salary.service.*;
import com.engine.salary.sys.constant.SalarySysConstant;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.sys.entity.vo.OrderRuleVO;
import com.engine.salary.sys.enums.OpenEnum;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.*;
import com.engine.salary.util.db.IdGenerator;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.excel.ExcelUtil;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.wrapper.TaxAgentWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import weaver.conn.mybatis.MyBatisFactory;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.engine.salary.sys.constant.SalarySysConstant.WEL_BASE_AUTO_ADJUST;
import static com.engine.salary.sys.constant.SalarySysConstant.WEL_BASE_DIFF_BY_PER_AND_COM;

/**
 * @Author weaver_cl
 * @Description:
 * @Date 2022/3/11
 * @Version V1.0
 **/
@Slf4j
public class SIArchivesServiceImpl extends Service implements SIArchivesService {
    private final BaseBean baseBean = new BaseBean();

    private final Boolean isLog = "true".equals(baseBean.getPropValue("hrmSalary", "log"));

//    private SIArchivesBiz siArchivesBiz = new SIArchivesBiz();

    private EncryptUtil encryptUtil = new EncryptUtil();

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }

    private SalarySysConfService getSalarySysConfService(User user) {
        return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
    }

    private InsuranceBaseInfoMapper getInsuranceBaseInfoMapper() {
        return MapperProxyFactory.getProxy(InsuranceBaseInfoMapper.class);
    }

    private TaxAgentEmpChangeService getTaxAgentEmpChangeService(User user) {
        return ServiceUtil.getService(TaxAgentEmpChangeServiceImpl.class, user);
    }

    private SocialSchemeMapper getSocialSchemeMapper() {
        return MapperProxyFactory.getProxy(SocialSchemeMapper.class);
    }

    private FundSchemeMapper getFundSchemeMapper() {
        return MapperProxyFactory.getProxy(FundSchemeMapper.class);
    }

    private OtherSchemeMapper getOtherSchemeMapper() {
        return MapperProxyFactory.getProxy(OtherSchemeMapper.class);
    }

    private TaxAgentMapper getTaxAgentMapper() {
        return MapperProxyFactory.getProxy(TaxAgentMapper.class);
    }

    private InsuranceSchemeDetailMapper getInsuranceSchemeDetailMapper() {
        return MapperProxyFactory.getProxy(InsuranceSchemeDetailMapper.class);
    }

    private InsuranceSchemeMapper getInsuranceSchemeMapper() {
        return MapperProxyFactory.getProxy(InsuranceSchemeMapper.class);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private TaxAgentWrapper getTaxAgentWrapper(User user) {
        return ServiceUtil.getService(TaxAgentWrapper.class, user);
    }

    public SICategoryService getSICategoryService(User user) {
        return ServiceUtil.getService(SICategoryServiceImpl.class, user);
    }

    private SISchemeService getSISchemeService(User user) {
        return ServiceUtil.getService(SISchemeServiceImpl.class,user);
    }

    private EmployMapper getEmployMapper() {
        return MapperProxyFactory.getProxy(EmployMapper.class);
    }


    private InsuranceBaseAdjustHistoryMapper getInsuranceBaseAdjustHistoryMapper() {
        return MapperProxyFactory.getProxy(InsuranceBaseAdjustHistoryMapper.class);
    }


    @Override
    public Map<String, Object> getTips(Map<String, Object> params) {
        return commandExecutor.execute(new SIArchivesTipsCmd(params, user));
    }

    @Override
    public Map<String, Object> getBaseForm(Map<String, Object> params) {
        long currentEmployeeId = user.getUID();
        Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId);
        Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAllTaxAgentsAsAdmin(currentEmployeeId);

        Map<String, Object> apidatas = new HashMap<>(16);
//        SIArchivesBiz siArchivesBiz = new SIArchivesBiz();
////        siArchivesBiz.setNeedAuth(needAuth);
////        siArchivesBiz.setTaxAgentPOS(taxAgentPOS);
        WelfareTypeEnum welfareTypeEnum = (WelfareTypeEnum) params.get("welfareTypeEnum");
        Long employeeId = Long.valueOf(Util.null2String(params.get("employeeId")));
        Long paymentOrganization = welfareTypeEnum != null ? Long.valueOf(Util.null2String(params.get("paymentOrganization"))) : null;
//        apidatas = siArchivesBiz.getBaseForm(welfareTypeEnum, employeeId, (long) user.getUID(), user, paymentOrganization);
        apidatas = getBaseForm(welfareTypeEnum, employeeId, paymentOrganization, taxAgentPOS);
        return apidatas;
    }

    @Override
    public Map<String, Object> getPaymentForm(Map<String, Object> params) {
        Map<String, Object> apidatas = new HashMap<>(16);
        WelfareTypeEnum welfareTypeEnum = (WelfareTypeEnum) params.get("welfareTypeEnum");
        Long employeeId = Long.valueOf(Util.null2String(params.get("employeeId")));
        String schemeIdStr = Util.null2String(params.get("schemeId"));
        Long paymentOrganization = Long.valueOf(Util.null2String(params.get("paymentOrganization")));
        Long schemeId = null;
        if (StringUtils.isNotBlank(schemeIdStr)) {
            schemeId = Long.valueOf(schemeIdStr);
        }
//        apidatas = siArchivesBiz.getPaymentForm(user, welfareTypeEnum, employeeId, (long) user.getUID(), schemeId, paymentOrganization);
        apidatas = getPaymentForm(user, welfareTypeEnum, employeeId, schemeId, paymentOrganization);
        return apidatas;
    }


    @Override
    public String insert(InsuranceArchivesSaveParam param) {
        SalaryAssert.notNull(param.getWelfareType(), "福利类型为空");
        //判断是否要区分个人和单位福利基数
        SalarySysConfPO welBaseDiff = getSalarySysConfService(user).getOneByCode(WEL_BASE_DIFF_BY_PER_AND_COM);
        boolean welBaseDiffSign = welBaseDiff != null && welBaseDiff.getConfValue().equals(OpenEnum.OPEN.getValue());
        switch (param.getWelfareType()) {
            case SOCIAL_SECURITY:
                socialSave(param, user, welBaseDiffSign);
                break;
            case ACCUMULATION_FUND:
                fundSave(param, user, welBaseDiffSign);
                break;
            case OTHER:
                otherSave(param, user, welBaseDiffSign);
                break;
            default:
                throw new SalaryRunTimeException("福利类型不存在");
        }
        return null;
    }

    @Override
    public Map<String, Object> listPage(InsuranceArchivesListParam param) {
        long currentEmployeeId = user.getUID();
        log.info("获取福利档案列表逻辑开始： {}", param);
        StopWatch sw = new StopWatch();
        sw.start("福利档案-历史数据处理");
        // 1.历史数据处理
        handleHistoryData(currentEmployeeId);
        sw.stop();

        sw.start("福利档案-待减员自动处理");
        // 2.待减员自动处理
        handleStayDelData(currentEmployeeId);
        sw.stop();

//        sw.start("福利档案-增量数据处理");
//        // 3.增量数据处理
//        String welSign = (String) Util_DataCache.getObjVal("welfareChangeSign");
//        if (welSign == null || "0".equals(welSign)) {
//            handleChangeData(currentEmployeeId);
//        }
//        sw.stop();

        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        param.setOrderRule(orderRule);

        Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId);
        param.setNeedAuth(needAuth);
        if (needAuth) {
            List<TaxAgentEmployeeDTO> taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployee(currentEmployeeId);
            Set<Long> employeeIds = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getEmployeeId);
            Set<Long> taxAgentIds = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getTaxAgentId);
            param.setTaxAgentEmployeeIds(employeeIds);
            param.setTaxAgentIds(taxAgentIds);
        }

        Map<String, Object> apidatas = new HashMap<>(16);
//        apidatas = siArchivesBiz.listPage(param, (long) user.getUID());
        apidatas = listPage(param, (long) user.getUID());

        //记录操作日志
        List<String> runStatuses = param.getRunStatuses() == null ? Collections.emptyList() : param.getRunStatuses().stream().map(s -> EmployeeStatusEnum.parseByValue(s).getDefaultLabel()).collect(Collectors.toList());
        String runStatusStr = CollectionUtils.isEmpty(runStatuses) ? "" : StringUtils.join(runStatuses, "");
        if (param.isExtWelArchiveList()) {
            runStatusStr = "非系统人员";
        }
        LoggerContext loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetName(runStatusStr);
        loggerContext.setOperateType(OperateTypeEnum.READ.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "查看福利档案列表"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "查看福利档案列表"));
        SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);

        log.info("各操作计时 {}", sw.prettyPrint());
        return apidatas;
    }

    /**
     * 福利档案中历史数据自动处理
     * @param currentEmployeeId
     */
    private void handleHistoryData(long currentEmployeeId) {
        //如果触发历史数据处理，则进行一次全量增员
        if (createOldInsuranceBaseInfo(currentEmployeeId)) {
            //批量增员
            List<InsuranceArchivesBaseInfoPO> allBaseInfoList = getInsuranceBaseInfoMapper().listAll();
            Collection<Long> stayAddIds = allBaseInfoList.stream().filter(f->f.getRunStatus().equals(EmployeeStatusEnum.STAY_ADD.getValue()))
                    .map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
            if (stayAddIds.size() > 0) {
                stayAddToPay(stayAddIds);
            }
        }

    }

    /**
     * 福利档案中待减员数据自动处理
     * @param currentEmployeeId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleStayDelData(long currentEmployeeId) {
        log.info("福利档案中待减员数据自动处理逻辑开始：");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        String today = simpleDateFormat.format(new Date());
        //part1，员工维护了社保/公积金/其他福利最后缴纳日,且任一类信息大于今天的，自动将待减员状态置为正在缴纳状态
        List<InsuranceArchivesBaseInfoPO> rePayList = getInsuranceBaseInfoMapper().getRePayList(today);
        updateInsuranceBaseInfoRunStatus(rePayList, EmployeeStatusEnum.PAYING.getValue());
        log.info("自动将待减员状态置为正在缴纳状态的档案数量 {}：", rePayList.size());
        //part2，员工维护了社保/公积金/其他福利最后缴纳日,且三类信息都小于今天的，自动置为待减员状态
        List<InsuranceArchivesBaseInfoPO> reStayDelList = getInsuranceBaseInfoMapper().getReStayDelList(today);
        updateInsuranceBaseInfoRunStatus(reStayDelList, EmployeeStatusEnum.STAY_DEL.getValue());
        log.info("自动置为待减员状态的档案数量 {}：", reStayDelList.size());
        //part3，非在职员工且处于正常缴纳的福利档案置为待减员状态
        //定义非在职的人事状态
        List<String> personnelStatuses = new ArrayList<String>() {{
            add("5");
            add("6");
            add("7");
        }};

        if (CollectionUtils.isNotEmpty(personnelStatuses)) {
            //获取非在职员工的福利档案基础信息
            InsuranceArchivesListParam insuranceArchivesListParam = new InsuranceArchivesListParam();
            insuranceArchivesListParam.setPersonnelStatuses(personnelStatuses);
            insuranceArchivesListParam.setRunStatuses(Collections.singletonList(EmployeeStatusEnum.PAYING.getValue()));

            List<InsuranceArchivesBaseInfoPO> noNormalList = getInsuranceBaseInfoMapper().getAbnormalList(insuranceArchivesListParam);
            updateInsuranceBaseInfoRunStatus(noNormalList, EmployeeStatusEnum.STAY_DEL.getValue());
            log.info("自动处理非在职员工的档案数量 {}：", noNormalList.size());
        }
    }

    /**
     * 福利档案中增量数据处理
     * @param currentEmployeeId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handleChangeData(long currentEmployeeId) {
        try {
            Util_DataCache.setObjVal("welfareChangeSign", "1");
            log.info("福利档案中增量数据处理逻辑开始：");
            // 所有增量人员列表
            List<TaxAgentEmpChangePO> taxAgentEmpChangeList = getTaxAgentEmpChangeService(user).listAllByModule(TaxAgentEmpChangeModuleEnum.INSURANCE_ARCHIVE);
            log.info("待处理的福利档案增量数据数量 {}：", taxAgentEmpChangeList.size());
            if (CollectionUtils.isEmpty(taxAgentEmpChangeList)) {
                Util_DataCache.setObjVal("welfareChangeSign", "0");
                return;
            }
            // 当前可以管辖的人员
            Collection<TaxAgentPO> taxAgentList = new ArrayList<>();
            if (currentEmployeeId != 1L) {
                taxAgentList = getTaxAgentService(user).listAllTaxAgents(currentEmployeeId);
                Collection<TaxAgentPO> finalTaxAgentList = taxAgentList;
                taxAgentEmpChangeList = taxAgentEmpChangeList.stream().filter(f -> finalTaxAgentList.stream().anyMatch(e -> e.getId().equals(f.getTaxAgentId()))).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(taxAgentEmpChangeList)) {
                    Util_DataCache.setObjVal("welfareChangeSign", "0");
                    return;
                }
            }
//        Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents(currentEmployeeId);
//        log.info("当前可以管辖的个税扣缴义务人数量 {}：", taxAgentList.size());
//        taxAgentEmpChangeList = taxAgentEmpChangeList.stream().filter(f -> taxAgentList.stream().anyMatch(e -> e.getId().equals(f.getTaxAgentId()))).collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(taxAgentEmpChangeList)) {
//            Util_DataCache.setObjVal("welfareChangeSign", "0");
//            return;
//        }
            log.info("根据当前可以管辖的个税扣缴义务人筛选出的可处理增量数据数量 {}：", taxAgentEmpChangeList.size());
            // 所有福利档案基础信息数据
            List<InsuranceArchivesBaseInfoPO> baseInfoPOList = getInsuranceBaseInfoMapper().listAll();
            log.info("当前数据库中所有福利档案基础信息数据数量 {}：", baseInfoPOList.size());
            StopWatch sw = new StopWatch();
            sw.start("将增量数据进一步处理为新增、更新两类数据");
            InsuranceArchivesBaseInfoBO.ChangeData changeData = InsuranceArchivesBaseInfoBO.buildChangeData(taxAgentEmpChangeList, baseInfoPOList, currentEmployeeId);
            sw.stop();
            // 批量修改福利档案
            if (CollectionUtils.isNotEmpty(changeData.getBaseInfoUpdateTodoList())) {
                log.info("增量数据中待更新的数据数量 {}：", changeData.getBaseInfoUpdateTodoList().size());
                //对于即将调整为“待减员”的数据，更新社保、公积金、其他福利档案的停止缴纳时间
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
                String today = simpleDateFormat.format(new Date());
                sw.start("生成增量数据中即将置为“待减员”的数据");
                List<InsuranceArchivesBaseInfoPO> toStayDelList = changeData.getBaseInfoUpdateTodoList().stream()
                        .filter(f -> f.getRunStatus().equals(EmployeeStatusEnum.STAY_DEL.getValue()))
                        .collect(Collectors.toList());
                if (isLog) {
                    log.info("福利档案-待减员明细:{}", toStayDelList);
                }
                if (toStayDelList.size() > 0) {
                    List<List<InsuranceArchivesBaseInfoPO>> partitionUpdateEndTime = Lists.partition(toStayDelList, 100);
                    partitionUpdateEndTime.forEach(part->{
                        List<Long> socialIds =  part.stream().map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
                        List<Long> fundIds =  part.stream().map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
                        List<Long> otherIds =  part.stream().map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());

                        getSocialSchemeMapper().batchUpdateEndTime(socialIds, today);
                        getFundSchemeMapper().batchUpdateEndTime(fundIds, today);
                        getOtherSchemeMapper().batchUpdateEndTime(otherIds, today);
                    });

                }
                sw.stop();

                sw.start("生成增量数据中即将置为“逻辑删除”的数据");
                //对于逻辑删除的数据，同样逻辑删除相关的社保、公积金、其他福利档案
                List<InsuranceArchivesBaseInfoPO> delList = changeData.getBaseInfoUpdateTodoList().stream()
                        .filter(f -> f.getDeleteType().equals(DeleteTypeEnum.DELETED.getValue()))
                        .collect(Collectors.toList());
                if (isLog) {
                    log.info("福利档案-逻辑删除明细:{}", delList);
                }
                if (delList.size() > 0) {
                    for (InsuranceArchivesBaseInfoPO po : delList) {
                        getSocialSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesSocialSchemePO.builder()
                                .employeeId(po.getEmployeeId())
                                .paymentOrganization(po.getPaymentOrganization())
                                .build());
                        getFundSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesFundSchemePO.builder()
                                .employeeId(po.getEmployeeId())
                                .paymentOrganization(po.getPaymentOrganization())
                                .build());
                        getOtherSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesOtherSchemePO.builder()
                                .employeeId(po.getEmployeeId())
                                .paymentOrganization(po.getPaymentOrganization())
                                .build());
                    }
                }
                sw.stop();
                //修改福利档案基础信息
                sw.start("增量数据中待更新数据入库");
                if (isLog) {
                    log.info("福利档案-增量数据中待更新数据入库明细:{}", changeData.getBaseInfoUpdateTodoList());
                }
                List<List<InsuranceArchivesBaseInfoPO>> partitionUpdateBase = Lists.partition(changeData.getBaseInfoUpdateTodoList(), 100);
                partitionUpdateBase.forEach(part-> getInsuranceBaseInfoMapper().batchUpdate(part));
                sw.stop();
                log.info("增量数据中待更新的数据处理完成！");
            }

            sw.start("处理增量数据中待新增的数据");
            // 批量新增福利档案
            if (CollectionUtils.isNotEmpty(changeData.getBaseInfoAddTodoList())) {
                log.info("增量数据中待新增的数据数量 {}：", changeData.getBaseInfoAddTodoList().size());
                //新增社保、公积金、其他福利档案、福利档案基础信息
                addNewInsuranceBaseInfo(changeData.getBaseInfoAddTodoList(), currentEmployeeId);
                log.info("增量数据中待新增的数据处理完成！");
            }
            sw.stop();

            // 删除增量数据
            if (CollectionUtils.isNotEmpty(changeData.getChangeIds())) {
                getTaxAgentEmpChangeService(user).deleleByIds(changeData.getChangeIds());
            }
            log.info("各操作计时 {}", sw.prettyPrint());
            Util_DataCache.setObjVal("welfareChangeSign", "0");
        }  catch (Exception e) {
            log.info("福利档案-增量数据处理出错：{}", e.getMessage(), e);
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "福利档案-增量数据处理出错"));
        }
    }

    /**
     * 删除档案
     * @param archiveIds
     */
    @Override
    public void deleteArchive(Collection<Long> archiveIds) {
        if(CollectionUtils.isEmpty(archiveIds)){
            throw new SalaryRunTimeException("社保福利档案参数为空!");
        }
        SalarySysConfPO canDelete = getSalarySysConfService(user).getOneByCode(SalarySysConstant.SALARY_ARCHIVE_DELETE);
        if(Objects.isNull(canDelete) || StringUtils.equals(canDelete.getConfValue(),"0") ){
            throw new SalaryRunTimeException("不允许删除社保福利档案，请先开启删除档案规则配置！");
        }
        List<InsuranceArchivesBaseInfoPO> insuranceArchivesList = getInsuranceBaseInfoMapper().listByIds(archiveIds);

        //查询当前登录人员管理的个税扣缴义务人
        List<Long> canDeleteTaxAgentIds = getTaxAgentService(user).listAllTaxAgentsAsAdmin((long) user.getUID())
                .stream().map(TaxAgentPO::getId).collect(Collectors.toList());
        boolean err = insuranceArchivesList.stream().anyMatch(po -> !canDeleteTaxAgentIds.contains(po.getPaymentOrganization()));

        if (CollectionUtils.isEmpty(insuranceArchivesList) || err) {
            throw new SalaryRunTimeException("社保档案不存在，或没有权限删除该社保案！");
        }

        Optional<InsuranceArchivesBaseInfoPO> fixedList = insuranceArchivesList.stream().filter(archive -> !StringUtils.equals(archive.getRunStatus(), EmployeeStatusEnum.STAY_ADD.getValue())
                && !StringUtils.equals(archive.getRunStatus(), EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue())).findFirst();
        if(fixedList.isPresent()){
            throw new SalaryRunTimeException("在缴员工、待减员、停止缴纳-来自待减员，无法删除薪资档案！");
        }
        List<Long> archiveDelIds = insuranceArchivesList.stream().map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
        List<Long> socialArchiveDelIds = insuranceArchivesList.stream().map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
        List<Long> fundArchiveDelIds = insuranceArchivesList.stream().map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
        List<Long> otherArchiveDelIds = insuranceArchivesList.stream().map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());
        //获取子表数据，方便记录操作日志
        List<InsuranceArchivesSocialSchemePO> socialArchives = getSocialSchemeMapper().getSocialById(socialArchiveDelIds);
        List<InsuranceArchivesFundSchemePO> fundArchives = getFundSchemeMapper().getFundById(fundArchiveDelIds);
        List<InsuranceArchivesOtherSchemePO> otherArchives = getOtherSchemeMapper().getOtherById(otherArchiveDelIds);
        Map<Long, InsuranceArchivesSocialSchemePO> socialArchiveMap = SalaryEntityUtil.convert2Map(socialArchives, InsuranceArchivesSocialSchemePO::getId);
        Map<Long, InsuranceArchivesFundSchemePO> fundArchiveMap = SalaryEntityUtil.convert2Map(fundArchives, InsuranceArchivesFundSchemePO::getId);
        Map<Long, InsuranceArchivesOtherSchemePO> otherArchiveMap = SalaryEntityUtil.convert2Map(otherArchives, InsuranceArchivesOtherSchemePO::getId);
        // 删除社保档案主表及3张明细表数据
        if(CollectionUtils.isNotEmpty(archiveDelIds)){
            getInsuranceBaseInfoMapper().deleteByIds(archiveDelIds);
        }
        if(CollectionUtils.isNotEmpty(socialArchiveDelIds)){
            getSocialSchemeMapper().deleteByIds(socialArchiveDelIds);
        }
        if(CollectionUtils.isNotEmpty(fundArchiveDelIds)){
            getFundSchemeMapper().deleteByIds(fundArchiveDelIds);
        }
        if(CollectionUtils.isNotEmpty(otherArchiveDelIds)){
            getOtherSchemeMapper().deleteByIds(otherArchiveDelIds);
        }
        //记录操作日志
        List<InsuranceArchivesBaseInfoPO> targetPOList = insuranceArchivesList.stream().filter(f -> archiveDelIds.contains(f.getId())).collect(Collectors.toList());
        if (targetPOList.size() > 0) {
            targetPOList.forEach(targetPO -> {
                DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
                TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
                targetPO.setDeleteType(DeleteTypeEnum.DELETED.getValue());
                //记录主表操作日志
                LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
                loggerContext.setUser(user);
                loggerContext.setTargetId(String.valueOf(targetPO.getId()));
                loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
                loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除福利档案主表"));
                loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除福利档案") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                loggerContext.setNewValues(targetPO);
                SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
                //记录明细表操作日志
                InsuranceArchivesSocialSchemePO socialTargetDetail = socialArchiveMap.get(targetPO.getSocialArchivesId());
                if (socialTargetDetail != null) {
                    socialTargetDetail.setDeleteType(DeleteTypeEnum.DELETED.getValue());
                    LoggerContext<InsuranceArchivesSocialSchemePO> detailLoggerContext = new LoggerContext<>();
                    detailLoggerContext.setUser(user);
                    detailLoggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    detailLoggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
                    detailLoggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-社保明细"));
                    detailLoggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-社保明细") + ":" + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setNewValues(socialTargetDetail);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(detailLoggerContext);
                }
                InsuranceArchivesFundSchemePO fundTargetDetail = fundArchiveMap.get(targetPO.getFundArchivesId());
                if (fundTargetDetail != null) {
                    fundTargetDetail.setDeleteType(DeleteTypeEnum.DELETED.getValue());
                    LoggerContext<InsuranceArchivesFundSchemePO> detailLoggerContext = new LoggerContext<>();
                    detailLoggerContext.setUser(user);
                    detailLoggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    detailLoggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
                    detailLoggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-公积金明细"));
                    detailLoggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-公积金明细") + ":" + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setNewValues(fundTargetDetail);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(detailLoggerContext);
                }
                InsuranceArchivesOtherSchemePO otherTargetDetail = otherArchiveMap.get(targetPO.getOtherArchivesId());
                if (otherTargetDetail != null) {
                    otherTargetDetail.setDeleteType(DeleteTypeEnum.DELETED.getValue());
                    LoggerContext<InsuranceArchivesOtherSchemePO> detailLoggerContext = new LoggerContext<>();
                    detailLoggerContext.setUser(user);
                    detailLoggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    detailLoggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
                    detailLoggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-其他福利明细"));
                    detailLoggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除福利档案-其他福利明细") + ":" + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    detailLoggerContext.setNewValues(otherTargetDetail);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(detailLoggerContext);
                }
            });
        }
    }

    //新增社保、公积金、其他福利档案、福利档案基础信息
    private List<InsuranceArchivesBaseInfoPO> addNewInsuranceBaseInfo(List<InsuranceArchivesBaseInfoPO> baseInfoPOList, Long currentEmployeeId) {
        try {
            List<InsuranceArchivesSocialSchemePO> socialList = new ArrayList<>();
            List<InsuranceArchivesFundSchemePO> fundList = new ArrayList<>();
            List<InsuranceArchivesOtherSchemePO> otherList = new ArrayList<>();
            for (InsuranceArchivesBaseInfoPO baseInfoPO : baseInfoPOList) {
                InsuranceArchivesSocialSchemePO insuranceArchivesSocialSchemePO = new InsuranceArchivesSocialSchemePO();
                insuranceArchivesSocialSchemePO.setTenantKey("");
                insuranceArchivesSocialSchemePO.setWelfareType(WelfareTypeEnum.SOCIAL_SECURITY.getValue());
                insuranceArchivesSocialSchemePO.setPaymentOrganization(baseInfoPO.getPaymentOrganization());
                insuranceArchivesSocialSchemePO.setNonPayment(NonPaymentEnum.YES.getValue());
                insuranceArchivesSocialSchemePO.setCreator(currentEmployeeId);
                insuranceArchivesSocialSchemePO.setCreateTime(new Date());
                insuranceArchivesSocialSchemePO.setUpdateTime(new Date());
                insuranceArchivesSocialSchemePO.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                insuranceArchivesSocialSchemePO.setEmployeeId(baseInfoPO.getEmployeeId());
                socialList.add(insuranceArchivesSocialSchemePO);

                InsuranceArchivesFundSchemePO insuranceArchivesFundSchemePO = new InsuranceArchivesFundSchemePO();
                insuranceArchivesFundSchemePO.setTenantKey("");
                insuranceArchivesFundSchemePO.setWelfareType(WelfareTypeEnum.ACCUMULATION_FUND.getValue());
                insuranceArchivesFundSchemePO.setPaymentOrganization(baseInfoPO.getPaymentOrganization());
                insuranceArchivesFundSchemePO.setNonPayment(NonPaymentEnum.YES.getValue());
                insuranceArchivesFundSchemePO.setCreator(currentEmployeeId);
                insuranceArchivesFundSchemePO.setCreateTime(new Date());
                insuranceArchivesFundSchemePO.setUpdateTime(new Date());
                insuranceArchivesFundSchemePO.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                insuranceArchivesFundSchemePO.setEmployeeId(baseInfoPO.getEmployeeId());
                fundList.add(insuranceArchivesFundSchemePO);

                InsuranceArchivesOtherSchemePO insuranceArchivesOtherSchemePO = new InsuranceArchivesOtherSchemePO();
                insuranceArchivesOtherSchemePO.setTenantKey("");
                insuranceArchivesOtherSchemePO.setWelfareType(WelfareTypeEnum.OTHER.getValue());
                insuranceArchivesOtherSchemePO.setPaymentOrganization(baseInfoPO.getPaymentOrganization());
                insuranceArchivesOtherSchemePO.setNonPayment(NonPaymentEnum.YES.getValue());
                insuranceArchivesOtherSchemePO.setCreator(currentEmployeeId);
                insuranceArchivesOtherSchemePO.setCreateTime(new Date());
                insuranceArchivesOtherSchemePO.setUpdateTime(new Date());
                insuranceArchivesOtherSchemePO.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                insuranceArchivesOtherSchemePO.setEmployeeId(baseInfoPO.getEmployeeId());
                otherList.add(insuranceArchivesOtherSchemePO);

            }
            //导入社保档案
            if (CollectionUtils.isNotEmpty(socialList)) {
                log.info("新增社保档案数量：{}", socialList.size());
                //根据人员id和个税扣缴义务人id删除对应档案
                socialList.forEach(getSocialSchemeMapper()::deleteByEmployeeIdAndPayOrg);
                log.info("删除历史社保档案");
                if (isLog) {
                    log.info("新增社保档案明细:{}", socialList);
                }
                List<List<InsuranceArchivesSocialSchemePO>> partition = Lists.partition(socialList, 100);
                partition.forEach(getSocialSchemeMapper()::batchSave);
                log.info("新增社保档案成功");
            }
            //导入公积金档案
            if (CollectionUtils.isNotEmpty(fundList)) {
                log.info("新增公积金档案数量：{}", fundList.size());
                //根据人员id和个税扣缴义务人id删除对应档案
                fundList.forEach(getFundSchemeMapper()::deleteByEmployeeIdAndPayOrg);
                log.info("删除历史公积金档案");
                if (isLog) {
                    log.info("新增公积金档案明细:{}", fundList);
                }
                List<List<InsuranceArchivesFundSchemePO>> partition = Lists.partition(fundList, 100);
                partition.forEach(getFundSchemeMapper()::batchSave);
                log.info("新增公积金档案成功");
            }
            //导入其他福利档案
            if (CollectionUtils.isNotEmpty(otherList)) {
                log.info("新增其他福利档案数量：{}", otherList.size());
                //根据人员id和个税扣缴义务人id删除对应档案
                otherList.forEach(getOtherSchemeMapper()::deleteByEmployeeIdAndPayOrg);
                log.info("删除历史其他福利档案");
                if (isLog) {
                    log.info("新增其他福利档案明细:{}", otherList);
                }
                List<List<InsuranceArchivesOtherSchemePO>> partition = Lists.partition(otherList, 100);
                partition.forEach(getOtherSchemeMapper()::batchSave);
                log.info("新增其他福利档案成功");
            }
            //导入福利档案基础信息
            if (CollectionUtils.isNotEmpty(baseInfoPOList)) {
                //根据人员id和个税扣缴义务人id删除对应档案
                baseInfoPOList.forEach(getInsuranceBaseInfoMapper()::deleteByEmployeeIdAndPayOrg);
                log.info("删除历史福利档案基础信息");
    //            //分批批量删除
                List<Long> baseInfoEmployeeIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getEmployeeId).collect(Collectors.toList());

                //查询目标人员的剩余的福利档案基础信息（社保、公积金、其他福利档案id）
                List<InsuranceArchivesBaseInfoPO> moreBaseInfoPOS = new ArrayList<>();
                log.info("查询目标人员的剩余的福利档案基础信息（社保、公积金、其他福利档案id）");
                List<List<Long>> partitionInfo = Lists.partition((List<Long>) baseInfoEmployeeIds, 1000);
                partitionInfo.forEach(part -> moreBaseInfoPOS.addAll(
                        getInsuranceBaseInfoMapper().getInsuranceBaseInfoListByInsuranceDetail(part)));
                
                List<InsuranceArchivesBaseInfoPO> newInsuranceArchivesBaseInfoList = new ArrayList<>();
                //设置社保、公积金、其他福利档案id
                log.info("设置社保、公积金、其他福利档案id");
                for (InsuranceArchivesBaseInfoPO po : baseInfoPOList) {
                    InsuranceArchivesBaseInfoPO moreBaseInfo = moreBaseInfoPOS.stream().filter(s -> Objects.equals(s.getEmployeeId(), po.getEmployeeId()) && Objects.equals(s.getPaymentOrganization(), po.getPaymentOrganization())).findFirst().orElse(null);
                    po.setSocialArchivesId(moreBaseInfo.getSocialArchivesId());
                    po.setFundArchivesId(moreBaseInfo.getFundArchivesId());
                    po.setOtherArchivesId(moreBaseInfo.getOtherArchivesId());
                    newInsuranceArchivesBaseInfoList.add(po);
                }
                log.info("福利档案基础信息分批批量入库，入库数量：{}", newInsuranceArchivesBaseInfoList.size());
                //分批批量入库
                if (isLog) {
                    log.info("新增福利档案基础信息明细:{}", newInsuranceArchivesBaseInfoList);
                }
                List<List<InsuranceArchivesBaseInfoPO>> partition = Lists.partition(newInsuranceArchivesBaseInfoList, 100);
                partition.forEach(getInsuranceBaseInfoMapper()::batchSave);
            }

            return baseInfoPOList;
        } catch (Exception e) {
            log.info("新增福利档案出错：{}", e.getMessage(), e);
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "福利档案新增失败"));
        }
    }
    /**
     * 分批更新福利档案基础信息的runStatus
     * @param baseInfoPOList
     * @param runStatus
     */
    private void updateInsuranceBaseInfoRunStatus(List<InsuranceArchivesBaseInfoPO> baseInfoPOList, String runStatus) {
        if (CollectionUtils.isNotEmpty(baseInfoPOList)) {
            List<Long> idList = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
            List<List<Long>> partition = Lists.partition(idList, 999);
            partition.forEach(
                    part -> {
                        InsuranceArchivesBaseInfoPO baseInfoPO = new InsuranceArchivesBaseInfoPO();
                        baseInfoPO.setIds(part);
                        baseInfoPO.setRunStatus(runStatus);
                        getInsuranceBaseInfoMapper().updateRunStatusByIds(baseInfoPO);
                    }

            );
        }
    }

    @Override
    public Map<String, Object> getSearchCondition(Map<String, Object> param) {
        Map<String, Object> apidatas = new HashMap<>(16);
//        apidatas = siArchivesBiz.getSearchCondition(user);
        apidatas = getSearchCondition();
        return apidatas;
    }

    @Override
    public XSSFWorkbook export(InsuranceArchivesListParam param) {
        InsuranceArchivesListParam request = InsuranceArchivesListParam.builder().build();
        if (param.getHireDate() != null && param.getHireDate().length == 2) {
            param.setHiredateStart(param.getHireDate()[0]);
            param.setHiredateEnd(param.getHireDate()[1]);
        }
        if (param.getDimissionDate() != null && param.getDimissionDate().length == 2) {
            param.setDimissionDateStart(param.getDimissionDate()[0]);
            param.setDimissionDateEnd(param.getDimissionDate()[1]);
        }
        if (Objects.equals("fromQuickSearch", param.getDataSource())) {
//            request.setStatuses(param.getStatuses());
            if (StringUtils.isNotBlank(param.getStatusesStr())) {
                request.setStatuses(Arrays.stream(param.getStatusesStr().split(",")).map(String::new).collect(Collectors.toList()));
            }
            request.setKeyword(param.getUserName());
        } else {
            request = param;
        }
        request.setPageSize(null);
        request.setStartNum(null);
        List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS = listPageEmployeePOS(request);
        if (insuranceArchivesEmployeePOS == null) {
            insuranceArchivesEmployeePOS = new ArrayList<>();
        }
//        List<Map<String, Object>> records = siArchivesBiz.buildTableData(insuranceArchivesEmployeePOS);
        List<Map<String, Object>> records = buildTableData(insuranceArchivesEmployeePOS);
//        List<WeaTableColumn> columns = siArchivesBiz.buildWeaTableColumns(insuranceArchivesEmployeePOS, user.getUID());
        List<WeaTableColumn> columns = buildWeaTableColumns(insuranceArchivesEmployeePOS);

        //工作簿list
        List<List<Object>> excelSheetData = new ArrayList<>();

        //工作簿名称
        String sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案");        //表头
        //表头
        excelSheetData.add(Arrays.asList(columns.stream().map(WeaTableColumn::getText).toArray(String[]::new)));
        //工作簿数据
        List<List<Object>> rows = new LinkedList<>();
        for (Map<String, Object> recordData : records) {
            List<Object> row = new LinkedList<>();
            for (WeaTableColumn column : columns) {
                row.add(recordData.get(column.getColumn()));
            }
            rows.add(row);
        }
        excelSheetData.addAll(rows);
        return ExcelUtil.genWorkbookV2(excelSheetData, sheetName);

    }

    @Override
    public List<InsuranceArchivesEmployeePO> listPageEmployeePOS(InsuranceArchivesListParam param) {
        long currentEmployeeId = user.getUID();
        Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId);
        if (needAuth) {
            List<TaxAgentEmployeeDTO> taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployee(currentEmployeeId);
            Set<Long> employeeIds = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getEmployeeId);
            List<InsuranceArchivesEmployeePO> list = getSocialSchemeMapper().queryEmployeeList(param);
            return list.stream().filter(f -> employeeIds.contains(f.getEmployeeId())).collect(Collectors.toList());
        }

        return getSocialSchemeMapper().queryEmployeeList(param);
    }

    /**
     * 获取福利档案各tab总人数
     */
    @Override
    public Map<String, Long> queryInsuranceTabTotal() {
        long currentEmployeeId = user.getUID();
        // tab页签数量
        Map<String, Long> result = new HashMap<>();
        Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId);
        //获取管理的人员范围
        List<TaxAgentManageRangeEmployeeDTO> taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        Map<Long, List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee>> taxAgentEmployeesMap = SalaryEntityUtil.convert2Map(taxAgentEmployeeDTOS, TaxAgentManageRangeEmployeeDTO::getTaxAgentId, TaxAgentManageRangeEmployeeDTO::getEmployeeList);
        List<InsuranceArchivesBaseInfoPO> list = null;
        if (needAuth) {
            // 获取作为管理员的所有个税扣缴义务人列表
            Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAllTaxAgentsAsAdmin(currentEmployeeId);
            Set<Long> taxAgentIds = SalaryEntityUtil.properties(taxAgentPOS, TaxAgentPO::getId);
            //获取所有福利档案基础信息
            List<InsuranceArchivesBaseInfoPO> archiveListDTOS = getInsuranceBaseInfoMapper().listAll();
            list = archiveListDTOS.stream().filter(dto -> taxAgentIds.contains(dto.getPaymentOrganization())).collect(Collectors.toList());
            Boolean adminEnable = getTaxAgentService(user).isAdminEnable(currentEmployeeId);
            //不是管理员看不到数据，返回空
            if (!adminEnable) {
                list = new ArrayList<>();
            }
        } else {
            list = getInsuranceBaseInfoMapper().listAll();
        }

        long stayAddTotal = 0L;
        long payTotal = 0L;
        long stayDelTotal = 0L;
        long stopTotal = 0L;
        long extTotal = 0L;

        for (InsuranceArchivesBaseInfoPO baseInfoPO : list) {
            Integer employeeType = baseInfoPO.getEmployeeType();
            if (employeeType == null || employeeType == 0) {
                if (baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STAY_ADD.getValue())) {
                    stayAddTotal += 1;
                } else if (baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.PAYING.getValue()) || baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STAY_DEL.getValue())) {
                    payTotal += 1;
                    if (baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STAY_DEL.getValue())) {
                        stayDelTotal += 1;
                    }
                } else if (baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue()) || baseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue())) {
                    stopTotal += 1;
                }
            } else {
                extTotal += 1;
            }

        }

        result.put("stayAdd", stayAddTotal);
        result.put("paying", payTotal);
        result.put("stayDel", stayDelTotal);
        result.put("stopPay", stopTotal);
        result.put("ext", extTotal);
        return result;
    }

    /**
     * 批量变更档案列表的runStatus，目前仅在待增员tab中删除待办使用，后边其他方调用时需修改操作日志记录
     */
    @Override
    public void updateRunStatus(InsuranceArchivesBaseInfoPO po) {
        getInsuranceBaseInfoMapper().updateRunStatusByIds(po);
        //记录操作日志
        List<InsuranceArchivesBaseInfoPO> targetPOList = getInsuranceBaseInfoMapper().listByIds(po.getIds());
        if (targetPOList != null && targetPOList.size() > 0) {
            targetPOList.forEach(targetPO -> {
                DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
                TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
                LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
                loggerContext.setUser(user);
                loggerContext.setTargetId(String.valueOf(targetPO.getId()));
                loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
                loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "待增员档案-删除待办"));
                loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "待增员档案-删除待办") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
//                loggerContext.setNewValues(targetPO);
                SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
            });
        }
    }

    @Override
    public void cancelStopPayment(Collection<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
        List<InsuranceArchivesBaseInfoPO> pos = getInsuranceBaseInfoMapper().listByIds(ids);

        List<Long> stayAddIds = new ArrayList<>();
        List<Long> stayDelIds = new ArrayList<>();
        List<TaxAgentEmployeeDTO> taxAgentManageRangeEmployees = getTaxAgentService(user).listTaxAgentAndEmployee((long) user.getUID());

        List<InsuranceArchivesBaseInfoPO> oldStayAddList = pos.stream().filter(f -> f.getRunStatus().equals(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue())).collect(Collectors.toList());

        boolean isNotExist = oldStayAddList.stream().anyMatch(te -> taxAgentManageRangeEmployees.stream().noneMatch(p -> p.getEmployeeId() != null && p.getEmployeeId().equals(te.getEmployeeId()) && p.getTaxAgentId().equals(te.getPaymentOrganization())));
        if (isNotExist) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(116196, "不在当前个税扣缴义人的人员范围中，不可取消停缴"));
        }
        for(InsuranceArchivesBaseInfoPO po : pos) {
            if (po.getRunStatus().equals(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue())) {
                //来自待增员的停缴->待增员
                stayAddIds.add(po.getId());
            } else if (po.getRunStatus().equals(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue())) {
                //来自待减员的停缴->待减员
                stayDelIds.add(po.getId());
            }
        }

        //更新调整为待增员的数据
        InsuranceArchivesBaseInfoPO stayAddPO = InsuranceArchivesBaseInfoPO.builder().ids(stayAddIds).runStatus(EmployeeStatusEnum.STAY_ADD.getValue()).build();
        if (stayAddPO.getIds().size() > 0) {
            getInsuranceBaseInfoMapper().updateRunStatusByIds(stayAddPO);
        }
        //更新调整为待减员的数据
        InsuranceArchivesBaseInfoPO stayDelPO = InsuranceArchivesBaseInfoPO.builder().ids(stayDelIds).runStatus(EmployeeStatusEnum.STAY_DEL.getValue()).build();
        if (stayDelPO.getIds().size() > 0) {
            getInsuranceBaseInfoMapper().updateRunStatusByIds(stayDelPO);
        }
        //记录操作日志
        Map<String, InsuranceArchivesBaseInfoPO> oldBaseInfoMap = SalaryEntityUtil.convert2Map(pos, e -> e.getPaymentOrganization() + "-" + e.getEmployeeId());
        List<InsuranceArchivesBaseInfoPO> newPos = getInsuranceBaseInfoMapper().listByIds(ids);
        newPos.forEach(targetPO -> {
            DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
            TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
            LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
            loggerContext.setUser(user);
            loggerContext.setTargetId(String.valueOf(targetPO.getId()));
            loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
            loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
            loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "停缴档案-取消停缴"));
            loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "停缴档案-取消停缴") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
            loggerContext.setOldValues(oldBaseInfoMap.get(targetPO.getPaymentOrganization() + "-" + targetPO.getEmployeeId()));
            loggerContext.setNewValues(targetPO);
            SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
        });
    }

    /**
     * 批量减员
     */
    @Override
    public Map<String, Object> stayDelToStop(Collection<Long> ids) {

        if (CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
        List<InsuranceArchivesBaseInfoPO> baseInfoPOList = getInsuranceBaseInfoMapper().listByIds(ids);
        //分别新建福利档案基础信息相关的社保、公积金、其他福利档案列表
        List<InsuranceArchivesSocialSchemePO> socialList = new ArrayList<>();
        List<InsuranceArchivesFundSchemePO> fundList = new ArrayList<>();
        List<InsuranceArchivesOtherSchemePO> otherList = new ArrayList<>();
        //新建最终可以进行减员的福利档案基础信息id列表
        List<Long> toStopBaseInfoIdList = new ArrayList<>();
        //新建最终不可以进行减员的福利档案基础信息id列表
        List<Long> noStopBaseInfoIds = new ArrayList<>();
        //获取待处理的福利档案基础信息id列表
        List<Long> baseInfoIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
        //设置最后缴纳月的比较月份
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        String todayMonth = simpleDateFormat.format(new Date());
        //分别获取福利档案基础信息相关的社保、公积金、其他福利档案id列表
        List<Long> socialIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
        List<Long> fundIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
        List<Long> otherIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());

        List<Long> toStopSocialIds = new ArrayList<>();
        List<Long> toStopFundIds = new ArrayList<>();
        List<Long> toStopOtherIds = new ArrayList<>();
        //获取可进行减员的社保档案相关人员数据
        if (socialIds.size() > 0) {
            //获取社保档案
            socialList = getSocialSchemeMapper().getSocialById(socialIds);
            //筛选可减员的社保档案相关信息
            toStopSocialIds = socialList.stream().filter(f-> f.getSocialSchemeId() == null || (f.getSocialEndTime() != null && f.getSocialEndTime().length() > 0 && (f.getSocialEndTime().compareTo(todayMonth)) <= 0))
                    .map(InsuranceArchivesSocialSchemePO::getId).collect(Collectors.toList());

            List<Long> finalToStopSocialIds = toStopSocialIds;
            noStopBaseInfoIds = baseInfoPOList.stream().filter(f -> !finalToStopSocialIds.contains(f.getSocialArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());

        }
        if (fundIds.size() > 0) {
            fundList = getFundSchemeMapper().getFundById(fundIds);

            toStopFundIds = fundList.stream().filter(f->f.getFundSchemeId() == null || (f.getFundEndTime() != null && f.getFundEndTime().length() > 0 && (f.getFundEndTime().compareTo(todayMonth)) <= 0))
                    .map(InsuranceArchivesFundSchemePO::getId).collect(Collectors.toList());
            List<Long> finalToStopFundIds = toStopFundIds;
            noStopBaseInfoIds = (List<Long>) CollectionUtils.union(noStopBaseInfoIds, baseInfoPOList.stream().filter(f -> !finalToStopFundIds.contains(f.getFundArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList()));

        }
        if (otherIds.size() > 0) {
            otherList = getOtherSchemeMapper().getOtherById(otherIds);

            toStopOtherIds= otherList.stream().filter(f->f.getOtherSchemeId() == null || (f.getOtherEndTime() != null && f.getOtherEndTime().length() > 0 && (f.getOtherEndTime().compareTo(todayMonth)) <= 0))
                    .map(InsuranceArchivesOtherSchemePO::getId).collect(Collectors.toList());
            List<Long> finalToStopOtherIds = toStopOtherIds;
            noStopBaseInfoIds = (List<Long>) CollectionUtils.union(noStopBaseInfoIds, baseInfoPOList.stream().filter(f -> !finalToStopOtherIds.contains(f.getOtherArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList()));

        }
        //获取最终基础信息表中的可减员数据
        if (noStopBaseInfoIds.size() == 0) {
            //社保、公积金、其他福利档案的可减员的人员信息与入参中的人员信息一致时
            toStopBaseInfoIdList = baseInfoIds;
        } else {
            //与最终不可减员的baseInfoId信息做差集
            toStopBaseInfoIdList = (List<Long>) CollectionUtils.subtract(baseInfoIds, noStopBaseInfoIds);
        }
        //进行减员操作
        if (toStopBaseInfoIdList.size() > 0) {
            getInsuranceBaseInfoMapper().updateRunStatusByIds(InsuranceArchivesBaseInfoPO.builder()
                    .ids(toStopBaseInfoIdList).runStatus(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue()).build());
            //记录操作日志
            toStopBaseInfoIdList.forEach(f -> {
                InsuranceArchivesBaseInfoPO targetPO = getInsuranceBaseInfoMapper().getById(f);
                if (targetPO != null) {
                    DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
                    TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
                    LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
                    loggerContext.setUser(user);
                    loggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
                    loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "福利档案减员"));
                    loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "停缴一名在缴员工") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    loggerContext.setNewValues(targetPO);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
                }
            });
        }

        Map<String, Object> resultMap = new HashMap<>(2);
        String resultMsg = "操作成功";
        String resultType = "success";
        // 批量设为定薪提示

        //输出结果，此处需区分单一减员和批量减员
        if (baseInfoPOList.size() == toStopBaseInfoIdList.size()) {
            //减员成功
            if (baseInfoPOList.size() == 1) {
                resultMsg = "减员成功";

            } else {
                resultMsg = "批量减员成功";

            }
        } else {
            //减员失败
            resultType = "fail";
            if (baseInfoPOList.size() == 1) {
                resultMsg = "减员失败，失败原因：最后缴纳月数据未正常维护";

            } else {
                resultMsg = "部分或全部失败：【共提交减员数据"
                        + baseInfoIds.size()
                        +"条，成功" + toStopBaseInfoIdList.size()
                        +"条，失败" + noStopBaseInfoIds.size()
                        +"条，失败原因：最后缴纳月数据未正常维护】";

            }
        }
        resultMap.put("type", resultType);
        resultMap.put("msg", resultMsg);
        return resultMap;
    }

    @Override
    public Map<String, Object> stopWithoutLimit(Collection<Long> ids, String yearMonth) {

        if (CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
        List<InsuranceArchivesBaseInfoPO> baseInfoPOList = getInsuranceBaseInfoMapper().listByIds(ids);

        //分别新建福利档案基础信息相关的社保、公积金、其他福利档案列表
        List<InsuranceArchivesSocialSchemePO> socialList = new ArrayList<>();
        List<InsuranceArchivesFundSchemePO> fundList = new ArrayList<>();
        List<InsuranceArchivesOtherSchemePO> otherList = new ArrayList<>();
        //获取待处理的福利档案基础信息id列表
        List<Long> baseInfoIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
        //分别获取福利档案基础信息相关的社保、公积金、其他福利档案id列表
        List<Long> socialIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
        List<Long> fundIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
        List<Long> otherIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());
        //进行减员操作
        if (baseInfoIds.size() > 0) {
            getInsuranceBaseInfoMapper().updateRunStatusByIds(InsuranceArchivesBaseInfoPO.builder()
                    .ids(baseInfoIds).runStatus(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue()).build());

            getSocialSchemeMapper().batchUpdateEndTime(socialIds, yearMonth);
            getFundSchemeMapper().batchUpdateEndTime(fundIds, yearMonth);
            getOtherSchemeMapper().batchUpdateEndTime(otherIds, yearMonth);
        }


        Map<String, Object> resultMap = new HashMap<>(2);
        String resultMsg = "操作成功";
        String resultType = "success";

        resultMap.put("type", resultType);
        resultMap.put("msg", resultMsg);
        return resultMap;
    }

    /**
     * 全量减员
     */
    @Override
    public Map<String, Object> allStayDelToStop() {
        long currentEmployeeId = user.getUID();
        List<InsuranceArchivesBaseInfoPO> allBaseInfoList = getInsuranceBaseInfoMapper().listAll();
        if (allBaseInfoList.size() > 0) {
            //筛选当前人员可管辖（个税扣缴义务人）范围
            Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents(currentEmployeeId);
            List<Long> paymentOrganizationList = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList());

            Collection<Long> stayDelIds = allBaseInfoList.stream().filter(f->f.getRunStatus().equals(EmployeeStatusEnum.STAY_DEL.getValue())
                    && paymentOrganizationList.contains(f.getPaymentOrganization())
                    && (f.getEmployeeType() == null || Objects.equals(f.getEmployeeType(), EmployeeTypeEnum.ORGANIZATION.getValue())))
                    .map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
            if (stayDelIds.size() > 0) {
                return stayDelToStop(stayDelIds);
            } else {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
            }
        } else {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
    }

    /**
     * 批量增员
     */
    @Override
    public Map<String, Object> stayAddToPay(Collection<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
        List<InsuranceArchivesBaseInfoPO> baseInfoPOList = new ArrayList<>();

        List<List<Long>> partitionInfo = Lists.partition((List<Long>) ids, 100);
        partitionInfo.forEach(part -> baseInfoPOList.addAll(
                getInsuranceBaseInfoMapper().listByIds(part)));
        //分别新建福利档案基础信息相关的社保、公积金、其他福利档案列表
        List<InsuranceArchivesSocialSchemePO> socialList = new ArrayList<>();
        List<InsuranceArchivesFundSchemePO> fundList = new ArrayList<>();
        List<InsuranceArchivesOtherSchemePO> otherList = new ArrayList<>();
        //新建最终可以进行增员的福利档案基础信息id列表
        List<Long> toPayBaseInfoIdList = new ArrayList<>();
        //新建最终不可以进行增员的福利档案基础信息id列表
        List<Long> noPayBaseInfoIds = new ArrayList<>();
        //获取待处理的福利档案基础信息id列表
        List<Long> baseInfoIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
        //设置最后缴纳月的比较月份
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        String todayMonth = simpleDateFormat.format(new Date());
        //分别获取福利档案基础信息相关的社保、公积金、其他福利档案id列表
        List<Long> socialIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
        List<Long> fundIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
        List<Long> otherIds = baseInfoPOList.stream().map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());

        List<Long> toStopSocialIds = new ArrayList<>();
        List<Long> toStopFundIds = new ArrayList<>();
        List<Long> toStopOtherIds = new ArrayList<>();
        //获取可进行增员的社保档案相关人员数据
        if (socialIds.size() > 0) {
            //获取社保档案
            List<List<Long>> partitionSocial = Lists.partition((List<Long>) socialIds, 100);
            partitionSocial.forEach(part -> socialList.addAll(
                    getSocialSchemeMapper().getSocialById(part)));

            //筛选可增员的社保档案相关人员信息
            toStopSocialIds = socialList.stream().filter(f->
            {
                boolean flag = true;
                if (f.getSocialStartTime() == null || f.getSocialStartTime().length() == 0 || f.getSocialSchemeId() == null) {
                    flag = false;
                }
                if (f.getSocialEndTime() != null && f.getSocialEndTime().length() > 0 && (f.getSocialEndTime().compareTo(todayMonth)) <= 0) {
                    flag = false;
                }
                return flag;
            })
                    .map(InsuranceArchivesSocialSchemePO::getId).collect(Collectors.toList());
            List<Long> finalToStopSocialIds = toStopSocialIds;
            toPayBaseInfoIdList = baseInfoPOList.stream().filter(f -> finalToStopSocialIds.contains(f.getSocialArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());


        }
        if (fundIds.size() > 0) {
            List<List<Long>> partitionFund = Lists.partition((List<Long>) fundIds, 100);
            partitionFund.forEach(part -> fundList.addAll(
                    getFundSchemeMapper().getFundById(part)));

            toStopFundIds = fundList.stream().filter(f->
            {
                boolean flag = true;
                if (f.getFundStartTime() == null || f.getFundStartTime().length() == 0 || f.getFundSchemeId() == null) {
                    flag = false;
                }
                if (f.getFundEndTime() != null && f.getFundEndTime().length() > 0 && (f.getFundEndTime().compareTo(todayMonth)) <= 0) {
                    flag = false;
                }
                return flag;
            })
                    .map(InsuranceArchivesFundSchemePO::getId).collect(Collectors.toList());
            List<Long> finalToStopFundIds = toStopFundIds;
            toPayBaseInfoIdList = (List<Long>) CollectionUtils.union(toPayBaseInfoIdList, baseInfoPOList.stream().filter(f -> finalToStopFundIds.contains(f.getFundArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList()));

        }
        if (otherIds.size() > 0) {
            List<List<Long>> partitionOther = Lists.partition((List<Long>) otherIds, 100);
            partitionOther.forEach(part -> otherList.addAll(
                    getOtherSchemeMapper().getOtherById(part)));

            toStopOtherIds = otherList.stream().filter(f->
            {
                boolean flag = true;
                if (f.getOtherStartTime() == null || f.getOtherStartTime().length() == 0 || f.getOtherSchemeId() == null) {
                    flag = false;
                }
                if (f.getOtherEndTime() != null && f.getOtherEndTime().length() > 0 && (f.getOtherEndTime().compareTo(todayMonth)) <= 0) {
                    flag = false;
                }
                return flag;
            })
                    .map(InsuranceArchivesOtherSchemePO::getId).collect(Collectors.toList());
            List<Long> finalToStopOtherIds = toStopOtherIds;
            toPayBaseInfoIdList = (List<Long>) CollectionUtils.union(toPayBaseInfoIdList, baseInfoPOList.stream().filter(f -> finalToStopOtherIds.contains(f.getOtherArchivesId())).map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList()));

        }
        //获取最终基础信息表中的不可增员数据
        noPayBaseInfoIds = (List<Long>) CollectionUtils.subtract(baseInfoIds, toPayBaseInfoIdList);

        //其他的个税扣缴义务人下的在缴员工中存在该员工，在缴员工未进入停缴员工时，不可进行增员

        //进行增员操作
        if (toPayBaseInfoIdList.size() > 0) {
            List<List<Long>> partitionToPay = Lists.partition((List<Long>) toPayBaseInfoIdList, 100);
            partitionToPay.forEach(part -> {
                getInsuranceBaseInfoMapper().updateRunStatusByIds(InsuranceArchivesBaseInfoPO.builder()
                        .ids(part).runStatus(EmployeeStatusEnum.PAYING.getValue()).build());
            });

            //记录操作日志
            toPayBaseInfoIdList.forEach(f -> {
                InsuranceArchivesBaseInfoPO targetPO = getInsuranceBaseInfoMapper().getById(f);
                if (targetPO != null) {
                    DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
                    TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
                    LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
                    loggerContext.setUser(user);
                    loggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
                    loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "福利档案增员"));
                    loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "增加一名在缴员工") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    loggerContext.setNewValues(targetPO);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
                }
            });
        }

        Map<String, Object> resultMap = new HashMap<>(2);
        String resultMsg = "操作成功";
        String resultType = "success";
        // 批量设为定薪提示

        //输出结果，此处需区分单一增员和批量增员
        if (baseInfoPOList.size() == toPayBaseInfoIdList.size()) {
            //增员成功
            if (baseInfoPOList.size() == 1) {
                resultMsg = "增员成功";

            } else {
                resultMsg = "批量增员成功";
            }
        } else {
            //增员失败
            resultType = "fail";
            if (baseInfoPOList.size() == 1) {
                resultMsg = "增员失败，失败原因：起始缴纳月/福利方案数据未正常维护";
            } else {
                resultMsg = "部分或全部失败：【共提交增员数据"
                        + baseInfoIds.size()
                        +"条，成功" + toPayBaseInfoIdList.size()
                        +"条，失败" + noPayBaseInfoIds.size()
                        +"条，失败原因：起始缴纳月/福利方案数据未正常维护】";

            }
        }
        resultMap.put("type", resultType);
        resultMap.put("msg", resultMsg);
        return resultMap;
    }

    /**
     * 全量增员
     */
    @Override
    public Map<String, Object> allStayAddToPay() {
        long currentEmployeeId = user.getUID();
        List<InsuranceArchivesBaseInfoPO> allBaseInfoList = getInsuranceBaseInfoMapper().listAll();
        if (allBaseInfoList.size() > 0) {
            //筛选当前人员可管辖（个税扣缴义务人）范围
            Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents(currentEmployeeId);
            List<Long> paymentOrganizationList = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList());

            Collection<Long> stayAddIds = allBaseInfoList.stream().filter(f->f.getRunStatus().equals(EmployeeStatusEnum.STAY_ADD.getValue())
                    && paymentOrganizationList.contains(f.getPaymentOrganization())
                    && (f.getEmployeeType() == null || Objects.equals(f.getEmployeeType(), EmployeeTypeEnum.ORGANIZATION.getValue())))
                    .map(InsuranceArchivesBaseInfoPO::getId).collect(Collectors.toList());
            if (stayAddIds.size() > 0) {
                return stayAddToPay(stayAddIds);
            } else {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
            }
        } else {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145969, "没有可以操作的记录"));
        }
    }

    /**
     * 待减员页面的删除待办
     */
    @Override
    public void cancelStayDel(InsuranceArchivesBaseInfoPO insuranceArchivesBaseInfoPO) {

        if (insuranceArchivesBaseInfoPO.getIds() == null || StringUtils.isBlank(insuranceArchivesBaseInfoPO.getRunStatus())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }
        if (insuranceArchivesBaseInfoPO.getRunStatus().equals(EmployeeStatusEnum.STAY_DEL.getValue())) {
            List<List<Long>> baseInfoIdsPartition = Lists.partition((List<Long>) insuranceArchivesBaseInfoPO.getIds(), 100);
            List<InsuranceArchivesBaseInfoPO> nowList = new ArrayList<>();
            baseInfoIdsPartition.forEach(part -> {
                nowList.addAll(getInsuranceBaseInfoMapper().listByIds(part));
            });
            //判断当前被操作人员是否都在对应的个税扣缴义务人下
            List<TaxAgentEmployeeDTO> taxAgentManageRangeEmployees = getTaxAgentService(user).listTaxAgentAndEmployee((long) user.getUID());

            boolean isNotExist = nowList.stream().anyMatch(te ->
                    taxAgentManageRangeEmployees.stream().noneMatch(p ->
                            p.getEmployeeId() != null && p.getEmployeeId().equals(te.getEmployeeId()) && p.getTaxAgentId().equals(te.getPaymentOrganization())));

            if (isNotExist) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(116196, "个税扣缴义务人不存在或不在权限范围内，删除失败！"));
            }
            //置空社保、公积金、其他福利档案的最后缴纳月信息，并将福利档案基础信息表的状态置为“正在缴纳”
            if (nowList.size() > 0) {
                List<Long> socialIds = nowList.stream()
                        .map(InsuranceArchivesBaseInfoPO::getSocialArchivesId).collect(Collectors.toList());
                List<Long> fundIds = nowList.stream()
                        .map(InsuranceArchivesBaseInfoPO::getFundArchivesId).collect(Collectors.toList());
                List<Long> otherIds = nowList.stream()
                        .map(InsuranceArchivesBaseInfoPO::getOtherArchivesId).collect(Collectors.toList());

                List<List<Long>> socialIdsPartition = Lists.partition(socialIds, 100);
                socialIdsPartition.forEach(getSocialSchemeMapper()::batchUpdateEndTimeToNull);

                List<List<Long>> fundIdsPartition = Lists.partition(fundIds, 100);
                fundIdsPartition.forEach(getFundSchemeMapper()::batchUpdateEndTimeToNull);

                List<List<Long>> otherIdsPartition = Lists.partition(otherIds, 100);
                otherIdsPartition.forEach(getOtherSchemeMapper()::batchUpdateEndTimeToNull);

                baseInfoIdsPartition.forEach(part -> {
                    getInsuranceBaseInfoMapper().updateRunStatusByIds(InsuranceArchivesBaseInfoPO.builder()
                            .ids(part)
                            .runStatus(EmployeeStatusEnum.PAYING.getValue())
                            .build());
                });
                nowList.forEach(targetPO -> {
                    DataCollectionEmployee empInfo = getEmployMapper().getEmployeeById(targetPO.getEmployeeId());
                    TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
                    LoggerContext<InsuranceArchivesBaseInfoPO> loggerContext = new LoggerContext<>();
                    loggerContext.setUser(user);
                    loggerContext.setTargetId(String.valueOf(targetPO.getId()));
                    loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
                    loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
                    loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "待减员档案-删除待办"));
                    loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "待减员档案-删除待办") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
//                    loggerContext.setNewValues(targetPO);
                    SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
                });
            }

        }
    }

    @Override
    public PageInfo<InsuranceArchivesBaseHistoryDTO> getAdjustHistoryList(SIArchiveBaseHistoryListParam param) {

        if (param.getWelfareTypeEnum() == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "参数错误"));
        }
//        List<InsuranceArchivesBaseHistoryDTO> adjustHistoryDTOS = siArchivesBiz.getAdjustHistoryList(param.getPaymentOrganization(), param.getEmployeeId());
        List<InsuranceArchivesBaseHistoryDTO> adjustHistoryDTOS = getAdjustHistoryList(param.getPaymentOrganization(), param.getEmployeeId());

        List<InsuranceArchivesBaseHistoryDTO> targetHistory = adjustHistoryDTOS.stream()
                    .filter(f -> f.getWelfareType().equals(param.getWelfareTypeEnum().getValue())).collect(Collectors.toList());

        PageInfo<InsuranceArchivesBaseHistoryDTO> listPage = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(),
                targetHistory , InsuranceArchivesBaseHistoryDTO.class);

        return listPage;
    }

    @Override
    public PageInfo<InsuranceArchivesBaseHistoryDTO> historyListByEmployeeIdAndOperator(SIArchiveBaseHistoryListParam param) {

//        List<InsuranceArchivesBaseHistoryDTO> adjustHistoryDTOS = siArchivesBiz.getBaseHistoryByEmployeeIdAndOperator(param.getOperator(), param.getEmployeeId());
        List<InsuranceArchivesBaseHistoryDTO> adjustHistoryDTOS = getBaseHistoryByEmployeeIdAndOperator(param.getOperator(), param.getEmployeeId());
        // 分权逻辑
        Boolean needAuth = getTaxAgentService(user).isNeedAuth((long) user.getUID());
        if (needAuth) {
            Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAllTaxAgents((long) user.getUID());
            List<Long> taxAgents = taxAgentPOS.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(taxAgents)) {
                //防止普通用户查询
                adjustHistoryDTOS = new ArrayList<>();
            } else {
                adjustHistoryDTOS = adjustHistoryDTOS.stream().filter(f -> taxAgents.contains(f.getPaymentOrganization())).collect(Collectors.toList());
            }
        }

        adjustHistoryDTOS.forEach(f -> {
            if (StringUtils.isNotBlank(f.getPaymentScope())) {
                if(f.getPaymentScope().equals(PaymentScopeEnum.SCOPE_PERSON.getValue().toString())) {
                    f.setPaymentScope(SalaryI18nUtil.getI18nLabel(0, "个人"));
                } else if(f.getPaymentScope().equals(PaymentScopeEnum.SCOPE_COMPANY.getValue().toString())) {
                    f.setPaymentScope(SalaryI18nUtil.getI18nLabel(0, "公司"));
                } else {
                    f.setPaymentScope(SalaryI18nUtil.getI18nLabel(0, "个人") + "," + SalaryI18nUtil.getI18nLabel(0, "公司"));
                }
            } else {
                f.setPaymentScope(SalaryI18nUtil.getI18nLabel(0, "个人") + "," + SalaryI18nUtil.getI18nLabel(0, "公司"));
            }
        });

        PageInfo<InsuranceArchivesBaseHistoryDTO> listPage = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(),
                adjustHistoryDTOS , InsuranceArchivesBaseHistoryDTO.class);

        return listPage;
    }

    /**
     * 拷贝福利档案到新的个税扣缴义务人并置为在缴
     */
    @Override
    public Map<String, Object> copyToPay(Long toCopyTaxAgentId, Long toUpdateTaxAgentId, Long employeeId, String payStartYearMonth) {
        if (toCopyTaxAgentId == null || toUpdateTaxAgentId == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "个税扣缴义务人不能为空"));
        }
        if (employeeId == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "人员id不能为空"));
        }
        //获取待拷贝的福利档案明细
        InsuranceArchivesBaseInfoPO toCopyBaseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(toCopyTaxAgentId, employeeId);
        if(toCopyBaseInfoPO == null){
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "待复制个税扣缴义务人下该员工不存在福利档案，请检查后重试！"));
        }
        InsuranceArchivesSocialSchemePO toCopySocialInfo = getSocialSchemeMapper().getOneById(toCopyBaseInfoPO.getSocialArchivesId());
        InsuranceArchivesFundSchemePO toCopyFundInfo = getFundSchemeMapper().getOneById(toCopyBaseInfoPO.getFundArchivesId());
        InsuranceArchivesOtherSchemePO toCopyOtherInfo = getOtherSchemeMapper().getOneById(toCopyBaseInfoPO.getOtherArchivesId());
        //获取待更新的福利档案
        InsuranceArchivesBaseInfoPO toUpdateBaseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(toUpdateTaxAgentId, employeeId);
        if(toUpdateBaseInfoPO == null){
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "待更新个税扣缴义务人下该员工不存在福利档案，请检查后重试！"));
        }
        InsuranceArchivesSocialSchemePO toUpdateSocialInfo = getSocialSchemeMapper().getOneById(toUpdateBaseInfoPO.getSocialArchivesId());
        InsuranceArchivesFundSchemePO toUpdateFundInfo = getFundSchemeMapper().getOneById(toUpdateBaseInfoPO.getFundArchivesId());
        InsuranceArchivesOtherSchemePO toUpdateOtherInfo = getOtherSchemeMapper().getOneById(toUpdateBaseInfoPO.getOtherArchivesId());
        //设置福利档案基数调整记录数据
        encryptUtil.decrypt(toCopySocialInfo, InsuranceArchivesSocialSchemePO.class);
        encryptUtil.decrypt(toUpdateSocialInfo, InsuranceArchivesSocialSchemePO.class);
        encryptUtil.decrypt(toCopyFundInfo, InsuranceArchivesFundSchemePO.class);
        encryptUtil.decrypt(toUpdateFundInfo, InsuranceArchivesFundSchemePO.class);
        encryptUtil.decrypt(toCopyOtherInfo, InsuranceArchivesOtherSchemePO.class);
        encryptUtil.decrypt(toUpdateOtherInfo, InsuranceArchivesOtherSchemePO.class);

        InsuranceArchivesBaseHistoryDTO socialAdjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(toCopySocialInfo.getSocialSchemeId())
                .adjustAfterBaseJson(toCopySocialInfo.getSocialPaymentBaseString())
                .adjustAfterComBaseJson(toCopySocialInfo.getSocialPaymentComBaseString())
                .welfareType(toUpdateSocialInfo.getWelfareType())
                .employeeId(toUpdateSocialInfo.getEmployeeId())
                .paymentOrganization(toUpdateSocialInfo.getPaymentOrganization())
                .adjustBeforeSchemeId(toUpdateSocialInfo.getSocialSchemeId())
                .adjustBeforeBaseJson(toUpdateSocialInfo.getSocialPaymentBaseString())
                .adjustBeforeComBaseJson(toUpdateSocialInfo.getSocialPaymentComBaseString())
                .build();
        InsuranceArchivesBaseHistoryDTO fundAdjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(toCopyFundInfo.getFundSchemeId())
                .adjustAfterBaseJson(toCopyFundInfo.getFundPaymentBaseString())
                .adjustAfterComBaseJson(toCopyFundInfo.getFundPaymentComBaseString())
                .welfareType(toUpdateFundInfo.getWelfareType())
                .employeeId(toUpdateFundInfo.getEmployeeId())
                .paymentOrganization(toUpdateFundInfo.getPaymentOrganization())
                .adjustBeforeSchemeId(toUpdateFundInfo.getFundSchemeId())
                .adjustBeforeBaseJson(toUpdateFundInfo.getFundPaymentBaseString())
                .adjustBeforeComBaseJson(toUpdateFundInfo.getFundPaymentComBaseString())
                .build();
        InsuranceArchivesBaseHistoryDTO otherAdjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(toCopyOtherInfo.getOtherSchemeId())
                .adjustAfterBaseJson(toCopyOtherInfo.getOtherPaymentBaseString())
                .adjustAfterComBaseJson(toCopyOtherInfo.getOtherPaymentComBaseString())
                .welfareType(toUpdateOtherInfo.getWelfareType())
                .employeeId(toUpdateOtherInfo.getEmployeeId())
                .paymentOrganization(toUpdateOtherInfo.getPaymentOrganization())
                .adjustBeforeSchemeId(toUpdateOtherInfo.getOtherSchemeId())
                .adjustBeforeBaseJson(toUpdateOtherInfo.getOtherPaymentBaseString())
                .adjustBeforeComBaseJson(toUpdateOtherInfo.getOtherPaymentComBaseString())
                .build();
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = new ArrayList<>();
        adjustHistoryList.addAll(createAdjustInfo(socialAdjustInfo, (long) user.getUID()));
        adjustHistoryList.addAll(createAdjustInfo(fundAdjustInfo, (long) user.getUID()));
        adjustHistoryList.addAll(createAdjustInfo(otherAdjustInfo, (long) user.getUID()));
        //更新字段
        toUpdateBaseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());

        toUpdateSocialInfo.setSocialAccount(toCopySocialInfo.getSocialAccount());
        toUpdateSocialInfo.setSocialSchemeId(toCopySocialInfo.getSocialSchemeId());
        toUpdateSocialInfo.setSocialPaymentBaseString(toCopySocialInfo.getSocialPaymentBaseString());
        toUpdateSocialInfo.setSocialPaymentComBaseString(toCopySocialInfo.getSocialPaymentComBaseString());
        toUpdateSocialInfo.setNonPayment(toCopySocialInfo.getNonPayment());
        toUpdateSocialInfo.setUnderTake(toCopySocialInfo.getUnderTake());
        toUpdateSocialInfo.setSocialStartTime(StringUtils.isNotBlank(payStartYearMonth) ? payStartYearMonth : toCopySocialInfo.getSocialStartTime());
        toUpdateSocialInfo.setUpdateTime(new Date());

        toUpdateFundInfo.setFundAccount(toCopyFundInfo.getFundAccount());
        toUpdateFundInfo.setSupplementFundAccount(toCopyFundInfo.getSupplementFundAccount());
        toUpdateFundInfo.setFundSchemeId(toCopyFundInfo.getFundSchemeId());
        toUpdateFundInfo.setFundPaymentBaseString(toCopyFundInfo.getFundPaymentBaseString());
        toUpdateFundInfo.setFundPaymentComBaseString(toCopyFundInfo.getFundPaymentComBaseString());
        toUpdateFundInfo.setNonPayment(toCopyFundInfo.getNonPayment());
        toUpdateFundInfo.setUnderTake(toCopyFundInfo.getUnderTake());
        toUpdateFundInfo.setFundStartTime(StringUtils.isNotBlank(payStartYearMonth) ? payStartYearMonth : toCopyFundInfo.getFundStartTime());
        toUpdateFundInfo.setUpdateTime(new Date());

        toUpdateOtherInfo.setOtherSchemeId(toCopyOtherInfo.getOtherSchemeId());
        toUpdateOtherInfo.setOtherPaymentBaseString(toCopyOtherInfo.getOtherPaymentBaseString());
        toUpdateOtherInfo.setOtherPaymentComBaseString(toCopyOtherInfo.getOtherPaymentComBaseString());
        toUpdateOtherInfo.setNonPayment(toCopyOtherInfo.getNonPayment());
        toUpdateOtherInfo.setUnderTake(toCopyOtherInfo.getUnderTake());
        toUpdateOtherInfo.setOtherStartTime(StringUtils.isNotBlank(payStartYearMonth) ? payStartYearMonth : toCopyOtherInfo.getOtherStartTime());
        toUpdateOtherInfo.setUpdateTime(new Date());
        //档案入库
        encryptUtil.encrypt(toUpdateSocialInfo, InsuranceArchivesSocialSchemePO.class);
        encryptUtil.encrypt(toUpdateFundInfo, InsuranceArchivesFundSchemePO.class);
        encryptUtil.encrypt(toUpdateOtherInfo, InsuranceArchivesOtherSchemePO.class);

        getInsuranceBaseInfoMapper().updateById(toUpdateBaseInfoPO);
        getSocialSchemeMapper().updateById(toUpdateSocialInfo);
        getFundSchemeMapper().updateById(toUpdateFundInfo);
        getOtherSchemeMapper().updateById(toUpdateOtherInfo);
        //基数调整记录入库
//        siArchivesBiz.batchInsertAdjustHistory(adjustHistoryList, (long) user.getUID());
        batchInsertAdjustHistory(adjustHistoryList);

        Map<String, Object> resultMap = new HashMap<>(2);
        String resultMsg = "操作成功";
        String resultType = "success";

        resultMap.put("type", resultType);
        resultMap.put("msg", resultMsg);
        return resultMap;
    }

    /*****以下代码为SIArchivesBiz中逻辑迁移，旨在减少Biz类的使用*****/
    /**
     * 判断是否需要生成历史福利档案基本信息
     */
    public Boolean createOldInsuranceBaseInfo(Long creator) {
        log.info("判断是否需要生成历史数据");
        List<InsuranceArchivesBaseInfoPO> nowBaseInfoList = getInsuranceBaseInfoMapper().getInsuranceBaseInfoList();
        if (nowBaseInfoList.size() == 0) {
            StopWatch sw = new StopWatch();
            log.info("福利档案基础信息表为空，开始生成历史数据：");
            //处理公积金、其他福利档案中个税扣缴义务人为空的情况
            sw.start("处理公积金、其他福利档案中个税扣缴义务人为空的情况");
            List<InsuranceArchivesSocialSchemePO> socialList = getSocialSchemeMapper().listAll();
            List<InsuranceArchivesFundSchemePO> fundList = getFundSchemeMapper().listAll();
            List<InsuranceArchivesOtherSchemePO> otherList = getOtherSchemeMapper().listAll();

            List<InsuranceArchivesFundSchemePO> updateFundList = new ArrayList<>();
            List<InsuranceArchivesOtherSchemePO> updateOtherList = new ArrayList<>();
            for (InsuranceArchivesSocialSchemePO socialSchemePO : socialList) {
                List<InsuranceArchivesFundSchemePO> toDealFundList = fundList.stream().filter(f -> f.getEmployeeId().equals(socialSchemePO.getEmployeeId()) && f.getPaymentOrganization() == null).collect(Collectors.toList());
                if (toDealFundList.size() > 0) {
                    InsuranceArchivesFundSchemePO toDealFundPO = toDealFundList.get(0);
                    toDealFundPO.setPaymentOrganization(socialSchemePO.getPaymentOrganization());
                    updateFundList.add(toDealFundPO);
                }

                List<InsuranceArchivesOtherSchemePO> toDealOtherList = otherList.stream().filter(f -> f.getEmployeeId().equals(socialSchemePO.getEmployeeId()) && f.getPaymentOrganization() == null).collect(Collectors.toList());
                if (toDealOtherList.size() > 0) {
                    InsuranceArchivesOtherSchemePO toDealOtherPO = toDealOtherList.get(0);
                    toDealOtherPO.setPaymentOrganization(socialSchemePO.getPaymentOrganization());
                    updateOtherList.add(toDealOtherPO);
                }

            }
            log.info("重置个税扣缴义务人id的公积金档案数：{}", updateFundList.size());
            log.info("重置个税扣缴义务人id的其他福利档案数：{}", updateOtherList.size());
            //更新公积金和其他福利档案
            updateFundList.forEach(getFundSchemeMapper()::updateById);
            updateOtherList.forEach(getOtherSchemeMapper()::updateById);
            sw.stop();

            sw.start("处理待入库的历史福利档案基础信息并入库");
            List<InsuranceArchivesBaseInfoPO> addBaseInfoList = new ArrayList<>();

            List<InsuranceArchivesBaseInfoPO> oldBaseInfoList = getInsuranceBaseInfoMapper().getInsuranceBaseInfoListByInsuranceDetail(null);
            log.info("获取待生成的历史福利档案基础信息条数：{}", oldBaseInfoList.size());
            //去重
            oldBaseInfoList = oldBaseInfoList.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getPaymentOrganization() + "-" + f.getEmployeeId()))), ArrayList::new));
            log.info("去重后的待生成历史福利档案基础信息条数：{}", oldBaseInfoList.size());
            if (oldBaseInfoList.size() > 0) {
                //设置基本信息表字段
                for (InsuranceArchivesBaseInfoPO po : oldBaseInfoList) {
                    po.setId(IdGenerator.generate());
                    po.setCreateTime(new Date());
                    po.setDeleteType(0);
                    po.setCreator(creator);
                    po.setRunStatus(EmployeeStatusEnum.STAY_ADD.getValue());
                    po.setUpdateTime(new Date());
                    po.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);

                    addBaseInfoList.add(po);
                }
                //将历史基本信息入库
                List<List<InsuranceArchivesBaseInfoPO>> partition = Lists.partition(addBaseInfoList, 50);
                partition.forEach(getInsuranceBaseInfoMapper()::batchSave);

                sw.stop();
                log.info("各操作计时 {}", sw.prettyPrint());
                return true;
            }else {
                return false;
            }
        } else {
            return false;
        }

    }
    @Override
    public List<Map<String, Object>> buildTableData(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {
        return buildTableData(insuranceArchivesEmployeePOS, false);
    }

    /**
     * @param insuranceArchivesEmployeePOS
     * @return
     */
    public List<Map<String, Object>> buildTableData(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS, boolean export) {
        boolean welBaseDiffSign = isDiffWelBase();

        List<TaxAgentPO> taxAgentPOS = getTaxAgentMapper().listAll();
        Map<Long, TaxAgentPO> longTaxAgentPOMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getId);


        List<Map<String, Object>> records = new ArrayList<>();

        Map<Long, InsuranceArchivesSocialSchemePO> socialSchemePOMap = encryptUtil.decryptList(this.getSocialByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS), InsuranceArchivesSocialSchemePO.class)
                .stream().collect(Collectors.toMap(InsuranceArchivesSocialSchemePO::getId, Function.identity()));

        Map<Long, InsuranceArchivesFundSchemePO> fundSchemePOMap = encryptUtil.decryptList(this.getFundByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS), InsuranceArchivesFundSchemePO.class)
                .stream().collect(Collectors.toMap(InsuranceArchivesFundSchemePO::getId, Function.identity()));
        List<InsuranceArchivesOtherSchemePO> otherByEmployeeList = this.getOtherByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS);
        encryptUtil.decryptList(otherByEmployeeList, InsuranceArchivesOtherSchemePO.class);
        Map<Long, InsuranceArchivesOtherSchemePO> otherSchemePOMap = otherByEmployeeList
                .stream().collect(Collectors.toMap(InsuranceArchivesOtherSchemePO::getId, Function.identity()));
        insuranceArchivesEmployeePOS.forEach(item -> {
            InsuranceArchivesSocialSchemePO socialItem = socialSchemePOMap.get(item.getSocialId());
            InsuranceArchivesFundSchemePO fundItem = fundSchemePOMap.get(item.getFundId());
            InsuranceArchivesOtherSchemePO otherItem = otherSchemePOMap.get(item.getOtherId());
            Map<String, Object> map = new HashMap<>();
            map.put("employeeName", item.getUserName());
            map.put("paymentOrganizationName", longTaxAgentPOMap.get(item.getPaymentOrganization()) != null ? longTaxAgentPOMap.get(item.getPaymentOrganization()).getName() : "");
            map.put("employeeId", item.getEmployeeId());
            map.put("departmentName", item.getDepartmentName());
            map.put("subcompanyName", item.getSubcompanyName());
            map.put("departmentId", item.getDepartmentId());
            map.put("jobNum", item.getJobNum());
            map.put("companystartdate", item.getCompanystartdate());
            map.put("dismissdate", item.getDimissionDate());
            map.put("mobile", item.getTelephone());
            map.put("siSchemeId", item.getSiSchemeId());
            map.put("fundSchemeId", item.getFundSchemeId());
            map.put("otherSchemeId", item.getOtherSchemeId());
            map.put("status", item.getUserStatus() != null ? UserStatusEnum.getDefaultLabelByValue(item.getUserStatus()) : "");
            map.put("baseInfo", item.getBaseInfoId());
            map.put("paymentOrganization", item.getPaymentOrganization());
            if (socialItem != null) {
                map.put("socialName", getInsuranceSchemeMapper().querySchemeName(socialItem.getSocialSchemeId()));
                Map<String, Object> socialJson = JSON.parseObject(socialItem.getSocialPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (welBaseDiffSign) {
                    if (socialJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(socialItem.getSocialSchemeId(), PaymentScopeEnum.SCOPE_PERSON.getValue());
                        socialJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "per", v);
                            }
                        });
                    }
                    Map<String, Object> socialComJson = JSON.parseObject(socialItem.getSocialPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (socialComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(socialItem.getSocialSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        socialComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "com", v);
                            }
                        });
                    }
                } else {
                    if (socialJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(socialItem.getSocialSchemeId());
                        socialJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k, v);
                            }
                        });
                    }
                }

                map.put("socialAccount", socialItem.getSocialAccount());
                map.put("socialStartTime", socialItem.getSocialStartTime());
                map.put("socialEndTime", socialItem.getSocialEndTime());
            }
            if (fundItem != null) {
                map.put("fundName", getInsuranceSchemeMapper().querySchemeName(fundItem.getFundSchemeId()));
                map.put("fundAccount", fundItem.getFundAccount());
                Map<String, Object> fundJson = JSON.parseObject(fundItem.getFundPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (welBaseDiffSign) {
                    if (fundJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(fundItem.getFundSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        fundJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "per", v);
                            }
                        });
                    }
                    Map<String, Object> fundComJson = JSON.parseObject(fundItem.getFundPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (fundComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(fundItem.getFundSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        fundComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "com", v);
                            }
                        });
                    }
                } else {
                    if (fundJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(fundItem.getFundSchemeId());
                        fundJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k, v);
                            }
                        });
                    }
                }

                map.put("supplementFundAccount", fundItem.getSupplementFundAccount());
                map.put("fundStartTime", fundItem.getFundStartTime());
                map.put("fundEndTime", fundItem.getFundEndTime());

            }
            if (otherItem != null) {
                map.put("otherName", getInsuranceSchemeMapper().querySchemeName(otherItem.getOtherSchemeId()));
                Map<String, Object> otherJson = JSON.parseObject(otherItem.getOtherPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (welBaseDiffSign) {
                    if (otherJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(otherItem.getOtherSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        otherJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "per", v);
                            }
                        });
                    }
                    Map<String, Object> otherComJson = JSON.parseObject(otherItem.getOtherPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (otherComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(otherItem.getOtherSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        otherComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k + "com", v);
                            }
                        });
                    }
                } else {
                    if (otherJson != null) {
                        //查询该福利方案下开启缴纳的福利项
                        List<Long> insuranceIdList = payInsuranceIds(otherItem.getOtherSchemeId());
                        otherJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                map.put(k, v);
                            }
                        });
                    }
                }

                map.put("otherStartTime", otherItem.getOtherStartTime());
                map.put("otherEndTime", otherItem.getOtherEndTime());
            }
            records.add(map);
        });
        return records;


    }

    @Override
    public boolean isDiffWelBase() {
        User user = (User) SalaryContext.get().getValue("user");
        //判断是否要区分个人和单位福利基数
        SalarySysConfPO welBaseDiff = getSalarySysConfService(user).getOneByCode(WEL_BASE_DIFF_BY_PER_AND_COM);

        return welBaseDiff != null && welBaseDiff.getConfValue().equals(OpenEnum.OPEN.getValue());
    }

    /**
     * 根据人员id和个税扣缴人id获取记录
     */
    public List<InsuranceArchivesSocialSchemePO> getSocialByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {

        List<InsuranceArchivesSocialSchemePO> allList = new ArrayList<>();
        for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
            List<InsuranceArchivesSocialSchemePO> socialList = getSocialSchemeMapper().getSocialByEmployeeIdAndPayOrg(po);
            if (socialList.size() > 0) {
                allList.add(socialList.get(0));
            }
        }
        return allList;
    }

    public List<InsuranceArchivesFundSchemePO> getFundByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {

        List<InsuranceArchivesFundSchemePO> allList = new ArrayList<>();
        for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
            List<InsuranceArchivesFundSchemePO> fundList = getFundSchemeMapper().getFundByEmployeeIdAndPayOrg(po);
            if (fundList.size() > 0) {
                allList.add(fundList.get(0));
            }
        }
        return allList;
    }

    public List<InsuranceArchivesOtherSchemePO> getOtherByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {

        List<InsuranceArchivesOtherSchemePO> allList = new ArrayList<>();
        for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
            List<InsuranceArchivesOtherSchemePO> otherList = getOtherSchemeMapper().getOtherByEmployeeIdAndPayOrg(po);
            if (otherList.size() > 0) {
                allList.add(otherList.get(0));
            }
        }
        return allList;
    }

    @Override
    public List<Long> payInsuranceIds(Long socialSchemeId, Integer paymentScope) {
        //查询该福利方案下开启缴纳的福利项
        List<InsuranceSchemeDetailPO> detailPOS = getInsuranceSchemeDetailMapper().queryListBySchemeId(socialSchemeId);
        List<Long> insuranceIdList = new ArrayList<>();
        if (detailPOS != null && detailPOS.size() > 0) {
            //开启缴纳的
            insuranceIdList = detailPOS.stream().filter(f -> f.getIsPayment().equals(IsPaymentEnum.YES.getValue()) && f.getPaymentScope().equals(paymentScope))
                    .map(InsuranceSchemeDetailPO::getInsuranceId).collect(Collectors.toList());
        }
        return insuranceIdList;
    }

    @Override
    public List<Long> payInsuranceIds(Long socialSchemeId) {
        //查询该福利方案下开启缴纳的福利项
        List<InsuranceSchemeDetailPO> detailPOS = getInsuranceSchemeDetailMapper().queryListBySchemeId(socialSchemeId);
        List<Long> insuranceIdList = new ArrayList<>();
        if (detailPOS != null && detailPOS.size() > 0) {
            //开启缴纳的
            insuranceIdList = detailPOS.stream().filter(f -> f.getIsPayment().equals(IsPaymentEnum.YES.getValue())).map(InsuranceSchemeDetailPO::getInsuranceId).collect(Collectors.toList());
        }
        return insuranceIdList;
    }

    @Override
    public List<WeaTableColumn> buildWeaTableColumns(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {

        Map<Integer, Map<String, String>> titleMap = buildColumnTitle(insuranceArchivesEmployeePOS);
        List<WeaTableColumn> list = new ArrayList<>();
        WeaTableColumn nameColumn = new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(0, "姓名"), "employeeName");
        nameColumn.setFixed("left");
        list.add(nameColumn);
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "个税扣缴义务人"), "paymentOrganizationName"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "分部"), "subcompanyName"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "部门"), "departmentName"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "手机号"), "mobile"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "员工状态"), "status"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "工号"), "jobNum"));

        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "入职日期"), "companystartdate"));
//        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "合同到期日期"), "dismissdate"));

        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "社保方案名称"), "socialName"));
        titleMap.get(WelfareTypeEnum.SOCIAL_SECURITY.getValue()).forEach((k, v) -> list.add(new WeaTableColumn("150px", v, k)));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "社保账号"), "socialAccount"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "社保起始缴纳月"), "socialStartTime"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "社保最后缴纳月"), "socialEndTime"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "公积金方案名称"), "fundName"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "公积金账号"), "fundAccount"));
        titleMap.get(WelfareTypeEnum.ACCUMULATION_FUND.getValue()).forEach((k, v) -> list.add(new WeaTableColumn("150px", v, k)));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "补充公积金账号"), "supplementFundAccount"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "公积金起始缴纳月"), "fundStartTime"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "公积金最后缴纳月"), "fundEndTime"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "其他福利方案名称"), "otherName"));
        titleMap.get(WelfareTypeEnum.OTHER.getValue()).forEach((k, v) -> list.add(new WeaTableColumn("150px", v, k)));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "其他福利起始缴纳月"), "otherStartTime"));
        list.add(new WeaTableColumn("150px", SalaryI18nUtil.getI18nLabel(0, "其他福利最后缴纳月"), "otherEndTime"));
        return list;
    }

    public Map<Integer, Map<String, String>> buildColumnTitle(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {

        boolean welBaseDiffSign = isDiffWelBase();

        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        Map<Integer, Map<String, String>> result = new HashMap<>();

        insuranceArchivesEmployeePOS = insuranceArchivesEmployeePOS.stream()
                .filter(f -> f.getEmployeeId() != null)
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InsuranceArchivesEmployeePO::getEmployeeId))), ArrayList::new));
        try {

            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);
            ICategoryMapper iCategoryMapper = sqlSession.getMapper(ICategoryMapper.class);

            Set<String> socialSet = new HashSet<>();
            Set<String> fundSet = new HashSet<>();
            Set<String> otherSet = new HashSet<>();

            Set<String> socialComSet = new HashSet<>();
            Set<String> fundComSet = new HashSet<>();
            Set<String> otherComSet = new HashSet<>();

            insuranceArchivesEmployeePOS.forEach(item -> {
                List<InsuranceArchivesSocialSchemePO> socialList = socialSchemeMapper.getSocialByEmployeeId(Collections.singletonList(item.getEmployeeId()));
                encryptUtil.decryptList(socialList, InsuranceArchivesSocialSchemePO.class);
                List<InsuranceArchivesFundSchemePO> fundList = fundSchemeMapper.getFundByEmployeeId(Collections.singletonList(item.getEmployeeId()));
                encryptUtil.decryptList(fundList, InsuranceArchivesFundSchemePO.class);
                List<InsuranceArchivesOtherSchemePO> otherList = otherSchemeMapper.getOtherByEmployeeId(Collections.singletonList(item.getEmployeeId()));
                encryptUtil.decryptList(otherList, InsuranceArchivesOtherSchemePO.class);
                if (socialList.size() > 0) {
                    for (InsuranceArchivesSocialSchemePO socialSchemePO : socialList) {

                        Map<String, Object> socialJson = JSON.parseObject(socialSchemePO.getSocialPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                        });
                        if (socialJson != null) {
                            socialJson.forEach((k, v) -> socialSet.add(k));
                        }
                        //如果需要区分个人和公司福利基数
                        if (welBaseDiffSign) {
                            Map<String, Object> socialComJson = JSON.parseObject(socialSchemePO.getSocialPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                            });
                            if (socialComJson != null) {
                                socialComJson.forEach((k, v) -> socialComSet.add(k));
                            }
                        }
                    }

                }
                if (fundList.size() > 0) {
                    for (InsuranceArchivesFundSchemePO fundSchemePO : fundList) {
                        Map<String, Object> fundJson = JSON.parseObject(fundSchemePO.getFundPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                        });
                        if (fundJson != null) {
                            fundJson.forEach((k, v) -> fundSet.add(k));
                        }
                        //如果需要区分个人和公司福利基数
                        if (welBaseDiffSign) {
                            Map<String, Object> fundComJson = JSON.parseObject(fundSchemePO.getFundPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                            });
                            if (fundComJson != null) {
                                fundComJson.forEach((k, v) -> fundComSet.add(k));
                            }
                        }
                    }

                }
                if (otherList.size() > 0) {
                    for (InsuranceArchivesOtherSchemePO otherSchemePO : otherList) {
                        Map<String, Object> otherJson = JSON.parseObject(otherSchemePO.getOtherPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                        });
                        if (otherJson != null) {
                            otherJson.forEach((k, v) -> otherSet.add(k));
                        }
                        //如果需要区分个人和公司福利基数
                        if (welBaseDiffSign) {
                            Map<String, Object> otherComJson = JSON.parseObject(otherSchemePO.getOtherPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                            });
                            if (otherComJson != null) {
                                otherComJson.forEach((k, v) -> otherComSet.add(k));
                            }
                        }
                    }

                }
            });
            Map<String, String> socialMap = new HashMap<>();
            Map<String, String> socialComMap = new HashMap<>();
            Map<Long, ICategoryPO> socialCollect = new HashMap<>();
            Map<Long, ICategoryPO> customSocial = iCategoryMapper.listByWelfareType(WelfareTypeEnum.SOCIAL_SECURITY.getValue(), null)
                    .stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));

            Map<Long, ICategoryPO> sysSocial = iCategoryMapper.listByWelfareType(WelfareTypeEnum.SOCIAL_SECURITY.getValue(), DataTypeEnum.SYSTEM.getValue())
                    .stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));

            socialCollect.putAll(customSocial);
            socialCollect.putAll(sysSocial);

            if (welBaseDiffSign) {
                socialSet.forEach(item -> {
                    if (socialCollect.containsKey(Long.valueOf(item))) {
                        socialMap.put(item + "per", socialCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"个人"));
                    }
                });
                socialComSet.forEach(item -> {
                    if (socialCollect.containsKey(Long.valueOf(item))) {
                        socialComMap.put(item + "com", socialCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"单位"));
                    }
                });
            } else {
                socialSet.forEach(item -> {
                    if (socialCollect.containsKey(Long.valueOf(item))) {
                        socialMap.put(item, socialCollect.get(Long.valueOf(item)).getInsuranceName() + SalaryI18nUtil.getI18nLabel(0, "申报基数"));
                    }
                });
            }
            Map<String, String> fundMap = new HashMap<>();
            Map<String, String> fundComMap = new HashMap<>();
            Map<Long, ICategoryPO> fundCollect = new HashMap<>();
            Map<Long, ICategoryPO> customFund = iCategoryMapper.listByWelfareType(WelfareTypeEnum.ACCUMULATION_FUND.getValue(), null).stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));
            Map<Long, ICategoryPO> sysFund = iCategoryMapper.listByWelfareType(WelfareTypeEnum.ACCUMULATION_FUND.getValue(), DataTypeEnum.SYSTEM.getValue()).stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));
            fundCollect.putAll(customFund);
            fundCollect.putAll(sysFund);
            if (welBaseDiffSign) {
                fundSet.forEach(item -> {
                    if (fundCollect.containsKey(Long.valueOf(item))) {
                        fundMap.put(item + "per", fundCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"个人"));
                    }
                });
                fundComSet.forEach(item -> {
                    if (fundCollect.containsKey(Long.valueOf(item))) {
                        fundComMap.put(item + "com", fundCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"单位"));
                    }
                });
            } else {
                fundSet.forEach(item -> {
                    if (fundCollect.containsKey(Long.valueOf(item))) {
                        fundMap.put(item, fundCollect.get(Long.valueOf(item)).getInsuranceName() + SalaryI18nUtil.getI18nLabel(0, "申报基数"));
                    }
                });
            }
            Map<String, String> otherMap = new HashMap<>();
            Map<String, String> otherComMap = new HashMap<>();
            Map<Long, ICategoryPO> otherCollect = new HashMap<>();
            Map<Long, ICategoryPO> customOther = iCategoryMapper.listByWelfareType(WelfareTypeEnum.OTHER.getValue(), null).stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));
            Map<Long, ICategoryPO> sysOther = iCategoryMapper.listByWelfareType(WelfareTypeEnum.OTHER.getValue(), DataTypeEnum.SYSTEM.getValue()).stream().collect(Collectors.toMap(ICategoryPO::getId, Function.identity()));
            otherCollect.putAll(customOther);
            otherCollect.putAll(sysOther);

            if (welBaseDiffSign) {
                otherSet.forEach(item -> {
                    if (otherCollect.containsKey(Long.valueOf(item))) {
                        otherMap.put(item + "per", otherCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"个人"));
                    }
                });
                otherComSet.forEach(item -> {
                    if (otherCollect.containsKey(Long.valueOf(item))) {
                        otherComMap.put(item + "com", otherCollect.get(Long.valueOf(item)).getInsuranceName()
                                + SalaryI18nUtil.getI18nLabel(0, "申报基数")
                                + SalaryI18nUtil.getI18nLabel(0,"单位"));
                    }
                });
            } else {
                otherSet.forEach(item -> {
                    if (otherCollect.containsKey(Long.valueOf(item))) {
                        otherMap.put(item, otherCollect.get(Long.valueOf(item)).getInsuranceName() + SalaryI18nUtil.getI18nLabel(0, "申报基数"));
                    }
                });
            }
            // map根据key排序
            LinkedHashMap<String, String> socialMapWithAscKey = socialMap.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                            LinkedHashMap::new));
            LinkedHashMap<String, String> fundMapWithAscKey = fundMap.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                            LinkedHashMap::new));
            LinkedHashMap<String, String> otherMapWithAscKey = otherMap.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                            LinkedHashMap::new));
            if (welBaseDiffSign) {
                LinkedHashMap<String, String> socialComMapWithAscKey = socialComMap.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                                LinkedHashMap::new));
                LinkedHashMap<String, String> fundComMapWithAscKey = fundComMap.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                                LinkedHashMap::new));
                LinkedHashMap<String, String> otherComMapWithAscKey = otherComMap.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                                LinkedHashMap::new));
                socialMapWithAscKey.putAll(socialComMapWithAscKey);
                fundMapWithAscKey.putAll(fundComMapWithAscKey);
                otherMapWithAscKey.putAll(otherComMapWithAscKey);
            }

            result.put(WelfareTypeEnum.SOCIAL_SECURITY.getValue(), socialMapWithAscKey);
            result.put(WelfareTypeEnum.ACCUMULATION_FUND.getValue(), fundMapWithAscKey);
            result.put(WelfareTypeEnum.OTHER.getValue(), otherMapWithAscKey);
            return result;
        } finally {
            sqlSession.close();
        }


    }

    /**
     * 获取福利档案基数调整记录
     *
     */
    public List<InsuranceArchivesBaseHistoryDTO> getAdjustHistoryList(Long paymentOrganization, Long employeeId) {

        if (paymentOrganization == null && employeeId == null) {
            return null;
        }
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            InsuranceBaseAdjustHistoryMapper mapper = sqlSession.getMapper(InsuranceBaseAdjustHistoryMapper.class);
            List<InsuranceArchivesBaseHistoryDTO> list = mapper.listByEmployeeIdAndPayOrg(paymentOrganization, employeeId);
            return list;
        } finally {
            sqlSession.close();
        }
    }

    /**
     * 获取福利档案基数调整记录
     *
     */
    public List<InsuranceArchivesBaseHistoryDTO> getBaseHistoryByEmployeeIdAndOperator(Long operator, Long employeeId) {

        List<InsuranceArchivesBaseHistoryDTO> empList = getInsuranceBaseAdjustHistoryMapper().listByEmployeeIdAndOperator(operator, employeeId);
        List<InsuranceArchivesBaseHistoryDTO> extEmpList = getInsuranceBaseAdjustHistoryMapper().listByExtEmpIdAndOperator(operator, employeeId);
        if (extEmpList != null) {
            empList.addAll(extEmpList);
            empList = empList.stream().filter(f -> org.apache.commons.lang.StringUtils.isNotBlank(f.getEmployeeName()))
                    .sorted(Comparator.comparing(InsuranceArchivesBaseHistoryDTO::getOperateTime).reversed()).collect(Collectors.toList());
        }
        return empList;
    }

    //生成基数调整记录（基数单元未变化则忽略）
    public List<InsuranceArchivesBaseHistoryPO> createAdjustInfo(InsuranceArchivesBaseHistoryDTO adjustInfo, Long creator) {
        Date now = new Date();
        boolean welBaseDiffSign = isDiffWelBase();

        List<InsuranceArchivesBaseHistoryPO> toCreateAdjustHistoryList = new ArrayList<>();
        //旧档案不存在基数信息，则直接遍历新的基数数据，生成调整记录；旧档案存在基数信息，则合并新旧基数数据，遍历合并后的技术数据中的key，生成调整记录。
        if(org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustAfterBaseJson()) && org.apache.commons.lang.StringUtils.isBlank(adjustInfo.getAdjustBeforeBaseJson())) {
            Map<String, Object> adjustAfterBaseMap = JSON.parseObject(adjustInfo.getAdjustAfterBaseJson(), new TypeReference<Map<String, Object>>() {
            });
            for (String key : adjustAfterBaseMap.keySet()) {
                InsuranceArchivesBaseHistoryPO adjustItem = new InsuranceArchivesBaseHistoryPO();
                BeanUtils.copyProperties(adjustInfo, adjustItem);
                adjustItem.setAdjustWelfareItemId(Long.valueOf(key));
                adjustItem.setAdjustAfterBaseValue((String) adjustAfterBaseMap.get(key));
                adjustItem.setOperateTime(now);
                adjustItem.setOperator(creator);
                adjustItem.setCreator(creator);
                adjustItem.setCreateTime(now);
                adjustItem.setUpdateTime(now);
                adjustItem.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                adjustItem.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);
                adjustItem.setId(IdGenerator.generate());
                adjustItem.setPaymentScope(welBaseDiffSign ? PaymentScopeEnum.SCOPE_PERSON.getValue().toString()  : PaymentScopeEnum.SCOPE_PERSON.getValue().toString() + "," + PaymentScopeEnum.SCOPE_COMPANY.getValue().toString());
                toCreateAdjustHistoryList.add(adjustItem);
            }
        } else if (org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustAfterBaseJson()) && org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustBeforeBaseJson())) {
            Map<String, Object> adjustAfterBaseMap = JSON.parseObject(adjustInfo.getAdjustAfterBaseJson(), new TypeReference<Map<String, Object>>() {
            });
            Map<String, Object> adjustBeforeBaseMap = JSON.parseObject(adjustInfo.getAdjustBeforeBaseJson(), new TypeReference<Map<String, Object>>() {
            });
            Map<String, Object> reDealMap = new HashMap<>();
            if (adjustAfterBaseMap != null) {
                reDealMap.putAll(adjustAfterBaseMap);
            }
            if (adjustBeforeBaseMap != null) {
                reDealMap.putAll(adjustBeforeBaseMap);
            }
            if (reDealMap.size() >0) {
                for (String key : reDealMap.keySet()) {
                    String beforeValue = (String) adjustBeforeBaseMap.get(key);
                    String afterValue = (String) adjustAfterBaseMap.get(key);
                    if (SalaryEntityUtil.empty2Zero(beforeValue).compareTo(SalaryEntityUtil.empty2Zero(afterValue)) == 0) {
                        continue;
                    }
                    InsuranceArchivesBaseHistoryPO adjustItem = new InsuranceArchivesBaseHistoryPO();
                    BeanUtils.copyProperties(adjustInfo, adjustItem);
                    adjustItem.setAdjustWelfareItemId(Long.valueOf(key));
                    adjustItem.setAdjustBeforeBaseValue(beforeValue);
                    adjustItem.setAdjustAfterBaseValue(afterValue);
                    adjustItem.setOperateTime(now);
                    adjustItem.setOperator(creator);
                    adjustItem.setCreator(creator);
                    adjustItem.setCreateTime(now);
                    adjustItem.setUpdateTime(now);
                    adjustItem.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                    adjustItem.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);
                    adjustItem.setId(IdGenerator.generate());
                    adjustItem.setPaymentScope(welBaseDiffSign ? PaymentScopeEnum.SCOPE_PERSON.getValue().toString()  : PaymentScopeEnum.SCOPE_PERSON.getValue().toString() + "," + PaymentScopeEnum.SCOPE_COMPANY.getValue().toString());

                    toCreateAdjustHistoryList.add(adjustItem);
                }
            }

        }
        //如果系统应用设置拆分了个人和公司福利基数，则对adjustBeforeComBaseJson，adjustAfterComBaseJson也进行处理
        if (welBaseDiffSign) {
            //旧档案不存在基数信息，则直接遍历新的基数数据，生成调整记录；旧档案存在基数信息，则合并新旧基数数据，遍历合并后的技术数据中的key，生成调整记录。
            if(org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustAfterComBaseJson()) && org.apache.commons.lang.StringUtils.isBlank(adjustInfo.getAdjustBeforeComBaseJson())) {
                Map<String, Object> adjustAfterComBaseMap = JSON.parseObject(adjustInfo.getAdjustAfterComBaseJson(), new TypeReference<Map<String, Object>>() {
                });
                for (String key : adjustAfterComBaseMap.keySet()) {
                    InsuranceArchivesBaseHistoryPO adjustItem = new InsuranceArchivesBaseHistoryPO();
                    BeanUtils.copyProperties(adjustInfo, adjustItem);
                    adjustItem.setAdjustWelfareItemId(Long.valueOf(key));
                    adjustItem.setAdjustAfterBaseValue((String) adjustAfterComBaseMap.get(key));
                    adjustItem.setOperateTime(now);
                    adjustItem.setOperator(creator);
                    adjustItem.setCreator(creator);
                    adjustItem.setCreateTime(now);
                    adjustItem.setUpdateTime(now);
                    adjustItem.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                    adjustItem.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);
                    adjustItem.setId(IdGenerator.generate());
                    adjustItem.setPaymentScope(PaymentScopeEnum.SCOPE_COMPANY.getValue().toString());
                    toCreateAdjustHistoryList.add(adjustItem);
                }
            } else if (org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustAfterComBaseJson()) && org.apache.commons.lang.StringUtils.isNotBlank(adjustInfo.getAdjustBeforeComBaseJson())) {
                Map<String, Object> adjustAfterComBaseMap = JSON.parseObject(adjustInfo.getAdjustAfterComBaseJson(), new TypeReference<Map<String, Object>>() {
                });
                Map<String, Object> adjustBeforeComBaseMap = JSON.parseObject(adjustInfo.getAdjustBeforeComBaseJson(), new TypeReference<Map<String, Object>>() {
                });
                Map<String, Object> reDealMap = new HashMap<>();
                if (adjustAfterComBaseMap != null) {
                    reDealMap.putAll(adjustAfterComBaseMap);
                }
                if (adjustBeforeComBaseMap != null) {
                    reDealMap.putAll(adjustBeforeComBaseMap);
                }
                if (reDealMap.size() >0) {
                    for (String key : reDealMap.keySet()) {
                        String beforeValue = (String) adjustBeforeComBaseMap.get(key);
                        String afterValue = (String) adjustAfterComBaseMap.get(key);
                        if (SalaryEntityUtil.empty2Zero(beforeValue).compareTo(SalaryEntityUtil.empty2Zero(afterValue)) == 0) {
                            continue;
                        }
                        InsuranceArchivesBaseHistoryPO adjustItem = new InsuranceArchivesBaseHistoryPO();
                        BeanUtils.copyProperties(adjustInfo, adjustItem);
                        adjustItem.setAdjustWelfareItemId(Long.valueOf(key));
                        adjustItem.setAdjustBeforeBaseValue(beforeValue);
                        adjustItem.setAdjustAfterBaseValue(afterValue);
                        adjustItem.setOperateTime(now);
                        adjustItem.setOperator(creator);
                        adjustItem.setCreator(creator);
                        adjustItem.setCreateTime(now);
                        adjustItem.setUpdateTime(now);
                        adjustItem.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue());
                        adjustItem.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);
                        adjustItem.setId(IdGenerator.generate());
                        adjustItem.setPaymentScope( PaymentScopeEnum.SCOPE_COMPANY.getValue().toString());

                        toCreateAdjustHistoryList.add(adjustItem);
                    }
                }

            }
        }
        return toCreateAdjustHistoryList;
    }

    /**
     * 新增福利档案基数调整记录
     *
     */
    @Override
    public void batchInsertAdjustHistory(List<InsuranceArchivesBaseHistoryPO> adjustHistoryList) {

        if (org.apache.commons.collections.CollectionUtils.isEmpty(adjustHistoryList)) {
            return;
        }
        List<List<InsuranceArchivesBaseHistoryPO>> partition = Lists.partition(adjustHistoryList, 100);
        partition.forEach(getInsuranceBaseAdjustHistoryMapper()::batchSave);
    }

    public Map<String, Object> getBaseForm(WelfareTypeEnum welfareType, Long employeeId, Long paymentOrganization, Collection<TaxAgentPO> taxAgentPOS) {
        Map<String, Object> data = new HashMap<>(16);
        SalaryAssert.notNull(employeeId, SalaryI18nUtil.getI18nLabel(0, "员工id不可为空"));
        List<DataCollectionEmployee> employeeByIds = getSalaryEmployeeService(user).getEmployeeByIdsAll(Collections.singletonList(employeeId));
        SalaryAssert.notEmpty(employeeByIds, SalaryI18nUtil.getI18nLabel(0, "员工信息不存在"));
        DataCollectionEmployee item = employeeByIds.get(0);

        if (welfareType == null) {
            //基础信息表单
            InsuranceArchivesBaseDTO insuranceArchivesBaseDTO = InsuranceArchivesBaseDTO.builder().department(item.getDepartmentName())
                    .hiredate(item.getCompanystartdate())
                    .position(item.getJobtitleName())
                    .username(item.getUsername())
                    .telephone(item.getMobile())
                    .dimissionDate(item.getDismissdate())
                    .build();

            data.put("data", insuranceArchivesBaseDTO);
            return data;
        }

//        List<InsuranceSchemePO> list = siSchemeBiz.listAll();
        List<InsuranceSchemePO> list = getSISchemeService(user).listAll();
        // 过滤可见性范围
        list = filterList(list, taxAgentPOS);
        List<SearchConditionItem> selectItems = new ArrayList<>();
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionOption> paymentOptions = paymentOrganizationOptions(taxAgentPOS);
        List<SearchConditionOption> underTakeOptions = Arrays.stream(UndertakerEnum.values())
                .map(e -> new SearchConditionOption(e.getValue().toString(), e.getDefaultLabel())).collect(Collectors.toList());
        //返回数据
        switch (welfareType) {
            case SOCIAL_SECURITY:
                InsuranceArchivesSocialSchemeDTO insuranceArchivesSocialSchemeDTO = buildSocialForm(employeeId, paymentOrganization);
                List<InsuranceSchemePO> socialList = list.stream().filter(e -> Objects.equals(e.getWelfareType(), WelfareTypeEnum.SOCIAL_SECURITY.getValue())).collect(Collectors.toList());
                List<SearchConditionOption> socialOptions = new ArrayList<>();
                socialList.forEach(social -> {
                    socialOptions.add(new SearchConditionOption(Util.null2String(social.getId()), social.getSchemeName()));
                });
                SearchConditionItem socialName = SalaryFormItemUtil.selectItem(user, socialOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "社保方案名称"), "socialSchemeId");
                SearchConditionItem organizationName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "社保缴纳组织"), "paymentOrganization");
                SearchConditionItem underTakeName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "社保个人实际承担方"), "underTake");

                selectItems.add(socialName);
                selectItems.add(organizationName);
                selectItems.add(underTakeName);

                addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "社保基础信息"), true, selectItems));
                data.put("data", insuranceArchivesSocialSchemeDTO);
                data.put("items", addGroups);
                break;
            case ACCUMULATION_FUND:
                InsuranceArchivesFundSchemeDTO insuranceArchivesFundSchemeDTO = buildFundForm(employeeId, paymentOrganization);
                List<InsuranceSchemePO> fundList = list.stream().filter(e -> Objects.equals(e.getWelfareType(), WelfareTypeEnum.ACCUMULATION_FUND.getValue())).collect(Collectors.toList());
                List<SearchConditionOption> fundOptions = new ArrayList<>();
                fundList.forEach(social -> {
                    fundOptions.add(new SearchConditionOption(Util.null2String(social.getId()), social.getSchemeName()));
                });
                SearchConditionItem fundName = SalaryFormItemUtil.selectItem(user, fundOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "公积金方案名称"), "fundSchemeId");
                SearchConditionItem organizationFundName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "公积金缴纳组织"), "paymentOrganization");
                SearchConditionItem underTakeFundName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "公积金个人实际承担方"), "underTake");

                selectItems.add(fundName);
                selectItems.add(organizationFundName);
                selectItems.add(underTakeFundName);
                addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "公积金基础信息"), true, selectItems));
                data.put("data", insuranceArchivesFundSchemeDTO);
                data.put("items", addGroups);
                break;
            case OTHER:
                InsuranceArchivesOtherSchemeDTO insuranceArchivesOtherSchemeDTO = buildOtherForm(employeeId, paymentOrganization);
                List<InsuranceSchemePO> otherList = list.stream().filter(e -> Objects.equals(e.getWelfareType(), WelfareTypeEnum.OTHER.getValue())).collect(Collectors.toList());
                List<SearchConditionOption> otherOptions = new ArrayList<>();
                otherList.forEach(social -> {
                    otherOptions.add(new SearchConditionOption(Util.null2String(social.getId()), social.getSchemeName()));
                });
                SearchConditionItem otherName = SalaryFormItemUtil.selectItem(user, otherOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "其他福利名称"), "otherSchemeId");
                SearchConditionItem organizationOtherName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "其他福利缴纳组织"), "paymentOrganization");
                SearchConditionItem underTakeOtherName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, SalaryI18nUtil.getI18nLabel(0, "其他福利个人实际承担方"), "underTake");

                selectItems.add(otherName);
                selectItems.add(organizationOtherName);
                selectItems.add(underTakeOtherName);
                addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "其他福利基础信息"), true, selectItems));
                data.put("data", insuranceArchivesOtherSchemeDTO);
                data.put("items", addGroups);
                break;
            default:
        }
        return data;
    }

    /***
     * @description 过滤没有权限访问的
     * @return List<InsuranceSchemePO>
     * @author Harryxzy
     * @date 2022/9/19 18:32
     */
    List<InsuranceSchemePO> filterList(List<InsuranceSchemePO> list, Collection<TaxAgentPO> taxAgentPOS){
        List<String> ids = taxAgentPOS.stream().map(i -> String.valueOf(i.getId())).collect(Collectors.toList());
        List<InsuranceSchemePO> result = list.stream().filter(item -> {
            boolean flag = true;
            if (item.getSharedType()!= null && item.getSharedType().equals("1")) {
                flag = false;
                String taxAgentIds = item.getTaxAgentIds();
                if(org.apache.commons.lang.StringUtils.isNotBlank(taxAgentIds)){
                    String splitFlag = ",";
                    String[] split = taxAgentIds.split(splitFlag);
                    for (int i = 0; i < split.length; i++) {
                        if (ids.contains(split[i])) {
                            flag = true;
                        }
                    }
                }
            }
            return flag;
        }).collect(Collectors.toList());
        return result;
    }

    /**
     * 社保缴纳组织
     *
     * @return
     */
    public List<SearchConditionOption> paymentOrganizationOptions(Collection<TaxAgentPO> taxAgentPOS) {
        Collection<TaxAgentPO> list = taxAgentPOS;
        if (org.apache.commons.collections.CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list
                .stream()
                .map(item -> new SearchConditionOption(String.valueOf(item.getId()), item.getName())).collect(Collectors.toList());
    }

    /**
     * 其它基础表单
     *
     * @param employeeId
     * @return
     */
    public InsuranceArchivesOtherSchemeDTO buildOtherForm(Long employeeId, Long paymentOrganization) {

        List<InsuranceArchivesOtherSchemePO> otherList = getOtherSchemeMapper().getOtherByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                .employeeId(employeeId)
                .paymentOrganization(paymentOrganization)
                .build());
        encryptUtil.decryptList(otherList, InsuranceArchivesOtherSchemePO.class);
        InsuranceArchivesOtherSchemePO insuranceArchivesOtherSchemePO = otherList.size() != 0 ? otherList.get(0) : null;
        InsuranceArchivesOtherSchemeDTO data = InsuranceArchivesBO.convertOtherPOtoDTO(insuranceArchivesOtherSchemePO, employeeId);
        if (insuranceArchivesOtherSchemePO == null) {
            data.setEmployeeId(employeeId);
            data.setUnderTake(UndertakerEnum.SCOPE_PERSON.getValue().toString());
        }
        return data;
    }

    /**
     * 公积金基础表单
     *
     * @param employeeId
     * @return
     */
    public InsuranceArchivesFundSchemeDTO buildFundForm(Long employeeId, Long paymentOrganization) {

        List<InsuranceArchivesFundSchemePO> fundList = getFundSchemeMapper().getFundByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                .employeeId(employeeId)
                .paymentOrganization(paymentOrganization)
                .build());
        encryptUtil.decryptList(fundList, InsuranceArchivesFundSchemePO.class);
        InsuranceArchivesFundSchemePO insuranceArchivesFundSchemePO = fundList.size() != 0 ? fundList.get(0) : null;
        InsuranceArchivesFundSchemeDTO data = InsuranceArchivesBO.convertFundPOtoDTO(insuranceArchivesFundSchemePO, employeeId);
        if (insuranceArchivesFundSchemePO == null) {
            data.setEmployeeId(employeeId);
            data.setUnderTake(UndertakerEnum.SCOPE_PERSON.getValue().toString());
        }
        return data;
    }

    /**
     * 社保基础表单
     *
     * @param employeeId
     * @return
     */
    public InsuranceArchivesSocialSchemeDTO buildSocialForm(Long employeeId, Long paymentOrganization) {
        InsuranceArchivesSocialSchemePO insuranceArchivesSocialSchemePO = getSocialByEmployeeId(employeeId, paymentOrganization);
        InsuranceArchivesSocialSchemeDTO data = InsuranceArchivesBO.convertSocialPOtoDTO(insuranceArchivesSocialSchemePO, employeeId);
        if (insuranceArchivesSocialSchemePO == null) {
            data.setEmployeeId(employeeId);
            data.setUnderTake(UndertakerEnum.SCOPE_PERSON.getValue().toString());
        }
        return data;
    }

    /**
     * 获取社保档案表
     *
     * @param employeeId
     * @return
     */
    public InsuranceArchivesSocialSchemePO getSocialByEmployeeId(Long employeeId, Long paymentOrganization) {

        List<InsuranceArchivesSocialSchemePO> socialList = getSocialSchemeMapper().getSocialByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                .employeeId(employeeId)
                .paymentOrganization(paymentOrganization)
                .build());
        encryptUtil.decryptList(socialList, InsuranceArchivesSocialSchemePO.class);
        return socialList.size() != 0 ? socialList.get(0) : null;
    }

    /**
     * 获取详细表单
     *
     * @param user
     * @param welfareType
     * @param employeeId
     * @param schemeId
     * @return
     */
    public Map<String, Object> getPaymentForm(User user, WelfareTypeEnum welfareType, Long employeeId, Long schemeId, Long paymentOrganization) {
        Map<String, Object> data = new HashMap<>(16);
        //判断是否要区分个人和单位福利基数
        SalarySysConfPO welBaseDiff = getSalarySysConfService(user).getOneByCode(WEL_BASE_DIFF_BY_PER_AND_COM);
        boolean welBaseDiffSign = welBaseDiff != null && welBaseDiff.getConfValue().equals(OpenEnum.OPEN.getValue());
        //判断是否要自动调整基数
        SalarySysConfPO welBaseAutoAdjust = getSalarySysConfService(user).getOneByCode(WEL_BASE_AUTO_ADJUST);
        boolean welBaseAutoAdjustSign = welBaseAutoAdjust != null && welBaseAutoAdjust.getConfValue().equals(OpenEnum.OPEN.getValue());

        switch (welfareType) {
            case SOCIAL_SECURITY:
                data = buildSocialPaymentForm(user, employeeId, schemeId,welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            case ACCUMULATION_FUND:
                data = buildFundPaymentForm(user, employeeId, schemeId, welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            case OTHER:
                data = buildOtherPaymentForm(user, employeeId, schemeId, welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            default:
        }
        return data;
    }

    /**
     * 其他payForm
     *
     * @param employeeId
     * @param schemeId
     * @return
     */
    public Map<String, Object> buildOtherPaymentForm(User user, Long employeeId, Long schemeId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {
        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesOtherSchemeDTO data = buildOtherForm(employeeId, paymentOrganization);
        Map<String, Object> insuranceValueMap = new HashMap<>();
        Map<String, Object> insuranceComValueMap = new HashMap<>();
        if (data != null) {
            insuranceValueMap = StrUtil.isNotBlank(data.getOtherPaymentBaseString())
                    ? JSONObject.parseObject(data.getOtherPaymentBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            if (welBaseDiffSign) {
                insuranceComValueMap = StrUtil.isNotBlank(data.getOtherPaymentComBaseString())
                        ? JSONObject.parseObject(data.getOtherPaymentComBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            }
        }
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionItem> inputItems = buildPaymentBase(user, schemeId, welfareType, welBaseDiffSign);
        //如果查询结果中存在 方案中缺失福利险种的值，设置初始值
        for (SearchConditionItem item : inputItems) {
            String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
            if (StrUtil.isNotBlank(insuranceId) && insuranceValueMap.get(insuranceId) == null) {
                String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                insuranceValueMap.put(insuranceId, basicValue);
            }
        }
        dataMap.put("data", insuranceValueMap);
        addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "其他福利缴纳基数"), true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "其他福利缴纳基数"), true, inputComItems));
            dataMap.put("comItems", addComGroups);

            for (SearchConditionItem item : inputComItems) {
                String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
                if (StrUtil.isNotBlank(insuranceId) && insuranceComValueMap.get(insuranceId) == null) {
                    String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                    insuranceComValueMap.put(insuranceId, basicValue);
                }
            }
            dataMap.put("comData", insuranceComValueMap);
        }
        return dataMap;
    }

    /**
     * 公积金payForm
     *
     * @param employeeId
     * @param schemeId
     * @return
     */
    public Map<String, Object> buildFundPaymentForm(User user, Long employeeId, Long schemeId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {

        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesFundSchemeDTO data = buildFundForm(employeeId, paymentOrganization);
        Map<String, Object> insuranceValueMap = new HashMap<>();
        Map<String, Object> insuranceComValueMap = new HashMap<>();
        if (data != null) {
            insuranceValueMap = StrUtil.isNotBlank(data.getFundPaymentBaseString())
                    ? JSONObject.parseObject(data.getFundPaymentBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            if (welBaseDiffSign) {
                insuranceComValueMap = StrUtil.isNotBlank(data.getFundPaymentComBaseString())
                        ? JSONObject.parseObject(data.getFundPaymentComBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            }
        }

        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionItem> inputItems = buildPaymentBase(user, schemeId, welfareType, welBaseDiffSign);
        //如果查询结果中存在 方案中缺失福利险种的值，设置初始值
        for (SearchConditionItem item : inputItems) {
            String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
            if (StrUtil.isNotBlank(insuranceId) && insuranceValueMap.get(insuranceId) == null) {
                String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                insuranceValueMap.put(insuranceId, basicValue);
            }
        }
        dataMap.put("data", insuranceValueMap);
        addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "公积金缴纳基数"), true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "公积金缴纳基数"), true, inputComItems));
            dataMap.put("comItems", addComGroups);

            for (SearchConditionItem item : inputComItems) {
                String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
                if (StrUtil.isNotBlank(insuranceId) && insuranceComValueMap.get(insuranceId) == null) {
                    String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                    insuranceComValueMap.put(insuranceId, basicValue);
                }
            }
            dataMap.put("comData", insuranceComValueMap);
        }
        return dataMap;
    }

    /**
     * 社保payForm
     *
     * @param employeeId
     * @param schemeId
     * @return
     */
    public Map<String, Object> buildSocialPaymentForm(User user, Long employeeId, Long schemeId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {
        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesSocialSchemeDTO data = buildSocialForm(employeeId, paymentOrganization);
        Map<String, Object> insuranceValueMap = new HashMap<>();
        Map<String, Object> insuranceComValueMap = new HashMap<>();
        if (data != null) {
            insuranceValueMap = StrUtil.isNotBlank(data.getSchemePaymentBaseString())
                    ? JSONObject.parseObject(data.getSchemePaymentBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            if (welBaseDiffSign) {
                insuranceComValueMap = StrUtil.isNotBlank(data.getSchemePaymentComBaseString())
                        ? JSONObject.parseObject(data.getSchemePaymentComBaseString(), new TypeReference<Map<String, Object>>() {}) : new HashMap<>();
            }
        }

        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionItem> inputItems = buildPaymentBase(user, schemeId, welfareType, welBaseDiffSign);
        //如果查询结果中存在 方案中缺失福利险种的值，设置初始值
        for (SearchConditionItem item : inputItems) {
            String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
            if (StrUtil.isNotBlank(insuranceId) && insuranceValueMap.get(insuranceId) == null) {
                String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                insuranceValueMap.put(insuranceId, basicValue);
            }
        }
        dataMap.put("data", insuranceValueMap);
        addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "社保缴纳基数"), true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0, "社保缴纳基数"), true, inputComItems));
            dataMap.put("comItems", addComGroups);

            for (SearchConditionItem item : inputComItems) {
                String insuranceId = item.getDomkey().length > 0 ? item.getDomkey()[0] : null;
                if (StrUtil.isNotBlank(insuranceId) && insuranceComValueMap.get(insuranceId) == null) {
                    String basicValue = welBaseAutoAdjustSign ? ("0.000".equals(item.getMin()) ? "0" : item.getMin()) : "0";
                    insuranceComValueMap.put(insuranceId, basicValue);
                }
            }
            dataMap.put("comData", insuranceComValueMap);
        }
        return dataMap;

    }

    /**
     * 构造payment(items)
     *
     * @param schemeId
     * @return
     */
    public List<SearchConditionItem> buildPaymentBase(User user, Long schemeId, Integer welfareType, boolean welBaseDiffSign) {
        List<SearchConditionItem> inputItems = new ArrayList<>();
        if (schemeId == null) {
            return new ArrayList<>();
        }
        List<InsuranceSchemeDetailPO> list = queryListByPrimaryIdIsPayment(schemeId, welfareType).stream()
                .filter(f -> f.getPaymentScope().equals(PaymentScopeEnum.SCOPE_PERSON.getValue())).collect(Collectors.toList());
        if (!welBaseDiffSign) {
            List<Long> perInsuranceIdList = list.stream().map(InsuranceSchemeDetailPO::getInsuranceId).collect(Collectors.toList());
            List<InsuranceSchemeDetailPO> moreComList = queryListByPrimaryIdIsPayment(schemeId, welfareType).stream()
                    .filter(f -> f.getPaymentScope().equals(PaymentScopeEnum.SCOPE_COMPANY.getValue()) && !perInsuranceIdList.contains(f.getInsuranceId())).collect(Collectors.toList());
            if (moreComList.size() > 0) {
                list.addAll(moreComList);
            }
        }

        list.forEach(insuranceSchemeDetail -> {
//            ICategoryPO iCategoryPO = siCategoryBiz.getByID(insuranceSchemeDetail.getInsuranceId());
            ICategoryPO iCategoryPO = getSICategoryService(user).getICategoryPOByID(insuranceSchemeDetail.getInsuranceId());
            if (iCategoryPO != null) {
//                inputItems.add(SalaryFormItemUtil.inputNumberItem(user, "precision:2", 2, 12, 2, iCategoryPO.getInsuranceName(), String.valueOf(insuranceSchemeDetail.getInsuranceId())));
                inputItems.add(SalaryFormItemUtil.inputNumberItemWithMaxAndMin(user, "precision:2", 2, 12, 2, iCategoryPO.getInsuranceName(), String.valueOf(insuranceSchemeDetail.getInsuranceId())
                        , insuranceSchemeDetail.getUpperLimit(), insuranceSchemeDetail.getLowerLimit()));
            }
        });
        return inputItems;
    }

    public List<SearchConditionItem> buildPaymentComBase(User user, Long schemeId, Integer welfareType) {
        List<SearchConditionItem> inputItems = new ArrayList<>();
        if (schemeId == null) {
            return new ArrayList<>();
        }
        List<InsuranceSchemeDetailPO> list = queryListByPrimaryIdIsPayment(schemeId, welfareType).stream()
                .filter(f -> f.getPaymentScope().equals(PaymentScopeEnum.SCOPE_COMPANY.getValue())).collect(Collectors.toList());
        list.forEach(insuranceSchemeDetail -> {
//            ICategoryPO iCategoryPO = siCategoryBiz.getByID(insuranceSchemeDetail.getInsuranceId());
            ICategoryPO iCategoryPO = getSICategoryService(user).getICategoryPOByID(insuranceSchemeDetail.getInsuranceId());
            if (iCategoryPO != null) {
//                inputItems.add(SalaryFormItemUtil.inputNumberItem(user, "precision:2", 2, 12, 2, iCategoryPO.getInsuranceName(), String.valueOf(insuranceSchemeDetail.getInsuranceId())));
                inputItems.add(SalaryFormItemUtil.inputNumberItemWithMaxAndMin(user, "precision:2", 2, 12, 2, iCategoryPO.getInsuranceName(), String.valueOf(insuranceSchemeDetail.getInsuranceId())
                        , insuranceSchemeDetail.getUpperLimit(), insuranceSchemeDetail.getLowerLimit()));
            }
        });
        return inputItems;
    }

    /**
     * 获取方案明细
     *
     * @param schemeId
     * @return
     */
    public List<InsuranceSchemeDetailPO> queryListByPrimaryIdIsPayment(Long schemeId, Integer welfareType) {

        List<InsuranceSchemeDetailPO> insuranceSchemeDetailPOS = getInsuranceSchemeDetailMapper().queryListByPrimaryIdIsPayment(schemeId, IsPaymentEnum.YES.getValue(), welfareType);
        encryptUtil.decryptList(insuranceSchemeDetailPOS, InsuranceSchemeDetailPO.class);
        return insuranceSchemeDetailPOS;
    }

    public void otherSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        InsuranceArchivesOtherSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesOtherSaveParam.class);
        SalaryAssert.notNull(SalaryI18nUtil.getI18nLabel(0, "员工id为空"), param, param.getEmployeeId());

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherStartTime()) && !SalaryDateUtil.checkYearMonth(param.getOtherStartTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "其他福利起始缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherEndTime()) && !SalaryDateUtil.checkYearMonth(param.getOtherEndTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "其他福利最后缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }
        //创建操作日志记录对象
        InsuranceArchivesBaseInfoPO targetPO = new InsuranceArchivesBaseInfoPO();
        InsuranceArchivesOtherSchemePO targetDetailPO = new InsuranceArchivesOtherSchemePO();

        List<Long> otherIds = new ArrayList();
        otherIds.add(param.getId());
        List<InsuranceArchivesOtherSchemePO> oldOtherInfoList = getOtherSchemeMapper().getOtherById(otherIds);
        //设置福利档案基数调整记录数据
        InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(param.getOtherSchemeId())
                .adjustAfterBaseJson(paramReq.getPaymentForm())
                .adjustAfterComBaseJson(paramReq.getPaymentComForm())
                .welfareType(paramReq.getWelfareType().getValue())
                .employeeId(param.getEmployeeId())
                .paymentOrganization(param.getPaymentOrganization())
                .build();

        if (oldOtherInfoList.size() == 1) {
            InsuranceArchivesOtherSchemePO oldOtherInfo = oldOtherInfoList.get(0);
            //设置福利档案基数调整记录数据
            encryptUtil.decrypt(oldOtherInfo, InsuranceArchivesOtherSchemePO.class);
            adjustInfo.setAdjustBeforeBaseJson(oldOtherInfo.getOtherPaymentBaseString());
            adjustInfo.setAdjustBeforeSchemeId(oldOtherInfo.getOtherSchemeId());
            adjustInfo.setAdjustBeforeComBaseJson(oldOtherInfo.getOtherPaymentComBaseString());
            //新数据
            InsuranceArchivesOtherSchemePO updateOtherInfo =
                    InsuranceArchivesOtherSchemePO.builder()
                            .id(oldOtherInfo.getId())
                            .otherSchemeId(param.getOtherSchemeId())
                            .otherStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherStartTime()) ? param.getOtherStartTime() : null)
                            .underTake(param.getUnderTake())
                            .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                            .welfareType(paramReq.getWelfareType().getValue())
                            .otherEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherEndTime()) ? param.getOtherEndTime() : null)
                            .employeeId(param.getEmployeeId())
                            .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                            .createTime(oldOtherInfo.getCreateTime())
                            .updateTime(new Date())
                            .nonPayment(param.getNonPayment())
                            .creator(employeeId)
                            .paymentOrganization(param.getPaymentOrganization())
                            .otherPaymentBaseString(paramReq.getPaymentForm())
                            .build();
            //校验福利基数是否符合上下限要求，
            if (!checkWelBaseLimit(updateOtherInfo.getOtherSchemeId(),updateOtherInfo.getOtherPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                updateOtherInfo.setOtherPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(updateOtherInfo.getOtherSchemeId(),updateOtherInfo.getOtherPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(updateOtherInfo, InsuranceArchivesOtherSchemePO.class);
            getOtherSchemeMapper().updateById(updateOtherInfo);
            //更新base_info表状态
            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null && baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                //对于非系统人员，编辑后状态切换为正在缴纳
                baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
            }
            baseInfoPO.setOtherArchivesId(updateOtherInfo.getId());
            getInsuranceBaseInfoMapper().updateById(baseInfoPO);

            targetPO = baseInfoPO;
            encryptUtil.decrypt(updateOtherInfo, InsuranceArchivesOtherSchemePO.class);
            targetDetailPO = updateOtherInfo;
        } else {
            getOtherSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesOtherSchemePO.builder()
                    .employeeId(param.getEmployeeId())
                    .paymentOrganization(param.getPaymentOrganization())
                    .build());
            //新建社保档案，并关联主表
            InsuranceArchivesOtherSchemePO insertOtherInfo = InsuranceArchivesOtherSchemePO.builder()
                    .otherSchemeId(param.getOtherSchemeId())
                    .otherStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherStartTime()) ? param.getOtherStartTime() : null)
                    .underTake(param.getUnderTake())
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .welfareType(paramReq.getWelfareType().getValue())
                    .otherEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getOtherEndTime()) ? param.getOtherEndTime() : null)
                    .employeeId(param.getEmployeeId())
                    .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .nonPayment(param.getNonPayment())
                    .creator(employeeId)
                    .paymentOrganization(param.getPaymentOrganization())
                    .otherPaymentBaseString(paramReq.getPaymentForm())
                    .build();
            //校验福利基数是否符合上下限要求，
            if (!checkWelBaseLimit(insertOtherInfo.getOtherSchemeId(),insertOtherInfo.getOtherPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                insertOtherInfo.setOtherPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(insertOtherInfo.getOtherSchemeId(),insertOtherInfo.getOtherPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(insertOtherInfo, InsuranceArchivesOtherSchemePO.class);
            getOtherSchemeMapper().insert(insertOtherInfo);

            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null) {
                List<InsuranceArchivesOtherSchemePO> otherInfos = getOtherSchemeMapper().getOtherByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .employeeId(param.getEmployeeId())
                        .paymentOrganization(param.getPaymentOrganization())
                        .build());
                baseInfoPO.setOtherArchivesId(otherInfos.get(0).getId());
                //对于非系统人员，编辑后状态切换为正在缴纳
                if (baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                    baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
                }
                getInsuranceBaseInfoMapper().updateById(baseInfoPO);

                targetPO = baseInfoPO;
                encryptUtil.decrypt(insertOtherInfo, InsuranceArchivesOtherSchemePO.class);
                targetDetailPO = insertOtherInfo;
            } else {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
            }
        }
        //记录操作日志
        DataCollectionEmployee empInfo = getSalaryEmployeeService(user).getEmployeeById(targetDetailPO.getEmployeeId());
        TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
        LoggerContext<InsuranceArchivesOtherSchemePO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(String.valueOf(targetPO.getId()));
        loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "福利档案-其他福利明细保存"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "福利档案-其他福利明细保存") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
        if (oldOtherInfoList.size() == 1) {
            loggerContext.setOldValues(oldOtherInfoList.get(0));
        }
        loggerContext.setNewValues(targetDetailPO);
        SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
        //生成福利档案基数调整记录数据
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
        //福利档案基数调整记录数据入库
        batchInsertAdjustHistory(adjustHistoryList);

    }

    /**
     * @param paramReq
     * @param
     */
    public void fundSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        InsuranceArchivesFundSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesFundSaveParam.class);
        SalaryAssert.notNull(SalaryI18nUtil.getI18nLabel(0,"员工id为空"), param, param.getEmployeeId());

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getFundStartTime()) && !SalaryDateUtil.checkYearMonth(param.getFundStartTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "公积金起始缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getFundEndTime()) && !SalaryDateUtil.checkYearMonth(param.getFundEndTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "公积金最后缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }
        //创建操作日志记录对象
        InsuranceArchivesBaseInfoPO targetPO = new InsuranceArchivesBaseInfoPO();
        InsuranceArchivesFundSchemePO targetDetailPO = new InsuranceArchivesFundSchemePO();

        List<Long> fundIds = new ArrayList();
        fundIds.add(param.getId());
        List<InsuranceArchivesFundSchemePO> oldFundInfoList = getFundSchemeMapper().getFundById(fundIds);
        //设置福利档案基数调整记录数据
        InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(param.getFundSchemeId())
                .adjustAfterBaseJson(paramReq.getPaymentForm())
                .adjustAfterComBaseJson(paramReq.getPaymentComForm())
                .welfareType(paramReq.getWelfareType().getValue())
                .employeeId(param.getEmployeeId())
                .paymentOrganization(param.getPaymentOrganization())
                .build();

        if (oldFundInfoList.size() == 1) {
            InsuranceArchivesFundSchemePO oldFundInfo = oldFundInfoList.get(0);
            //设置福利档案基数调整记录数据
            encryptUtil.decrypt(oldFundInfo, InsuranceArchivesFundSchemePO.class);
            adjustInfo.setAdjustBeforeBaseJson(oldFundInfo.getFundPaymentBaseString());
            adjustInfo.setAdjustBeforeSchemeId(oldFundInfo.getFundSchemeId());
            adjustInfo.setAdjustBeforeComBaseJson(oldFundInfo.getFundPaymentComBaseString());
            //新数据
            InsuranceArchivesFundSchemePO updateFundInfo = InsuranceArchivesFundSchemePO.builder()
                    .id(oldFundInfo.getId())
                    .fundSchemeId(param.getFundSchemeId())
                    .fundAccount(param.getFundAccount())
                    .fundEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getFundEndTime()) ? param.getFundEndTime() : null)
                    .fundStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getFundStartTime()) ? param.getFundStartTime() : null)
                    .fundPaymentBaseString(paramReq.getPaymentForm())
                    .supplementFundAccount(param.getSupplementFundAccount())
                    .creator(employeeId)
                    .nonPayment(param.getNonPayment())
                    .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .underTake(param.getUnderTake())
                    .paymentOrganization(param.getPaymentOrganization())
                    .createTime(oldFundInfo.getCreateTime())
                    .updateTime(new Date())
                    .welfareType(paramReq.getWelfareType().getValue())
                    .employeeId(param.getEmployeeId())
                    .build();
            //校验福利基数是否符合上下限要求，
            if (!checkWelBaseLimit(updateFundInfo.getFundSchemeId(),updateFundInfo.getFundPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                updateFundInfo.setFundPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(updateFundInfo.getFundSchemeId(),updateFundInfo.getFundPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(updateFundInfo, InsuranceArchivesFundSchemePO.class);
            getFundSchemeMapper().updateById(updateFundInfo);
            //更新base_info表状态
            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null && baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                //对于非系统人员，编辑后状态切换为正在缴纳
                baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
            }
            baseInfoPO.setFundArchivesId(updateFundInfo.getId());
            getInsuranceBaseInfoMapper().updateById(baseInfoPO);

            targetPO = baseInfoPO;
            encryptUtil.decrypt(updateFundInfo, InsuranceArchivesFundSchemePO.class);
            targetDetailPO = updateFundInfo;
        } else {
            getFundSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesFundSchemePO.builder()
                    .employeeId(param.getEmployeeId())
                    .paymentOrganization(param.getPaymentOrganization())
                    .build());
            //新建社保档案，并关联主表
            InsuranceArchivesFundSchemePO insertFundInfo = InsuranceArchivesFundSchemePO.builder()
                    .fundSchemeId(param.getFundSchemeId())
                    .fundAccount(param.getFundAccount())
                    .fundEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getFundEndTime()) ? param.getFundEndTime() : null)
                    .fundStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getFundStartTime()) ? param.getFundStartTime() : null)
                    .fundPaymentBaseString(paramReq.getPaymentForm())
                    .supplementFundAccount(param.getSupplementFundAccount())
                    .creator(employeeId)
                    .nonPayment(param.getNonPayment())
                    .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .underTake(param.getUnderTake())
                    .paymentOrganization(param.getPaymentOrganization())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .welfareType(paramReq.getWelfareType().getValue())
                    .employeeId(param.getEmployeeId())
                    .build();
            //校验福利基数是否符合上下限要求，
            if (!checkWelBaseLimit(insertFundInfo.getFundSchemeId(),insertFundInfo.getFundPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                insertFundInfo.setFundPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(insertFundInfo.getFundSchemeId(),insertFundInfo.getFundPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(insertFundInfo, InsuranceArchivesFundSchemePO.class);
            getFundSchemeMapper().insert(insertFundInfo);

            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null) {
                List<InsuranceArchivesFundSchemePO> fundInfos = getFundSchemeMapper().getFundByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .employeeId(param.getEmployeeId())
                        .paymentOrganization(param.getPaymentOrganization())
                        .build());
                baseInfoPO.setFundArchivesId(fundInfos.get(0).getId());
                //对于非系统人员，编辑后状态切换为正在缴纳
                if (baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                    baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
                }
                getInsuranceBaseInfoMapper().updateById(baseInfoPO);

                targetPO = baseInfoPO;
                encryptUtil.decrypt(insertFundInfo, InsuranceArchivesFundSchemePO.class);
                targetDetailPO = insertFundInfo;
            } else {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
            }
        }
        //记录操作日志
        DataCollectionEmployee empInfo = getSalaryEmployeeService(user).getEmployeeById(targetPO.getEmployeeId());
        TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
        LoggerContext<InsuranceArchivesFundSchemePO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(String.valueOf(targetPO.getId()));
        loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "福利档案-公积金明细保存"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "福利档案-公积金明细保存") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
        if (oldFundInfoList.size() == 1) {
            loggerContext.setOldValues(oldFundInfoList.get(0));
        }
        loggerContext.setNewValues(targetDetailPO);
        SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
        //生成福利档案基数调整记录数据
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
        //福利档案基数调整记录数据入库
        batchInsertAdjustHistory(adjustHistoryList);
    }

    /**
     * @param paramReq
     * @param
     */
    public void socialSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        InsuranceArchivesSocialSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesSocialSaveParam.class);
        SalaryAssert.notNull(SalaryI18nUtil.getI18nLabel(0,"员工id为空"), param, param.getEmployeeId());

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialStartTime()) && !SalaryDateUtil.checkYearMonth(param.getSocialStartTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "社保起始缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialEndTime()) && !SalaryDateUtil.checkYearMonth(param.getSocialEndTime())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "社保最后缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
        }

//            //删除社保数据
//            socialSchemeMapper.batchDeleteByEmployeeIds(Collections.singletonList(param.getEmployeeId()));

        //创建操作日志记录对象
        InsuranceArchivesBaseInfoPO targetPO = new InsuranceArchivesBaseInfoPO();
        InsuranceArchivesSocialSchemePO targetDetailPO = new InsuranceArchivesSocialSchemePO();
        //查询已有数据
        List<Long> socialIds = new ArrayList();
        socialIds.add(param.getId());
        List<InsuranceArchivesSocialSchemePO> oldSocialInfoList = getSocialSchemeMapper().getSocialById(socialIds);
        //设置福利档案基数调整记录数据
        InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                .adjustAfterSchemeId(param.getSocialSchemeId())
                .adjustAfterBaseJson(paramReq.getPaymentForm())
                .adjustAfterComBaseJson(paramReq.getPaymentComForm())
                .welfareType(paramReq.getWelfareType().getValue())
                .employeeId(param.getEmployeeId())
                .paymentOrganization(param.getPaymentOrganization())
                .build();
        //组装新数据
        if (oldSocialInfoList.size() == 1) {
            //老数据
            InsuranceArchivesSocialSchemePO oldSocialInfo = oldSocialInfoList.get(0);
            //设置福利档案基数调整记录数据
            encryptUtil.decrypt(oldSocialInfo, InsuranceArchivesSocialSchemePO.class);
            adjustInfo.setAdjustBeforeBaseJson(oldSocialInfo.getSocialPaymentBaseString());
            adjustInfo.setAdjustBeforeSchemeId(oldSocialInfo.getSocialSchemeId());
            adjustInfo.setAdjustBeforeComBaseJson(oldSocialInfo.getSocialPaymentComBaseString());
            //新数据
            InsuranceArchivesSocialSchemePO updateSocialInfo =
                    InsuranceArchivesSocialSchemePO.builder()
                            .id(oldSocialInfo.getId())
                            .welfareType(paramReq.getWelfareType().getValue())
                            .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                            .socialPaymentBaseString(paramReq.getPaymentForm())
                            .socialSchemeId(param.getSocialSchemeId())
                            .socialEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialEndTime()) ? param.getSocialEndTime() : null)
                            .socialStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialStartTime()) ? param.getSocialStartTime() : null)
                            .creator(employeeId)
                            .nonPayment(param.getNonPayment())
                            .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                            .employeeId(param.getEmployeeId())
                            .createTime(oldSocialInfo.getCreateTime())
                            .updateTime(new Date())
                            .underTake(param.getUnderTake())
                            .socialAccount(param.getSchemeAccount())
                            .paymentOrganization(param.getPaymentOrganization())
                            .build();
            //校验福利基数是否符合上下限要求
            if (!checkWelBaseLimit(updateSocialInfo.getSocialSchemeId(),updateSocialInfo.getSocialPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                updateSocialInfo.setSocialPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(updateSocialInfo.getSocialSchemeId(),updateSocialInfo.getSocialPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(updateSocialInfo, InsuranceArchivesSocialSchemePO.class);
            getSocialSchemeMapper().updateById(updateSocialInfo);
            //更新base_info表状态
            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null && baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                //对于非系统人员，编辑后状态切换为正在缴纳
                baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
            }
            baseInfoPO.setSocialArchivesId(updateSocialInfo.getId());
            getInsuranceBaseInfoMapper().updateById(baseInfoPO);

            targetPO = baseInfoPO;
            encryptUtil.decrypt(updateSocialInfo, InsuranceArchivesSocialSchemePO.class);
            targetDetailPO = updateSocialInfo;
        } else {
            getSocialSchemeMapper().deleteByEmployeeIdAndPayOrg(InsuranceArchivesSocialSchemePO.builder()
                    .employeeId(param.getEmployeeId())
                    .paymentOrganization(param.getPaymentOrganization())
                    .build());
            //新建社保档案，并关联主表
            InsuranceArchivesSocialSchemePO insertSocialInfo =
                    InsuranceArchivesSocialSchemePO.builder()
                            .welfareType(paramReq.getWelfareType().getValue())
                            .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                            .socialPaymentBaseString(paramReq.getPaymentForm())
                            .socialSchemeId(param.getSocialSchemeId())
                            .socialEndTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialEndTime()) ? param.getSocialEndTime() : null)
                            .socialStartTime(org.apache.commons.lang.StringUtils.isNotBlank(param.getSocialStartTime()) ? param.getSocialStartTime() : null)
                            .creator(employeeId)
                            .nonPayment(param.getNonPayment())
                            .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                            .employeeId(param.getEmployeeId())
                            .createTime(new Date())
                            .updateTime(new Date())
                            .underTake(param.getUnderTake())
                            .socialAccount(param.getSchemeAccount())
                            .paymentOrganization(param.getPaymentOrganization())
                            .build();
            //校验福利基数是否符合上下限要求
            if (!checkWelBaseLimit(insertSocialInfo.getSocialSchemeId(),insertSocialInfo.getSocialPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
            }
            //需要拆分个人和公司福利基数时
            if (welBaseDiffSign) {
                insertSocialInfo.setSocialPaymentComBaseString(paramReq.getPaymentComForm());
                //校验福利基数是否符合上下限要求
                if (!checkWelBaseLimit(insertSocialInfo.getSocialSchemeId(),insertSocialInfo.getSocialPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！"));
                }
            }
            encryptUtil.encrypt(insertSocialInfo, InsuranceArchivesSocialSchemePO.class);
            getSocialSchemeMapper().insert(insertSocialInfo);

            InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
            if(baseInfoPO != null) {
                List<InsuranceArchivesSocialSchemePO> socialInfos = getSocialSchemeMapper().getSocialByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .employeeId(param.getEmployeeId())
                        .paymentOrganization(param.getPaymentOrganization())
                        .build());
                baseInfoPO.setSocialArchivesId(socialInfos.get(0).getId());
                //对于非系统人员，编辑后状态切换为正在缴纳
                if (baseInfoPO.getEmployeeType() != null && baseInfoPO.getEmployeeType().equals(DataCollectionEmployeeTypeEnum.EXT_EMPLOYEE.getValue())) {
                    baseInfoPO.setRunStatus(EmployeeStatusEnum.PAYING.getValue());
                }
                getInsuranceBaseInfoMapper().updateById(baseInfoPO);

                targetPO = baseInfoPO;
                encryptUtil.decrypt(insertSocialInfo, InsuranceArchivesSocialSchemePO.class);
                targetDetailPO = insertSocialInfo;
            } else {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
            }
        }
        //记录操作日志
        DataCollectionEmployee empInfo = getSalaryEmployeeService(user).getEmployeeById(targetPO.getEmployeeId());
        TaxAgentPO taxAgentInfo = getTaxAgentMapper().getById(targetPO.getPaymentOrganization());
        LoggerContext<InsuranceArchivesSocialSchemePO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(String.valueOf(targetPO.getId()));
        loggerContext.setTargetName(taxAgentInfo.getName() + "-" + empInfo.getUsername());
        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "福利档案-社保明细保存"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "福利档案-社保明细保存") + ": " + taxAgentInfo.getName() + "-" + empInfo.getUsername());
        if (oldSocialInfoList.size() == 1) {
            loggerContext.setOldValues(oldSocialInfoList.get(0));
        }
        loggerContext.setNewValues(targetDetailPO);
        SalaryElogConfig.siArchivesLoggerTemplate.write(loggerContext);
        //生成福利档案基数调整记录数据
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
        //福利档案基数调整记录数据入库
        batchInsertAdjustHistory(adjustHistoryList);
    }

    /**
     * 校验福利基数是否符合上下限要求
     * @param primaryId
     * @param paymentBaseString
     * @return
     */
    @Override
    public Boolean checkWelBaseLimit(Long primaryId, String paymentBaseString, Integer paymentScope) {

        if (primaryId ==null || paymentBaseString == null) {
            return true;
        }
        Map<String, String> paymentBaseJson = JSON.parseObject(paymentBaseString, new HashMap<String, String>().getClass());
        if (paymentBaseJson == null) {
            return true;
        }

        for (Map.Entry<String, String> entry : paymentBaseJson.entrySet()) {

            //判断福利值是否为空/数字
            if (entry.getValue() == null || entry.getValue().length() == 0) {
                continue;
            } else if (!isNumeric(entry.getValue())) {
                log.info("福利值非数字！");
                return false;
            }

            //根据福利方案id、险种id、缴纳对象、缴费状态查询明细
            List<InsuranceSchemeDetailPO> insuranceSchemeDetailPOList = getInsuranceSchemeDetailMapper().getByPI(primaryId, Long.valueOf(entry.getKey()));
            log.info("福利方案id: {},, 福利明细项id：{}", primaryId, Long.valueOf(entry.getKey()));
            if (insuranceSchemeDetailPOList.size() == 0) {
                log.info("根据福利方案id、险种id、缴纳对象查询明细为null！福利方案id: {}, 福利明细项id：{}", primaryId, Long.valueOf(entry.getKey()));
                return false;
            }
            List<InsuranceSchemeDetailPO> isPaymentList = insuranceSchemeDetailPOList.stream()
                    .filter(f -> f.getIsPayment().equals(IsPaymentEnum.YES.getValue()) && f.getPaymentScope().equals(paymentScope)).collect(Collectors.toList());
            if (isPaymentList.size() > 0) {
                InsuranceSchemeDetailPO insuranceSchemeDetailPO = isPaymentList.get(0);

                encryptUtil.decrypt(insuranceSchemeDetailPO, InsuranceSchemeDetailPO.class);
                String lowerLimit = "0.000".equals(insuranceSchemeDetailPO.getLowerLimit()) ? null : insuranceSchemeDetailPO.getLowerLimit();
                String upperLimit = "0.000".equals(insuranceSchemeDetailPO.getUpperLimit()) ? null : insuranceSchemeDetailPO.getUpperLimit();
                if (lowerLimit != null && lowerLimit.length() > 0 && Double.parseDouble(entry.getValue()) < Double.parseDouble(lowerLimit)) {
                    //数值低于对应福利明细下限
                    log.info("社保基数 {} 数值 {} 低于对应福利明细下限 {}！", entry.getKey(), entry.getValue(), lowerLimit);
                    return false;
                }
                if (upperLimit != null && upperLimit.length() > 0 && Double.parseDouble(entry.getValue()) > Double.parseDouble(upperLimit)) {
                    //数值高于对应福利明细上限
                    log.info("社保基数 {} 数值 {} 高于对应福利明细上限 {} ！", entry.getKey(), entry.getValue(), upperLimit);
                    return false;
                }
            } else {
                log.info("福利明细项属于未缴费状态，不对上下限进行约束");
            }


        }
        return true;
    }


    /**
     * 校验福利基数是否符合上下限要求，并返回符合要求的数据
     * @param primaryId
     * @param paymentBaseString
     * @return
     */
    @Override
    public String checkAndBuildWelBaseWithLimit(Long primaryId, String paymentBaseString, Integer paymentScope) {

        if (primaryId ==null || paymentBaseString == null) {
            return paymentBaseString;
        }
        Map<String, String> paymentBaseJson = JSON.parseObject(paymentBaseString, HashMap.class);
        Map<String, String> newPaymentBaseJson = JSON.parseObject(paymentBaseString, HashMap.class);
        if (paymentBaseJson == null) {
            return null;
        }

        for (Map.Entry<String, String> entry : paymentBaseJson.entrySet()) {
            //判断福利值是否为空/数字
            if (entry.getValue() == null || entry.getValue().length() == 0) {
                continue;
            } else if (!isNumeric(entry.getValue())) {
                log.info("福利值非数字！");
                newPaymentBaseJson.remove(entry.getKey());
                continue;
            }
            //根据福利方案id、险种id
            List<InsuranceSchemeDetailPO> insuranceSchemeDetailPOList = getInsuranceSchemeDetailMapper().getByPI(primaryId, Long.valueOf(entry.getKey()));
            log.info("福利方案id: {},, 福利明细项id：{}", primaryId, Long.valueOf(entry.getKey()));
            if (insuranceSchemeDetailPOList.size() == 0) {
                log.info("根据福利方案id、险种id、缴纳对象查询明细为null！福利方案id: {}, 福利明细项id：{}", primaryId, Long.valueOf(entry.getKey()));
                newPaymentBaseJson.remove(entry.getKey());
                continue;
            }
            List<InsuranceSchemeDetailPO> checkList = insuranceSchemeDetailPOList.stream()
                    .filter(f -> f.getPaymentScope().equals(paymentScope)).collect(Collectors.toList());
            if (checkList.size() > 0) {
                InsuranceSchemeDetailPO insuranceSchemeDetailPO = checkList.get(0);
                encryptUtil.decrypt(insuranceSchemeDetailPO, InsuranceSchemeDetailPO.class);
                String lowerLimit = "0.000".equals(insuranceSchemeDetailPO.getLowerLimit()) ? null : insuranceSchemeDetailPO.getLowerLimit();
                String upperLimit = "0.000".equals(insuranceSchemeDetailPO.getUpperLimit()) ? null : insuranceSchemeDetailPO.getUpperLimit();
                if (lowerLimit != null && lowerLimit.length() > 0 && Double.parseDouble(entry.getValue()) < Double.parseDouble(lowerLimit)) {
                    //数值低于对应福利明细下限
                    log.info("社保基数 {} 数值 {} 低于对应福利明细下限 {}！", entry.getKey(), entry.getValue(), lowerLimit);
                    newPaymentBaseJson.put(entry.getKey(), lowerLimit);
                }
                if (upperLimit != null && upperLimit.length() > 0 && Double.parseDouble(entry.getValue()) > Double.parseDouble(upperLimit)) {
                    //数值高于对应福利明细上限
                    log.info("社保基数 {} 数值 {} 高于对应福利明细上限 {} ！", entry.getKey(), entry.getValue(), upperLimit);
                    newPaymentBaseJson.put(entry.getKey(), upperLimit);
                }
            }
        }
        return JSON.toJSONString(newPaymentBaseJson);
    }

    /**
     * 判断字符串是否为整数或者小数或者负数
     */
    public static boolean isNumeric(String str){

        Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;

    }

    /**
     * 档案列表
     * <p>
     * 这里是一个含有比较多动态字段的列表，用的是手动拼装的方式
     *
     * @param param     高级搜索条件
     * @param operateId 操作员id
     * @return table
     */
    public Map<String, Object> listPage(InsuranceArchivesListParam param, long operateId) {
        Map<String, Object> apidatas = new HashMap<>(16);
        InsuranceArchivesListParam request = InsuranceArchivesListParam.builder().build();
        if (param.getHireDate() != null && param.getHireDate().length == 2) {
            param.setHiredateStart(param.getHireDate()[0]);
            param.setHiredateEnd(param.getHireDate()[1]);
        }
        if (param.getDimissionDate() != null && param.getDimissionDate().length == 2) {
            param.setDimissionDateStart(param.getDimissionDate()[0]);
            param.setDimissionDateEnd(param.getDimissionDate()[1]);
        }

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getDepartmentIdsStr())) {
            request.setDepartmentIds(Arrays.stream(param.getDepartmentIdsStr().split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getSubcompanyIdsStr())) {
            request.setSubcompanyIds(Arrays.stream(param.getSubcompanyIdsStr().split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }


        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getPositionsStr())) {
            request.setPositions(Arrays.stream(param.getPositionsStr().split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }

        if (org.apache.commons.lang.StringUtils.isNotBlank(param.getStatusesStr())) {
            request.setStatuses(Arrays.stream(param.getStatusesStr().split(",")).map(String::new).collect(Collectors.toList()));
        }

        request.setNeedAuth(param.getNeedAuth());
        request.setTaxAgentEmployeeIds(param.getTaxAgentEmployeeIds());
        request.setTaxAgentIds(param.getTaxAgentIds());

        Integer current = param.getCurrent() == null ? 1 : param.getCurrent();
        Integer pageSize = param.getPageSize() == null ? 10 : param.getPageSize();
        long startNum = (current - 1) * pageSize;
        param.setStartNum(startNum);
        param.setPageSize(pageSize);
//        request.setStatuses(param.getStatuses());
        request.setKeyword(param.getUserName());

        request.setSiSchemeId(param.getSiSchemeId());
        request.setFundSchemeId(param.getFundSchemeId());
        request.setOtherSchemeId(param.getOtherSchemeId());

        request.setPageSize(param.getPageSize());
        request.setCurrent(param.getCurrent());

        request.setJobNum(param.getJobNum());

        request.setOrderRule(param.getOrderRule());

        request.setRunStatuses(param.getRunStatuses());

        request.setTaxAgentId(param.getTaxAgentId());

        request.setExtWelArchiveList(param.isExtWelArchiveList());

        apidatas = listPageEmployeePOS(request, operateId);

        return apidatas;
    }

    /**
     * 获取员工的基本信息
     * <p>
     * 此处主要是一个公共接口，有多处引用。我们薪资系统只保存员工id（employeeId），
     * 但是页面上需要展示员工的更多信息（姓名，部门，状态。。。），
     * 所以这里主要是用于接收联表数据的一个接口
     *
     * @param param     高级搜索条件，用于过滤数据
     * @param operateId 操作员id
     * @return list
     */
    public Map<String, Object> listPageEmployeePOS(InsuranceArchivesListParam param, long operateId) {
        //是否分权
        Boolean needAuth = param.getNeedAuth();
        StopWatch sw = new StopWatch();
        Map<String, Object> datas = new HashMap<>(16);

        List<InsuranceArchivesEmployeePO> page = new ArrayList<>();
        PageInfo<InsuranceArchivesEmployeePO> pageInfo = new PageInfo<>(InsuranceArchivesEmployeePO.class);
        //获取福利档案列表数据
        if (needAuth) {
            Collection<Long> taxAgentEmployeeIds = param.getTaxAgentEmployeeIds();
            Collection<Long> taxAgentIds = param.getTaxAgentIds();
            log.info("从数据库获取档案列表数据开始");
            sw.start("获取福利档案列表数据");
            if (param.isExtWelArchiveList()) {
                page = getSocialSchemeMapper().queryExtEmployeeList(param);
            } else {
                page = getSocialSchemeMapper().queryEmployeeList(param);
            }
            sw.stop();
            log.info("从数据库获取档案列表数据完成！");
            page = page.stream().filter(f ->
//                        taxAgentEmployeeIds.contains(f.getEmployeeId())||
                            taxAgentIds.contains(f.getPaymentOrganization())
            ).collect(Collectors.toList());
            // 填充总数和当页数据
            // 分页参数
            pageInfo = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), InsuranceArchivesEmployeePO.class);
            pageInfo.setTotal(page.size());
            pageInfo.setList(SalaryPageUtil.subList(pageInfo.getPageNum(), pageInfo.getPageSize(), page));
        } else {
            log.info("从数据库获取档案列表数据开始");
            sw.start("获取档案列表数据");
            if (param.isExtWelArchiveList()) {
                page = getSocialSchemeMapper().queryExtEmployeeList(param);
            } else {
                page = getSocialSchemeMapper().queryEmployeeList(param);
            }
            sw.stop();
            log.info("从数据库获取档案列表数据完成！");
            pageInfo = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(),
                    page, InsuranceArchivesEmployeePO.class);
        }
        SalaryI18nUtil.i18nList(pageInfo.getList());
        List<Map<String, Object>> records = null;
        log.info("buildTableData方法处理福利档案列表数据开始");
        sw.start("buildTableData方法处理福利档案列表数据");
        if (param.getExportData() != null && param.getExportData()) {
            records = buildTableData(pageInfo.getList(), true);
        } else {
            records = buildTableData(pageInfo.getList(), false);
        }
        sw.stop();
        log.info("buildTableData方法处理福利档案列表数据完成！");

        log.info("buildWeaTableColumns方法处理福利档案列表数据开始");
        sw.start("buildWeaTableColumns方法处理福利档案列表数据");
        List<WeaTableColumn> columns = buildWeaTableColumns(pageInfo.getList());
        sw.stop();
        log.info("buildWeaTableColumns方法处理福利档案列表数据完成！");
        WeaTable table = new WeaTable();
        table.setColumns(columns);
        //设置check是否可用
        List<WeaTableCheckboxpopedom> checkboxpopedomList = new ArrayList<>();
        WeaTableCheckboxpopedom checkboxpopedom = new WeaTableCheckboxpopedom();
        checkboxpopedom.setPopedompara("column:system_type");
        checkboxpopedom.setShowmethod("com.engine.salary.transmethod.TaxRateTransMethod.getCheckBoxPopedom");
        checkboxpopedomList.add(checkboxpopedom);
        table.setCheckboxList(checkboxpopedomList);
        table.setCheckboxpopedom(null);

        WeaResultMsg result = new WeaResultMsg(false);
        result.putAll(table.makeDataResult());
        result.success();

        datas.put("pageInfo", pageInfo);
        datas.put("datas", records);
        datas.put("columns", columns);
        datas.put("dataKey", result.getResultMap());

        log.info("各操作计时 {}", sw.prettyPrint());
        return datas;
    }

    /**
     * 高级搜索
     *
     * @return
     */
    public Map<String, Object> getSearchCondition() {

        List<SearchConditionOption> userStatusOptions = Arrays.stream(UserStatusEnum.values()).map(e -> new SearchConditionOption(String.valueOf(e.getValue()), e.getDefaultLabel())).collect(Collectors.toList());
//        List<InsuranceSchemePO> list = new SISchemeBiz().listAll();
        List<InsuranceSchemePO> list = getSISchemeService(user).listAll();

        List<SearchConditionOption> schemeOption = list.stream().filter(item -> Objects.equals(item.getWelfareType(), WelfareTypeEnum.SOCIAL_SECURITY.getValue()))
                .collect(Collectors.toList())
                .stream().map(item -> new SearchConditionOption(item.getId().toString(), item.getSchemeName())).collect(Collectors.toList());

        List<SearchConditionOption> fundOption = list.stream().filter(item -> Objects.equals(item.getWelfareType(), WelfareTypeEnum.ACCUMULATION_FUND.getValue()))
                .collect(Collectors.toList())
                .stream().map(item -> new SearchConditionOption(item.getId().toString(), item.getSchemeName())).collect(Collectors.toList());

        List<SearchConditionOption> otherOption = list.stream().filter(item -> Objects.equals(item.getWelfareType(), WelfareTypeEnum.OTHER.getValue()))
                .collect(Collectors.toList())
                .stream().map(item -> new SearchConditionOption(item.getId().toString(), item.getSchemeName())).collect(Collectors.toList());

        List<Map<String, Object>> taxAgentList = getTaxAgentWrapper(user).selectListAsAdmin();
        List<SearchConditionOption> taxAgentOption = taxAgentList.stream().map(item -> new SearchConditionOption(item.get("id").toString(), item.get("content").toString())).collect(Collectors.toList());

        Map<String, Object> apidatas = new HashMap<String, Object>();
        ConditionFactory conditionFactory = new ConditionFactory(user);
        //条件组
        List<SearchConditionGroup> addGroups = new ArrayList<SearchConditionGroup>();
        List<SearchConditionItem> conditionItems = new ArrayList<SearchConditionItem>();
        //文本输入框
        SearchConditionItem username = conditionFactory.createCondition(ConditionType.INPUT, 25034, "username");
        username.setInputType("input");
        username.setColSpan(2);//定义一行显示条件数，默认值为2,当值为1时标识该条件单独占一行
        username.setFieldcol(16);    //条件输入框所占宽度，默认值18
        username.setLabelcol(8);
        username.setViewAttr(2);  //	 编辑权限  1：只读，2：可编辑， 3：必填   默认2
        username.setLabel(SalaryI18nUtil.getI18nLabel(0,"姓名")); //设置文本值  这个将覆盖多语言标签的值
        conditionItems.add(username);
        //文本输入框
        SearchConditionItem jobNum = conditionFactory.createCondition(ConditionType.INPUT, 25034, "jobNum");
        jobNum.setInputType("input");
        jobNum.setColSpan(2);//定义一行显示条件数，默认值为2,当值为1时标识该条件单独占一行
        jobNum.setFieldcol(16);    //条件输入框所占宽度，默认值18
        jobNum.setLabelcol(8);
        jobNum.setViewAttr(2);  //	 编辑权限  1：只读，2：可编辑， 3：必填   默认2
        jobNum.setLabel(SalaryI18nUtil.getI18nLabel(0,"工号")); //设置文本值  这个将覆盖多语言标签的值
        conditionItems.add(jobNum);

        SearchConditionItem departmentIds = conditionFactory.createCondition(ConditionType.BROWSER, 502329, "departmentIdsStr", "57");
        departmentIds.setColSpan(2);
        departmentIds.setFieldcol(16);
        departmentIds.setLabelcol(8);
        departmentIds.setLabel(SalaryI18nUtil.getI18nLabel(0,"部门"));
        conditionItems.add(departmentIds);

        SearchConditionItem statuses = conditionFactory.createCondition(ConditionType.SELECT, 502327, "statusesStr");
        statuses.setInputType("select");
        statuses.setMultiple(true);
        statuses.setOptions(userStatusOptions);
        statuses.setColSpan(2);
        statuses.setFieldcol(16);
        statuses.setLabelcol(8);
        statuses.setIsQuickSearch(true);
        statuses.setLabel(SalaryI18nUtil.getI18nLabel(0,"状态"));
        conditionItems.add(statuses);

        SearchConditionItem positions = conditionFactory.createCondition(ConditionType.BROWSER, 502327, "positionsStr", "278");
        positions.setInputType("browser");
        positions.setColSpan(2);
        positions.setFieldcol(16);
        positions.setLabelcol(8);
        positions.setIsQuickSearch(true);
        positions.setLabel(SalaryI18nUtil.getI18nLabel(0,"岗位"));
        conditionItems.add(positions);

        SearchConditionItem subcompanyIds = conditionFactory.createCondition(ConditionType.BROWSER, 502327, "subcompanyIdsStr", "194");
        subcompanyIds.setInputType("browser");
        subcompanyIds.setColSpan(2);
        subcompanyIds.setFieldcol(16);
        subcompanyIds.setLabelcol(8);
        subcompanyIds.setIsQuickSearch(true);
        subcompanyIds.setLabel(SalaryI18nUtil.getI18nLabel(0,"分部"));
        conditionItems.add(subcompanyIds);

//        SearchConditionItem hireDate = conditionFactory.createCondition(ConditionType.TIMEPICKER,502327,new String[]{"hireDate", "hireDate"});
//        hireDate.setInputType("timepicker");
//        hireDate.setColSpan(2);
//        hireDate.setFieldcol(16);
//        hireDate.setViewAttr(8);
//        hireDate.setFormat("yyyy-MM-dd");
//        hireDate.setLabel(SalaryI18nUtil.getI18nLabel(0,"入职日期"));
//        conditionItems.add(hireDate);
//
//
//        SearchConditionItem dimissionDate = conditionFactory.createCondition(ConditionType.TIMEPICKER,502327,new String[]{"dimissionDate", "dimissionDate"});
//        dimissionDate.setInputType("timepicker");
//        dimissionDate.setColSpan(2);
//        dimissionDate.setFieldcol(16);
//        dimissionDate.setViewAttr(8);
//        dimissionDate.setFormat("yyyy-MM-dd");
//        dimissionDate.setLabel(SalaryI18nUtil.getI18nLabel(0,"离职日期"));
//        conditionItems.add(dimissionDate);


        SearchConditionItem siSchemeId = conditionFactory.createCondition(ConditionType.SELECT, 502327, "siSchemeId");
        siSchemeId.setInputType("select");
        siSchemeId.setOptions(schemeOption);
        siSchemeId.setColSpan(2);
        siSchemeId.setFieldcol(16);
        siSchemeId.setLabelcol(8);
        siSchemeId.setIsQuickSearch(true);
        siSchemeId.setLabel(SalaryI18nUtil.getI18nLabel(0,"社保方案"));
        conditionItems.add(siSchemeId);

        SearchConditionItem fundSchemeId = conditionFactory.createCondition(ConditionType.SELECT, 502327, "fundSchemeId");
        fundSchemeId.setInputType("select");
        fundSchemeId.setOptions(fundOption);
        fundSchemeId.setColSpan(2);
        fundSchemeId.setFieldcol(16);
        fundSchemeId.setLabelcol(8);
        fundSchemeId.setIsQuickSearch(true);
        fundSchemeId.setLabel(SalaryI18nUtil.getI18nLabel(0,"公积金方案"));
        conditionItems.add(fundSchemeId);

        SearchConditionItem otherSchemeId = conditionFactory.createCondition(ConditionType.SELECT, 502327, "otherSchemeId");
        otherSchemeId.setInputType("select");
        otherSchemeId.setOptions(otherOption);
        otherSchemeId.setColSpan(2);
        otherSchemeId.setFieldcol(16);
        otherSchemeId.setLabelcol(8);
        otherSchemeId.setIsQuickSearch(true);
        otherSchemeId.setLabel(SalaryI18nUtil.getI18nLabel(0,"其他福利方案"));
        conditionItems.add(otherSchemeId);

        SearchConditionItem taxAgentId = conditionFactory.createCondition(ConditionType.SELECT, 502327, "taxAgentId");
        taxAgentId.setInputType("select");
        taxAgentId.setOptions(taxAgentOption);
        taxAgentId.setColSpan(2);
        taxAgentId.setFieldcol(16);
        taxAgentId.setLabelcol(8);
        taxAgentId.setIsQuickSearch(true);
        taxAgentId.setLabel(SalaryI18nUtil.getI18nLabel(0,"个税扣缴义务人"));
        conditionItems.add(taxAgentId);

        addGroups.add(new SearchConditionGroup(SalaryI18nUtil.getI18nLabel(0,"常用条件"), true, conditionItems));
        apidatas.put("condition", addGroups);
        return apidatas;
    }

    @Override
    public List<InsuranceArchivesSocialSchemePO> getSocialByEmployeeIds(List<Long> employeeIds) {

        List<List<Long>> partition = Lists.partition(employeeIds, 1000);
        List<InsuranceArchivesSocialSchemePO> allList = new ArrayList<>();
        for (List<Long> longs : partition) {
            List<InsuranceArchivesSocialSchemePO> socialList = getSocialSchemeMapper().getSocialByEmployeeId(longs);
            allList.addAll(socialList);
        }
        return allList;
    }

    @Override
    public List<InsuranceArchivesFundSchemePO> getFundByEmployeeIds(List<Long> employeeIds) {

        List<List<Long>> partition = Lists.partition(employeeIds, 1000);
        List<InsuranceArchivesFundSchemePO> allList = new ArrayList<>();
        for (List<Long> longs : partition) {
            List<InsuranceArchivesFundSchemePO> fundList = getFundSchemeMapper().getFundByEmployeeId(longs);
            allList.addAll(fundList);
        }
        return allList;
    }

    @Override
    public List<InsuranceArchivesOtherSchemePO> getOtherByEmployeeIds(List<Long> employeeIds) {

        List<List<Long>> partition = Lists.partition(employeeIds, 1000);
        List<InsuranceArchivesOtherSchemePO> allList = new ArrayList<>();
        for (List<Long> longs : partition) {
            List<InsuranceArchivesOtherSchemePO> otherList = getOtherSchemeMapper().getOtherByEmployeeId(longs);
            allList.addAll(otherList);
        }
        return allList;
    }

    /**
     * 组装员工的社保，公积金，其他福利数据
     *
     * @param ids 员工id集合
     * @return map
     */
    @Override
    public Map<Long, InsuranceArchivesAccountPO> buildBatchAccount(List<Long> ids, Long paymentOrganization) {
        if (org.apache.commons.collections.CollectionUtils.isEmpty(ids)) {
            return new HashMap<>();
        }
        //设置获取社保/公积金/其他福利档案方法的入参
        List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS = new ArrayList<>();
        for (Long employeeId : ids) {
            insuranceArchivesEmployeePOS.add(InsuranceArchivesEmployeePO.builder()
                    .employeeId(employeeId)
                    .paymentOrganization(paymentOrganization)
                    .build());
        }

        Map<Long, InsuranceArchivesAccountPO> result = new HashMap<>();
        Map<Long, InsuranceArchivesSocialSchemePO> socialMap = new HashMap<>();
        Map<Long, InsuranceArchivesFundSchemePO> funMap = new HashMap<>();
        Map<Long, InsuranceArchivesOtherSchemePO> otherMap = new HashMap<>();
        List<InsuranceArchivesSocialSchemePO> socialPOS = encryptUtil.decryptList(this.getSocialByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS), InsuranceArchivesSocialSchemePO.class);
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(socialPOS)) {
            socialMap = socialPOS.stream().collect(Collectors.toMap(InsuranceArchivesSocialSchemePO::getEmployeeId, Function.identity()));
        }
        List<InsuranceArchivesFundSchemePO> fundPOS = encryptUtil.decryptList(this.getFundByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS), InsuranceArchivesFundSchemePO.class);
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(fundPOS)) {
            funMap = fundPOS.stream().collect(Collectors.toMap(InsuranceArchivesFundSchemePO::getEmployeeId, Function.identity()));
        }
        List<InsuranceArchivesOtherSchemePO> otherPOS = this.getOtherByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS);
        encryptUtil.decryptList(otherPOS, InsuranceArchivesOtherSchemePO.class);
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(otherPOS)) {
            otherMap = otherPOS.stream().collect(Collectors.toMap(InsuranceArchivesOtherSchemePO::getEmployeeId, Function.identity()));
        }
        for (Long id : ids) {
            InsuranceArchivesAccountPO po = new InsuranceArchivesAccountPO();
            po.setSocial(socialMap.get(id));
            po.setFund(funMap.get(id));
            po.setOther(otherMap.get(id));
            result.put(id, po);
        }
        return result;
    }

    @Override
    public List<InsuranceArchivesBaseHistoryPO> dealSocialBaseAdjustInfoList(List<InsuranceArchivesSocialSchemePO> adjustList, Long creator) {
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = new ArrayList<>();
        if (adjustList.size() > 0) {
            //遍历待更新的福利档案数据，对每组档案生成基数调整记录（基数单元未变化则忽略）
            for (InsuranceArchivesSocialSchemePO po : adjustList) {
                List<InsuranceArchivesSocialSchemePO> oldBaseInfoList = getSocialSchemeMapper().getSocialByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .paymentOrganization(po.getPaymentOrganization()).employeeId(po.getEmployeeId()).build());

                InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                        .adjustAfterSchemeId(po.getSocialSchemeId())
                        .adjustAfterBaseJson(po.getSocialPaymentBaseString())
                        .adjustAfterComBaseJson(po.getSocialPaymentComBaseString())
                        .welfareType(po.getWelfareType())
                        .employeeId(po.getEmployeeId())
                        .paymentOrganization(po.getPaymentOrganization())
                        .build();
                if (oldBaseInfoList.size() == 1) {
                    //新增调整记录，变更
                    InsuranceArchivesSocialSchemePO oldBaseInfo = oldBaseInfoList.get(0);
                    encryptUtil.decrypt(oldBaseInfo, InsuranceArchivesSocialSchemePO.class);
                    adjustInfo.setAdjustBeforeBaseJson(oldBaseInfo.getSocialPaymentBaseString());
                    adjustInfo.setAdjustBeforeComBaseJson(oldBaseInfo.getSocialPaymentComBaseString());
                    adjustInfo.setAdjustBeforeSchemeId(oldBaseInfo.getSocialSchemeId());
                } else if (oldBaseInfoList.size() > 1) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"社保档案存在冗余数据！"));
                }
                adjustHistoryList.addAll(createAdjustInfo(adjustInfo, creator));
            }
        }
        return adjustHistoryList;

    }

    @Override
    public List<InsuranceArchivesBaseHistoryPO> dealFundBaseAdjustInfoList(List<InsuranceArchivesFundSchemePO> adjustList, Long creator) {
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = new ArrayList<>();
        if (adjustList.size() > 0) {
            //遍历待更新的福利档案数据，对每组档案生成基数调整记录（基数单元未变化则忽略）
            for (InsuranceArchivesFundSchemePO po : adjustList) {
                List<InsuranceArchivesFundSchemePO> oldBaseInfoList = getFundSchemeMapper().getFundByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .paymentOrganization(po.getPaymentOrganization()).employeeId(po.getEmployeeId()).build());

                InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                        .adjustAfterSchemeId(po.getFundSchemeId())
                        .adjustAfterBaseJson(po.getFundPaymentBaseString())
                        .adjustAfterComBaseJson(po.getFundPaymentComBaseString())
                        .welfareType(po.getWelfareType())
                        .employeeId(po.getEmployeeId())
                        .paymentOrganization(po.getPaymentOrganization())
                        .build();
                if (oldBaseInfoList.size() == 1) {
                    //新增调整记录，变更
                    InsuranceArchivesFundSchemePO oldBaseInfo = oldBaseInfoList.get(0);
                    encryptUtil.decrypt(oldBaseInfo, InsuranceArchivesFundSchemePO.class);
                    adjustInfo.setAdjustBeforeBaseJson(oldBaseInfo.getFundPaymentBaseString());
                    adjustInfo.setAdjustBeforeComBaseJson(oldBaseInfo.getFundPaymentComBaseString());
                    adjustInfo.setAdjustBeforeSchemeId(oldBaseInfo.getFundSchemeId());
                } else if (oldBaseInfoList.size() > 1) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"公积金档案存在冗余数据！"));
                }
                adjustHistoryList.addAll(createAdjustInfo(adjustInfo, creator));
            }
        }
        return adjustHistoryList;
    }

    @Override
    public List<InsuranceArchivesBaseHistoryPO> dealOtherBaseAdjustInfoList(List<InsuranceArchivesOtherSchemePO> adjustList, Long creator) {
        List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = new ArrayList<>();
        if (adjustList.size() > 0) {
            //遍历待更新的福利档案数据，对每组档案生成基数调整记录（基数单元未变化则忽略）
            for (InsuranceArchivesOtherSchemePO po : adjustList) {
                List<InsuranceArchivesOtherSchemePO> oldBaseInfoList = getOtherSchemeMapper().getOtherByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                        .paymentOrganization(po.getPaymentOrganization()).employeeId(po.getEmployeeId()).build());

                InsuranceArchivesBaseHistoryDTO adjustInfo = InsuranceArchivesBaseHistoryDTO.builder()
                        .adjustAfterSchemeId(po.getOtherSchemeId())
                        .adjustAfterBaseJson(po.getOtherPaymentBaseString())
                        .adjustAfterComBaseJson(po.getOtherPaymentComBaseString())
                        .welfareType(po.getWelfareType())
                        .employeeId(po.getEmployeeId())
                        .paymentOrganization(po.getPaymentOrganization())
                        .build();
                if (oldBaseInfoList.size() == 1) {
                    //新增调整记录，变更
                    InsuranceArchivesOtherSchemePO oldBaseInfo = oldBaseInfoList.get(0);
                    encryptUtil.decrypt(oldBaseInfo, InsuranceArchivesOtherSchemePO.class);
                    adjustInfo.setAdjustBeforeBaseJson(oldBaseInfo.getOtherPaymentBaseString());
                    adjustInfo.setAdjustBeforeComBaseJson(oldBaseInfo.getOtherPaymentComBaseString());
                    adjustInfo.setAdjustBeforeSchemeId(oldBaseInfo.getOtherSchemeId());
                } else if (oldBaseInfoList.size() > 1) {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0,"其他福利档案存在冗余数据！"));
                }
                adjustHistoryList.addAll(createAdjustInfo(adjustInfo, creator));
            }
        }
        return adjustHistoryList;
    }

    /**
     * 获取没有设置社保、公积金最后缴纳月的档案
     * @param employeeIds
     * @return
     */
    @Override
    public List<InsuranceArchivesBaseInfoPO> listEndDateIsNull(List<Long> employeeIds) {
        if (org.apache.commons.collections.CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }
        return getInsuranceBaseInfoMapper().listEndDateIsNull(employeeIds);
    }

    /**
     * 获取没有设置社保、公积金最后缴纳月的档案
     * @param employeeIds
     * @return
     */
    @Override
    public List<InsuranceArchivesBaseInfoPO> listStartDateIsNull(List<Long> employeeIds) {
        return getInsuranceBaseInfoMapper().listStartDateIsNull(employeeIds);
    }
    /*****以上代码为SIArchivesBiz中方法逻辑迁移，旨在减少Biz类的使用*****/

    @Override
    public List<InsuranceArchivesSocialSchemePO> listInsuranceArchivesSocialSchemeByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<List<Long>> partition = Lists.partition(ids, 1000);
        ArrayList<InsuranceArchivesSocialSchemePO> resultList = new ArrayList<>();
        partition.forEach(list -> resultList.addAll(getSocialSchemeMapper().getSocialById(list)));
        return resultList;
    }

    @Override
    public List<InsuranceArchivesFundSchemePO> listInsuranceArchivesFundSchemeByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<List<Long>> partition = Lists.partition(ids, 1000);
        ArrayList<InsuranceArchivesFundSchemePO> resultList = new ArrayList<>();
        partition.forEach(list -> resultList.addAll(getFundSchemeMapper().getFundById(list)));
        return resultList;
    }

    @Override
    public List<InsuranceArchivesOtherSchemePO> listInsuranceArchivesOtherSchemeByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<List<Long>> partition = Lists.partition(ids, 1000);
        ArrayList<InsuranceArchivesOtherSchemePO> resultList = new ArrayList<>();
        partition.forEach(list -> resultList.addAll(getOtherSchemeMapper().getOtherById(list)));
        return resultList;
    }
}
