package com.engine.salary.service.impl; import cn.hutool.core.util.ObjectUtil; import com.cloudstore.eccom.pc.table.WeaTableColumn; 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.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.*; 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.SalaryValueTypeEnum; 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.IdGenerator; 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.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.conn.RecordSet; import weaver.general.BaseBean; import weaver.general.Util; import weaver.hrm.User; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; 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 SalaryEmployeeService getSalaryEmployeeService() { return ServiceUtil.getService(SalaryEmployeeServiceImpl.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, user); return salaryAcctResultPOS; } @Override public List listBySalaryAcctEmployeeId(Long salaryAcctEmployeeId) { List salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(salaryAcctEmployeeId).build()); encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class, user); // 解密 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, user); 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, user); return salaryAcctResultPOS; } @Override public SalaryAcctResultDetailDTO getBySalaryAcctEmployeeId(Long salaryAcctEmployeeId) { // 查询薪资核算人员 SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(salaryAcctEmployeeId); if (Objects.isNull(salaryAcctEmployeePO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542301, "薪资核算人员不存在或已被删除")); } // 查询是否是回算 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) ? SalaryI18nUtil.getI18nLabel(user.getLanguage(),554, "输入") : 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()); List lockItems = byId.getLockSalaryItemIds() == null ? Collections.emptyList() : byId.getLockSalaryItemIds(); // 转换成薪资核算结果详情dto return SalaryAcctResultBO.convert2DetailDTO(simpleEmployee, taxAgent, salaryAcctEmployeePO, salarySobEmpFieldPOS, salarySobItemGroupPOS, salarySobItemPOS, salaryItemPOS, salaryAcctResultPOS, salarySobBackItemPOList, salaryBackItemPOS, salaryBackItemFormula, formulaContentMap, user, 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(user.getLanguage(),542300, "薪资核算记录不存在或已被删除")); } // 查询薪资核算所用薪资账套的薪资项目 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(user.getLanguage(),542300, "薪资核算记录不存在或已被删除")); } boolean isBackCalc = Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1); // 查询薪资核算所用的薪资账套的员工信息字段 List salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); // 查询薪资核算所用薪资账套的薪资项目 List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); 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(user.getLanguage(),542339, "输入/导入"); } return expressFormulaMap.getOrDefault(salarySobItemPO.getFormulaId(), StringUtils.EMPTY); }); // 回算公式内容转换 Map customBackCalcParameters = SalaryEntityUtil.convert2Map(salarySobBackItemPOList, SalarySobBackItemPO::getSalaryItemId, salarySobBackItemPO -> { if (salarySobBackItemPO.getFormulaId() <= 0) { return SalaryI18nUtil.getI18nLabel(user.getLanguage(),542339, "输入/导入"); } return expressFormulaMap.getOrDefault(salarySobBackItemPO.getFormulaId(), StringUtils.EMPTY); }); // 转换成薪资核算结果列表 return SalaryAcctResultBO.buildTableData(salaryItemPOS, salarySobEmpFieldPOS, simpleEmployees, salaryAcctEmployeePOS, salaryAcctResultPOS, taxAgentPOS, salaryAcctEmployeeIds4ConsolidatedTax, customParameters, customBackCalcParameters, isBackCalc, user); } @Override public ConsolidatedTaxDetailDTO getConsolidatedTaxDetail(Long salaryAcctEmployeeId) { // 查询当前的薪资核算人员 SalaryAcctEmployeePO salaryAcctEmployeePO = getSalaryAcctEmployeeService(user).getById(salaryAcctEmployeeId); if (Objects.isNull(salaryAcctEmployeePO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542301, "薪资核算人员不存在或已被删除")); } // 查询当前的薪资核算人员的个税扣缴义务人 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(user.getLanguage(),542300, "薪资核算记录不存在或已被删除")); } Map resultMap = Maps.newHashMap(); // 查询薪资核算使用的薪资账套下的薪资项目 SalarySobItemAggregateDTO salarySobItemAggregateDTO = getSalarySobItemService(user).getAggregateBySalarySobId(salaryAcctRecordPO.getSalarySobId()); 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(user.getLanguage(),542301, "薪资核算人员不存在或已被删除")); } // 查询原来的薪资核算结果 List salaryAcctResultPOSOld = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(saveParam.getSalaryAcctEmpId()).build()); // 解密 encryptUtil.decryptList(salaryAcctResultPOSOld, SalaryAcctResultPO.class, user); // 保存参数转换成薪资核算结果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, user); List> partition = Lists.partition(salaryAcctResultPOS, 100); partition.forEach(getSalaryAcctResultMapper()::batchInsert); } //报表 todo 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()); saveSalaryAcctResultLog(salaryAcctResultPOSOld, salaryAcctResultPOS); // 查询操作日志的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, user); 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) { StopWatch stopWatch = new StopWatch(calculateParam.getSalaryAcctRecordId() + ""); try { stopWatch.start("核算总耗时数据准备"); // 1、查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(calculateParam.getSalaryAcctRecordId()); if (Objects.isNull(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542300, "薪资核算记录不存在或已被删除")); } //查询对应账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId()); if (Objects.isNull(salarySobPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542303, "薪资账套不存在或已被删除")); } // 1.1、如果薪资核算记录已经归档了,就不能继续核算 if (!Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542340, "当前薪资核算记录已归档,请重新打开后再进行核算")); } // 2、查询薪资核算记录的薪资周期、考勤周期等 SalarySobCycleDTO salarySobCycleDTO = getSalaryAcctRecordService(user).getSalarySobCycleById(calculateParam.getSalaryAcctRecordId()); // 3、查询薪资核算记录所用薪资账套的薪资项目副本 List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); if (CollectionUtils.isEmpty(salarySobItemPOS)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542341, "当前所用的薪资账套未选择任何薪资项目,无法核算")); } // 回算薪资项目 List salarySobBackItems = Collections.emptyList(); if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1)) { salarySobBackItems = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); } // 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 lockSalaryItemIds = salaryAcctRecordPO.getLockSalaryItemIds(); Map acctResults = new HashMap<>(); if (CollectionUtils.isNotEmpty(lockSalaryItemIds)) { List acctResultPOS = listBySalaryAcctRecordIdsAndSalaryItemIds(Collections.singleton(calculateParam.getSalaryAcctRecordId()), lockSalaryItemIds); // List acctResultPOS = listBySalaryAcctRecordIds(Collections.singleton(calculateParam.getSalaryAcctRecordId())); acctResults = Optional.ofNullable(acctResultPOS).orElse(new ArrayList<>()).stream().filter(po -> lockSalaryItemIds.contains(po.getSalaryItemId())).collect(Collectors.toMap(po -> po.getSalaryItemId() + "_" + po.getSalaryAcctEmpId(), a -> a, (a, b) -> a)); } // 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, user); // 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(user.getLanguage(),542342, "薪资核算人员不能为空")); } stopWatch.stop(); stopWatch.start("核算完毕计时"); // 11.1、初始化进度 ProgressDTO initProgress = new ProgressDTO().setTitle(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542322, "核算中")).setTitleLabelId(542322L).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、对薪资核算人员进行拆分 List> partition = Lists.partition(salaryAcctEmployeePOS, 5000); // 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).setSalaryAcctLockResultPOS(MapUtils.emptyIfNull(acctResults)).setLockSalaryItemIds(lockSalaryItemIds).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).setTaxDeclarationFunction(taxDeclarationFunction); List finalSalarySobBackItems = salarySobBackItems; LocalRunnable localRunnable = new LocalRunnable() { @Override public void execute() { getSalaryAcctCalculateService(user).calculate(salaryAcctCalculateBO, simpleEmployee, finalSalarySobBackItems); } }; ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.HRM, "salaryAcctCalculateV2", 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()); // 存储薪资核算数据来源日志 new Thread() { public void run() { List exceptItemIds = new ArrayList<>(); List salaryAcctEmployeeIds = salaryAcctEmployeePOS.stream().map(SalaryAcctEmployeePO::getId).collect(Collectors.toList()); exceptItemIds.addAll(lockSalaryItemIds); exceptItemIds.addAll(salaryItemPOS.stream().filter(PO -> Objects.equals(PO.getValueType(), NumberUtils.INTEGER_ONE) && Objects.equals(PO.getUseInEmployeeSalary(), 0)).map(SalaryItemPO::getId).collect(Collectors.toList())); getSalaryAcctResultLogService(user).deleteBySalaryAcctEmpIdExceptItemIds(salaryAcctEmployeeIds, exceptItemIds); } }.start(); // 记录日志 // 查询操作日志的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(user.getLanguage(),542343, "薪资核算出错") + ": " + 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(); new Thread() { public void run() { //保存核算报表数据 List salaryAcctResultReportPOS = SalaryAcctResultReportBO.convert2ReportPO(salaryAcctResultTempPOS, calculateParam.getEmps()); getSalaryAcctReportService(user).batchSave(salaryAcctResultReportPOS); } }.start(); // 删除薪资核算临时存储表中的数据 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, user); } // /** // * 查询薪资核算人员 // * // * @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 updateLockStatusByParam(SalaryAcctResultUpdateLockStatusParam updateParam) { // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(updateParam.getSalaryAcctRecordId()); if (CollectionUtils.isEmpty(salaryAcctRecord.getLockSalaryItemIds())) { salaryAcctRecord.setLockSalaryItemIds(new ArrayList<>()); } List salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(updateParam.getSalaryAcctRecordId()); if (CollectionUtils.isEmpty(salaryAcctEmployees)) { return; } // 查询薪资核算结果 // List salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployees, SalaryAcctEmployeePO::getId,Collectors.toList()); // List salaryAcctResultValues = this.listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds); // Map salaryAcctResultValueMap = SalaryEntityUtil.convert2Map(salaryAcctResultValues, SalaryAcctResultPO::getSalaryAcctEmpId); // 值可以锁定的薪资项目 // Set salaryItemIds = canLockSalaryItemIds(salaryAcctRecord.getSalarySobId()); // if (Objects.nonNull(updateParam.getSalaryItemId())) { // if (!salaryItemIds.contains(updateParam.getSalaryItemId())) { // return; // } // salaryItemIds = Collections.singleton(updateParam.getSalaryItemId()); // } Set salaryItemIds; if (CollectionUtils.isNotEmpty(updateParam.getSalaryItemIds())) { salaryItemIds = updateParam.getSalaryItemIds(); } else { salaryItemIds = Collections.singleton(updateParam.getSalaryItemId()); } if (updateParam.getLockStatus() == LockStatusEnum.LOCK) { Set lockSalaryItemIds = new HashSet<>(); lockSalaryItemIds.addAll(salaryAcctRecord.getLockSalaryItemIds()); lockSalaryItemIds.addAll(salaryItemIds); salaryAcctRecord.setLockSalaryItemIds(new ArrayList(lockSalaryItemIds)); } else { salaryAcctRecord.getLockSalaryItemIds().removeAll(salaryItemIds); } getSalaryAcctRecordService(user).updateLockSalaryItemIds(salaryAcctRecord); } @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, user); } @Override public List listByAcctEmployeeIdsAndSalaryItemIds(List salaryAcctEmployeeIds, Collection salaryItemIds) { if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) { return Collections.emptyList(); } List> partition = Lists.partition((List) 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, user); 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; } private Set canLockSalaryItemIds(Long salarySobId) { // 值可以锁定的薪资项目 Set salaryItemIds = Sets.newHashSet(); // 查询薪资核算记录所用的薪资账套的薪资项目 List salarySobItems = Lists.newArrayList(); SalarySobItemAggregateDTO salarySobItemAggregate = getSalarySobItemService(user).getAggregateBySalarySobId(salarySobId); for (SalarySobItemIncomeCategoryDTO incomeCategory : salarySobItemAggregate.getIncomeCategories()) { for (SalarySobItemGroupDTO itemGroup : incomeCategory.getItemGroups()) { salarySobItems.addAll(itemGroup.getItems()); } salarySobItems.addAll(incomeCategory.getItems()); } for (SalarySobItemDTO salarySobItem : salarySobItems) { if (Objects.equals(salarySobItem.getValueType(), SalaryValueTypeEnum.FORMULA.getValue()) && salarySobItem.isCanEdit()) { salaryItemIds.add(salarySobItem.getSalaryItemId()); } } // for (SalarySobItemDTO backCalcItem : salarySobItemAggregate.getBackCalcItems()) { // if (Objects.equals(backCalcItem.getValueType(), SalaryValueTypeEnum.FORMULA.getValue()) && backCalcItem.isCanEdit()) { // salaryItemIds.add(backCalcItem.getSalaryItemId()); // } // } return salaryItemIds; } @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 Map sumForWorkflow(SalaryAcctResultQueryParam param) { SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(param.getSalaryAcctRecordId()); if (ObjectUtil.isEmpty(salaryAcctRecordPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542300, "薪资核算记录不存在或已被删除")); } BaseBean baseBean = new BaseBean(); String fieldNameStr = baseBean.getPropValue("shgwSalary", "fieldName"); String[] fields = fieldNameStr.split(","); Map sumMap = new HashMap<>(); Map fieldItemMap = new HashMap<>(); List salaryItemIds = new ArrayList<>(); for (String field : fields) { Long salaryItemId = Long.valueOf(StringUtils.isEmpty(baseBean.getPropValue("shgwSalary", field)) ? "0" : baseBean.getPropValue("shgwSalary", field)); salaryItemIds.add(salaryItemId); fieldItemMap.put(field, salaryItemId); } List itemList = getSalaryItemService(user).listByIds(salaryItemIds); Map salaryItemMap = SalaryEntityUtil.convert2Map(itemList, SalaryItemPO::getId); List salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId()); Map sobItemMap = SalaryEntityUtil.convert2Map(salarySobItemPOS, SalarySobItemPO::getSalaryItemId); // 查询薪资核算结果 List salaryAcctResultList = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordId(param.getSalaryAcctRecordId()).salaryItemIds(salaryItemIds).build()); encryptUtil.decryptList(salaryAcctResultList, SalaryAcctResultPO.class, user); Map> acctResultMap = SalaryEntityUtil.group2Map(salaryAcctResultList, SalaryAcctResultPO::getSalaryItemId); fieldItemMap.forEach((field,itemId) -> { SalaryItemPO salaryItemPO = salaryItemMap.get(itemId); if (salaryItemPO != null && SalaryDataTypeEnum.NUMBER.getValue().equals(salaryItemPO.getDataType())) { BigDecimal sum = Optional.ofNullable(acctResultMap.get(salaryItemPO.getId())).orElse(new ArrayList<>()).stream().map(SalaryAcctResultPO::getResultValue).filter(NumberUtils::isCreatable).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add); sumMap.put(field, SalaryAcctFormulaBO.roundResultValue(sum.toString(), salaryItemPO, Collections.emptyList(), Collections.emptyMap(), sobItemMap)); } }); return sumMap; } @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, user); 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); } } @Override public Map fygsdReport(SalaryAcctRecordQueryParam param) { if (param.getStartMonth() == null || param.getEndMonth() == null) { throw new SalaryRunTimeException("报表参数错误"); } RecordSet rs = new RecordSet(); Map resultMap = new HashMap<>(); // 获取薪资核算记录信息 Collection taxAgentList = getTaxAgentService(user).listAllTaxAgents(Long.valueOf(user.getUID())); List taxAgentIds = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList()); List salarySobList = getSalarySobService(user).listByTaxAgentIds(taxAgentIds); List salarySobIds = salarySobList.stream().map(SalarySobPO::getId).collect(Collectors.toList()); List salaryAcctRecordList= new ArrayList<>(); if (CollectionUtils.isNotEmpty(salarySobIds)) { // 查询参数 SalaryAcctRecordPO po = SalaryAcctRecordPO.builder().salarySobIds(salarySobIds).build(); LocalDateRange localDateRange = new LocalDateRange(); localDateRange.setFromDate(SalaryDateUtil.localDateToDate(param.getStartMonth().atDay(1))); localDateRange.setEndDate(SalaryDateUtil.localDateToDate(param.getEndMonth().atEndOfMonth())); po.setSalaryMonths(localDateRange); salaryAcctRecordList.addAll(getSalaryAcctRecordService(user).listSome(po)); // 获取薪资核算人员 List salaryAcctRecordIds = salaryAcctRecordList.stream().map(SalaryAcctRecordPO::getId).collect(Collectors.toList()); List salaryAcctEmployeeList = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordIds(salaryAcctRecordIds); List employeeIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList()); // 获取这些员工的费用类型信息 List fylbInfoList = getGwEmpFylxInfo(employeeIds, rs, localDateRange); List gwFylbDataDTOS = buildGwFylbData(fylbInfoList, localDateRange, employeeIds); // 获取需要查询哪些薪资项目(有序) List itemRelationList = getGwReportItems(rs); // 查询这些员工每个人每个费用类型下的人天数及薪资数据 Map>> salaryAcctEmpReportInfo = getGwReportInfoByAcctEmp(salaryAcctEmployeeList, gwFylbDataDTOS, itemRelationList, localDateRange, rs); // 获取费用类型下拉框信息 Map fylxMap = getFylxSelectItemMap(rs); // 根据薪资账套分组 Map> acctEmpGroupBySob = SalaryEntityUtil.group2Map(salaryAcctEmployeeList, SalaryAcctEmployeePO::getSalarySobId, SalaryAcctEmployeePO::getId); // 构建报表信息,计算小计 List> dataList = buildReportData(acctEmpGroupBySob, fylxMap, salaryAcctEmpReportInfo, itemRelationList, salarySobList); // 构建表头 List columns = new ArrayList<>(); columns.add(new WeaTableColumn("100px", "国家", "gj")); columns.add(new WeaTableColumn("100px", "费用类型", "fylx1")); columns.add(new WeaTableColumn("100px", "费用类型", "fylx2")); columns.add(new WeaTableColumn("100px", "人数", "empNums")); for (GwSalaryItemRelation itemRelation : itemRelationList) { columns.add(new WeaTableColumn("100px", itemRelation.getSalaryItemShowName(), itemRelation.getSalaryItemId().toString())); } resultMap.put("column", columns); resultMap.put("dataList", dataList); } return resultMap; } /** * 构建报表信息,计算小计 * * @param acctEmpGroupBySob * @param fylxMap * @param salaryAcctEmpReportInfo * @return */ private List> buildReportData(Map> acctEmpGroupBySob, Map fylxMap, Map>> salaryAcctEmpReportInfo, List itemRelationList, List salarySobList) { List> resultList = new ArrayList<>(); Set fylxIds = fylxMap.keySet(); List itemIdList = itemRelationList.stream().map(item -> item.getSalaryItemId().toString()).collect(Collectors.toList()); Map salarySobNameMap = SalaryEntityUtil.convert2Map(salarySobList, SalarySobPO::getId, SalarySobPO::getName); // 获取办公室费用、其他关系对应的id BaseBean baseBean = new BaseBean(); int bgsfySelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue(); int qtgxSelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_qtgx_select_id")).intValue(); for (Map.Entry> entry : acctEmpGroupBySob.entrySet()){ // 该账套下的结果(用于计算小计) List> resultListBySob = new ArrayList<>(); String sobName = salarySobNameMap.getOrDefault(entry.getKey(), ""); // 该分组下的薪资核算人员id Set acctEmpIds = entry.getValue(); List>> reportInfoListBySob = new ArrayList<>(); acctEmpIds.stream().forEach(acctEmpId -> { if (salaryAcctEmpReportInfo.get(acctEmpId) != null) { reportInfoListBySob.add(salaryAcctEmpReportInfo.get(acctEmpId)); } }); // 计算每一个费用类型的合计值 double threshold = 1e-10; for (Integer fylxId : fylxIds) { String fylxName = fylxMap.getOrDefault(fylxId, ""); // 获取该账套下 该费用类型下所有报表结果 List> reportInfoListByFylx = reportInfoListBySob.stream().map(map -> map.get(fylxId)) .filter(m -> m != null) .collect(Collectors.toList()); // 先获取该费用类型下的人数是否为0 BigDecimal empNums = reportInfoListByFylx.stream() .map(map -> map.get("empNums")) .filter(NumberUtils::isCreatable) .map(BigDecimal::new) .reduce(BigDecimal.ZERO, BigDecimal::add); if ( empNums.doubleValue() > threshold ) { Map fylxSumMap = new HashMap<>(); // 薪资项目值 itemIdList.stream().forEach(itemId -> { BigDecimal sum = reportInfoListByFylx.stream() .map(map -> map.get(itemId)) .filter(NumberUtils::isCreatable) .map(BigDecimal::new) .reduce(BigDecimal.ZERO, BigDecimal::add); fylxSumMap.put(itemId.toString(), sum.toPlainString()); }); // 人数 fylxSumMap.put("empNums", empNums.toPlainString()); // 国家 fylxSumMap.put("gj", sobName); // 2个费用类型 if (fylxId.equals(bgsfySelectId)) { fylxSumMap.put("fylx1","办公室费用"); fylxSumMap.put("fylx2", "办公室费用"); } else if (fylxId.equals(qtgxSelectId)) { fylxSumMap.put("fylx1", "其他费用"); fylxSumMap.put("fylx2", fylxName); } else { fylxSumMap.put("fylx1", "项目费用"); fylxSumMap.put("fylx2", fylxName); } resultListBySob.add(fylxSumMap); } } // 该账套下的小计 Map xjMap = new HashMap<>(); // 薪资项目值 List> finalResultListBySob = resultListBySob; itemIdList.stream().forEach(itemId -> { BigDecimal xjSum = finalResultListBySob.stream() .map(map -> map.get(itemId)) .filter(NumberUtils::isCreatable) .map(BigDecimal::new) .reduce(BigDecimal.ZERO, BigDecimal::add); xjMap.put(itemId.toString(), xjSum.toPlainString()); }); // 排序 resultListBySob = resultListBySob.stream().sorted(Comparator.comparing(map -> map.get("gj") + "-" + map.get("fylx1"))).collect(Collectors.toList()); // 人数 BigDecimal xjEmpNums = resultListBySob.stream() .map(map -> map.get("empNums")) .filter(NumberUtils::isCreatable) .map(BigDecimal::new) .reduce(BigDecimal.ZERO, BigDecimal::add) .setScale(0,BigDecimal.ROUND_HALF_UP); xjMap.put("empNums", xjEmpNums.toPlainString()); // 国家 xjMap.put("gj", sobName); // 2个费用类型 xjMap.put("fylx1", "小计"); xjMap.put("fylx2", "小计"); resultListBySob.add(xjMap); resultList.addAll(resultListBySob); } return resultList; } /** * 获取港湾费用类型下拉框信息 * * @return */ private Map getFylxSelectItemMap(RecordSet rs) { Map resultMap = new HashMap<>(); BaseBean baseBean = new BaseBean(); String fylxFieldId = baseBean.getPropValue("shgwSalaryReport", "fylx_field_id"); rs.execute("select selectvalue,selectname from workflow_selectitem where fieldid = " + fylxFieldId); while (rs.next()) { resultMap.put(rs.getInt(1), Util.formatMultiLang(rs.getString(2))); } resultMap.put(-1, ""); return resultMap; } /** * 查询这些员工每个人每个费用类型下的人天数及薪资数据 * * @param salaryAcctEmployeeList * @param gwFylbDataDTOS * @param itemRelationList * @return */ private Map>> getGwReportInfoByAcctEmp(List salaryAcctEmployeeList, List gwFylbDataDTOS, List itemRelationList, LocalDateRange localDateRange, RecordSet rs) { Map>> resultMap = new HashMap<>(); // 查询这个核算人员的薪资核算结果 if (CollectionUtils.isNotEmpty(salaryAcctEmployeeList) && CollectionUtils.isNotEmpty(itemRelationList)) { List salaryAcctEmpIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getId).collect(Collectors.toList()); List salaryItemIds = itemRelationList.stream().map(GwSalaryItemRelation::getSalaryItemId).collect(Collectors.toList()); List acctResultList = listByAcctEmployeeIdsAndSalaryItemIds(salaryAcctEmpIds, salaryItemIds); Map> acctResultMap = SalaryEntityUtil.group2Map(acctResultList, SalaryAcctResultPO::getSalaryAcctEmpId); // 获取这些员工的项目经历信息 List xmjlList = gwGetEmpXmjlInfo(rs, localDateRange, salaryAcctEmployeeList); Map> xmjlMapByEmpId = SalaryEntityUtil.group2Map(xmjlList, GwXmjl::getEmployeeId); // 获取办公室费用、其他关系对应的id BaseBean baseBean = new BaseBean(); int bgsfySelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue(); int qtgxSelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_qtgx_select_id")).intValue(); Map gwFylbDataMap = SalaryEntityUtil.convert2Map(gwFylbDataDTOS, GwFylbDataDTO::getEmployeeId); for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctEmployeeList) { Map> empFylbMap = new HashMap>(); // 获取该员工的费用类型信息 GwFylbDataDTO gwFylbDataDTO = gwFylbDataMap.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), GwFylbDataDTO.builder().fylbItemValues(Collections.emptyList()).build()); List fylbItemValues = gwFylbDataDTO.getFylbItemValues(); // 获取该员工薪资核算信息 List salaryValueList = acctResultMap.get(salaryAcctEmployeePO.getId()); Map acctResultValueMap = SalaryEntityUtil.convert2Map(salaryValueList, SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue); if (CollectionUtils.isNotEmpty(fylbItemValues)) { // 存在费用类型信息 // 获取该员工的项目经历信息 List empXmjlList = xmjlMapByEmpId.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), Collections.emptyList()); if (fylbItemValues.size() == 1) { // 薪资周期内没有发生过费用类型调整 LocalDateRange effectiveDateRange = fylbItemValues.get(0).getEffectiveDateRange(); int fylx = fylbItemValues.get(0).getValue(); if (fylx == bgsfySelectId || fylx == qtgxSelectId) { // 费用类型是办公室费用、其他关系则不需要再查询项目经历表,不需要考虑分段计算 Map empSalaryMap = new HashMap(); empSalaryMap.put("empNums", "1.00"); // 获取薪资数据 for (Long salaryItemId : salaryItemIds) { empSalaryMap.put(salaryItemId.toString(), acctResultValueMap.getOrDefault(salaryItemId, "")); } empFylbMap.put(fylx, empSalaryMap); } else { // 费用类型不是办公室费用、其他关系需要查项目经历中项目有几天,其余归类为办公室费用 // 获取薪资周期内有多少天是有项目经历的 Map xmDaysMap = gwGetDaysInRange(effectiveDateRange.getFromDate(), effectiveDateRange.getEndDate(), empXmjlList); BigDecimal xmDays = new BigDecimal(xmDaysMap.get("xmDays")); BigDecimal officeDays = new BigDecimal(xmDaysMap.get("officeDays")); BigDecimal totalDays = xmDays.add(officeDays); // 分段计算人数和薪资封装项目天数、办公室天数 BigDecimal baseDay = new BigDecimal(1).divide(totalDays, 15, RoundingMode.HALF_UP); Map empXmSalaryMap = new HashMap(); empXmSalaryMap.put("empNums", baseDay.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); Map empOfficeSalaryMap = new HashMap(); empOfficeSalaryMap.put("empNums", baseDay.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); for (Long salaryItemId : salaryItemIds) { BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, "")) : new BigDecimal("0"); BigDecimal itemValeBase = itemValue.divide(totalDays, 15, RoundingMode.HALF_UP); empXmSalaryMap.put(salaryItemId.toString(), itemValeBase.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); empOfficeSalaryMap.put(salaryItemId.toString(), itemValeBase.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); } empFylbMap.put(fylx, empXmSalaryMap); empFylbMap.put(bgsfySelectId, empOfficeSalaryMap); } } else { // 薪资周期内发生过费用类型变更 // 获取费用类型周期 LocalDateRange effectiveDateRange = LocalDateRange.builder() .fromDate(fylbItemValues.get(fylbItemValues.size()-1).getEffectiveDateRange().getFromDate()) .endDate(fylbItemValues.get(0).getEffectiveDateRange().getEndDate()) .build(); // 获取总计天数 BigDecimal totalDays = new BigDecimal(SalaryDateUtil.getDays(effectiveDateRange.getFromDate(), effectiveDateRange.getEndDate())); BigDecimal totalXmDays = new BigDecimal(0); BigDecimal baseDay = new BigDecimal(1).divide(totalDays, 15, RoundingMode.HALF_UP); for (GwFylbItemDataDTO fylbItemData : fylbItemValues) { if (fylbItemData.getValue() == bgsfySelectId) { // 费用类别就是 办公室,则不获取是否有项目经历,该周期内都是办公室 } else { // 获取此费用类别中有多少天有项目经历(这里不能取计算出来的办公室天数) Map xmDaysMap = gwGetDaysInRange(fylbItemData.getEffectiveDateRange().getFromDate(), fylbItemData.getEffectiveDateRange().getEndDate(), empXmjlList); BigDecimal xmDays = new BigDecimal(xmDaysMap.get("xmDays")); totalXmDays = totalXmDays.add(xmDays); // 封装各个项目的天数和薪资(分段计算) Map empXmSalaryMap = new HashMap(); empXmSalaryMap.put("empNums", baseDay.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); for (Long salaryItemId : salaryItemIds) { BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, "")) : new BigDecimal("0"); empXmSalaryMap.put(salaryItemId.toString(), itemValue.divide(totalDays, 15, RoundingMode.HALF_UP).multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); } empFylbMap.put(fylbItemData.getValue(), empXmSalaryMap); } } // 封装计算办公室类型 BigDecimal officeDays = totalDays.subtract(totalXmDays); Map empOfficeSalaryMap = new HashMap(); empOfficeSalaryMap.put("empNums", baseDay.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); for (Long salaryItemId : salaryItemIds) { BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, "")) : new BigDecimal("0"); empOfficeSalaryMap.put(salaryItemId.toString(), itemValue.divide(totalDays, 15, RoundingMode.HALF_UP).multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); } empFylbMap.put(bgsfySelectId, empOfficeSalaryMap); } } else { // 不存在费用费别信息 Map empSalaryMap = new HashMap(); empSalaryMap.put("empNums", "1.00"); for (Long salaryItemId : salaryItemIds) { BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, "")) : new BigDecimal("0"); empSalaryMap.put(salaryItemId.toString(), itemValue.toPlainString()); } empFylbMap.put(-1, empSalaryMap); } resultMap.put(salaryAcctEmployeePO.getId(), empFylbMap); } } return resultMap; } /** * 获取薪资周期内多少天有项目经历 * * @return */ private Map gwGetDaysInRange(Date startDate, Date endDate, List xmjlList) { Map resultMap = new HashMap<>(); // 项目天数 int xmDays = 0; // 办公室天数 int officeDays = 0; if (CollectionUtils.isEmpty(xmjlList)) { resultMap.put("xmDays", xmDays); resultMap.put("officeDays", SalaryDateUtil.getDays(startDate, endDate)); return resultMap; } LocalDate startLocalDate = SalaryDateUtil.dateToLocalDate(startDate); LocalDate endLocalDate = SalaryDateUtil.dateToLocalDate(endDate); LocalDate tempLocalDate = startLocalDate; while (!tempLocalDate.isAfter(endLocalDate)) { // 默认不在范围内 boolean flag = false; for (int i = 0; i < xmjlList.size(); i++) { Date xmjlStartDate = xmjlList.get(i).getStartDate(); Date xmjlEndDate = xmjlList.get(i).getEndDate(); if (SalaryDateUtil.dayInRange(tempLocalDate, SalaryDateUtil.dateToLocalDate(xmjlStartDate), SalaryDateUtil.dateToLocalDate(xmjlEndDate))) { flag = true; break; } } if (flag == true) { xmDays++; } else { officeDays++; } tempLocalDate = tempLocalDate.plusDays(1); } resultMap.put("xmDays", xmDays); resultMap.put("officeDays", officeDays); return resultMap; } /** * 获取需要查询哪些薪资项目(有序) * * @return */ private List getGwReportItems(RecordSet rs) { List resultList = new ArrayList<>(); List salaryItemPOList = getSalaryItemService(user).listAll(); Map salaryItemMap = SalaryEntityUtil.convert2Map(salaryItemPOList, item -> Util.formatMultiLang(item.getName(), "7"), item -> item.getId()); rs.execute("select xzxm,xsmc,px from uf_fygsdxzxm a order by px"); while (rs.next()) { String itemName = rs.getString(1); Long itemId = salaryItemMap.get(itemName); if (itemId != null) { GwSalaryItemRelation itemRelation = new GwSalaryItemRelation(); itemRelation.setSalaryItemName(rs.getString(1)); itemRelation.setSalaryItemShowName(rs.getString("xsmc")); itemRelation.setSortedId(rs.getInt("px")); itemRelation.setSalaryItemId(itemId); resultList.add(itemRelation); } } return resultList; } /** * 获取港湾员工项目经历信息 * @param localDateRange * @param salaryAcctEmployeeList * @return */ private List gwGetEmpXmjlInfo(RecordSet rs, LocalDateRange localDateRange, List salaryAcctEmployeeList) { String startDate = SalaryDateUtil.getFormatDate(localDateRange.getFromDate()); String endDate = SalaryDateUtil.getFormatDate(localDateRange.getEndDate()); List empIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList()); List> partition = Lists.partition(empIds, 800); List xmjlList = new ArrayList<>(); partition.forEach(part -> { String empStr = "(" + StringUtils.join(part, ",") + ")"; rs.execute("select ygxm,xxmbdrq,lkrq from uf_xmjlgljmb where CAST(xxmbdrq as DATE) <= CAST('"+ endDate +"' as DATE) and (lkrq is null or lkrq = '' or CAST(lkrq as DATE) >= CAST('"+ startDate +"' as DATE)) and ygxm in " + empStr); while (rs.next()) { GwXmjl gwXmjl = new GwXmjl(); gwXmjl.setEmployeeId(Long.valueOf(rs.getInt(1))); gwXmjl.setStartDate(SalaryDateUtil.stringToDate(rs.getString(2))); gwXmjl.setEndDate(SalaryDateUtil.stringToDate(rs.getString(3))); xmjlList.add(gwXmjl); } }); return xmjlList; } /** * 获取港湾员工费用类型信息 * @param employeeIds * @return */ private List getGwEmpFylxInfo(List employeeIds, RecordSet rs, LocalDateRange localDateRange) { List resultList = new ArrayList<>(); if (CollectionUtils.isEmpty(employeeIds)) { return resultList; } List> partition = Lists.partition(employeeIds, 500); partition.forEach(part -> { String sql = "select xm,sxrq,fylx from uf_fylxgx where cast(sxrq as DATE) <= cast('"+ SalaryDateUtil.getFormatDate(localDateRange.getEndDate()) +"' as date) and xm in (" + StringUtils.join(part, ",") + ")"; rs.execute(sql); while (rs.next()) { Date sxrqDate = SalaryDateUtil.dateStrToLocalDate(rs.getString("sxrq")); int fylx = rs.getInt("fylx"); if (sxrqDate != null) { resultList.add(GwFylxInfo.builder().employeeId(Long.valueOf(rs.getInt("xm"))).sxrq(sxrqDate).fylxId(fylx).build()); } } }); return resultList; } /** * 构建港湾费用类别数据 * * @return */ public List buildGwFylbData(List fylbInfoList, LocalDateRange localDateRange, List allEmployeeIds) { // 获取离职员工的离职日期 List dismissEmpList = getSalaryEmployeeService(user).listDismissEmpByIds(allEmployeeIds); Map dismissDateMap = SalaryEntityUtil.convert2Map(dismissEmpList, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getDismissdate); Map> fylbInfoMap = SalaryEntityUtil.group2Map(fylbInfoList, GwFylxInfo::getEmployeeId); List list = new ArrayList<>(); allEmployeeIds.forEach(e -> { GwFylbDataDTO gwFylbData = new GwFylbDataDTO(); gwFylbData.setEmployeeId(e); // 获取该员工的费用类别信息 List gwFylxInfos = fylbInfoMap.getOrDefault(e, Collections.emptyList()); // 费用类型信息降序排序 gwFylxInfos = gwFylxInfos.stream().sorted(Comparator.comparing(GwFylxInfo::getSxrq).reversed()).collect(Collectors.toList()); // 开始日期 Date startItem = localDateRange.getFromDate(); // 结束日期 Date endItem = localDateRange.getEndDate(); // 对于离职的员工,结束日期就是离职日期 if (dismissDateMap.containsKey(e)) { endItem = SalaryDateUtil.dateStrToLocalDate(dismissDateMap.get(e)); } Date endTempItem = endItem; List gwFylbItemDataValues = new ArrayList<>(); boolean flag = false; for (GwFylxInfo gwFylxInfo : gwFylxInfos) { Date fromDateItem = gwFylxInfo.getSxrq(); if (fromDateItem.after(endTempItem) || endTempItem.before(startItem)) { continue; } if (endTempItem.equals(startItem) && flag) { continue; } GwFylbItemDataDTO gwFylbItemDataValue = new GwFylbItemDataDTO(); LocalDateRange dateRange = LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build(); if (flag == true) { // 不是第一条,结束日期都要减1天 dateRange.setEndDate(SalaryDateUtil.localDateToDate(SalaryDateUtil.dateToLocalDate(dateRange.getEndDate()).minusDays(1))); } gwFylbItemDataValue.setEffectiveDateRange(dateRange); gwFylbItemDataValue.setValue(gwFylxInfo.getFylxId()); gwFylbItemDataValues.add(gwFylbItemDataValue); flag = true; endTempItem = fromDateItem; } gwFylbData.setFylbItemValues(gwFylbItemDataValues); list.add(gwFylbData); }); return list; } }