package com.engine.salary.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.cache.SalaryCacheKey;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.dto.AttendQuoteFieldListDTO;
import com.engine.salary.entity.datacollection.po.VariableItemPO;
import com.engine.salary.entity.hrm.DeptInfo;
import com.engine.salary.entity.hrm.JobCallInfo;
import com.engine.salary.entity.hrm.PositionInfo;
import com.engine.salary.entity.hrm.SubCompanyInfo;
import com.engine.salary.entity.progress.ProgressDTO;
import com.engine.salary.entity.report.po.SalaryAcctResultReportPO;
import com.engine.salary.entity.salaryacct.bo.*;
import com.engine.salary.entity.salaryacct.dto.*;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.*;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO;
import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO;
import com.engine.salary.entity.salaryformula.ExpressFormula;
import com.engine.salary.entity.salaryformula.po.FormulaVar;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.dto.*;
import com.engine.salary.entity.salarysob.po.*;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.common.FilterEnum;
import com.engine.salary.enums.common.SalaryLogGroupTypeEnum;
import com.engine.salary.enums.common.SalaryLogOperateTypeEnum;
import com.engine.salary.enums.salaryaccounting.LockStatusEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctResultDataSourceEnum;
import com.engine.salary.enums.salaryformula.SalaryFormulaReferenceEnum;
import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum;
import com.engine.salary.enums.salarysob.IncomeCategoryEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.hrm.HrmSnapshotMapper;
import com.engine.salary.mapper.salaryacct.SalaryAcctResultMapper;
import com.engine.salary.report.service.SalaryStatisticsReportService;
import com.engine.salary.report.service.impl.SalaryStatisticsReportServiceImpl;
import com.engine.salary.service.*;
import com.engine.salary.sys.constant.SalarySysConstant;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.sys.enums.TaxDeclarationFunctionEnum;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.Column;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StopWatch;
import weaver.conn.RecordSet;
import weaver.conn.RecordSetDataSource;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.BaseBean;
import weaver.general.TimeUtil;
import weaver.hrm.User;
import weaver.wechat.util.Utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.YearMonth;
import java.util.*;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static com.engine.salary.constant.SalaryFormulaFieldConstant.SALARY_PATTERN;
import static com.engine.salary.sys.constant.SalarySysConstant.SALARY_ACCT_SYNC_TYPE;
/**
* 薪资核算结果
*
Copyright: Copyright (c) 2022
* Company: 泛微软件
*
* @author qiantao
* @version 1.0
**/
@Slf4j
public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctResultService {
private EncryptUtil encryptUtil = new EncryptUtil();
private SalaryAcctResultMapper getSalaryAcctResultMapper() {
return MapperProxyFactory.getProxy(SalaryAcctResultMapper.class);
}
private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) {
return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
}
private SalarySobItemService getSalarySobItemService(User user) {
return ServiceUtil.getService(SalarySobItemServiceImpl.class, user);
}
private SalaryItemService getSalaryItemService(User user) {
return ServiceUtil.getService(SalaryItemServiceImpl.class, user);
}
private SalarySobEmpFieldService getSalarySobEmpFieldService(User user) {
return ServiceUtil.getService(SalarySobEmpFieldServiceImpl.class, user);
}
private SalarySobService getSalarySobService(User user) {
return ServiceUtil.getService(SalarySobServiceImpl.class, user);
}
private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
}
private TaxAgentService getTaxAgentService(User user) {
return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
}
private SalaryEmployeeService getSalaryEmployeeService(User user) {
return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
}
private SalaryFormulaService getSalaryFormulaService(User user) {
return ServiceUtil.getService(SalaryFormulaServiceImpl.class, user);
}
private SalarySobAdjustRuleService getSalarySobAdjustRuleService(User user) {
return ServiceUtil.getService(SalarySobAdjustRuleServiceImpl.class, user);
}
private SalarySobItemHideService getSalarySobItemHideService(User user) {
return (SalarySobItemHideService) ServiceUtil.getService(SalarySobItemHideServiceImpl.class, user);
}
private SalaryAcctCalculateService getSalaryAcctCalculateService(User user) {
return ServiceUtil.getService(SalaryAcctCalculateServiceImpl.class, user);
}
private ProgressService getSalaryAcctProgressService(User user) {
return ServiceUtil.getService(ProgressServiceImpl.class, user);
}
private DataSourceTransactionManager dataSourceTransactionManager;
private SalaryAcctResultTempService getSalaryAcctResultTempService(User user) {
return ServiceUtil.getService(SalaryAcctResultTempServiceImpl.class, user);
}
private SIAccountService getSIAccountService(User user) {
return ServiceUtil.getService(SIAccountServiceImpl.class, user);
}
private AttendQuoteFieldService getAttendQuoteFieldService(User user) {
return ServiceUtil.getService(AttendQuoteFieldServiceImpl.class, user);
}
private SalaryAcctReportService getSalaryAcctReportService(User user) {
return ServiceUtil.getService(SalaryAcctReportServiceImpl.class, user);
}
private SalarySobItemGroupService getSalarySobItemGroupService(User user) {
return (SalarySobItemGroupService) ServiceUtil.getService(SalarySobItemGroupServiceImpl.class, user);
}
private SalarySobBackItemService getSalarySobBackItemService(User user) {
return ServiceUtil.getService(SalarySobBackItemServiceImpl.class, user);
}
private SalaryAcctResultService getSalaryAcctResultService(User user) {
return (SalaryAcctResultService) ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user);
}
private SalaryAcctResultLogService getSalaryAcctResultLogService(User user) {
return ServiceUtil.getService(SalaryAcctResultLogServiceImpl.class, user);
}
private SalarySysConfService getSalarySysConfService(User user) {
return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
}
private SalaryStatisticsReportService getSalaryStatisticsReportService(User user) {
return ServiceUtil.getService(SalaryStatisticsReportServiceImpl.class, user);
}
private TaxAgentAdminService getTaxAgentAdminService(User user) {
return ServiceUtil.getService(TaxAgentAdminServiceImpl.class, user);
}
private VariableItemService getVariableItemService(User user) {
return ServiceUtil.getService(VariableItemServiceImpl.class, user);
}
private SalaryApprovalRuleService getSalaryApprovalRuleService(User user) {
return ServiceUtil.getService(SalaryApprovalRuleServiceImpl.class, user);
}
private SalaryCheckResultService salaryCheckResultService;
private SalaryAcctSobConfigService getSalaryAcctSobConfigService(User user) {
return ServiceUtil.getService(SalaryAcctSobConfigServiceImpl.class, user);
}
private SalarySobTaxRuleService getSalarySobTaxRuleService(User user) {
return ServiceUtil.getService(SalarySobTaxRuleServiceImpl.class, user);
}
private VariableArchiveService getVariableArchiveService(User user) {
return ServiceUtil.getService(VariableArchiveServiceImpl.class, user);
}
private VariableArchiveItemService getVariableArchiveItemService(User user) {
return ServiceUtil.getService(VariableArchiveItemServiceImpl.class, user);
}
private SalaryArchiveService getSalaryArchiveService(User user) {
return ServiceUtil.getService(SalaryArchiveServiceImpl.class, user);
}
private SalaryArchiveItemService getSalaryArchiveItemService(User user) {
return ServiceUtil.getService(SalaryArchiveItemServiceImpl.class, user);
}
private HrmSnapshotMapper getHrmSnapshotMapper() {
return MapperProxyFactory.getProxy(HrmSnapshotMapper.class);
}
@Override
public List listBySalaryAcctRecordIds(Collection salaryAcctRecordIds) {
if (CollectionUtils.isEmpty(salaryAcctRecordIds)) {
return Collections.emptyList();
}
List salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).build());
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class);
return salaryAcctResultPOS;
}
@Override
public List listBySalaryAcctEmployeeId(Long salaryAcctEmployeeId) {
List salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(salaryAcctEmployeeId).build());
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class);
// 解密
return salaryAcctResultPOS;
}
@Override
public List listBySalaryAcctEmployeeIds(Collection salaryAcctEmployeeIds) {
if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) {
return Collections.emptyList();
}
List> partition = Lists.partition((List) salaryAcctEmployeeIds, 500);
List salaryAcctResultPOS = new ArrayList<>();
partition.forEach(empIds -> {
List resultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpIds(empIds).build());
encryptUtil.decryptList(resultPOS, SalaryAcctResultPO.class);
salaryAcctResultPOS.addAll(resultPOS);
});
// 解密
return salaryAcctResultPOS;
}
@Override
public List listBySalaryAcctRecordIdsAndEmployeeIds(Collection salaryAcctRecordIds, Collection employeeIds) {
if (CollectionUtils.isEmpty(salaryAcctRecordIds) || CollectionUtils.isEmpty(employeeIds)) {
return Collections.emptyList();
}
List> partition = Lists.partition((List) employeeIds, 500);
List salaryAcctResultPOS = new ArrayList<>();
partition.forEach(empIds -> {
salaryAcctResultPOS.addAll(getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).employeeIds(empIds).build()));
});
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class);
return salaryAcctResultPOS;
}
@Override
public SalaryAcctResultDetailDTO getBySalaryAcctEmployeeId(Long salaryAcctEmployeeId) {
// 查询薪资核算人员
SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(salaryAcctEmployeeId);
if (Objects.isNull(salaryAcctEmployeePO)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98831, "薪资核算人员不存在或已被删除"));
}
// 查询是否是回算
SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctEmployeePO.getSalaryAcctRecordId());
boolean isBackCal = Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1);
SalaryAcctConfig salaryAcctConfig = getSalaryAcctSobConfigService(user).getSalaryAcctConfig(salaryAcctRecordPO.getId());
// 查询薪资账套的薪资项目分类
List salarySobItemGroupPOS = salaryAcctConfig.getSalarySobItemGroups();
// 过滤关闭显示的薪资项目分类
salarySobItemGroupPOS = salarySobItemGroupPOS.stream().filter(group -> group.getItemHide() == null || group.getItemHide().equals(0L)).collect(Collectors.toList());
// 获取薪资项目分类ID
List salarySobItemGroupIds = salarySobItemGroupPOS.stream().map(SalarySobItemGroupPO::getId).collect(Collectors.toList());
//加上未分类
salarySobItemGroupIds.add(0L);
// 查询薪资账套的薪资项目副本(已经过滤关闭分类显示按钮的薪资项目)
List salarySobItemPOS = salaryAcctConfig.getSalarySobItems();
// 过滤薪资项目
salarySobItemPOS = salarySobItemPOS.stream().filter(item -> item.getItemHide() == null || item.getItemHide().equals(0L)).collect(Collectors.toList());
// 查询已发补发薪资项目
List salarySobBackItemPOList = Collections.emptyList();
List salaryBackItemPOS = Collections.emptyList();
// key:账套中回算薪资项目的薪资项目id value:账套中回算薪资项目所对应的公式内容
Map salaryBackItemFormula = new HashMap<>();
if (isBackCal) {
salarySobBackItemPOList = salaryAcctConfig.getSalarySobBackItems();
Set salarySobBackItemIds = SalaryEntityUtil.properties(salarySobBackItemPOList, SalarySobBackItemPO::getSalaryItemId);
salaryBackItemPOS = getSalaryItemService(user).listByIds(salarySobBackItemIds);
// 查询薪资账套中已发补发的公式内容
List expressFormulas = getSalaryFormulaService(user).listExpressFormula(SalaryEntityUtil.properties(salarySobBackItemPOList, SalarySobBackItemPO::getFormulaId));
Map expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId, ExpressFormula::getFormula);
for (SalarySobBackItemPO salarySobBackItemPO : salarySobBackItemPOList) {
String exp = Objects.equals(expressFormulaMap.get(salarySobBackItemPO.getFormulaId()), 0) ? "输入" : expressFormulaMap.get(salarySobBackItemPO.getFormulaId());
salaryBackItemFormula.put(salarySobBackItemPO.getSalaryItemId(), exp);
}
}
// 查询薪资项目
Set salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
List salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds);
// 查询薪资核算所用薪资账套的人员信息字段
List salarySobEmpFieldPOS = salaryAcctConfig.getSalarySobEmpFields();
// 查询人员信息
DataCollectionEmployee simpleEmployee = getSalaryEmployeeService(user).getEmployeeById(salaryAcctEmployeePO.getEmployeeId());
// 查询薪资核算结果
List salaryAcctResultPOS = listBySalaryAcctEmployeeId(salaryAcctEmployeeId);
// 查询个税扣缴义务人
TaxAgentPO taxAgent = getTaxAgentService(user).getById(salaryAcctEmployeePO.getTaxAgentId());
// 查询公式
Map formulaContentMap = getSalaryAcctResultService(user).getColumnBySalaryAcctRecordId(salaryAcctEmployeePO.getSalaryAcctRecordId());
List lockItems = salaryAcctRecordPO.getLockSalaryItemIds() == null ? Collections.emptyList() : salaryAcctRecordPO.getLockSalaryItemIds();
// 转换成薪资核算结果详情dto
return SalaryAcctResultBO.convert2DetailDTO(simpleEmployee, taxAgent, salaryAcctEmployeePO, salarySobEmpFieldPOS, salarySobItemGroupPOS, salarySobItemPOS, salaryItemPOS, salaryAcctResultPOS, salarySobBackItemPOList, salaryBackItemPOS, salaryBackItemFormula, formulaContentMap, lockItems);
}
@Override
public PageInfo