package com.engine.salary.biz;

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.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.salary.common.SalaryContext;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
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.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.po.TaxAgentPO;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.datacollection.DataCollectionEmployeeTypeEnum;
import com.engine.salary.enums.siaccount.EmployeeStatusEnum;
import com.engine.salary.enums.sicategory.*;
import com.engine.salary.exception.SalaryRunTimeException;
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.SalaryEmployeeService;
import com.engine.salary.service.impl.SalaryEmployeeServiceImpl;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
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.SalaryAssert;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryFormItemUtil;
import com.engine.salary.util.*;
import com.engine.salary.util.db.MapperProxyFactory;
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 com.engine.salary.util.db.IdGenerator;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StopWatch;
import weaver.conn.mybatis.MyBatisFactory;
import weaver.general.Util;
import weaver.hrm.User;

import java.math.BigDecimal;
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/12
 * @Version V1.0
 **/
@Data
@Slf4j
public class SIArchivesBiz {

    Boolean needAuth;
    Collection<TaxAgentPO> taxAgentPOS;

    private EncryptUtil encryptUtil = new EncryptUtil();

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

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

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

    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 TaxAgentWrapper getTaxAgentWrapper(User user) {
        return ServiceUtil.getService(TaxAgentWrapper.class, user);
    }

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

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

    /**
     * @param welfareType
     * @param employeeId
     * @param operateId
     * @param user
     * @return
     */
    public Map<String, Object> getBaseForm(WelfareTypeEnum welfareType, Long employeeId, Long operateId, User user, Long paymentOrganization) {
        Map<String, Object> data = new HashMap<>(16);
        SalaryAssert.notNull(employeeId, "员工id不可为空");
        List<DataCollectionEmployee> employeeByIds = getSalaryEmployeeService(user).getEmployeeByIdsAll(Collections.singletonList(employeeId));
        SalaryAssert.notEmpty(employeeByIds, "员工信息不存在");
        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();

//            if (item.getStatus() == UserStatusEnum.unavailable) {
//                InsuranceArchivesListParam insuranceArchivesListParam = new InsuranceArchivesListParam();
//                insuranceArchivesListParam.setEmployeeIds(Collections.singletonList(employeeId));
//                List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS = siArchivesSocialMapper.queryEmployeeList(insuranceArchivesListParam, tenantKey);
//                if (CollectionUtils.isNotEmpty(insuranceArchivesEmployeePOS)) {
//                    insuranceArchivesBaseDTO.setDimissionDate(SalaryDateUtil.getFormatLocalDate(insuranceArchivesEmployeePOS.get(0).getDimissionDate()));
//                }
//            }

            //WeaForm weaForm = SalaryFormatUtil.<InsuranceArchivesBaseDTO>getInstance().buildForm(InsuranceArchivesBaseDTO.class, insuranceArchivesBaseDTO);
            // weaForm.getGroups().add(new WeaFormGroup("g1", "员工信息"));
            // weaForm.getLayout().forEach(items -> items.forEach(e -> e.setGroupId("g1")));
            data.put("data", insuranceArchivesBaseDTO);
            return data;
        }

