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.encrypt.salaryacct.SalaryAcctResultPOEncrypt;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.dto.AttendQuoteFieldListDTO;
import com.engine.salary.entity.report.bo.SalaryAcctResultReportBO;
import com.engine.salary.entity.report.po.SalaryAcctResultReportPO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctCalculateBO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctCalculatePriorityBO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctFormulaBO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctResultBO;
import com.engine.salary.entity.salaryacct.dto.ConsolidatedTaxDetailDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctProgressDTO;
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.SalaryAcctEmployeePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultTempPO;
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.TaxAgentPO;
import com.engine.salary.enums.SalaryValueTypeEnum;
import com.engine.salary.enums.salaryaccounting.LockStatusEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
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.service.*;
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.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 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 SalaryAcctProgressService getSalaryAcctProgressService(User user) {
return ServiceUtil.getService(SalaryAcctProgressServiceImpl.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 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 salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpIds(salaryAcctEmployeeIds).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 salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).employeeIds(employeeIds).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());
// 查询薪资账套的薪资项目副本(已经过滤关闭分类显示按钮的薪资项目)
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());
// 转换成薪资核算结果详情dto
return SalaryAcctResultBO.convert2DetailDTO(simpleEmployee, taxAgent, salaryAcctEmployeePO, salarySobEmpFieldPOS, salarySobItemPOS, salaryItemPOS, salaryAcctResultPOS, salarySobBackItemPOList, salaryBackItemPOS, salaryBackItemFormula);
}
@Override
public PageInfo