package com.engine.salary.service.impl;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.cache.SalaryCacheKey;
import com.engine.salary.common.LocalDateRange;
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.progress.ProgressDTO;
import com.engine.salary.entity.report.bo.SalaryAcctResultReportBO;
import com.engine.salary.entity.report.po.SalaryAcctResultReportPO;
import com.engine.salary.entity.salaryacct.bo.*;
import com.engine.salary.entity.salaryacct.dto.ConsolidatedTaxDetailDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultDetailDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultListColumnDTO;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.*;
import com.engine.salary.entity.salaryformula.ExpressFormula;
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.TaxAgentAdminPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.SalaryValueTypeEnum;
import com.engine.salary.enums.common.FilterEnum;
import com.engine.salary.enums.UserStatusEnum;
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.salaryitem.SalaryDataTypeEnum;
import com.engine.salary.enums.salarysob.IncomeCategoryEnum;
import com.engine.salary.exception.SalaryRunTimeException;
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.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.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
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.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StopWatch;
import weaver.hrm.User;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.stream.Collectors;
/**
* 薪资核算结果
*
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 LoggerTemplate salaryAcctRecordLoggerTemplate;
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 SalaryCheckResultService salaryCheckResultService;
@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 -> {
salaryAcctResultPOS.addAll(getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpIds(empIds).build()));
});
// 解密
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class);
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 byId = getSalaryAcctRecordService(user).getById(salaryAcctEmployeePO.getSalaryAcctRecordId());
boolean isBackCal = Objects.equals(byId.getBackCalcStatus(), 1);
//----------------------------------------------
// 查询薪资账套的薪资项目分类
List salarySobItemGroupPOS = getSalarySobItemGroupService(user).listBySalarySobIdWithItemHide(salaryAcctEmployeePO.getSalarySobId());
// 获取关闭显示的分类
List hideGroupIDs = getSalarySobItemHideService(user).listHideGroupBysalarySobId(SalarySobItemHidePO.builder().salarySobId(salaryAcctEmployeePO.getSalarySobId()).isGroup(1).build());
// 过滤关闭显示的薪资项目分类
salarySobItemGroupPOS = salarySobItemGroupPOS.stream().filter(group -> !(hideGroupIDs.contains(group.getId()))).collect(Collectors.toList());
// 获取薪资项目分类ID
List salarySobItemGroupIds = salarySobItemGroupPOS.stream().map(SalarySobItemGroupPO::getId).collect(Collectors.toList());
//加上未分类
salarySobItemGroupIds.add(0L);
// 查询薪资账套的薪资项目副本(已经过滤关闭分类显示按钮的薪资项目)
List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobIdAndGroupId(salaryAcctEmployeePO.getSalarySobId(), salarySobItemGroupIds);
//----------------------------------------------
// 查询薪资核算所用薪资账套的薪资项目副本
// List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctEmployeePO.getSalarySobId());
// 获取关闭显示的薪资项目
List hideItemIDs = getSalarySobItemHideService(user).listHideGroupBysalarySobId(SalarySobItemHidePO.builder().salarySobId(salaryAcctEmployeePO.getSalarySobId()).isGroup(0).build());
// 过滤薪资项目
salarySobItemPOS = salarySobItemPOS.stream().filter(item -> !(hideItemIDs.contains(item.getSalaryItemId()))).collect(Collectors.toList());
// 查询已发补发薪资项目
List salarySobBackItemPOList = Collections.emptyList();
List salaryBackItemPOS = Collections.emptyList();
// key:账套中回算薪资项目的薪资项目id value:账套中回算薪资项目所对应的公式内容
Map salaryBackItemFormula = new HashMap<>();
if (isBackCal) {
salarySobBackItemPOList = getSalarySobBackItemService(user).listBySalarySobId(byId.getSalarySobId());
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 = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctEmployeePO.getSalarySobId());
// 查询人员信息
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());
// 转换成薪资核算结果详情dto
return SalaryAcctResultBO.convert2DetailDTO(simpleEmployee, taxAgent, salaryAcctEmployeePO, salarySobEmpFieldPOS, salarySobItemGroupPOS, salarySobItemPOS, salaryItemPOS, salaryAcctResultPOS, salarySobBackItemPOList, salaryBackItemPOS, salaryBackItemFormula, formulaContentMap);
}
@Override
public PageInfo