package com.engine.salary.service.impl; 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.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.OperateTypeEnum; import com.engine.salary.enums.UserStatusEnum; import com.engine.salary.enums.common.FilterEnum; 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.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.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.util.StopWatch; import weaver.general.BaseBean; 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 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 SalaryCheckResultService salaryCheckResultService; private SalaryAcctSobConfigService getSalaryAcctSobConfigService(User user) { return ServiceUtil.getService(SalaryAcctSobConfigServiceImpl.class, user); } @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> listPageByParam(SalaryAcctResultQueryParam queryParam) { PageInfo page = null; //其他条件 List otherConditions = queryParam.getOtherConditions(); if (CollectionUtils.isNotEmpty(otherConditions)) { List items = SalaryEntityUtil.properties(otherConditions, SalaryAcctResultQueryParam.OtherCondition::getItemId, Collectors.toList()); List list = listBySalaryAcctRecordIdsAndSalaryItemIds(Collections.singletonList(queryParam.getSalaryAcctRecordId()), items); for (int i = 0; i < otherConditions.size(); i++) { SalaryAcctResultQueryParam.OtherCondition otherCondition = otherConditions.get(i); Long itemId = otherCondition.getItemId(); FilterEnum filter = otherCondition.getFilter(); List params = otherCondition.getParams(); list = list.stream().filter(a -> Objects.equals(a.getSalaryItemId(), itemId)).filter(a -> filter.filter(params).test(a.getResultValue())).collect(Collectors.toList()); } List salaryAcctEmpId = SalaryEntityUtil.properties(list, SalaryAcctResultPO::getSalaryAcctEmpId, Collectors.toList()); if (CollectionUtils.isEmpty(salaryAcctEmpId)) { //条件不满足直接返回空列表 page = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), new ArrayList<>(), SalaryAcctEmployeePO.class); } else { queryParam.setIds(salaryAcctEmpId); // 查询薪资核算人员(分页) page = getSalaryAcctEmployeeService(user).listPageByResultQueryParam(queryParam); } } else { // 查询薪资核算人员(分页) page = getSalaryAcctEmployeeService(user).listPageByResultQueryParam(queryParam); } // 查询薪资核算结果 List> data = listBySalaryAcctEmployees(page.getList(), queryParam); // 薪资核算结果的分页结果 PageInfo> resultPage = new PageInfo<>(); resultPage.setList(data); resultPage.setTotal(page.getTotal()); resultPage.setPageNum(page.getPageNum()); resultPage.setPageSize(page.getPageSize()); return resultPage; } @Override public Map sumRow(SalaryAcctResultQueryParam queryParam) { //其他条件 List otherConditions = queryParam.getOtherConditions(); if (CollectionUtils.isNotEmpty(otherConditions)) { List items = SalaryEntityUtil.properties(otherConditions, SalaryAcctResultQueryParam.OtherCondition::getItemId, Collectors.toList()); List list = listBySalaryAcctRecordIdsAndSalaryItemIds(Collections.singletonList(queryParam.getSalaryAcctRecordId()), items); for (int i = 0; i < otherConditions.size(); i++) { SalaryAcctResultQueryParam.OtherCondition otherCondition = otherConditions.get(i); Long itemId = otherCondition.getItemId(); FilterEnum filter = otherCondition.getFilter(); List params = otherCondition.getParams(); list = list.stream().filter(a -> Objects.equals(a.getSalaryItemId(), itemId)).filter(a -> filter.filter(params).test(a.getResultValue())).collect(Collectors.toList()); } List salaryAcctEmpId = SalaryEntityUtil.properties(list, SalaryAcctResultPO::getSalaryAcctEmpId, Collectors.toList()); if (CollectionUtils.isEmpty(salaryAcctEmpId)) { //条件不满足直接返回空列表 return new HashMap<>(); } else { queryParam.setIds(salaryAcctEmpId); } } // 查询薪资核算人员 List salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByResultQueryParam(queryParam); if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) { return null; } // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(queryParam.getSalaryAcctRecordId()); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除")); } // 查询薪资核算所用薪资账套的薪资项目 List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); Map salaryItemIdKeySalarySobItemPOMap = SalaryEntityUtil.convert2Map(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); Set salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), NumberUtils.INTEGER_ONE)) { // 是回算,获取回算项 List salarySobBackItemPOS = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); salaryItemIds.addAll(salarySobBackItemPOS.stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList())); } List salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds); // 查询薪资核算结果 List salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList()); List salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); Map map = new HashMap<>(); Map> acctResultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId); salaryItemPOS.stream().filter(item -> SalaryDataTypeEnum.NUMBER.getValue().equals(item.getDataType())).forEach(item -> { BigDecimal sum = Optional.ofNullable(acctResultMap.get(item.getId())).orElse(new ArrayList<>()).stream().map(SalaryAcctResultPO::getResultValue).filter(NumberUtils::isCreatable).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add); map.put(item.getId().toString(), SalaryAcctFormulaBO.roundResultValue(sum.toString(), item, Collections.emptyList(), Collections.emptyMap(), salaryItemIdKeySalarySobItemPOMap)); }); return map; } @Override public List> listByParam(SalaryAcctResultQueryParam queryParam) { // 查询薪资核算人员 List salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByResultQueryParam(queryParam); // 查询薪资核算结果 return listBySalaryAcctEmployees(salaryAcctEmployeePOS, queryParam); } /** * 根据薪资核算人员查询薪资核算结果 * * @param salaryAcctEmployeePOS 薪资核算人员 * @param queryParam 列表查询条件 * @return */ private List> listBySalaryAcctEmployees(List salaryAcctEmployeePOS, SalaryAcctResultQueryParam queryParam) { if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) { return Collections.emptyList(); } // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(queryParam.getSalaryAcctRecordId()); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除")); } boolean isBackCalc = Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1); SalaryAcctConfig salaryAcctConfig = getSalaryAcctSobConfigService(user).getSalaryAcctConfig(queryParam.getSalaryAcctRecordId()); // 查询薪资核算所用的薪资账套的员工信息字段 List salarySobEmpFieldPOS = salaryAcctConfig.getSalarySobEmpFields(); // 查询薪资核算所用薪资账套的薪资项目 List salarySobItemPOS = salaryAcctConfig.getSalarySobItems(); Set salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); // 是否是回算 List salarySobBackItemPOList = Collections.emptyList(); if (isBackCalc) { // 根据薪资账套获取回算信息项 salarySobBackItemPOList = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); salaryItemIds.addAll(salarySobBackItemPOList.stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList())); } List salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds); // 查询薪资核算结果 List salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList()); List salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); // 查询人员信息 List employeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getEmployeeId, Collectors.toList()); List simpleEmployees = getSalaryEmployeeService(user).getEmployeeByIdsAll(employeeIds); simpleEmployees.forEach(e -> { UserStatusEnum userStatusEnum = UserStatusEnum.parseByValue(Integer.parseInt(e.getStatus())); if (userStatusEnum != null) { e.setStatusName(userStatusEnum.getDefaultLabel()); } }); // 查询个税扣缴义务人 Set taxAgentIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getTaxAgentId); List taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds); // 判断是否存在合并计税 Set salaryAcctEmployeeIds4ConsolidatedTax; if (StringUtils.isNotEmpty(queryParam.getConsolidatedTaxation())) { // 如果查询条件中含有"合并计税",那么在入参中的salaryAcctEmployeePOS就已经全部都是存在合并计税的人员了(前面已经过滤了),无需再次查询合并计税的人员 salaryAcctEmployeeIds4ConsolidatedTax = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId); } else { // 如果查询条件中没有包含"合并计税",那么就需要查询出存在合并计税的人,标记给前端 SalaryAcctEmployeeQueryParam accEmployeeQueryParam = SalaryAcctEmployeeQueryParam.builder().salaryAcctRecordId(queryParam.getSalaryAcctRecordId()).ids(SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList())).build(); List salaryAcctEmployeePOS4ConsolidatedTax = getSalaryAcctEmployeeService(user).listByParam4ConsolidatedTax(accEmployeeQueryParam); salaryAcctEmployeeIds4ConsolidatedTax = SalaryEntityUtil.properties(salaryAcctEmployeePOS4ConsolidatedTax, SalaryAcctEmployeePO::getId); } // 查询公式详情 Set formulaIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getFormulaId); // 获取回算公式 if (isBackCalc) { formulaIds.addAll(salarySobBackItemPOList.stream().map(SalarySobBackItemPO::getFormulaId).collect(Collectors.toList())); } List expressFormulas = getSalaryFormulaService(user).listExpressFormula(formulaIds); Map expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId, ExpressFormula::getFormula); Map customParameters = SalaryEntityUtil.convert2Map(salarySobItemPOS, SalarySobItemPO::getSalaryItemId, salarySobItemPO -> { if (salarySobItemPO.getFormulaId() <= 0) { return SalaryI18nUtil.getI18nLabel(92004, "输入/导入"); } return expressFormulaMap.getOrDefault(salarySobItemPO.getFormulaId(), StringUtils.EMPTY); }); // 回算公式内容转换 Map customBackCalcParameters = SalaryEntityUtil.convert2Map(salarySobBackItemPOList, SalarySobBackItemPO::getSalaryItemId, salarySobBackItemPO -> { if (salarySobBackItemPO.getFormulaId() <= 0) { return SalaryI18nUtil.getI18nLabel(92004, "输入/导入"); } return expressFormulaMap.getOrDefault(salarySobBackItemPO.getFormulaId(), StringUtils.EMPTY); }); // 转换成薪资核算结果列表 return SalaryAcctResultBO.buildTableData(salaryItemPOS, salarySobEmpFieldPOS, simpleEmployees, salaryAcctEmployeePOS, salaryAcctResultPOS, taxAgentPOS, salaryAcctEmployeeIds4ConsolidatedTax, customParameters, customBackCalcParameters, queryParam.isDynamicEmpInfo()); } @Override public ConsolidatedTaxDetailDTO getConsolidatedTaxDetail(Long salaryAcctEmployeeId) { // 查询当前的薪资核算人员 SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(salaryAcctEmployeeId); if (Objects.isNull(salaryAcctEmployeePO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98831, "薪资核算人员不存在或已被删除")); } // 查询当前的薪资核算人员的个税扣缴义务人 TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(salaryAcctEmployeePO.getTaxAgentId()); // 查询当前的薪资核算人员的人员信息 DataCollectionEmployee simpleEmployee = getSalaryEmployeeService(user).getEmployeeById(salaryAcctEmployeePO.getEmployeeId()); // 查询当前的薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctEmployeePO.getSalaryAcctRecordId()); // 查询当前薪资核算记录所用的薪资账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId()); // 当前薪资核算记录所用的薪资账套的员工信息字段 List salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salarySobPO.getId()); List salaryAcctRecordPOS = Collections.singletonList(salaryAcctRecordPO); List salaryAcctEmployeePOS = Collections.singletonList(salaryAcctEmployeePO); // 如果当前薪资核算记录所用的薪资账套的薪资类型是工资薪金,代表可能存在合并计税 if (Objects.equals(salarySobPO.getIncomeCategory(), IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) { // 查询所有薪资类型为工资薪金的账套 List salarySobPOS = getSalarySobService(user).listByIncomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES); // 查询相同税款所属期内的薪资类型为工资薪金的账套的所有核算记录 Set salarySobIds = SalaryEntityUtil.properties(salarySobPOS, SalarySobPO::getId); LocalDateRange taxCycleDateRange = SalaryDateUtil.localDate2Range(salaryAcctRecordPO.getTaxCycle()); salaryAcctRecordPOS = getSalaryAcctRecordService(user).listBySalarySobIdsAndTaxCycle(salarySobIds, taxCycleDateRange); // 查询当前薪资核算人员所涉及的合并计税的所有薪资核算人员 Set salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId); salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByRecordIdsAndEmpIdAndTaxAgentId(salaryAcctRecordIds, salaryAcctEmployeePO.getEmployeeId(), salaryAcctEmployeePO.getTaxAgentId()); } // 查询薪资核算人员的薪资核算结果 List salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList()); List salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); // 查询薪资核算人员所有合并计税的薪资核算记录所用的账套 Set salarySobIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getSalarySobId); List salarySobPOS = getSalarySobService(user).listByIds(salarySobIds); // 查询薪资项目所引用的薪资项目 List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobIds(salarySobIds); // 查询薪资项目 Set salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); List salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds); // 转换成合并计税详情dto return SalaryAcctResultBO.convert2ConsolidatedTaxDetailDTO(simpleEmployee, taxAgentPO, salarySobEmpFieldPOS, salaryItemPOS, salaryAcctEmployeePOS, salarySobPOS, salaryAcctRecordPOS, salaryAcctResultPOS); } @Override public Map getColumnBySalaryAcctRecordId(Long salaryAcctRecordId) { SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除")); } Map resultMap = Maps.newHashMap(); // 查询薪资核算使用的薪资账套下的薪资项目 SalarySobItemAggregateDTO salarySobItemAggregateDTO = getSalarySobItemService(user).getAggregateByRecordId(salaryAcctRecordId, true); for (SalarySobItemIncomeCategoryDTO incomeCategoryDTO : salarySobItemAggregateDTO.getIncomeCategories()) { for (SalarySobItemGroupDTO salarySobItemGroupDTO : incomeCategoryDTO.getItemGroups()) { for (SalarySobItemDTO salarySobItemDTO : salarySobItemGroupDTO.getItems()) { SalaryAcctResultListColumnDTO salaryAcctResultListColumnDTO = new SalaryAcctResultListColumnDTO().setColumnName(salarySobItemDTO.getName()).setFormulaId(salarySobItemDTO.getFormulaId()).setFormulaContent(salarySobItemDTO.getFormulaContent()).setShowLock((!Objects.equals(salarySobItemDTO.getFormulaId(), NumberUtils.LONG_ZERO) && salarySobItemDTO.isCanEdit()) || Objects.equals(salarySobItemDTO.getUseInEmployeeSalary(), NumberUtils.INTEGER_ONE)); resultMap.put("" + salarySobItemDTO.getSalaryItemId(), salaryAcctResultListColumnDTO); } } for (SalarySobItemDTO salarySobItemDTO : incomeCategoryDTO.getItems()) { SalaryAcctResultListColumnDTO salaryAcctResultListColumnDTO = new SalaryAcctResultListColumnDTO().setColumnName(salarySobItemDTO.getName()).setFormulaId(salarySobItemDTO.getFormulaId()).setFormulaContent(salarySobItemDTO.getFormulaContent()).setShowLock((!Objects.equals(salarySobItemDTO.getFormulaId(), NumberUtils.LONG_ZERO) && salarySobItemDTO.isCanEdit()) || Objects.equals(salarySobItemDTO.getUseInEmployeeSalary(), NumberUtils.INTEGER_ONE)); resultMap.put("" + salarySobItemDTO.getSalaryItemId(), salaryAcctResultListColumnDTO); } } // 查询回算薪资项目 if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1)) { List backCalcItems = salarySobItemAggregateDTO.getBackCalcItems(); for (SalarySobItemDTO backCalcItem : backCalcItems) { SalaryAcctResultListColumnDTO salaryAcctResultListColumnDTO = new SalaryAcctResultListColumnDTO().setColumnName(backCalcItem.getName()).setFormulaId(backCalcItem.getFormulaId()).setFormulaContent(backCalcItem.getFormulaContent()).setShowLock(true); resultMap.put("" + backCalcItem.getSalaryItemId(), salaryAcctResultListColumnDTO); } } return resultMap; } @Override public void save(SalaryAcctResultSaveParam saveParam) { List dataCollectionEmployees = getSalaryEmployeeService(user).listAllForReport(); Map emps = SalaryEntityUtil.convert2Map(dataCollectionEmployees, DataCollectionEmployee::getEmployeeId); // 查询薪资核算人员 SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(saveParam.getSalaryAcctEmpId()); if (Objects.isNull(salaryAcctEmployeePO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98831, "薪资核算人员不存在或已被删除")); } // 更新员工基本信息值 saveParam.getEmployeeInfos().stream().forEach(info -> { if (info.getFieldValue() != null && StringUtils.isNotBlank(info.getFieldValue().toString())) { if (info.getFieldCode().equals("departmentName") || info.getFieldCode().equals("departmentId")) { // 修改部门信息 DeptInfo deptInfo = getSalaryEmployeeService(user).getDeptInfoById(NumberUtils.isCreatable(info.getFieldValue().toString()) ? Long.valueOf(info.getFieldValue().toString()) : 0L); if (Objects.nonNull(deptInfo)) { salaryAcctEmployeePO.setDepartmentName(deptInfo.getName()); salaryAcctEmployeePO.setDepartmentId(deptInfo.getId()); } } else if (info.getFieldCode().equals("subcompanyName") || info.getFieldCode().equals("subcompanyId")) { // 修改分部信息 SubCompanyInfo subCompanyInfo = getSalaryEmployeeService(user).getSubCompanyInfoById(NumberUtils.isCreatable(info.getFieldValue().toString()) ? Long.valueOf(info.getFieldValue().toString()) : 0L); if (Objects.nonNull(subCompanyInfo)) { salaryAcctEmployeePO.setSubcompanyName(subCompanyInfo.getName()); salaryAcctEmployeePO.setSubcompanyId(subCompanyInfo.getId()); } } else if (info.getFieldCode().equals("jobtitleName") || info.getFieldCode().equals("jobtitleId")) { // 修改岗位信息 PositionInfo positionInfo = getSalaryEmployeeService(user).getPositionInfoById(NumberUtils.isCreatable(info.getFieldValue().toString()) ? Long.valueOf(info.getFieldValue().toString()) : 0L); if (Objects.nonNull(positionInfo)) { salaryAcctEmployeePO.setJobtitleName(positionInfo.getName()); salaryAcctEmployeePO.setJobtitleId(positionInfo.getId()); } } else if (info.getFieldCode().equals("jobcall") || info.getFieldCode().equals("jobcallId")) { // 修改职称信息 JobCallInfo jobCallInfo = getSalaryEmployeeService(user).getJobCallInfoById(NumberUtils.isCreatable(info.getFieldValue().toString()) ? Long.valueOf(info.getFieldValue().toString()) : 0L); if (Objects.nonNull(jobCallInfo)) { salaryAcctEmployeePO.setJobcall(jobCallInfo.getName()); salaryAcctEmployeePO.setJobcallId(jobCallInfo.getId()); } } } }); getSalaryAcctEmployeeService(user).updateIgnoreNull(salaryAcctEmployeePO); // 查询原来的薪资核算结果 List salaryAcctResultPOSOld = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(saveParam.getSalaryAcctEmpId()).build()); // 解密 encryptUtil.decryptList(salaryAcctResultPOSOld, SalaryAcctResultPO.class); // 保存参数转换成薪资核算结果po List salaryAcctResultPOS = SalaryAcctResultBO.convert2PO(salaryAcctResultPOSOld, saveParam, salaryAcctEmployeePO, (long) user.getUID()); SalarySysConfPO autoLock = getSalarySysConfService(user).getOneByCode(SalarySysConstant.EDIT_IMPORT_AUTO_LOCK); if (autoLock != null && StringUtils.equals(autoLock.getConfValue(), "1")) { // 对比核算结果提取修改了哪些薪资项目 Set needLockItems = new HashSet<>(); Map oldResutMap = SalaryEntityUtil.convert2Map(salaryAcctResultPOSOld, SalaryAcctResultPO::getSalaryItemId); salaryAcctResultPOS.stream().forEach(PO -> { String oldValue = Optional.ofNullable(oldResutMap.get(PO.getSalaryItemId())).map(SalaryAcctResultPO::getResultValue).orElse(""); if (!StringUtils.equals(oldValue, PO.getResultValue())) { needLockItems.add(PO.getSalaryItemId()); } }); // 编辑的列都自动锁定 SalaryAcctResultUpdateLockStatusParam updateLockStatusParam = SalaryAcctResultUpdateLockStatusParam.builder().salaryItemIds(needLockItems).salaryAcctRecordId(salaryAcctEmployeePO.getSalaryAcctRecordId()).lockStatus(LockStatusEnum.LOCK).build(); getSalaryAcctResultService(user).updateLockStatusByParam(updateLockStatusParam); } // SalaryAcctRecordPO byId = getSalaryAcctRecordService(user).getById(salaryAcctEmployeePO.getSalaryAcctRecordId()); // 若保存编辑时一同传已发补发,则删除以下代码 // if(byId.getBackCalcStatus() != null && Objects.equals(byId.getBackCalcStatus(),1)){ // // 是回算 // List salarySobBackItemIds = getSalarySobBackItemService(user).listBySalarySobId(byId.getSalarySobId()).stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList()); // // 获取已发待发的薪资核算结果 // List salarySobBackItemResultPO = salaryAcctResultPOSOld.stream().filter(po -> salarySobBackItemIds.contains(po.getSalaryItemId())).collect(Collectors.toList()); // salaryAcctResultPOS.addAll(salarySobBackItemResultPO); // } // 删除原来的薪资核算结果 List saveItemIds = saveParam.getItems().stream().map(SalaryAcctResultSaveParam.SalaryAcctResultDetailItemParam::getSalaryItemId).collect(Collectors.toList()); deleteByAcctEmployeeIdsAndSalaryItemIds(Collections.singletonList(saveParam.getSalaryAcctEmpId()), saveItemIds); // 保存薪资核算结果 if (CollectionUtils.isNotEmpty(salaryAcctResultPOS)) { // 加密 encryptUtil.encryptList(salaryAcctResultPOS, SalaryAcctResultPO.class); List> partition = Lists.partition(salaryAcctResultPOS, 100); partition.forEach(getSalaryAcctResultMapper()::batchInsert); } //报表 // getSalaryAcctReportService(user).deleteByAcctEmployeeIdsAndSalaryItemIds(Collections.singletonList(saveParam.getSalaryAcctEmpId()), saveItemIds); // List salaryAcctResultReportPOS = SalaryAcctResultReportBO.convert2PO(saveParam, salaryAcctEmployeePO, (long) user.getUID(), emps); // if (CollectionUtils.isNotEmpty(salaryAcctResultReportPOS)) { // getSalaryAcctReportService(user).batchSave(salaryAcctResultReportPOS); // } // 存储薪资核算结果数据来源日志 salaryAcctResultPOS = getSalaryAcctRecordService(user).listBySalaryAcctEmpId(saveParam.getSalaryAcctEmpId()); // 查询操作日志的targetName String targetName = getSalaryAcctRecordService(user).getLogTargetNameById(salaryAcctEmployeePO.getSalaryAcctRecordId()); // 查询人员信息 DataCollectionEmployee simpleEmployee = getSalaryEmployeeService(user).getEmployeeById(salaryAcctEmployeePO.getEmployeeId()); // 查询个税扣缴义务人 TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(salaryAcctEmployeePO.getTaxAgentId()); // 记录日志 String operateDesc = simpleEmployee.getUsername() + "(" + Optional.ofNullable(taxAgentPO).map(TaxAgentPO::getName).orElse(StringUtils.EMPTY) + ")"; LoggerContext loggerContext = new LoggerContext<>(); loggerContext.setUser(user); loggerContext.setTargetId(String.valueOf(salaryAcctEmployeePO.getSalaryAcctRecordId())); loggerContext.setTargetName(targetName); loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue()); loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "编辑薪资核算结果") + ": " + operateDesc); loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "编辑薪资核算结果") + ": " + operateDesc); loggerContext.setNewValueList(Lists.newArrayList(salaryAcctResultPOS)); SalaryElogConfig.salaryAcctRecordLoggerTemplate.write(loggerContext); } /** * 存储薪资核算结果数据来源日志 * * @param salaryAcctResultPOSOld * @param salaryAcctResultPOS */ private void saveSalaryAcctResultLog(List salaryAcctResultPOSOld, List salaryAcctResultPOS) { // 对比核算结果提取修改了哪些薪资项目 List editItems = new ArrayList<>(); Map oldResutMap = SalaryEntityUtil.convert2Map(salaryAcctResultPOSOld, SalaryAcctResultPO::getSalaryItemId); salaryAcctResultPOS.stream().forEach(PO -> { if (oldResutMap.get(PO.getSalaryItemId()) == null) { editItems.add(PO); } else { String oldValue = oldResutMap.get(PO.getSalaryItemId()).getResultValue(); if (!StringUtils.equals(oldValue, PO.getResultValue())) { editItems.add(PO); } } }); List needInsertList = SalaryAcctResultLogBO.buildSalaryAcctResultLog(editItems, Long.valueOf(user.getUID()), SalaryAcctResultDataSourceEnum.EDIT); getSalaryAcctResultLogService(user).batchInsert(needInsertList); } @Override public void batchSave(List salaryAcctResultPOS) { if (CollectionUtils.isNotEmpty(salaryAcctResultPOS)) { // 数据加密 encryptUtil.encryptList(salaryAcctResultPOS, SalaryAcctResultPO.class); List> partition = Lists.partition(salaryAcctResultPOS, 100); partition.forEach(getSalaryAcctResultMapper()::batchInsert); } } @Override public void deleteBySalaryAcctEmployeeIds(Collection salaryAcctEmployeeIds) { getSalaryAcctResultMapper().deleteBySalaryAcctEmpIds(salaryAcctEmployeeIds); } @Override public void deleteByAcctEmployeeIdsAndSalaryItemIds(List salaryAcctEmployeeIds, Collection salaryItemIds) { List> partition = Lists.partition(salaryAcctEmployeeIds, 300); partition.forEach(part -> getSalaryAcctResultMapper().deleteByAcctEmpIdsAndSalaryItemIds(part, salaryItemIds)); } @Override public void deleteBySalaryAcctRecordIds(Collection salaryAcctRecordIds) { getSalaryAcctResultMapper().deleteBySalaryAcctRecordIds(salaryAcctRecordIds); } @Override public void calculate(SalaryAcctCalculateParam calculateParam, DataCollectionEmployee simpleEmployee) { try { log.info("开始核算V2 {}", calculateParam); StopWatch stopWatch = new StopWatch("总核算耗时,id:" + calculateParam.getSalaryAcctRecordId()); stopWatch.start("数据准备"); // 1、查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(calculateParam.getSalaryAcctRecordId()); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除")); } //查询对应账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId()); if (Objects.isNull(salarySobPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资账套不存在或已被删除")); } // 不是查询薪资账套下实时的薪资项目,而是查询发起薪资核算时存储的薪资项目快照 SalaryAcctConfig salaryAcctSobConfig = getSalaryAcctSobConfigService(user).getSalaryAcctConfig(calculateParam.getSalaryAcctRecordId()); // 1.1、如果薪资核算记录已经归档了,就不能继续核算 if (!Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(99148, "当前薪资核算记录已归档,请重新打开后再进行核算")); } // 2、查询薪资核算记录的薪资周期、考勤周期等 SalarySobCycleDTO salarySobCycleDTO = getSalaryAcctRecordService(user).getSalarySobCycleById(calculateParam.getSalaryAcctRecordId()); // 3、查询薪资核算记录所用薪资账套的薪资项目副本 List salarySobItemPOS = salaryAcctSobConfig.getSalarySobItems(); if (CollectionUtils.isEmpty(salarySobItemPOS)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(99151, "当前所用的薪资账套未选择任何薪资项目,无法核算")); } // 回算薪资项目 List salarySobBackItems = Collections.emptyList(); if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1)) { salarySobBackItems = salaryAcctSobConfig.getSalarySobBackItems(); } // 4、查询当前租户的所有薪资项目 List salaryItemPOS = getSalaryItemService(user).listAll(); // 5、查询薪资核算记录所用薪资账套的调薪计薪规则 List salarySobAdjustRulePOS = getSalarySobAdjustRuleService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 6、查询社保福利的所有字段 Map welfareColumns = getSIAccountService(user).welfareColumns(); // 7、查询考勤引用的所有字段 List attendQuoteFieldListDTOS = getAttendQuoteFieldService(user).listAll(); List variableItemPOS = getVariableItemService(user).listAll(); // 8、查询公式详情 Set formulaIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getFormulaId); formulaIds.addAll(SalaryEntityUtil.properties(salaryItemPOS, SalaryItemPO::getFormulaId)); formulaIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getFormulaId)); List expressFormulas = getSalaryFormulaService(user).listExpressFormula(formulaIds); // 本次运算的回算薪资项目所涉及的变量 Set issuedFieldIds = new HashSet<>(); // 9、计算薪资项目的运算优先级 List> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds); // 10、根据id查询其他合并计税的薪资核算记录 List otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId()); // 11、查询本次核算人员 List salaryAcctEmployeePOS; if (CollectionUtils.isEmpty(calculateParam.getIds())) { salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salaryAcctRecordPO.getId()); } else { salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByIds(calculateParam.getIds()); } if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(103378, "薪资核算人员不能为空")); } stopWatch.stop(); stopWatch.start("核算耗时"); // 11.1、初始化进度 ProgressDTO initProgress = new ProgressDTO().setTitle(SalaryI18nUtil.getI18nLabel(97515, "核算中")).setTitleLabelId(97515L).setTotalQuantity(salaryAcctEmployeePOS.size() * 2 + 1).setCalculatedQuantity(0).setProgress(BigDecimal.ZERO).setStatus(true).setMessage(StringUtils.EMPTY); getSalaryAcctProgressService(user).initProgress(SalaryCacheKey.ACCT_PROGRESS + calculateParam.getSalaryAcctRecordId(), initProgress); // 12、对薪资核算人员进行拆分 String personNumberInOneThread = new BaseBean().getPropValue("hrmSalaryCustom", "personNumberInOneThread"); int size = 100; if (StringUtils.isNotBlank(personNumberInOneThread)) { size = Integer.parseInt(personNumberInOneThread); } List> partition = Lists.partition(salaryAcctEmployeePOS, size); // 12.1、监控子线程的任务执行 CountDownLatch childMonitor = new CountDownLatch(partition.size()); // 12.2、记录子线程的执行结果 BlockingDeque calculateResults = new LinkedBlockingDeque<>(partition.size()); // 12.3、生成本次运算的key String calculateKey = UUID.randomUUID().toString(); // 12.4、是否采用系统算税 TaxDeclarationFunctionEnum taxDeclarationFunction = getSalarySysConfService(user).getTaxDeclaration(); // 12.5、多线程运算,运算结果存放在临时表中 for (List acctEmployeePOS : partition) { SalaryAcctCalculateBO salaryAcctCalculateBO = new SalaryAcctCalculateBO() .setSalaryAcctRecordPO(salaryAcctRecordPO) .setSalarySobPO(salarySobPO) .setSalarySobCycleDTO(salarySobCycleDTO) .setOtherSalaryAcctRecordPOS(otherSalaryAcctRecordPOS) .setSalarySobItemPOS(salarySobItemPOS) .setSalaryItemIdWithPriorityList(salarySobItemsWithPriority) .setExpressFormulas(expressFormulas) .setSalaryItemPOS(salaryItemPOS) .setSalarySobAdjustRulePOS(salarySobAdjustRulePOS) .setWelfareColumns(MapUtils.emptyIfNull(welfareColumns)) .setAttendQuoteFieldListDTOS(attendQuoteFieldListDTOS) .setSalaryAcctEmployeePOS(acctEmployeePOS) .setIssuedFieldIds(issuedFieldIds) .setChildMonitor(childMonitor) .setResults(calculateResults) .setCalculateKey(calculateKey) .setVariableItems(variableItemPOS) .setTaxDeclarationFunction(taxDeclarationFunction); List finalSalarySobBackItems = salarySobBackItems; LocalRunnable localRunnable = new LocalRunnable() { @Override public void execute() { getSalaryAcctCalculateService(user).calculate(salaryAcctCalculateBO, simpleEmployee, finalSalarySobBackItems); } }; ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.HRM, "salaryAcctCalculate", localRunnable); } // 13、等待所有子线程执行完毕 childMonitor.await(); stopWatch.stop(); stopWatch.start("数据写入耗时"); // 14、判断子线程执行结果 boolean allSuccess = calculateResults.stream().allMatch(SalaryAcctCalculateBO.Result::isStatus); if (!allSuccess) { // 薪资核算实现的线程的错误信息 String errorMsg = calculateResults.stream().filter(result -> !result.isStatus()).map(SalaryAcctCalculateBO.Result::getErrMsg).collect(Collectors.joining("|")); getSalaryAcctProgressService(user).fail(SalaryCacheKey.ACCT_PROGRESS + calculateParam.getSalaryAcctRecordId(), errorMsg); // 删除薪资核算临时存储表中的数据 getSalaryAcctResultTempService(user).deleteByCalculateKey(calculateKey); return; } // 15、处理核算结果临时表数据 handleSalaryAcctResultTemp(calculateParam, calculateKey); // 16、开始运行校验规则 // SalaryAcctCheckParam salaryAcctCheckParam = new SalaryAcctCheckParam() // .setSalaryAcctRecordId(calculateParam.getSalaryAcctRecordId()) // .setIds(calculateParam.getIds()); // salaryCheckResultService.check(salaryAcctCheckParam, true, simpleEmployee); // Thread.sleep(10); getSalaryAcctProgressService(user).finish(SalaryCacheKey.ACCT_PROGRESS + calculateParam.getSalaryAcctRecordId(), true); stopWatch.stop(); log.info(stopWatch.prettyPrint()); // 记录日志 // 查询操作日志的targetName String targetName = getSalaryAcctRecordService(user).getLogTargetNameById(calculateParam.getSalaryAcctRecordId()); LoggerContext loggerContext = new LoggerContext<>(); loggerContext.setUser(user); loggerContext.setTargetId(String.valueOf(calculateParam.getSalaryAcctRecordId())); loggerContext.setTargetName(targetName); loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue()); loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "薪资核算")); loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "薪资核算")); SalaryElogConfig.salaryAcctRecordLoggerTemplate.write(loggerContext); } catch (Exception e) { log.info("薪资核算出错:{}", e.getMessage(), e); // throw new SalaryRunTimeException(e); getSalaryAcctProgressService(user).fail(SalaryCacheKey.ACCT_PROGRESS + calculateParam.getSalaryAcctRecordId(), SalaryI18nUtil.getI18nLabel(99642, "薪资核算出错") + ": " + e.getMessage()); } finally { // 数据库字段加密用 } } /** * 处理薪资核算临时存储表中的数据 * * @param calculateParam * @param calculateKey */ private void handleSalaryAcctResultTemp(SalaryAcctCalculateParam calculateParam, String calculateKey) { StopWatch sw = new StopWatch(calculateParam.getSalaryAcctRecordId() + ""); // 查询薪资核算结果的临时存储 sw.start("处理核算数据,查询薪资核算结果的临时存储"); List salaryAcctResultTempPOS = getSalaryAcctResultTempService(user).listByCalculateKey(calculateKey); sw.stop(); // 删除原来的薪资核算结果 sw.start("处理核算数据,删除原来的薪资核算结果"); if (CollectionUtils.isNotEmpty(calculateParam.getIds())) { getSalaryAcctResultMapper().deleteBySalaryAcctEmpIds(calculateParam.getIds()); } else { getSalaryAcctResultMapper().deleteBySalaryAcctRecordIds(Collections.singleton(calculateParam.getSalaryAcctRecordId())); getSalaryAcctReportService(user).deleteBySalaryAcctRecordId(calculateParam.getSalaryAcctRecordId()); } sw.stop(); // 保存薪资的薪资核算结果 sw.start("处理核算数据,保存薪资的薪资核算结果"); List salaryAcctResultPOS = SalaryAcctResultBO.convert2ResultPO(salaryAcctResultTempPOS); batchSave(salaryAcctResultPOS); sw.stop(); // 删除薪资核算临时存储表中的数据 sw.start("处理核算数据,删除薪资核算临时存储表中的数据"); getSalaryAcctResultTempService(user).deleteByCalculateKey(calculateKey); sw.stop(); log.info(sw.prettyPrint()); } @Override public List listBySalaryAcctRecordIdsAndTaxAgentIds(Collection salaryAcctRecordIds, Collection taxAgentIds) { if (CollectionUtils.isEmpty(salaryAcctRecordIds)) { return Collections.emptyList(); } return encryptUtil.decryptList(getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).taxAgentIds(taxAgentIds).build()), SalaryAcctResultPO.class); } // /** // * 查询薪资核算人员 // * // * @param queryParam // * @param salaryAcctRecord // * @return // */ // private List querySalaryAcctEmployee(SalaryAcctResultListContext salaryAcctResultListContext, SalaryAcctResultQueryParam queryParam, SalaryAcctRecordPO salaryAcctRecord) { // // 构建薪资核算人员的查询参数 // SalaryAcctEmployeeQueryParam salaryAcctEmployeeListQueryParam = new SalaryAcctEmployeeQueryParam(); // BeanUtils.copyProperties(queryParam, salaryAcctEmployeeListQueryParam); // // 查询薪资核算人员 // List salaryAcctEmployees = getSalaryAcctEmployeeService(user).listByParam(salaryAcctEmployeeListQueryParam); // // 查询相同税款所属期内的薪资核算人员 // List sameTaxCycleSalaryAcctEmployees = salaryAcctEmployeeService // .listSameTaxCycle(salaryAcctEmployees, SalaryDateUtil.getFormatYearMonth(salaryAcctRecord.getTaxCycle())); // Set sameTaxCycleKeySet = SalaryEntityUtil.properties(sameTaxCycleSalaryAcctEmployees, o -> o.getEmployeeId() + "-" + o.getTaxAgentId()); // salaryAcctResultListContext.setSameTaxCycleKeySet(sameTaxCycleKeySet); // // 过滤合并计税的人员 // if (StringUtils.isNotEmpty(queryParam.getConsolidatedTaxation())) { // salaryAcctEmployees = salaryAcctEmployees.stream() // .filter(salaryAcctEmployeePO -> sameTaxCycleKeySet.contains(salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId())) // .collect(Collectors.toList()); // } // // 根据权限过滤 // return salaryAcctEmployeeService.filterByAuthority(salaryAcctEmployees, employeeId); // } @Override public void lock(SalaryAcctResultLockParam param) { ValidUtil.doValidator(param); SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(param.getAcctEmpId()); if (salaryAcctEmployeePO == null) { return; } List lockItemIds = salaryAcctEmployeePO.getLockItems() == null ? new ArrayList<>() : salaryAcctEmployeePO.getLockItems(); Long salaryItemId = param.getSalaryItemId(); if (param.getLockStatus() == LockStatusEnum.LOCK) { lockItemIds.add(salaryItemId); } else { lockItemIds.removeIf(salaryItemId::equals); } salaryAcctEmployeePO.setLockItems(Lists.newArrayList(new HashSet(lockItemIds))); getSalaryAcctEmployeeService(user).lock(salaryAcctEmployeePO); } @Override public void updateLockStatusByParam(SalaryAcctResultUpdateLockStatusParam updateParam) { List salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(updateParam.getSalaryAcctRecordId()); if (CollectionUtils.isEmpty(salaryAcctEmployees)) { return; } Set salaryItemIds; if (CollectionUtils.isNotEmpty(updateParam.getSalaryItemIds())) { salaryItemIds = updateParam.getSalaryItemIds(); } else { salaryItemIds = Collections.singleton(updateParam.getSalaryItemId()); } salaryAcctEmployees.forEach(salaryAcctEmployeePO -> { List lockItemIds = salaryAcctEmployeePO.getLockItems() == null ? new ArrayList<>() : salaryAcctEmployeePO.getLockItems(); if (updateParam.getLockStatus() == LockStatusEnum.LOCK) { lockItemIds.addAll(salaryItemIds); } else { lockItemIds.removeAll(salaryItemIds); } salaryAcctEmployeePO.setLockItems(Lists.newArrayList(new HashSet(lockItemIds))); getSalaryAcctEmployeeService(user).lock(salaryAcctEmployeePO); }); } @Override public void reCalc(Long id) { // 无需解密 SalaryAcctResultPO build = SalaryAcctResultPO.builder().salaryAcctRecordId(id).deleteType(0).build(); List salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(build); // 回算前的薪资核算结果 salaryAcctResultPOS.forEach(salaryAcctResult -> salaryAcctResult.setOriginResultValue(salaryAcctResult.getResultValue())); // 批量更新 batchUpdateOriginResultValue(salaryAcctResultPOS); } @Override public List listBySalaryAcctRecordIdsAndSalaryItemIds(Collection salaryAcctRecordIds, Collection salaryItemIds) { if (CollectionUtils.isEmpty(salaryAcctRecordIds) || CollectionUtils.isEmpty(salaryItemIds)) { return Collections.emptyList(); } List list = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).salaryItemIds(salaryItemIds).build()); return encryptUtil.decryptList(list, SalaryAcctResultPO.class); } @Override public List listByAcctEmployeeIdsAndSalaryItemIds(List salaryAcctEmployeeIds, Collection salaryItemIds) { if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) { return Collections.emptyList(); } List> partition = Lists.partition(salaryAcctEmployeeIds, 200); List result = new ArrayList<>(); partition.forEach(empIds -> { SalaryAcctResultPO build = SalaryAcctResultPO.builder().salaryAcctEmpIds(empIds).salaryItemIds(salaryItemIds).build(); result.addAll(getSalaryAcctResultMapper().listSome(build)); }); // 数据解密 encryptUtil.decryptList(result, SalaryAcctResultPO.class); return result; } @Override public void batchUpdateOriginResultValue(List salaryAcctResultValues) { int batchSize = 500; List> partition = Lists.partition(salaryAcctResultValues, batchSize); for (List subSalaryAcctResultValues : partition) { getSalaryAcctResultMapper().batchUpdateOriginResultValue(subSalaryAcctResultValues); } } @Override public List listAcctEmpIdByAcctEmpId(List salaryAcctEmployeeIds) { if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) { return Collections.emptyList(); } List> partition = Lists.partition((List) salaryAcctEmployeeIds, 1000); List result = new ArrayList<>(); partition.forEach(empIds -> { result.addAll(getSalaryAcctResultMapper().getAcctEmpIsExist(empIds)); }); return result; } @Override public Boolean checkAuth(Long salaryAcctRecordId) { // 获取该核算记录的个税扣缴义务 SalaryAcctRecordPO recordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId); if (Objects.isNull(recordPO)) { return false; } SalarySobPO salarySobPO = getSalarySobService(user).getById(recordPO.getSalarySobId()); Long taxAgentId = salarySobPO.getTaxAgentId(); List adminTaxAgentList = getTaxAgentAdminService(user).listByEmployeeId(Long.valueOf(user.getUID())); Optional canOperate = adminTaxAgentList.stream().filter(po -> NumberUtils.compare(taxAgentId, po.getTaxAgentId()) == 0).findFirst(); if (!canOperate.isPresent()) { return false; } return true; } @Override public void batchUpdate(SalaryAcctResultBatchUpdateParam param) { ValidUtil.doValidator(param); SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(param.getSalaryAcctRecordId()); if (salaryAcctRecordPO == null) { throw new SalaryRunTimeException("薪资核算记录不存在,或已被删除"); } List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 薪资账套中包含的薪资项目 List salarySobItemIds = salarySobItemPOS.stream().map(SalarySobItemPO::getSalaryItemId).collect(Collectors.toList()); if (!salarySobItemIds.contains(param.getSalaryItemId())) { throw new SalaryRunTimeException("该账套不包含该薪资项目或已被删除,请先检查账套"); } // 获取需要更新的核算人员信息 List salaryAcctEmployeePOList = new ArrayList<>(); if (CollectionUtils.isEmpty(param.getIdList())) { // 没有选择核算人员,更新核算记录中所有人员 salaryAcctEmployeePOList.addAll(getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salaryAcctRecordPO.getId())); } else { salaryAcctEmployeePOList.addAll(getSalaryAcctEmployeeService(user).listByIds(param.getIdList())); } if (CollectionUtils.isNotEmpty(salaryAcctEmployeePOList)) { List salaryAcctEmployeeIdList = SalaryEntityUtil.properties(salaryAcctEmployeePOList, SalaryAcctEmployeePO::getId, Collectors.toList()); // 查询薪资核算结果 List resultPOS = listByAcctEmployeeIdsAndSalaryItemIds(salaryAcctEmployeeIdList, Collections.singleton(param.getSalaryItemId())); Map salaryAcctResultPOMap = SalaryEntityUtil.convert2Map(resultPOS, SalaryAcctResultPO::getSalaryAcctEmpId); List dataCollectionEmployees = getSalaryEmployeeService(user).listAllForReport(); Map emps = SalaryEntityUtil.convert2Map(dataCollectionEmployees, DataCollectionEmployee::getEmployeeId); List needUpdateList = new ArrayList<>(); List needInsertList = new ArrayList<>(); Date now = new Date(); List salaryAcctResultReportPOS = new ArrayList<>(); salaryAcctEmployeePOList.forEach(salaryAcctEmployeePO -> { if (salaryAcctResultPOMap.containsKey(salaryAcctEmployeePO.getId())) { // 更新 SalaryAcctResultPO po = salaryAcctResultPOMap.get(salaryAcctEmployeePO.getId()); po.setResultValue(param.getValue()); po.setUpdateTime(now); needUpdateList.add(po); } else { // 新增 needInsertList.add(SalaryAcctResultPO.builder() .salarySobId(salaryAcctRecordPO.getSalarySobId()) .salaryItemId(param.getSalaryItemId()) .salaryAcctRecordId(param.getSalaryAcctRecordId()) .salaryAcctEmpId(salaryAcctEmployeePO.getId()) .employeeId(salaryAcctEmployeePO.getEmployeeId()) .taxAgentId(salaryAcctEmployeePO.getTaxAgentId()) .resultValue(param.getValue()) .originResultValue("") .creator(Long.valueOf(user.getUID())) .createTime(now) .updateTime(now) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); } // 报表 // SalaryAcctResultReportPO po = SalaryAcctResultReportPO.builder() // .id(IdGenerator.generate()) // .salarySobId(salaryAcctRecordPO.getSalarySobId()) // .salaryItemId(param.getSalaryItemId()) // .salaryAcctRecordId(param.getSalaryAcctRecordId()) // .salaryAcctEmpId(salaryAcctEmployeePO.getId().toString()) // .employeeId(salaryAcctEmployeePO.getEmployeeId().toString()) // .taxAgentId(salaryAcctEmployeePO.getTaxAgentId()) // .resultValue(param.getValue()) // .creator(Long.valueOf(user.getUID())) // .createTime(now) // .updateTime(now) // .deleteType(NumberUtils.INTEGER_ZERO) // .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) // .build(); // DataCollectionEmployee dataCollectionEmployee = emps.get(salaryAcctEmployeePO.getEmployeeId()); // if (dataCollectionEmployee != null) { // po.setDepartmentId(dataCollectionEmployee.getDepartmentId()); // po.setSubcompanyId(dataCollectionEmployee.getSubcompanyid()); // po.setCostcenterId(dataCollectionEmployee.getCostcenterId()); // po.setJobtitleId(dataCollectionEmployee.getJobtitleId()); // po.setLocationId(dataCollectionEmployee.getLocationId()); // } // salaryAcctResultReportPOS.add(po); }); // 入库 if (CollectionUtils.isNotEmpty(needUpdateList)) { // 数据加密 encryptUtil.encryptList(needUpdateList, SalaryAcctResultPO.class); List> partition = Lists.partition(needUpdateList, 100); partition.forEach(getSalaryAcctResultMapper()::batchUpdate); } batchSave(needInsertList); // 报表入库前先删除 // getSalaryAcctReportService(user).deleteByAcctEmployeeIdsAndSalaryItemIds(param.getIdList(), Collections.singletonList(param.getSalaryItemId())); // getSalaryAcctReportService(user).batchSave(salaryAcctResultReportPOS); } } }