        SISchemeBiz siSchemeBiz = new SISchemeBiz();
        List<InsuranceSchemePO> list = siSchemeBiz.listAll();
        // 过滤可见性范围
        list = filterList(list);
        List<SearchConditionItem> selectItems = new ArrayList<>();
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionOption> paymentOptions = paymentOrganizationOptions();
        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, operateId, 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, "社保方案名称", "socialSchemeId");
                SearchConditionItem organizationName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, "社保缴纳组织", "paymentOrganization");
                SearchConditionItem underTakeName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, "社保个人实际承担方", "underTake");

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

                addGroups.add(new SearchConditionGroup("社保基础信息", true, selectItems));
                data.put("data", insuranceArchivesSocialSchemeDTO);
                data.put("items", addGroups);
                break;
            case ACCUMULATION_FUND:
                InsuranceArchivesFundSchemeDTO insuranceArchivesFundSchemeDTO = buildFundForm(employeeId, operateId, 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, "公积金方案名称", "fundSchemeId");
                SearchConditionItem organizationFundName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, "公积金缴纳组织", "paymentOrganization");
                SearchConditionItem underTakeFundName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, "公积金个人实际承担方", "underTake");

                selectItems.add(fundName);
                selectItems.add(organizationFundName);
                selectItems.add(underTakeFundName);
                addGroups.add(new SearchConditionGroup("公积金基础信息", true, selectItems));
                data.put("data", insuranceArchivesFundSchemeDTO);
                data.put("items", addGroups);
                break;
            case OTHER:
                InsuranceArchivesOtherSchemeDTO insuranceArchivesOtherSchemeDTO = buildOtherForm(employeeId, operateId, 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, "其它福利名称", "otherSchemeId");
                SearchConditionItem organizationOtherName = SalaryFormItemUtil.selectItem(user, paymentOptions, 2, 12, 6, false, "其它福利缴纳组织", "paymentOrganization");
                SearchConditionItem underTakeOtherName = SalaryFormItemUtil.selectItem(user, underTakeOptions, 2, 12, 6, false, "其它福利个人实际承担方", "underTake");

                selectItems.add(otherName);
                selectItems.add(organizationOtherName);
                selectItems.add(underTakeOtherName);
                addGroups.add(new SearchConditionGroup("其它福利基础信息", 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){
        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(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;
    }

    /**
     * 获取详细表单
     *
     * @param user
     * @param welfareType
     * @param employeeId
     * @param operateId
     * @param schemeId
     * @return
     */
    public Map<String, Object> getPaymentForm(User user, WelfareTypeEnum welfareType, Long employeeId, long operateId, 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, operateId, welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            case ACCUMULATION_FUND:
                data = buildFundPaymentForm(user, employeeId, schemeId, operateId, welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            case OTHER:
                data = buildOtherPaymentForm(user, employeeId, schemeId, operateId, welfareType.getValue(), paymentOrganization, welBaseDiffSign, welBaseAutoAdjustSign);
                break;
            default:
        }
        return data;
    }

    /**
     * 其他payForm
     *
     * @param employeeId
     * @param schemeId
     * @param operateId
     * @return
     */
    public Map<String, Object> buildOtherPaymentForm(User user, Long employeeId, Long schemeId, long operateId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {
        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesOtherSchemeDTO data = buildOtherForm(employeeId, operateId, 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("其它福利缴纳基数", true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup("其它福利缴纳基数", 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
     * @param operateId
     * @return
     */
    public Map<String, Object> buildFundPaymentForm(User user, Long employeeId, Long schemeId, long operateId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {

        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesFundSchemeDTO data = buildFundForm(employeeId, operateId, 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("公积金缴纳基数", true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup("公积金缴纳基数", 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
     * @param operateId
     * @return
     */
    public Map<String, Object> buildSocialPaymentForm(User user, Long employeeId, Long schemeId, long operateId, Integer welfareType, Long paymentOrganization, boolean welBaseDiffSign, boolean welBaseAutoAdjustSign) {
        Map<String, Object> dataMap = new HashMap<>();
        InsuranceArchivesSocialSchemeDTO data = buildSocialForm(employeeId, operateId, 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("社保缴纳基数", true, inputItems));
        dataMap.put("items", addGroups);
        if (welBaseDiffSign) {
            List<SearchConditionGroup> addComGroups = new ArrayList<>();
            List<SearchConditionItem> inputComItems = buildPaymentComBase(user, schemeId, welfareType);
            addComGroups.add(new SearchConditionGroup("社保缴纳基数", 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);
            }
        }

        SICategoryBiz siCategoryBiz = new SICategoryBiz();
        list.forEach(insuranceSchemeDetail -> {
            ICategoryPO iCategoryPO = siCategoryBiz.getByID(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());
        SICategoryBiz siCategoryBiz = new SICategoryBiz();
        list.forEach(insuranceSchemeDetail -> {
            ICategoryPO iCategoryPO = siCategoryBiz.getByID(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) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            InsuranceSchemeDetailMapper insuranceSchemeDetailMapper = sqlSession.getMapper(InsuranceSchemeDetailMapper.class);
            List<InsuranceSchemeDetailPO> insuranceSchemeDetailPOS = insuranceSchemeDetailMapper.queryListByPrimaryIdIsPayment(schemeId, IsPaymentEnum.YES.getValue(), welfareType);
            encryptUtil.decryptList(insuranceSchemeDetailPOS, InsuranceSchemeDetailPO.class);
            return insuranceSchemeDetailPOS;
        } finally {
            sqlSession.close();
        }
    }


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

    /**
     * 其它基础表单
     *
     * @param employeeId
     * @param operateId
     * @return
     */
    public InsuranceArchivesOtherSchemeDTO buildOtherForm(Long employeeId, Long operateId, Long paymentOrganization) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);
//            List<InsuranceArchivesOtherSchemePO> otherList = otherSchemeMapper.getOtherByEmployeeId(Collections.singletonList(employeeId));
            List<InsuranceArchivesOtherSchemePO> otherList = otherSchemeMapper.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;
        } finally {
            sqlSession.close();
        }

    }

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

        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
//            List<InsuranceArchivesFundSchemePO> fundList = fundSchemeMapper.getFundByEmployeeId(Collections.singletonList(employeeId));
            List<InsuranceArchivesFundSchemePO> fundList = fundSchemeMapper.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;
        } finally {
            sqlSession.close();
        }

    }

    /**
     * 社保基础表单
     *
     * @param employeeId
     * @param operateId
     * @return
     */
    public InsuranceArchivesSocialSchemeDTO buildSocialForm(Long employeeId, Long operateId, 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) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<InsuranceArchivesSocialSchemePO> socialList = socialSchemeMapper.getSocialByEmployeeIdAndPayOrg(InsuranceArchivesEmployeePO.builder()
                    .employeeId(employeeId)
                    .paymentOrganization(paymentOrganization)
                    .build());
            encryptUtil.decryptList(socialList, InsuranceArchivesSocialSchemePO.class);
            return socialList.size() != 0 ? socialList.get(0) : null;
        } finally {
            sqlSession.close();
        }
    }

    public List<InsuranceArchivesSocialSchemePO> getSocialByEmployeeIds(List<Long> employeeIds) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<List<Long>> partition = Lists.partition(employeeIds, 1000);
            List<InsuranceArchivesSocialSchemePO> allList = new ArrayList<>();
            for (List<Long> longs : partition) {
                List<InsuranceArchivesSocialSchemePO> socialList = socialSchemeMapper.getSocialByEmployeeId(longs);
                allList.addAll(socialList);
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }


    public List<InsuranceArchivesFundSchemePO> getFundByEmployeeIds(List<Long> employeeIds) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
            List<List<Long>> partition = Lists.partition(employeeIds, 1000);
            List<InsuranceArchivesFundSchemePO> allList = new ArrayList<>();
            for (List<Long> longs : partition) {
                List<InsuranceArchivesFundSchemePO> fundList = fundSchemeMapper.getFundByEmployeeId(longs);
                allList.addAll(fundList);
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }

    public List<InsuranceArchivesOtherSchemePO> getOtherByEmployeeIds(List<Long> employeeIds) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);
            List<List<Long>> partition = Lists.partition(employeeIds, 1000);
            List<InsuranceArchivesOtherSchemePO> allList = new ArrayList<>();
            for (List<Long> longs : partition) {
                List<InsuranceArchivesOtherSchemePO> otherList = otherSchemeMapper.getOtherByEmployeeId(longs);
                allList.addAll(otherList);
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }

    /**
     * 根据人员id和个税扣缴人id获取记录
     */
    public List<InsuranceArchivesSocialSchemePO> getSocialByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<InsuranceArchivesSocialSchemePO> allList = new ArrayList<>();
            for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
                List<InsuranceArchivesSocialSchemePO> socialList = socialSchemeMapper.getSocialByEmployeeIdAndPayOrg(po);
                if (socialList.size() > 0) {
                    allList.add(socialList.get(0));
                }
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }


    public List<InsuranceArchivesFundSchemePO> getFundByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
            List<InsuranceArchivesFundSchemePO> allList = new ArrayList<>();
            for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
                List<InsuranceArchivesFundSchemePO> fundList = fundSchemeMapper.getFundByEmployeeIdAndPayOrg(po);
                if (fundList.size() > 0) {
                    allList.add(fundList.get(0));
                }
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }

    public List<InsuranceArchivesOtherSchemePO> getOtherByEmployeeIdAndPayOrg(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);
            List<InsuranceArchivesOtherSchemePO> allList = new ArrayList<>();
            for (InsuranceArchivesEmployeePO po : insuranceArchivesEmployeePOS) {
                List<InsuranceArchivesOtherSchemePO> otherList = otherSchemeMapper.getOtherByEmployeeIdAndPayOrg(po);
                if (otherList.size() > 0) {
                    allList.add(otherList.get(0));
                }
            }
            return allList;
        } finally {
            sqlSession.close();
        }
    }


    /**
     * 新增
     *
     * @param param
     * @param user
     */
    public void insert(InsuranceArchivesSaveParam param, User user) {
        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("福利类型不存在");
        }

    }

    /**
     * @param paramReq
     * @param
     */
    public void otherSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);

            InsuranceArchivesOtherSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesOtherSaveParam.class);
            SalaryAssert.notNull("员工id为空", param, param.getEmployeeId());

            if (StringUtils.isNotBlank(param.getOtherStartTime()) && !SalaryDateUtil.checkYearMonth(param.getOtherStartTime())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(542532, "其他福利起始缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
            }
            if (StringUtils.isNotBlank(param.getOtherEndTime()) && !SalaryDateUtil.checkYearMonth(param.getOtherEndTime())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(542533, "其他福利最后缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
            }

            List<Long> otherIds = new ArrayList();
            otherIds.add(param.getId());
            List<InsuranceArchivesOtherSchemePO> oldOtherInfoList = otherSchemeMapper.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(StringUtils.isNotBlank(param.getOtherStartTime()) ? param.getOtherStartTime() : null)
                                .underTake(param.getUnderTake())
                                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                                .welfareType(paramReq.getWelfareType().getValue())
                                .otherEndTime(StringUtils.isNotBlank(param.getOtherEndTime()) ? param.getOtherEndTime() : null)
                                .employeeId(param.getEmployeeId())
                                .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                                .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("其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    updateOtherInfo.setOtherPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(updateOtherInfo.getOtherSchemeId(),updateOtherInfo.getOtherPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(updateOtherInfo, InsuranceArchivesOtherSchemePO.class);
                otherSchemeMapper.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);
                sqlSession.commit();
            } else {
                otherSchemeMapper.deleteByEmployeeIdAndPayOrg(InsuranceArchivesOtherSchemePO.builder()
                        .employeeId(param.getEmployeeId())
                        .paymentOrganization(param.getPaymentOrganization())
                        .build());
                //新建社保档案，并关联主表
                InsuranceArchivesOtherSchemePO insertOtherInfo = InsuranceArchivesOtherSchemePO.builder()
                                .otherSchemeId(param.getOtherSchemeId())
                                .otherStartTime(StringUtils.isNotBlank(param.getOtherStartTime()) ? param.getOtherStartTime() : null)
                                .underTake(param.getUnderTake())
                                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                                .welfareType(paramReq.getWelfareType().getValue())
                                .otherEndTime(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("其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    insertOtherInfo.setOtherPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(insertOtherInfo.getOtherSchemeId(),insertOtherInfo.getOtherPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("其他福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(insertOtherInfo, InsuranceArchivesOtherSchemePO.class);
                otherSchemeMapper.insert(insertOtherInfo);
                sqlSession.commit();

                InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
                if(baseInfoPO != null) {
                    List<InsuranceArchivesOtherSchemePO> otherInfos = otherSchemeMapper.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);
                } else {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
                }
            }

            //生成福利档案基数调整记录数据
            List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
            //福利档案基数调整记录数据入库
            batchInsertAdjustHistory(adjustHistoryList, employeeId);

        } finally {
            sqlSession.close();
        }
    }

    /**
     * @param paramReq
     * @param
     */
    public void fundSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
            InsuranceArchivesFundSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesFundSaveParam.class);
            SalaryAssert.notNull("员工id为空", param, param.getEmployeeId());

            if (StringUtils.isNotBlank(param.getFundStartTime()) && !SalaryDateUtil.checkYearMonth(param.getFundStartTime())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(542530, "公积金起始缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
            }
            if (StringUtils.isNotBlank(param.getFundEndTime()) && !SalaryDateUtil.checkYearMonth(param.getFundEndTime())) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(542531, "公积金最后缴纳时间格式错误,正确格式为YYYY-MM或者yyyy-MM-dd"));
            }

            List<Long> fundIds = new ArrayList();
            fundIds.add(param.getId());
            List<InsuranceArchivesFundSchemePO> oldFundInfoList = fundSchemeMapper.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(StringUtils.isNotBlank(param.getFundEndTime()) ? param.getFundEndTime() : null)
                        .fundStartTime(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())
                        .updateTime(new Date())
                        .welfareType(paramReq.getWelfareType().getValue())
                        .employeeId(param.getEmployeeId())
                        .build();
                //校验福利基数是否符合上下限要求，
                if (!checkWelBaseLimit(updateFundInfo.getFundSchemeId(),updateFundInfo.getFundPaymentBaseString(), PaymentScopeEnum.SCOPE_PERSON.getValue())) {
                    throw new SalaryRunTimeException("公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    updateFundInfo.setFundPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(updateFundInfo.getFundSchemeId(),updateFundInfo.getFundPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(updateFundInfo, InsuranceArchivesFundSchemePO.class);
                fundSchemeMapper.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);
                sqlSession.commit();
            } else {
                fundSchemeMapper.deleteByEmployeeIdAndPayOrg(InsuranceArchivesFundSchemePO.builder()
                        .employeeId(param.getEmployeeId())
                        .paymentOrganization(param.getPaymentOrganization())
                        .build());
                //新建社保档案，并关联主表
                InsuranceArchivesFundSchemePO insertFundInfo = InsuranceArchivesFundSchemePO.builder()
                                .fundSchemeId(param.getFundSchemeId())
                                .fundAccount(param.getFundAccount())
                                .fundEndTime(StringUtils.isNotBlank(param.getFundEndTime()) ? param.getFundEndTime() : null)
                                .fundStartTime(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("公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    insertFundInfo.setFundPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(insertFundInfo.getFundSchemeId(),insertFundInfo.getFundPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("公积金福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(insertFundInfo, InsuranceArchivesFundSchemePO.class);
                fundSchemeMapper.insert(insertFundInfo);
                sqlSession.commit();

                InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
                if(baseInfoPO != null) {
                    List<InsuranceArchivesFundSchemePO> fundInfos = fundSchemeMapper.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);
                } else {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
                }

            }

            //生成福利档案基数调整记录数据
            List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
            //福利档案基数调整记录数据入库
            batchInsertAdjustHistory(adjustHistoryList, employeeId);

        } finally {
            sqlSession.close();
        }

    }

    /**
     * @param paramReq
     * @param 
     */
    public void socialSave(InsuranceArchivesSaveParam paramReq, User user, boolean welBaseDiffSign) {
        long employeeId = user.getUID();
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);

            InsuranceArchivesSocialSaveParam param = JSONObject.parseObject(paramReq.getBaseForm(), InsuranceArchivesSocialSaveParam.class);
            SalaryAssert.notNull("员工id为空", param, param.getEmployeeId());

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

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

            //查询已有数据
            List<Long> socialIds = new ArrayList();
            socialIds.add(param.getId());
            List<InsuranceArchivesSocialSchemePO> oldSocialInfoList = socialSchemeMapper.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(StringUtils.isNotBlank(param.getSocialEndTime()) ? param.getSocialEndTime() : null)
                                .socialStartTime(StringUtils.isNotBlank(param.getSocialStartTime()) ? param.getSocialStartTime() : null)
                                .creator(employeeId)
                                .nonPayment(param.getNonPayment())
                                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                                .employeeId(param.getEmployeeId())
                                .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("社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    updateSocialInfo.setSocialPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(updateSocialInfo.getSocialSchemeId(),updateSocialInfo.getSocialPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(updateSocialInfo, InsuranceArchivesSocialSchemePO.class);
                socialSchemeMapper.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);
                sqlSession.commit();
            } else {
                socialSchemeMapper.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(StringUtils.isNotBlank(param.getSocialEndTime()) ? param.getSocialEndTime() : null)
                                .socialStartTime(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("社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                }
                //需要拆分个人和公司福利基数时
                if (welBaseDiffSign) {
                    insertSocialInfo.setSocialPaymentComBaseString(paramReq.getPaymentComForm());
                    //校验福利基数是否符合上下限要求
                    if (!checkWelBaseLimit(insertSocialInfo.getSocialSchemeId(),insertSocialInfo.getSocialPaymentComBaseString(), PaymentScopeEnum.SCOPE_COMPANY.getValue())) {
                        throw new SalaryRunTimeException("社保福利明细中的基数更新内容不符合相关基数上下限要求，请检查后重试！");
                    }
                }
                encryptUtil.encrypt(insertSocialInfo, InsuranceArchivesSocialSchemePO.class);
                socialSchemeMapper.insert(insertSocialInfo);
                sqlSession.commit();

                InsuranceArchivesBaseInfoPO baseInfoPO = getInsuranceBaseInfoMapper().getOneByEmployeeIdAndPayOrg(param.getPaymentOrganization(), param.getEmployeeId());
                if(baseInfoPO != null) {
                    List<InsuranceArchivesSocialSchemePO> socialInfos = socialSchemeMapper.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);
                } else {
                    throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "档案不存在！"));
                }

            }

            //生成福利档案基数调整记录数据
            List<InsuranceArchivesBaseHistoryPO> adjustHistoryList = createAdjustInfo(adjustInfo, employeeId);
            //福利档案基数调整记录数据入库
            batchInsertAdjustHistory(adjustHistoryList, employeeId);
        } finally {
            sqlSession.close();
        }
    }

    /**
     * 校验福利基数是否符合上下限要求
     * @param primaryId
     * @param paymentBaseString
     * @return
     */
    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
     */
    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);
    }

    /**
     * 档案列表
     * <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 (StringUtils.isNotBlank(param.getDepartmentIdsStr())) {
            request.setDepartmentIds(Arrays.stream(param.getDepartmentIdsStr().split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }

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


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

        if (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();
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        Map<String, Object> datas = new HashMap<>(16);
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<InsuranceArchivesEmployeePO> page = new ArrayList<>();
            PageInfo<InsuranceArchivesEmployeePO> pageInfo = new PageInfo<>(InsuranceArchivesEmployeePO.class);
//            //生成福利档案历史基础信息（在福利档案基础信息表为空时）
//            createOldInsuranceBaseInfo(operateId);
            //获取福利档案列表数据
            if (needAuth) {
                Collection<Long> taxAgentEmployeeIds = param.getTaxAgentEmployeeIds();
                Collection<Long> taxAgentIds = param.getTaxAgentIds();
                log.info("从数据库获取档案列表数据开始");
                sw.start("获取福利档案列表数据");
                if (param.isExtWelArchiveList()) {
                    page = socialSchemeMapper.queryExtEmployeeList(param);
                } else {
                    page = socialSchemeMapper.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 = socialSchemeMapper.queryExtEmployeeList(param);
                } else {
                    page = socialSchemeMapper.queryEmployeeList(param);
                }
                sw.stop();
                log.info("从数据库获取档案列表数据完成！");
                pageInfo = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(),
                        page, InsuranceArchivesEmployeePO.class);
            }
            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(), operateId);
            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;

        } finally {
            sqlSession.close();
        }
    }

    /**
     * @param
     * @param operateId
     * @return
     */
    public List<WeaTableColumn> buildWeaTableColumns(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS, long operateId) {

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

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

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

    /**
     * @param insuranceArchivesEmployeePOS
     * @param operateId
     * @return
     */
    public Map<Integer, Map<String, String>> buildColumnTitle(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS, long operateId) {

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


        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        List<Map<String, Object>> records = new ArrayList<>();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            FundSchemeMapper fundSchemeMapper = sqlSession.getMapper(FundSchemeMapper.class);
            OtherSchemeMapper otherSchemeMapper = sqlSession.getMapper(OtherSchemeMapper.class);
            InsuranceSchemeMapper insuranceSchemeMapper = sqlSession.getMapper(InsuranceSchemeMapper.class);

//            List<Long> employeeIds = insuranceArchivesEmployeePOS.stream().map(InsuranceArchivesEmployeePO::getEmployeeId).collect(Collectors.toList());
            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", insuranceSchemeMapper.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", insuranceSchemeMapper.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", insuranceSchemeMapper.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;

        } finally {
            sqlSession.close();
        }
    }

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

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

    /**
     * 获取信息提示
     */
    public void tips() {
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<Long> employeeIds = socialSchemeMapper.tips();
            SalaryAssert.isEmpty(employeeIds, "当前有离职人员档案存在福利缴纳起始月,未维护福利最后缴纳月，请尽快处理");

        } finally {
            sqlSession.close();
        }
    }

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

        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<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("姓名"); //设置文本值  这个将覆盖多语言标签的值
        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("工号"); //设置文本值  这个将覆盖多语言标签的值
        conditionItems.add(jobNum);


        SearchConditionItem departmentIds = conditionFactory.createCondition(ConditionType.BROWSER, 502329, "departmentIdsStr", "57");
        departmentIds.setColSpan(2);
        departmentIds.setFieldcol(16);
        departmentIds.setLabelcol(8);
        departmentIds.setLabel("部门");
        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("状态");
        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("岗位");
        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("分部");
        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("入职日期");
