//package com.engine.salary.service.impl;
//
//import com.engine.salary.cache.SalaryCacheKey;
//import com.engine.salary.constant.SalaryDefaultTenantConstant;
//import com.engine.salary.entity.datacollection.DataCollectionEmployee;
//import com.engine.salary.entity.salaryacct.bo.*;
//import com.engine.salary.entity.salaryacct.dto.SalaryAcctRateDTO;
//import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
//import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
//import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
//import com.engine.salary.entity.salaryformula.ExpressFormula;
//import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
//import com.engine.salary.service.*;
//import com.engine.salary.util.SalaryEntityUtil;
//import com.google.common.collect.Lists;
//import com.google.common.collect.Maps;
//import com.googlecode.aviator.Expression;
//import com.weaver.common.distribution.genid.IdGenerator;
//import com.weaver.common.elog.dto.LoggerContext;
//import com.weaver.common.elog.util.Util;
//import com.weaver.common.hrm.domain.employee.HrmStatus;
//import com.weaver.datasecurity.interceptor.DSTenantKeyThreadVar;
//import com.weaver.excel.formula.api.entity.FormulaVar;
//import com.weaver.excel.formula.entity.parameter.standard.ExcelResult;
//import com.weaver.framework.util.JsonUtil;
//import com.weaver.hrm.salary.common.LocalDateRange;
//import com.weaver.hrm.salary.constant.SalaryFormulaFieldConstant;
//import com.weaver.hrm.salary.entity.customdata.param.CustomDataEmployeeQueryParam;
//import com.weaver.hrm.salary.entity.customdata.po.CustomDataEmployeePO;
//import com.weaver.hrm.salary.entity.customdata.po.CustomDataRecordPO;
//import com.weaver.hrm.salary.entity.datacollection.dto.AttendQuoteDataDTO;
//import com.weaver.hrm.salary.entity.datacollection.po.AddUpDeductionPO;
//import com.weaver.hrm.salary.entity.datacollection.po.AddUpSituationPO;
//import com.weaver.hrm.salary.entity.datacollection.po.OtherDeductionPO;
//import com.weaver.hrm.salary.entity.extemployee.po.ExtEmployeePO;
//import com.weaver.hrm.salary.entity.salaryacct.bo.*;
//import com.weaver.hrm.salary.entity.salaryacct.po.*;
//import com.weaver.hrm.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO;
//import com.weaver.hrm.salary.entity.salarysob.dto.SalarySobCycleDTO;
//import com.weaver.hrm.salary.entity.salarysob.po.SalarySobAdjustRulePO;
//import com.weaver.hrm.salary.entity.salarysob.po.SalarySobBackItemPO;
//import com.weaver.hrm.salary.entity.salarysob.po.SalarySobItemPO;
//import com.weaver.hrm.salary.entity.salarysob.po.SalarySobPO;
//import com.weaver.hrm.salary.enums.OperateTypeEnum;
//import com.weaver.hrm.salary.enums.salaryaccounting.EmployeeTypeEnum;
//import com.weaver.hrm.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
//import com.weaver.hrm.salary.enums.salaryitem.SalaryDataTypeEnum;
//import com.weaver.hrm.salary.enums.salaryitem.SalaryFormulaReferenceEnum;
//import com.weaver.hrm.salary.enums.salaryitem.SalaryRoundingModeEnum;
//import com.weaver.hrm.salary.enums.salarysob.IncomeCategoryEnum;
//import com.weaver.hrm.salary.enums.sicategory.DeleteTypeEnum;
//import com.weaver.hrm.salary.exception.SalaryRunTimeException;
//import com.weaver.hrm.salary.service.*;
//import com.weaver.hrm.salary.util.SalaryI18nUtil;
//import com.weaver.util.threadPool.ThreadPoolUtil;
//import com.weaver.util.threadPool.constant.ModulePoolEnum;
//import com.weaver.util.threadPool.entity.LocalRunnable;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.collections4.CollectionUtils;
//import org.apache.commons.collections4.MapUtils;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.lang3.math.NumberUtils;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//import java.time.LocalDateTime;
//import java.time.Month;
//import java.util.*;
//import java.util.concurrent.BlockingDeque;
//import java.util.concurrent.CountDownLatch;
//import java.util.concurrent.LinkedBlockingDeque;
//import java.util.stream.Collectors;
//
///**
// * 薪资核算
// *
// * <p>Copyright: Copyright (c) 2022</p>
// * <p>Company: 泛微软件</p>
// *
// * @author qiantao
// * @version 1.0
// **/
//@Slf4j
//public class SalaryAcctCalcServiceImpl implements SalaryAcctCalcService {
//
//
//    private SalaryAcctRecordService salaryAcctRecordService;
//
//    private SalarySobItemService salarySobItemService;
//
////    private SalarySobBackItemService salarySobBackItemService;
//
//    private SalarySobAdjustRuleService salarySobAdjustRuleService;
//
//    private SalaryFormulaService salaryFormulaService;
//
//    private SalaryItemService salaryItemService;
//
//    private SalaryAcctEmployeeService salaryAcctEmployeeService;
//
//    private SalaryArchiveService salaryArchiveService;
//
//    private AddUpSituationService addUpSituationService;
//
//    private AddUpDeductionService addUpDeductionService;
//
//    private OtherDeductionService otherDeductionService;
//
//    private AttendQuoteDataService attendQuoteDataService;
//
//    private SIAccountService siAccountService;
//
//    private SalaryCacheService salaryCacheService;
//
////    private CustomDataRecordService customDataRecordService;
//
////    private CustomDataEmployeeService customDataEmployeeService;
//
////    private HrmCommonEmployeeService hrmCommonEmployeeService;
//
////    private ExtEmployeeService extEmployeeService;
//
////    private SalaryAcctResultValueService salaryAcctResultValueService;
//
//
//    private SalarySobService salarySobService;
//
////    private SalaryAcctSobConfigService salaryAcctSobConfigService;
//
//
//    @Override
//    public void calcByRecordId(Long salaryAcctRecordId, DataCollectionEmployee simpleEmployee) throws Exception {
//        calcByEmployeeIds(salaryAcctRecordId, Collections.emptyList(), simpleEmployee);
//    }
//
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public void calcByEmployeeIds(Long salaryAcctRecordId, Collection<Long> salaryAcctEmployeeIds, DataCollectionEmployee simpleEmployee) throws Exception {
//        SalaryAcctRateDTO salaryAcctRate = new SalaryAcctRateDTO("" + salaryAcctRecordId);
//        try {
//            String tenantKey = SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY;
//            // 查询本次核算的薪资核算人员
//            List<SalaryAcctEmployeePO> salaryAcctEmployees;
//            if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) {
//                salaryAcctEmployees = salaryAcctEmployeeService.listBySalaryAcctRecordId(salaryAcctRecordId);
//            } else {
//                salaryAcctEmployees = salaryAcctEmployeeService.listByIds(salaryAcctEmployeeIds);
//            }
//            // 初始化核算进度(总数+1是因为所有人员核算完成后，数据保存入库还需要一定的时间)
//            salaryAcctRate.setTotalQty(salaryAcctEmployees.size() + 1);
//            salaryCacheService.set(SalaryCacheKey.ACCT_PROGRESS + salaryAcctRate.getIndex(), salaryAcctRate);
//            // 查询薪资核算记录
//            SalaryAcctRecordPO salaryAcctRecord = salaryAcctRecordService.getById(salaryAcctRecordId);
//            // 检查是否能够核算
//            checkBeforeCalc(salaryAcctRecord, salaryAcctEmployees);
//            // 加载函数
////            salaryFormulaService.initFunction();
//            // 构建核算上下文
//            SalaryCalcContext salaryCalcContext = loadContext(salaryAcctRecord, simpleEmployee);
//            // 分批核算
//            List<List<SalaryAcctEmployeePO>> salaryAcctEmployeePartition = SalaryAcctEmployeeBO.partitionByEmployeeId(salaryAcctEmployees);
//            // 监控子线程的任务执行
//            CountDownLatch childMonitor = new CountDownLatch(salaryAcctEmployeePartition.size());
//            // 记录子线程的执行结果
//            BlockingDeque<SalaryCalcResult> blockingDeque = new LinkedBlockingDeque<>(salaryAcctEmployeePartition.size());
//            for (List<SalaryAcctEmployeePO> partSalaryAcctEmployees : salaryAcctEmployeePartition) {
//                LocalRunnable localRunnable = new LocalRunnable() {
//                    @Override
//                    public void execute() {
//                        calc(salaryCalcContext, partSalaryAcctEmployees, childMonitor, blockingDeque, simpleEmployee);
//                    }
//                };
//                ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.OTHER, "salaryAcctCalculate", localRunnable);
//            }
//            // 等待核算结束
//            childMonitor.await();
//            // 处理核算结果
//            handleCalcResult(blockingDeque, salaryAcctRecordId, salaryAcctEmployeeIds, tenantKey);
//            // 记录日志
//            writeLog(salaryAcctRecordId, tenantKey);
//            // 核算结束，更新进度
//            salaryAcctRate.setFinish(true).setCalcQty(salaryAcctEmployees.size()).setRate(BigDecimal.ONE);
//        } finally {
//            // 更新进度
//            salaryCacheService.set(SalaryCacheKey.ACCT_PROGRESS + salaryAcctRate.getIndex(), salaryAcctRate);
//        }
//    }
//
//    private void calc(SalaryCalcContext salaryCalcContext,
//                      List<SalaryAcctEmployeePO> salaryAcctEmployees,
//                      CountDownLatch childMonitor,
//                      BlockingDeque<SalaryCalcResult> blockingDeque,
//                      DataCollectionEmployee simpleEmployee) {
//        try {
//            // 数据库字段加密用
//            LocalDateTime now = LocalDateTime.now();
//            // 加载公式计算时所需要的变量
//            SalaryCalcEmployeeContext salaryCalcEmployeeContext = loadEmployeeContext(salaryCalcContext, salaryAcctEmployees, simpleEmployee.getTenantKey());
//            // 对薪资核算人员进行分组，如果是合并计算(工资薪金、劳务一起计算)的话，会存在工资薪金和劳务费用的项目存在相互引用，所以相关联的人员要在同一组进行核算
//            Map<Long, List<SalaryAcctEmployeePO>> salaryAcctEmployeeMap = SalaryEntityUtil.group2Map(salaryAcctEmployees, SalaryAcctEmployeePO::getId);
////            if (salaryCalcContext.getSalarySobCycle().getIncomeCategories().size() > 1) {
////                salaryAcctEmployeeMap = SalaryEntityUtil.group2Map(salaryAcctEmployees, SalaryAcctEmployeePO::getEmployeeId);
////            }
//            // 计算公式
//            int calcQty = 0;
//            List<SalaryAcctResultPO> newSalaryAcctResultValues = Lists.newArrayListWithExpectedSize(salaryAcctEmployees.size());
//            for (Map.Entry<Long, List<SalaryAcctEmployeePO>> entry : salaryAcctEmployeeMap.entrySet()) {
//                // 获取锁定的薪资项目
//                Set<Long> lockSalaryItemIds = new HashSet<>(Collections.emptySet());
//                for (SalaryAcctEmployeePO salaryAcctEmployee : entry.getValue()) {
//                    SalaryAcctResultPO noDecryptSalaryAcctResultValue = salaryCalcEmployeeContext.getNoDecryptAcctResultValueMap().get(salaryAcctEmployee.getId());
////                    if (noDecryptSalaryAcctResultValue != null) {
////                        lockSalaryItemIds.addAll(noDecryptSalaryAcctResultValue.getLockSalaryItemIds());
////                    }
//                }
//                Map<String, Map<String, String>> incomeCategoryResultValueMap = Maps.newHashMap();
//                Map<String, SalaryAcctEmployeePO> incomeCategoryAcctEmployeeMap = SalaryEntityUtil.convert2Map(entry.getValue(), SalaryAcctEmployeePO::getIncomeCategory);
//                // 根据解析好的公式计算优先级计算公式
//                for (List<SalaryCalcFormula> formulaPriority : salaryCalcContext.getSalaryCalcFormulaContext().getSalaryCalcFormulas()) {
//                    for (SalaryCalcFormula salaryCalcFormula : formulaPriority) {
//                        SalaryAcctEmployeePO salaryAcctEmployee;
//                        if (Objects.equals(salaryCalcFormula.getIncomeCategory(), "0")) {
//                            salaryAcctEmployee = SalaryEntityUtil.findFirst(entry.getValue());
//                        } else {
//                            salaryAcctEmployee = incomeCategoryAcctEmployeeMap.get(salaryCalcFormula.getIncomeCategory());
//                        }
//                        if (salaryAcctEmployee == null) {
//                            continue;
//                        }
//                        // 找出需要计算的公式
//                        SalaryItemPO salaryItem = salaryCalcContext.getSalaryCalcFormulaContext().getSalaryItemMap().get(salaryCalcFormula.getSalaryItemId());
//                        ExpressFormula expressFormula = salaryCalcContext.getSalaryCalcFormulaContext().getExpressFormulaMap().get(salaryCalcFormula.getFormulaId());
//                        Expression expression = salaryCalcContext.getSalaryCalcFormulaContext().getExpressionMap().get(salaryCalcFormula.getFormulaId());
//                        // 获取变量的值
//                        Map<String, String> formulaVarValueMap = salaryCalcEmployeeContext.getFormulaVarValueMap().computeIfAbsent(salaryAcctEmployee.getId(), k -> new HashMap<>());
//                        // 运行公式获取结果
//                        String resultValue = calcResultValue(salaryCalcFormula, expressFormula, expression, formulaVarValueMap, lockSalaryItemIds, salaryCalcContext.getSimpleEmployee());
//                        // 处理合并计税
//                        resultValue = handleConsolidatedTax(salaryCalcContext, salaryCalcEmployeeContext, salaryAcctEmployee, resultValue, salaryItem);
//                        // 处理小数位数
//                        resultValue = roundResultValue(resultValue, salaryCalcFormula);
//                        // 将公式计算结果回填到变量map中
//                        formulaVarValueMap.put(SalaryFormulaReferenceEnum.SALARY_ITEM.getValue()
//                                + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItem.getCode(), resultValue);
//                        // 合并计算时工资薪金和劳务费用的项目存在相互引用，所以需要将公式计算结果回填到另一个相关联的薪资核算人员的变量map中
//                        for (SalaryAcctEmployeePO relationSalaryAcctEmployee : entry.getValue()) {
//                            if (!Objects.equals(relationSalaryAcctEmployee.getId(), salaryAcctEmployee.getId())) {
//                                Map<String, String> relationFormulaVarValueMap = salaryCalcEmployeeContext.getFormulaVarValueMap().computeIfAbsent(relationSalaryAcctEmployee.getId(), k -> new HashMap<>());
//                                relationFormulaVarValueMap.put(SalaryFormulaReferenceEnum.SALARY_ITEM.getValue()
//                                        + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItem.getCode(), resultValue);
//                            }
//                        }
//                        // 计算结果
//                        Map<String, String> resultValueMap = incomeCategoryResultValueMap.computeIfAbsent(salaryCalcFormula.getIncomeCategory(), k -> Maps.newHashMap());
//                        resultValueMap.put("" + salaryCalcFormula.getSalaryItemId(), resultValue);
//                    }
//                }
//                for (SalaryAcctEmployeePO salaryAcctEmployee : entry.getValue()) {
//                    Map<String, String> resultValueMap = Maps.newHashMap();
//                    // 根据薪资核算人员的收入所得项目(工资薪金或者劳务)，获取对应的薪资核算结果
//                    resultValueMap.putAll(incomeCategoryResultValueMap.getOrDefault(salaryAcctEmployee.getIncomeCategory(), Collections.emptyMap()));
//                    // 回算薪资项目既不属于工资薪金也不属于劳务，但是也要保存到人员的薪资核算结果中
//                    resultValueMap.putAll(incomeCategoryResultValueMap.getOrDefault("0", Collections.emptyMap()));
//                    SalaryAcctResultValuePO noDecryptSalaryAcctResultValue = salaryCalcEmployeeContext.getNoDecryptAcctResultValueMap().get(salaryAcctEmployee.getId());
//                    SalaryAcctResultValuePO newSalaryAcctResultValue = new SalaryAcctResultValuePO()
//                            .setId(IdGenerator.generate())
//                            .setSalaryAcctRecordId(salaryAcctEmployee.getSalaryAcctRecordId())
//                            .setSalaryAcctEmployeeId(salaryAcctEmployee.getId())
//                            .setResultValue(resultValueMap)
//                            .setOriginResultValueJson(noDecryptSalaryAcctResultValue == null
//                                    ? StringUtils.EMPTY : noDecryptSalaryAcctResultValue.getOriginResultValueJson())
//                            .setLockSalaryItemIds(lockSalaryItemIds)
//                            .setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue())
//                            .setTenantKey(simpleEmployee.getTenantKey())
//                            .setCreator(simpleEmployee.getEmployeeId())
//                            .setCreateTime(now)
//                            .setUpdateTime(now);
//                    newSalaryAcctResultValues.add(newSalaryAcctResultValue);
//                    // 更新计算进度
//                    updateRate(salaryCalcContext.getSalaryAcctRecord().getId(), ++calcQty, salaryAcctEmployees.size());
//                }
//            }
//            blockingDeque.add(new SalaryCalcResult(true, "", newSalaryAcctResultValues));
//        } catch (Exception e) {
//            log.info("薪资核算失败：{}", e.getMessage(), e);
//            blockingDeque.add(new SalaryCalcResult(false, e.getMessage(), Collections.emptyList()));
//        } finally {
//            // 子线程执行完毕
//            childMonitor.countDown();
//            // 数据库字段加密用
//            DSTenantKeyThreadVar.tenantKey.remove();
//        }
//    }
//
//    private void checkBeforeCalc(SalaryAcctRecordPO salaryAcctRecordPO, List<SalaryAcctEmployeePO> salaryAcctEmployees) {
//        if (Objects.isNull(salaryAcctRecordPO)) {
//            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145221, "薪资核算记录不存在或已被删除"));
//        }
//        // 归档状态或已申报状态下不能核算
//        if (!Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) {
//            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(145222, "薪资核算记录已经归档，不能再核算"));
//        }
//        // 没有薪资核算人员不能核算
//        if (CollectionUtils.isEmpty(salaryAcctEmployees)) {
//            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "当前核算人员为空，请先确认要核算的人员"));
//        }
//    }
//
//    private SalaryCalcContext loadContext(SalaryAcctRecordPO salaryAcctRecord, DataCollectionEmployee simpleEmployee) {
//        String tenantKey = simpleEmployee.getTenantKey();
//        // 查询考勤周期、薪资周期、税款所属期、社保福利台账月份
//        SalarySobCycleDTO salarySobCycle = salaryAcctRecordService.getSalarySobCycleById(salaryAcctRecord.getId(), tenantKey);
//        // 查询薪资核算记录的账套配置
//        SalaryAcctSobConfigPO salaryAcctSobConfig = salaryAcctSobConfigService.getBySalaryAcctRecordId(salaryAcctRecord.getId(), tenantKey);
//        // 薪资项目
//        List<SalarySobItemPO> salarySobItems = JsonUtil.parseList(salaryAcctSobConfig.getItemConfig(), SalarySobItemPO.class);
//        // 回算薪资项目
//        List<SalarySobBackItemPO> salarySobBackItems = !Objects.equals(salaryAcctRecord.getBackCalcStatus(), 1) ? Collections.emptyList()
//                : JsonUtil.parseList(salaryAcctSobConfig.getBackItemConfig(), SalarySobBackItemPO.class);
//        // 查询薪资项目所用的公式id
//        Set<Long> formulaIds = new HashSet<>();
//        formulaIds.addAll(SalaryEntityUtil.properties(salarySobItems, SalarySobItemPO::getFormulaId));
//        formulaIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getFormulaId));
//        List<ExpressFormula> expressFormulas = salaryFormulaService.listOriginExpressFormula(formulaIds, tenantKey);
//        // 查询薪资项目
//        Set<Long> salaryItemIds = new HashSet<>();
//        salaryItemIds.addAll(SalaryEntityUtil.properties(salarySobItems, SalarySobItemPO::getSalaryItemId));
//        salaryItemIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getSalaryItemId));
//        List<SalaryItemPO> salaryItems = salaryItemService.listByIds(salaryItemIds, tenantKey);
//        // 计算薪资项目的计算优先级
//        SalaryCalcPriority salaryCalcPriority = new SalaryCalcPriority(salaryItems, salarySobItems, salarySobBackItems, expressFormulas);
//        SalaryCalcFormulaContext salaryCalcFormulaContext = salaryCalcPriority.calc();
//        // 查询薪资核算所用的调薪计薪规则
//        List<SalarySobAdjustRulePO> salarySobAdjustRules = salarySobAdjustRuleService.listBySalarySobId(salaryAcctRecord.getSalarySobId(), tenantKey);
//        // 查询员工状态
//        List<HrmStatus> hrmStatusList = hrmCommonHrmStatusService.list(tenantKey);
//        Map<String, String> hrmStatusMap = SalaryEntityUtil.convert2Map(hrmStatusList, hrmStatus -> "" + hrmStatus.getCodeId(), HrmStatus::getName);
//
//        // 构建上下文
//        SalaryCalcContext salaryCalcContext = new SalaryCalcContext();
//        salaryCalcContext.setSimpleEmployee(simpleEmployee);
//        salaryCalcContext.setHrmStatusMap(hrmStatusMap);
//        salaryCalcContext.setSalaryAcctRecord(salaryAcctRecord);
//        salaryCalcContext.setSalarySobCycle(salarySobCycle);
//        salaryCalcContext.setSalaryAdjustmentRules(salarySobAdjustRules);
//        salaryCalcContext.setSalaryCalcFormulaContext(salaryCalcFormulaContext);
//        return salaryCalcContext;
//    }
//
//    private SalaryCalcEmployeeContext loadEmployeeContext(SalaryCalcContext salaryCalcContext, List<SalaryAcctEmployeePO> salaryAcctEmployees, String tenantKey) {
//        // 查询合并计税的薪资核算记录
//        LocalDateRange localDateRange = LocalDateRange.builder()
//                .fromDate(salaryCalcContext.getSalarySobCycle().getTaxCycle().atDay(1))
//                .endDate(salaryCalcContext.getSalarySobCycle().getTaxCycle().atEndOfMonth())
//                .build();
//        List<SalaryAcctRecordPO> salaryAcctRecords = salaryAcctRecordService.listByTaxCycle(localDateRange, tenantKey);
//        Map<Long, SalaryAcctRecordPO> salaryAcctRecordMap = SalaryEntityUtil.convert2Map(salaryAcctRecords, SalaryAcctRecordPO::getId);
//        // 查询合并计税的薪资核算人员
//        List<SalaryAcctEmployeePO> sameTaxCycleSalaryAcctEmployees = salaryAcctEmployeeService.listSameTaxCycle(salaryAcctEmployees, salaryCalcContext.getSalarySobCycle().getTaxCycle().toString(), tenantKey);
//        Map<String, List<SalaryAcctEmployeePO>> sameTaxCycleEmployeeMap = SalaryEntityUtil.group2Map(sameTaxCycleSalaryAcctEmployees, o -> o.getEmployeeId() + "-" + o.getTaxAgentId());
//        Set<Long> sameTaxCycleSalaryAcctEmployeeIds = SalaryEntityUtil.properties(sameTaxCycleSalaryAcctEmployees, SalaryAcctEmployeePO::getId);
//        List<SalaryAcctResultValuePO> sameTaxCycleResultValues = salaryAcctResultValueService
//                .listBySalaryAcctEmployeeIds(sameTaxCycleSalaryAcctEmployeeIds, tenantKey);
//        Map<Long, SalaryAcctResultValuePO> sameTaxCycleResultValueMap = SalaryEntityUtil.convert2Map(sameTaxCycleResultValues, SalaryAcctResultValuePO::getSalaryAcctEmployeeId);
//
//        SalaryCalcEmployeeContext salaryCalcEmployeeContext = new SalaryCalcEmployeeContext();
//        salaryCalcEmployeeContext.setSameTaxCycleRecordMap(salaryAcctRecordMap);
//        salaryCalcEmployeeContext.setSameTaxCycleEmployeeMap(sameTaxCycleEmployeeMap);
//        salaryCalcEmployeeContext.setSameTaxCycleResultValueMap(sameTaxCycleResultValueMap);
//        // 加载公式变量
//        loadFormulaVar(salaryCalcContext, salaryCalcEmployeeContext, salaryAcctEmployees);
//        return salaryCalcEmployeeContext;
//    }
//
//    private void loadFormulaVar(SalaryCalcContext salaryCalcContext, SalaryCalcEmployeeContext salaryCalcEmployeeContext, List<SalaryAcctEmployeePO> salaryAcctEmployees) {
//        String tenantKey = salaryCalcContext.getSimpleEmployee().getTenantKey();
//        // 薪资核算人员中的组织架构人员
//        List<Long> employeeIds = SalaryEntityUtil.properties(salaryAcctEmployees, SalaryAcctEmployeePO::getEmployeeId, Collectors.toList());
//        // 查询薪资档案
//        List<SalaryArchiveDataDTO> salaryArchiveDataList = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getSalaryArchiveFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            salaryArchiveDataList = salaryArchiveService.getSalaryArchiveData(salaryCalcContext.getSalarySobCycle().getSalaryCycle(), employeeIds, tenantKey);
//        }
//        // 查询往期累计情况
//        List<AddUpSituationPO> addUpSituations = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getAddUpSituationFieldIds())
//                && salaryCalcContext.getSalarySobCycle().getTaxCycle().getMonth() != Month.JANUARY
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            addUpSituations = addUpSituationService.getAddUpSituationList(salaryCalcContext.getSalarySobCycle().getTaxCycle().plusMonths(-1), employeeIds, tenantKey);
//        }
//        // 查询累计专项附加扣除
//        List<AddUpDeductionPO> addUpDeductions = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getAddUpDeductionFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            addUpDeductions = addUpDeductionService.getAddUpDeductionList(salaryCalcContext.getSalarySobCycle().getTaxCycle(), employeeIds, tenantKey);
//        }
//        // 查询其他扣除
//        List<OtherDeductionPO> otherDeductions = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getOtherDeductionFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            otherDeductions = otherDeductionService.getOtherDeductionList(salaryCalcContext.getSalarySobCycle().getTaxCycle(), employeeIds, tenantKey);
//        }
//        // 查询考勤
//        List<AttendQuoteDataDTO> attendQuoteDataList = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getAttendFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            SalarySobPO salarySob = salarySobService.getById(salaryCalcContext.getSalaryAcctRecord().getSalarySobId(), tenantKey);
//            attendQuoteDataList = attendQuoteDataService.getAttendQuoteData(salaryCalcContext.getSalarySobCycle().getSalaryMonth(), salarySob.getOriginSalarySobId(), employeeIds, tenantKey);
//        }
//        // 查询社保福利
//        List<Map<String, Object>> welfareMapList = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getWelfareFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            welfareMapList = siAccountService.welfareData(salaryCalcContext.getSalarySobCycle().getSocialSecurityCycle().toString(), employeeIds, tenantKey);
//        }
//        // 查询自定义业务数据
//        List<CustomDataEmployeePO> customDataEmployees = Collections.emptyList();
//        if (MapUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getCustomDataFieldIdMap())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            Set<Long> customFieldIds = salaryCalcContext.getSalaryCalcFormulaContext().getCustomDataFieldIdMap().values().stream()
//                    .flatMap(Collection::stream)
//                    .map(fieldId -> Util.getLongValue(fieldId, 0L))
//                    .collect(Collectors.toSet());
//            List<CustomDataRecordPO> customDataRecords = customDataRecordService.listByCustomFormIdsAndSalaryMonth(
//                    salaryCalcContext.getSalaryCalcFormulaContext().getCustomDataFieldIdMap().keySet(),
//                    salaryCalcContext.getSalarySobCycle().getSalaryMonth(),
//                    salaryCalcContext.getSimpleEmployee().getEmployeeId(), tenantKey);
//            CustomDataEmployeeQueryParam param = new CustomDataEmployeeQueryParam()
//                    .setCustomDataRecordIds(SalaryEntityUtil.properties(customDataRecords, CustomDataRecordPO::getId))
//                    .setEmployeeIds(employeeIds)
//                    .setCustomFieldIds(customFieldIds);
//            customDataEmployees = customDataEmployeeService.listByParam(param, tenantKey);
//        }
//        // 查询人员信息
//        List<DataCollectionEmployee> simpleEmployees = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getEmployeeInfoFieldIds())
//                && CollectionUtils.isNotEmpty(employeeIds)) {
//            simpleEmployees = hrmCommonEmployeeService.getEmployeeByIds(employeeIds, tenantKey);
//        }
//        // 查询外部人员
//        List<Long> extEmployeeIds = salaryAcctEmployees.stream()
//                .filter(salaryAcctEmployee -> Objects.equals(salaryAcctEmployee.getEmployeeType(), EmployeeTypeEnum.EXT_EMPLOYEE.getValue()))
//                .map(SalaryAcctEmployeePO::getEmployeeId)
//                .distinct()
//                .collect(Collectors.toList());
//        List<ExtEmployeePO> extEmployees = Collections.emptyList();
//        if (CollectionUtils.isNotEmpty(salaryCalcContext.getSalaryCalcFormulaContext().getExtEmployeeFieldIds())
//                && CollectionUtils.isNotEmpty(extEmployeeIds)) {
//            extEmployees = extEmployeeService.listByIdsWithDeleted(extEmployeeIds, tenantKey);
//        }
//        // 查询薪资核算结果(不解密)
//        Set<Long> salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployees, SalaryAcctEmployeePO::getId);
//        List<SalaryAcctResultValuePO> noDecryptSalaryAcctResultValues = salaryAcctResultValueService.listNoDecryptBySalaryAcctEmployeeIds(salaryAcctEmployeeIds, tenantKey);
//        Map<Long, SalaryAcctResultValuePO> noDecryptSalaryAcctResultValueMap = SalaryEntityUtil.convert2Map(noDecryptSalaryAcctResultValues, SalaryAcctResultValuePO::getSalaryAcctEmployeeId);
//        salaryCalcEmployeeContext.setNoDecryptAcctResultValueMap(noDecryptSalaryAcctResultValueMap);
//        // 查询薪资核算结果(解密)
//        List<SalaryAcctResultValuePO> salaryAcctResultValues = salaryAcctResultValueService.listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds, tenantKey);
//
//        SalaryCalcFormulaVar salaryCalcFormulaVar = new SalaryCalcFormulaVar(salaryArchiveDataList, addUpSituations,
//                addUpDeductions, otherDeductions, attendQuoteDataList, welfareMapList, customDataEmployees, simpleEmployees, extEmployees, salaryAcctResultValues);
//        Map<Long, List<SalaryCalcFormulaVarValue>> resultMap = salaryCalcFormulaVar.handleSalaryCalcFormulaVar(salaryCalcContext, salaryAcctEmployees);
//        Map<Long, Map<String, String>> formulaVarValueMap = Maps.newHashMapWithExpectedSize(resultMap.size());
//        resultMap.forEach((k, v) -> {
//            Map<String, String> map = SalaryEntityUtil.convert2Map(v, SalaryCalcFormulaVarValue::getFieldId, SalaryCalcFormulaVarValue::getFieldValue);
//            formulaVarValueMap.put(k, map);
//        });
//        salaryCalcEmployeeContext.setFormulaVarValueMap(formulaVarValueMap);
//    }
//
//    private String calcResultValue(SalaryCalcFormula salaryCalcFormula,
//                                   ExpressFormula expressFormula,
//                                   Expression expression,
//                                   Map<String, String> formulaVarValueMap,
//                                   Set<Long> lockSalaryItemIds,
//                                   DataCollectionEmployee simpleEmployee) {
//        String originValue = formulaVarValueMap.getOrDefault(SalaryFormulaReferenceEnum.SALARY_ITEM.getValue()
//                + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryCalcFormula.getSalaryItemCode(), "");
//        if (Objects.isNull(expressFormula) || lockSalaryItemIds.contains(salaryCalcFormula.getSalaryItemId())) {
//            if (Objects.equals(salaryCalcFormula.getUseInEmployeeSalary(), NumberUtils.INTEGER_ONE) && !lockSalaryItemIds.contains(salaryCalcFormula.getSalaryItemId())) {
//                return formulaVarValueMap.getOrDefault(SalaryFormulaReferenceEnum.SALARY_ARCHIVES.getValue()
//                        + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryCalcFormula.getSalaryItemId(), "");
//            }
//            return originValue;
//        }
//        // 如果只包含了优化的函数，走本模块的计算，否则走公式模块提供的公共方法计算
//        if (expression != null) {
//            try {
//                // 填充变量的值
//                Map<String, Object> envMap = ExpressFormulaBO.fillExpressionEnvMap(expressFormula, formulaVarValueMap);
//                // 运行公式
//                return Util.null2String(expression.execute(envMap));
//            } catch (Exception e) {
//                log.info("公式计算错误：{}", expressFormula.getFormula(), e);
//                return StringUtils.EMPTY;
//            }
//        }
//        // 填充变量的值
//        List<FormulaVar> formulaVars = ExpressFormulaBO.fillFormulaVarContent(expressFormula, formulaVarValueMap);
//        // 运行公式
//        ExcelResult excelResult = excelRunService.run(expressFormula, formulaVars, simpleEmployee);
//        if (excelResult.isStatus()) {
//            return excelResult.getStringData();
//        } else {
//            log.info("公式计算错误：{}, 错误原因：{}", expressFormula.getFormula(), excelResult.getErrorMsg());
//            return StringUtils.EMPTY;
//        }
//    }
//
//    private String handleConsolidatedTax(SalaryCalcContext salaryCalcContext,
//                                         SalaryCalcEmployeeContext salaryCalcEmployeeContext,
//                                         SalaryAcctEmployeePO salaryAcctEmployee,
//                                         String resultValue,
//                                         SalaryItemPO salaryItem) {
//        // 只有正常工资薪金所得才需要合并计税处理
//        if (!Objects.equals(salaryAcctEmployee.getIncomeCategory(), "" + IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) {
//            return resultValue;
//        }
//        List<SalaryAcctEmployeePO> sameTaxCycleSalaryAcctEmployees = salaryCalcEmployeeContext.getSameTaxCycleEmployeeMap()
//                .get(salaryAcctEmployee.getEmployeeId() + "-" + salaryAcctEmployee.getTaxAgentId());
//        if (CollectionUtils.isEmpty(sameTaxCycleSalaryAcctEmployees)) {
//            return resultValue;
//        }
//        // 第一次计算时不需要合并计税处理
//        boolean needConsolidatedTax = needConsolidatedTax(salaryCalcEmployeeContext, salaryAcctEmployee, sameTaxCycleSalaryAcctEmployees);
//        if (!needConsolidatedTax) {
//            return resultValue;
//        }
//        List<SalaryAcctResultValuePO> salaryAcctResultValues = Lists.newArrayList();
//        for (SalaryAcctEmployeePO sameTaxCycleSalaryAcctEmployee : sameTaxCycleSalaryAcctEmployees) {
//            SalaryAcctResultValuePO salaryAcctResultValue = salaryCalcEmployeeContext.getSameTaxCycleResultValueMap().get(sameTaxCycleSalaryAcctEmployee.getId());
//            if (salaryAcctResultValue != null) {
//                salaryAcctResultValues.add(salaryAcctResultValue);
//            }
//        }
//        List<SalaryItemPO> salaryItems = Lists.newArrayList(salaryCalcContext.getSalaryCalcFormulaContext().getSalaryItemMap().values());
//        return SalaryAcctConsolidatedTax.handleConsolidatedTaxValue(resultValue, salaryItem, salaryItems, salaryAcctResultValues);
//    }
//
//    /**
//     * 判断是否需要进行合并计税
//     *
//     * @param salaryCalcEmployeeContext
//     * @param salaryAcctEmployee
//     * @param sameTaxCycleSalaryAcctEmployees
//     * @return
//     */
//    private boolean needConsolidatedTax(SalaryCalcEmployeeContext salaryCalcEmployeeContext,
//                                        SalaryAcctEmployeePO salaryAcctEmployee,
//                                        List<SalaryAcctEmployeePO> sameTaxCycleSalaryAcctEmployees) {
//        SalaryAcctRecordPO salaryAcctRecord = salaryCalcEmployeeContext.getSameTaxCycleRecordMap().get(salaryAcctEmployee.getSalaryAcctRecordId());
//        if (salaryAcctRecord == null) {
//            return false;
//        }
//        for (SalaryAcctEmployeePO sameTaxCycleSalaryAcctEmployee : sameTaxCycleSalaryAcctEmployees) {
//            SalaryAcctRecordPO otherSalaryAcctRecord = salaryCalcEmployeeContext.getSameTaxCycleRecordMap()
//                    .get(sameTaxCycleSalaryAcctEmployee.getSalaryAcctRecordId());
//            if (otherSalaryAcctRecord == null) {
//                continue;
//            }
//            if (otherSalaryAcctRecord.getCreateTime().compareTo(salaryAcctRecord.getCreateTime()) < 0) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    private String roundResultValue(String resultValue, SalaryCalcFormula salaryCalcFormula) {
//        // 值为空，不需要四舍五入
//        if (StringUtils.isEmpty(resultValue)) {
//            return StringUtils.EMPTY;
//        }
//        // 薪资项目字段类型为string，无需四舍五入
//        SalaryDataTypeEnum dataTypeEnum = salaryCalcFormula.getDataType();
//        if (dataTypeEnum == SalaryDataTypeEnum.STRING) {
//            return resultValue;
//        }
//        BigDecimal bigDecimalValue = SalaryEntityUtil.empty2Zero(resultValue);
//        RoundingMode roundingMode = RoundingMode.HALF_UP;
//        if (salaryCalcFormula.getRoundingMode() == SalaryRoundingModeEnum.ROUND_UP) {
//            roundingMode = RoundingMode.UP;
//        }
//        if (salaryCalcFormula.getRoundingMode() == SalaryRoundingModeEnum.ROUND_DOWN) {
//            roundingMode = RoundingMode.DOWN;
//        }
//        return bigDecimalValue.setScale(salaryCalcFormula.getPattern(), roundingMode).toPlainString();
//    }
//
//    /**
//     * 更新核算进度
//     *
//     * @param salaryAcctRecordId
//     * @param calcQty
//     */
//    private synchronized void updateRate(Long salaryAcctRecordId, int calcQty, int salaryAcctEmployeeSize) {
//        int addQty = 0;
//        if (calcQty % 10 == 0) {
//            addQty = 10;
//        } else if (Objects.equals(calcQty, salaryAcctEmployeeSize)) {
//            addQty = calcQty % 10;
//        }
//        if (addQty > 0) {
//            SalaryAcctRateDTO salaryAcctRate = salaryCacheService
//                    .get(SalaryCacheKey.ACCT_PROGRESS, "" + salaryAcctRecordId, SalaryAcctRateDTO.class);
//            salaryAcctRate.setCalcQty(salaryAcctRate.getCalcQty() + addQty);
//            salaryCacheService.set(SalaryCacheKey.ACCT_PROGRESS, "" + salaryAcctRecordId, salaryAcctRate);
//        }
//    }
//
//    private void handleCalcResult(BlockingDeque<SalaryCalcResult> blockingDeque,
//                                  Long salaryAcctRecordId, Collection<Long> salaryAcctEmployeeIds,
//                                  String tenantKey) {
//        boolean allSuccess = blockingDeque.stream().allMatch(SalaryCalcResult::isStatus);
//        if (!allSuccess) {
//            // 薪资核算实现的线程的错误信息
//            String errorMsg = blockingDeque.stream()
//                    .filter(result -> !result.isStatus())
//                    .map(SalaryCalcResult::getErrMsg)
//                    .collect(Collectors.joining("|"));
//            // 返回错误信息
//            throw new SalaryRunTimeException("薪资核算失败：" + errorMsg);
//        }
//        // 删除历史数据
//        if (CollectionUtils.isNotEmpty(salaryAcctEmployeeIds)) {
//            salaryAcctResultValueService.deleteBySalaryAcctEmployeeIds(salaryAcctEmployeeIds, tenantKey);
//        } else {
//            salaryAcctResultValueService.deleteBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecordId), tenantKey);
//        }
//        // 保存新数据
//        List<SalaryAcctResultValuePO> salaryAcctResultValues = Lists.newArrayList();
//        for (SalaryCalcResult salaryCalcResult : blockingDeque) {
//            salaryAcctResultValues.addAll(salaryCalcResult.getSalaryAcctResultValues());
//        }
//        salaryAcctResultValueService.batchSave(salaryAcctResultValues, tenantKey);
//    }
//
//    private void writeLog(Long salaryAcctRecordId, String tenantKey) {
//        String targetName = salaryAcctRecordService.getLogTargetNameById(salaryAcctRecordId, tenantKey);
//        LoggerContext<SalaryCheckResultPO> loggerContext = new LoggerContext<>();
//        loggerContext.setTargetId(String.valueOf(salaryAcctRecordId));
//        loggerContext.setTargetName(targetName);
//        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
//        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(95783, "薪资核算"));
//        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(95783, "薪资核算"));
//        salaryAcctRecordLoggerTemplate.write(loggerContext);
//    }
//}
