package com.engine.salary.service.impl; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.component.WeaTableColumnGroup; import com.engine.salary.encrypt.EncryptUtil; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryacct.bo.SalaryAcctResultBO; import com.engine.salary.entity.salaryacct.dto.SalaryComparisonResultListDTO; import com.engine.salary.entity.salaryacct.param.SalaryAcctEmployeeQueryParam; import com.engine.salary.entity.salaryacct.param.SalaryComparisonResultQueryParam; import com.engine.salary.entity.salaryacct.po.ExcelAcctResultPO; import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO; import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO; import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO; import com.engine.salary.entity.salaryformula.ExpressFormula; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.entity.salarysob.bo.SalarySobItemAggregateBO; import com.engine.salary.entity.salarysob.dto.SalarySobItemAggregateDTO; import com.engine.salary.entity.salarysob.po.*; import com.engine.salary.entity.taxagent.po.TaxAgentPO; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.mapper.salaryacct.ExcelAcctResultMapper; import com.engine.salary.service.*; 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.Sets; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import weaver.hrm.User; import java.util.*; import java.util.stream.Collectors; /** * 薪资核算的线下对比结果 *

Copyright: Copyright (c) 2022

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ public class SalaryComparisonResultServiceImpl extends Service implements SalaryComparisonResultService { private EncryptUtil encryptUtil = new EncryptUtil(); private ExcelAcctResultMapper getExcelAcctResultMapper() { return MapperProxyFactory.getProxy(ExcelAcctResultMapper.class); } private SalaryAcctResultService getSalaryAcctResultService(User user) { return ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user); } private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) { return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user); } private SalarySobItemService getSalarySobItemService(User user) { return ServiceUtil.getService(SalarySobItemServiceImpl.class, user); } private SalaryAcctRecordService getSalaryAcctRecordService(User user) { return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user); } private SalarySobEmpFieldService getSalarySobEmpFieldService(User user) { return ServiceUtil.getService(SalarySobEmpFieldServiceImpl.class, user); } private SalaryEmployeeService getSalaryEmployeeService(User user) { return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user); } private TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } private SalaryFormulaService getSalaryFormulaService(User user) { return ServiceUtil.getService(SalaryFormulaServiceImpl.class, user); } private SalaryItemService getSalaryItemService(User user) { return ServiceUtil.getService(SalaryItemServiceImpl.class, user); } private SalarySobService getSalarySobService(User user) { return ServiceUtil.getService(SalarySobServiceImpl.class, user); } private SalarySobItemGroupService getSalarySobItemGroupService(User user) { return ServiceUtil.getService(SalarySobItemGroupServiceImpl.class, user); } private SalarySobItemHideService getSalarySobItemHideService(User user) { return ServiceUtil.getService(SalarySobItemHideServiceImpl.class, user); } @Override public List listBySalaryAcctRecordId(Long salaryAcctRecordId) { List excelAcctResultPOS = getExcelAcctResultMapper().listSome(ExcelAcctResultPO.builder().salaryAcctRecordId(salaryAcctRecordId).build()); return encryptUtil.decryptList(excelAcctResultPOS, ExcelAcctResultPO.class); } @Override public List listBySalaryAcctEmployeeIds(Collection salaryAcctEmployeeIds) { if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) { return Collections.emptyList(); } List excelAcctResultPOS = new ArrayList<>(); List> partition = Lists.partition((List) salaryAcctEmployeeIds, 2000); partition.forEach(empIds -> { excelAcctResultPOS.addAll(getExcelAcctResultMapper().listSome(ExcelAcctResultPO.builder().salaryAcctEmpIds(empIds).build())); }); return encryptUtil.decryptList(excelAcctResultPOS, ExcelAcctResultPO.class); } @Override public SalaryComparisonResultListDTO listPageByParam(SalaryComparisonResultQueryParam queryParam) { return listByParam(true, queryParam); } @Override public SalaryComparisonResultListDTO listByParam(SalaryComparisonResultQueryParam queryParam) { return listByParam(false, queryParam); } /** * 根据薪资核算人员查询薪资核算线下对比结果 * * @param queryParam 列表查询条件 * @return */ private SalaryComparisonResultListDTO listByParam(boolean needPage, SalaryComparisonResultQueryParam queryParam) { // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(queryParam.getSalaryAcctRecordId()); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除")); } // 查询薪资核算所用薪资账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId()); // 查询薪资核算所用的薪资账套的员工信息字段 List salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 查询薪资账套的薪资项目分类 List salarySobItemGroupPOS = getSalarySobItemGroupService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 查询薪资核算所用薪资账套的薪资项目副本 List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 过滤在账套中隐藏的薪资项目 List hideItemIds = getSalarySobItemHideService(user).listSome(SalarySobItemHidePO.builder().itemHide(1L).salarySobId(salaryAcctRecordPO.getSalarySobId()).build()) .stream().map(SalarySobItemHidePO::getSalaryItemId).collect(Collectors.toList()); salarySobItemPOS = salarySobItemPOS.stream().filter(po -> !hideItemIds.contains(po.getSalaryItemId())).collect(Collectors.toList()); // 查询公式详情 Set formulaIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getFormulaId); 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); }); // 查询薪资项目 Set salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); List salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds); // 转换成聚合dto SalarySobItemAggregateBO salarySobItemAggregateBO = new SalarySobItemAggregateBO(salarySobPO, salarySobEmpFieldPOS, salarySobItemGroupPOS, salarySobItemPOS, expressFormulas, salaryItemPOS, Collections.emptyList(), Collections.emptyList()); SalarySobItemAggregateDTO salarySobItemAggregateDTO = salarySobItemAggregateBO.convert2AggregateDTO(); // 薪资核算人员 List salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByResultQueryParam(queryParam); if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) { // 构建薪资核算结果列表表头 List weaTableColumns = SalaryAcctResultBO.buildTableColumns4ComparisonResultByGroup(salarySobItemAggregateDTO, Collections.emptySet()); // 构建列表数据 // 返回结果 return new SalaryComparisonResultListDTO().setWeaTableColumns(weaTableColumns).setData(new PageInfo<>()); } // 薪资核算结果 List salaryAcctResultPOS; // 线下导入结果 List excelAcctResultPOS; // 如果薪资核算人员太多,利用薪资核算人员id查询薪资核算结果的效率就不太好,改为直接用薪资核算记录id查询 if (salaryAcctEmployeePOS.size() > 1000) { // 查询薪资核算结果 salaryAcctResultPOS = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singleton(queryParam.getSalaryAcctRecordId())); // 查询线下导入结果 excelAcctResultPOS = listBySalaryAcctRecordId(queryParam.getSalaryAcctRecordId()); } else { // 薪资核算人员id List salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList()); // 查询薪资核算结果 salaryAcctResultPOS = getSalaryAcctResultService(user).listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); // 查询线下导入结果 excelAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); } // 查询个税扣缴义务人 Set taxAgentIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getTaxAgentId); List taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds); // 查询人员信息 List employeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getEmployeeId, Collectors.toList()); List simpleEmployees = getSalaryEmployeeService(user).getEmployeeByIdsAll(employeeIds); // 判断是否存在合并计税 Set salaryAcctEmployeeIds4ConsolidatedTax; if (StringUtils.isEmpty(queryParam.getConsolidatedTaxation())) { 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); } // 系统值和线下值不一致的薪资项目id Set includeSalaryItemIds = Sets.newHashSetWithExpectedSize(salaryItemPOS.size()); // 转换成薪资核算线下对比结果 List> resultMapList = SalaryAcctResultBO.buildComparisonTableData(salaryItemPOS, salarySobEmpFieldPOS, simpleEmployees, salaryAcctEmployeePOS, salaryAcctResultPOS, excelAcctResultPOS, taxAgentPOS, customParameters, salaryAcctEmployeeIds4ConsolidatedTax, includeSalaryItemIds); // 系统值和线下值一致的人员 if (queryParam.isOnlyDiffEmployee()) { // 过滤系统值和线下值一致的薪资核算人员 resultMapList = resultMapList.stream() .filter(map -> BooleanUtils.toBoolean(String.valueOf(map.get("different")))) .collect(Collectors.toList()); } // 分页 PageInfo> dtoPage = new PageInfo<>(); dtoPage.setTotal(resultMapList.size()); if (needPage) { dtoPage.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), resultMapList)); dtoPage.setPageSize(queryParam.getPageSize()); dtoPage.setPageNum(queryParam.getCurrent()); } else { dtoPage.setList(resultMapList); } Set excludeSalaryItemIds = Sets.newHashSet(); if (queryParam.isOnlyDiffSalaryItem()) { // 过滤系统值和线下值一致的薪资项目 excludeSalaryItemIds = salaryItemPOS.stream() .filter(salaryItemPO -> !includeSalaryItemIds.contains(salaryItemPO.getId())) .map(SalaryItemPO::getId) .collect(Collectors.toSet()); } // 构建薪资核算结果列表表头 List weaTableColumns = SalaryAcctResultBO.buildTableColumns4ComparisonResultByGroup(salarySobItemAggregateDTO, excludeSalaryItemIds); // 返回结果 return new SalaryComparisonResultListDTO().setWeaTableColumns(weaTableColumns).setData(dtoPage); } @Override public void batchSave(Collection excelAcctResultPOS) { if (CollectionUtils.isEmpty(excelAcctResultPOS)) { return; } excelAcctResultPOS = encryptUtil.encryptList(new ArrayList<>(excelAcctResultPOS), ExcelAcctResultPO.class); List> partition = Lists.partition((List) excelAcctResultPOS, 100); partition.forEach(getExcelAcctResultMapper()::batchInsert); } @Override public void deleteBySalaryAcctEmployeeIds(Collection salaryAcctEmployeeIds) { getExcelAcctResultMapper().deleteBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); } @Override public void deleteBySalaryAcctRecordIds(Collection salaryAcctRecordIds) { getExcelAcctResultMapper().deleteBySalaryAcctRecordIds(salaryAcctRecordIds); } }