//        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("离职日期");
//        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("社保方案");
        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("公积金方案");
        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("其它福利方案");
        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("个税扣缴义务人");
        conditionItems.add(taxAgentId);

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

    /**
     * 组装员工的社保，公积金，其他福利数据
     *
     * @param ids 员工id集合
     * @return map
     */
    public Map<Long, InsuranceArchivesAccountPO> buildBatchAccount(List<Long> ids, Long paymentOrganization) {
        if (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 (CollectionUtils.isNotEmpty(socialPOS)) {
            socialMap = socialPOS.stream().collect(Collectors.toMap(InsuranceArchivesSocialSchemePO::getEmployeeId, Function.identity()));
        }
        List<InsuranceArchivesFundSchemePO> fundPOS = encryptUtil.decryptList(this.getFundByEmployeeIdAndPayOrg(insuranceArchivesEmployeePOS), InsuranceArchivesFundSchemePO.class);
        if (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 (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;
    }


    /**
     * 判断是否需要生成历史福利档案基本信息
     */
    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;
        }

    }

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

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

    }

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

    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;

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

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

        List<InsuranceArchivesBaseHistoryPO> toCreateAdjustHistoryList = new ArrayList<>();
        //旧档案不存在基数信息，则直接遍历新的基数数据，生成调整记录；旧档案存在基数信息，则合并新旧基数数据，遍历合并后的技术数据中的key，生成调整记录。
        if(StringUtils.isNotBlank(adjustInfo.getAdjustAfterBaseJson()) && 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 (StringUtils.isNotBlank(adjustInfo.getAdjustAfterBaseJson()) && 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(StringUtils.isNotBlank(adjustInfo.getAdjustAfterComBaseJson()) && 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 (StringUtils.isNotBlank(adjustInfo.getAdjustAfterComBaseJson()) && 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;
    }

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

        if (CollectionUtils.isEmpty(adjustHistoryList)) {
            return;
        }
        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            InsuranceBaseAdjustHistoryMapper mapper = sqlSession.getMapper(InsuranceBaseAdjustHistoryMapper.class);
            List<List<InsuranceArchivesBaseHistoryPO>> partition = Lists.partition(adjustHistoryList, 100);
            partition.forEach(mapper::batchSave);
            sqlSession.commit();
        } 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) {


        SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
        try {
            InsuranceBaseAdjustHistoryMapper mapper = sqlSession.getMapper(InsuranceBaseAdjustHistoryMapper.class);
            List<InsuranceArchivesBaseHistoryDTO> empList = mapper.listByEmployeeIdAndOperator(operator, employeeId);
            List<InsuranceArchivesBaseHistoryDTO> extEmpList = mapper.listByExtEmpIdAndOperator(operator, employeeId);
            if (extEmpList != null) {
                empList.addAll(extEmpList);
                empList = empList.stream().filter(f -> StringUtils.isNotBlank(f.getEmployeeName()))
                        .sorted(Comparator.comparing(InsuranceArchivesBaseHistoryDTO::getOperateTime).reversed()).collect(Collectors.toList());
            }
            return empList;
        } finally {
            sqlSession.close();
        }
    }

    public List<WeaTableColumn> buildAdjustHistoryColumns(long operateId) {
        List<WeaTableColumn> list = new ArrayList<>();
        WeaTableColumn nameColumn = new WeaTableColumn("100px", "福利项名称", "welfareItemName");
        nameColumn.setFixed("left");
        list.add(nameColumn);
        list.add(new WeaTableColumn("150px", "调整前方案", "adjustBeforeSchemeName"));
        list.add(new WeaTableColumn("150px", "调整前基数", "adjustBeforeBaseValue"));
        list.add(new WeaTableColumn("150px", "调整后方案", "adjustAfterSchemeName"));
        list.add(new WeaTableColumn("150px", "调整后基数", "adjustAfterBaseValue"));
        list.add(new WeaTableColumn("150px", "操作人", "operatorName"));
        list.add(new WeaTableColumn("150px", "操作时间", "operatorTime"));
        return list;
    }

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