weaver-hrm-salary/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl...

1747 lines
108 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/**
* 薪资核算结果
* <p>Copyright: Copyright (c) 2022</p>
* <p>Company: 泛微软件</p>
*
* @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<SalaryAcctResultPO> listBySalaryAcctRecordIds(Collection<Long> salaryAcctRecordIds) {
if (CollectionUtils.isEmpty(salaryAcctRecordIds)) {
return Collections.emptyList();
}
List<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).build());
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class, user);
return salaryAcctResultPOS;
}
@Override
public List<SalaryAcctResultPO> listBySalaryAcctEmployeeId(Long salaryAcctEmployeeId) {
List<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(salaryAcctEmployeeId).build());
encryptUtil.decryptList(salaryAcctResultPOS, SalaryAcctResultPO.class, user);
// 解密
return salaryAcctResultPOS;
}
@Override
public List<SalaryAcctResultPO> listBySalaryAcctEmployeeIds(Collection<Long> salaryAcctEmployeeIds) {
if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) {
return Collections.emptyList();
}
List<List<Long>> partition = Lists.partition((List<Long>) salaryAcctEmployeeIds, 500);
List<SalaryAcctResultPO> 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<SalaryAcctResultPO> listBySalaryAcctRecordIdsAndEmployeeIds(Collection<Long> salaryAcctRecordIds, Collection<Long> employeeIds) {
if (CollectionUtils.isEmpty(salaryAcctRecordIds) || CollectionUtils.isEmpty(employeeIds)) {
return Collections.emptyList();
}
List<List<Long>> partition = Lists.partition((List<Long>) employeeIds, 500);
List<SalaryAcctResultPO> 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<SalarySobItemGroupPO> salarySobItemGroupPOS = getSalarySobItemGroupService(user).listBySalarySobIdWithItemHide(salaryAcctEmployeePO.getSalarySobId());
// 获取关闭显示的分类
List<Long> 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<Long> salarySobItemGroupIds = salarySobItemGroupPOS.stream().map(SalarySobItemGroupPO::getId).collect(Collectors.toList());
//加上未分类
salarySobItemGroupIds.add(0L);
// 查询薪资账套的薪资项目副本(已经过滤关闭分类显示按钮的薪资项目)
List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobIdAndGroupId(salaryAcctEmployeePO.getSalarySobId(), salarySobItemGroupIds);
//----------------------------------------------
// 查询薪资核算所用薪资账套的薪资项目副本
// List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctEmployeePO.getSalarySobId());
// 获取关闭显示的薪资项目
List<Long> 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<SalarySobBackItemPO> salarySobBackItemPOList = Collections.emptyList();
List<SalaryItemPO> salaryBackItemPOS = Collections.emptyList();
// key:账套中回算薪资项目的薪资项目id value:账套中回算薪资项目所对应的公式内容
Map<Long, String> salaryBackItemFormula = new HashMap<>();
if (isBackCal) {
salarySobBackItemPOList = getSalarySobBackItemService(user).listBySalarySobId(byId.getSalarySobId());
Set<Long> salarySobBackItemIds = SalaryEntityUtil.properties(salarySobBackItemPOList, SalarySobBackItemPO::getSalaryItemId);
salaryBackItemPOS = getSalaryItemService(user).listByIds(salarySobBackItemIds);
// 查询薪资账套中已发补发的公式内容
List<ExpressFormula> expressFormulas = getSalaryFormulaService(user).listExpressFormula(SalaryEntityUtil.properties(salarySobBackItemPOList, SalarySobBackItemPO::getFormulaId));
Map<Long, String> 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<Long> salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds);
// 查询薪资核算所用薪资账套的人员信息字段
List<SalarySobEmpFieldPO> salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctEmployeePO.getSalarySobId());
// 查询人员信息
DataCollectionEmployee simpleEmployee = getSalaryEmployeeService(user).getEmployeeById(salaryAcctEmployeePO.getEmployeeId());
// 查询薪资核算结果
List<SalaryAcctResultPO> salaryAcctResultPOS = listBySalaryAcctEmployeeId(salaryAcctEmployeeId);
// 查询个税扣缴义务人
TaxAgentPO taxAgent = getTaxAgentService(user).getById(salaryAcctEmployeePO.getTaxAgentId());
// 查询公式
Map<String, SalaryAcctResultListColumnDTO> formulaContentMap = getSalaryAcctResultService(user).getColumnBySalaryAcctRecordId(salaryAcctEmployeePO.getSalaryAcctRecordId());
List<Long> 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<Map<String, Object>> listPageByParam(SalaryAcctResultQueryParam queryParam) {
PageInfo<SalaryAcctEmployeePO> page = null;
//其他条件
List<SalaryAcctResultQueryParam.OtherCondition> otherConditions = queryParam.getOtherConditions();
if (CollectionUtils.isNotEmpty(otherConditions)) {
List<Long> items = SalaryEntityUtil.properties(otherConditions, SalaryAcctResultQueryParam.OtherCondition::getItemId, Collectors.toList());
List<SalaryAcctResultPO> 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<String> 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<Long> 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<Map<String, Object>> data = listBySalaryAcctEmployees(page.getList(), queryParam);
// 薪资核算结果的分页结果
PageInfo<Map<String, Object>> resultPage = new PageInfo<>();
resultPage.setList(data);
resultPage.setTotal(page.getTotal());
resultPage.setPageNum(page.getPageNum());
resultPage.setPageSize(page.getPageSize());
return resultPage;
}
@Override
public Map<String, Object> sumRow(SalaryAcctResultQueryParam queryParam) {
//其他条件
List<SalaryAcctResultQueryParam.OtherCondition> otherConditions = queryParam.getOtherConditions();
if (CollectionUtils.isNotEmpty(otherConditions)) {
List<Long> items = SalaryEntityUtil.properties(otherConditions, SalaryAcctResultQueryParam.OtherCondition::getItemId, Collectors.toList());
List<SalaryAcctResultPO> 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<String> 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<Long> salaryAcctEmpId = SalaryEntityUtil.properties(list, SalaryAcctResultPO::getSalaryAcctEmpId, Collectors.toList());
if (CollectionUtils.isEmpty(salaryAcctEmpId)) {
//条件不满足直接返回空列表
return new HashMap<>();
} else {
queryParam.setIds(salaryAcctEmpId);
}
}
// 查询薪资核算人员
List<SalaryAcctEmployeePO> 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<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
Map<Long, SalarySobItemPO> salaryItemIdKeySalarySobItemPOMap = SalaryEntityUtil.convert2Map(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
Set<Long> salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), NumberUtils.INTEGER_ONE)) {
// 是回算,获取回算项
List<SalarySobBackItemPO> salarySobBackItemPOS = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
salaryItemIds.addAll(salarySobBackItemPOS.stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList()));
}
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds);
// 查询薪资核算结果
List<Long> salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList());
List<SalaryAcctResultPO> salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds);
Map<String, Object> map = new HashMap<>();
Map<Long, List<SalaryAcctResultPO>> 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<Map<String, Object>> listByParam(SalaryAcctResultQueryParam queryParam) {
// 查询薪资核算人员
List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByResultQueryParam(queryParam);
// 查询薪资核算结果
return listBySalaryAcctEmployees(salaryAcctEmployeePOS, queryParam);
}
/**
* 根据薪资核算人员查询薪资核算结果
*
* @param salaryAcctEmployeePOS 薪资核算人员
* @param queryParam 列表查询条件
* @return
*/
private List<Map<String, Object>> listBySalaryAcctEmployees(List<SalaryAcctEmployeePO> 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<SalarySobEmpFieldPO> salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
// 查询薪资核算所用薪资账套的薪资项目
List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
Set<Long> salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
// 是否是回算
List<SalarySobBackItemPO> salarySobBackItemPOList = Collections.emptyList();
if (isBackCalc) {
// 根据薪资账套获取回算信息项
salarySobBackItemPOList = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
salaryItemIds.addAll(salarySobBackItemPOList.stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList()));
}
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds);
// 查询薪资核算结果
List<Long> salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList());
List<SalaryAcctResultPO> salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds);
// 查询人员信息
List<Long> employeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> simpleEmployees = getSalaryEmployeeService(user).getEmployeeByIdsAll(employeeIds);
simpleEmployees.forEach(e -> {
UserStatusEnum userStatusEnum = UserStatusEnum.parseByValue(Integer.parseInt(e.getStatus()));
if (userStatusEnum != null) {
e.setStatusName(userStatusEnum.getDefaultLabel());
}
});
// 查询个税扣缴义务人
Set<Long> taxAgentIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getTaxAgentId);
List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);
// 判断是否存在合并计税
Set<Long> 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<SalaryAcctEmployeePO> salaryAcctEmployeePOS4ConsolidatedTax = getSalaryAcctEmployeeService(user).listByParam4ConsolidatedTax(accEmployeeQueryParam);
salaryAcctEmployeeIds4ConsolidatedTax = SalaryEntityUtil.properties(salaryAcctEmployeePOS4ConsolidatedTax, SalaryAcctEmployeePO::getId);
}
// 查询公式详情
Set<Long> formulaIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getFormulaId);
// 获取回算公式
if (isBackCalc) {
formulaIds.addAll(salarySobBackItemPOList.stream().map(SalarySobBackItemPO::getFormulaId).collect(Collectors.toList()));
}
List<ExpressFormula> expressFormulas = getSalaryFormulaService(user).listExpressFormula(formulaIds);
Map<Long, String> expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId, ExpressFormula::getFormula);
Map<Long, String> 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<Long, String> 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<SalarySobEmpFieldPO> salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salarySobPO.getId());
List<SalaryAcctRecordPO> salaryAcctRecordPOS = Collections.singletonList(salaryAcctRecordPO);
List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = Collections.singletonList(salaryAcctEmployeePO);
// 如果当前薪资核算记录所用的薪资账套的薪资类型是工资薪金,代表可能存在合并计税
if (Objects.equals(salarySobPO.getIncomeCategory(), IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) {
// 查询所有薪资类型为工资薪金的账套
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByIncomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES);
// 查询相同税款所属期内的薪资类型为工资薪金的账套的所有核算记录
Set<Long> salarySobIds = SalaryEntityUtil.properties(salarySobPOS, SalarySobPO::getId);
LocalDateRange taxCycleDateRange = SalaryDateUtil.localDate2Range(salaryAcctRecordPO.getTaxCycle());
salaryAcctRecordPOS = getSalaryAcctRecordService(user).listBySalarySobIdsAndTaxCycle(salarySobIds, taxCycleDateRange);
// 查询当前薪资核算人员所涉及的合并计税的所有薪资核算人员
Set<Long> salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId);
salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listByRecordIdsAndEmpIdAndTaxAgentId(salaryAcctRecordIds, salaryAcctEmployeePO.getEmployeeId(), salaryAcctEmployeePO.getTaxAgentId());
}
// 查询薪资核算人员的薪资核算结果
List<Long> salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId, Collectors.toList());
List<SalaryAcctResultPO> salaryAcctResultPOS = listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds);
// 查询薪资核算人员所有合并计税的薪资核算记录所用的账套
Set<Long> salarySobIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getSalarySobId);
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByIds(salarySobIds);
// 查询薪资项目所引用的薪资项目
List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobIds(salarySobIds);
// 查询薪资项目
Set<Long> salaryItemIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listByIds(salaryItemIds);
// 转换成合并计税详情dto
return SalaryAcctResultBO.convert2ConsolidatedTaxDetailDTO(simpleEmployee, taxAgentPO, salarySobEmpFieldPOS, salaryItemPOS, salaryAcctEmployeePOS, salarySobPOS, salaryAcctRecordPOS, salaryAcctResultPOS);
}
@Override
public Map<String, SalaryAcctResultListColumnDTO> getColumnBySalaryAcctRecordId(Long salaryAcctRecordId) {
SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
if (Objects.isNull(salaryAcctRecordPO)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542300, "薪资核算记录不存在或已被删除"));
}
Map<String, SalaryAcctResultListColumnDTO> 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<SalarySobItemDTO> 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<DataCollectionEmployee> dataCollectionEmployees = getSalaryEmployeeService(user).listAllForReport();
Map<Long, DataCollectionEmployee> 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<SalaryAcctResultPO> salaryAcctResultPOSOld = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctEmpId(saveParam.getSalaryAcctEmpId()).build());
// 解密
encryptUtil.decryptList(salaryAcctResultPOSOld, SalaryAcctResultPO.class, user);
// 保存参数转换成薪资核算结果po
List<SalaryAcctResultPO> 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<Long> needLockItems = new HashSet<>();
Map<Long, SalaryAcctResultPO> 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<Long> salarySobBackItemIds = getSalarySobBackItemService(user).listBySalarySobId(byId.getSalarySobId()).stream().map(SalarySobBackItemPO::getSalaryItemId).collect(Collectors.toList());
// // 获取已发待发的薪资核算结果
// List<SalaryAcctResultPO> salarySobBackItemResultPO = salaryAcctResultPOSOld.stream().filter(po -> salarySobBackItemIds.contains(po.getSalaryItemId())).collect(Collectors.toList());
// salaryAcctResultPOS.addAll(salarySobBackItemResultPO);
// }
// 删除原来的薪资核算结果
List<Long> 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<List<SalaryAcctResultPO>> partition = Lists.partition(salaryAcctResultPOS, 100);
partition.forEach(getSalaryAcctResultMapper()::batchInsert);
}
//报表 todo
getSalaryAcctReportService(user).deleteByAcctEmployeeIdsAndSalaryItemIds(Collections.singletonList(saveParam.getSalaryAcctEmpId()), saveItemIds);
List<SalaryAcctResultReportPO> 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<SalaryCheckResultPO> 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<SalaryAcctResultPO> salaryAcctResultPOSOld, List<SalaryAcctResultPO> salaryAcctResultPOS) {
// 对比核算结果提取修改了哪些薪资项目
List<SalaryAcctResultPO> editItems = new ArrayList<>();
Map<Long, SalaryAcctResultPO> 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<SalaryAcctResultLogPO> needInsertList = SalaryAcctResultLogBO.buildSalaryAcctResultLog(editItems, Long.valueOf(user.getUID()), SalaryAcctResultDataSourceEnum.EDIT);
getSalaryAcctResultLogService(user).batchInsert(needInsertList);
}
@Override
public void batchSave(List<SalaryAcctResultPO> salaryAcctResultPOS) {
if (CollectionUtils.isNotEmpty(salaryAcctResultPOS)) {
// 数据加密
encryptUtil.encryptList(salaryAcctResultPOS, SalaryAcctResultPO.class, user);
List<List<SalaryAcctResultPO>> partition = Lists.partition(salaryAcctResultPOS, 100);
partition.forEach(getSalaryAcctResultMapper()::batchInsert);
}
}
@Override
public void deleteBySalaryAcctEmployeeIds(Collection<Long> salaryAcctEmployeeIds) {
getSalaryAcctResultMapper().deleteBySalaryAcctEmpIds(salaryAcctEmployeeIds);
}
@Override
public void deleteByAcctEmployeeIdsAndSalaryItemIds(List<Long> salaryAcctEmployeeIds, Collection<Long> salaryItemIds) {
List<List<Long>> partition = Lists.partition(salaryAcctEmployeeIds, 300);
partition.forEach(part -> getSalaryAcctResultMapper().deleteByAcctEmpIdsAndSalaryItemIds(part, salaryItemIds));
}
@Override
public void deleteBySalaryAcctRecordIds(Collection<Long> 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<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
if (CollectionUtils.isEmpty(salarySobItemPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(user.getLanguage(),542341, "当前所用的薪资账套未选择任何薪资项目,无法核算"));
}
// 回算薪资项目
List<SalarySobBackItemPO> salarySobBackItems = Collections.emptyList();
if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1)) {
salarySobBackItems = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
}
// 4、查询当前租户的所有薪资项目
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listAll();
// 5、查询薪资核算记录所用薪资账套的调薪计薪规则
List<SalarySobAdjustRulePO> salarySobAdjustRulePOS = getSalarySobAdjustRuleService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
// 6、查询社保福利的所有字段
Map<String, String> welfareColumns = getSIAccountService(user).welfareColumns();
// 7、查询考勤引用的所有字段
List<AttendQuoteFieldListDTO> attendQuoteFieldListDTOS = getAttendQuoteFieldService(user).listAll();
//核算锁定值
List<Long> lockSalaryItemIds = salaryAcctRecordPO.getLockSalaryItemIds();
Map<String, SalaryAcctResultPO> acctResults = new HashMap<>();
if (CollectionUtils.isNotEmpty(lockSalaryItemIds)) {
List<SalaryAcctResultPO> acctResultPOS = listBySalaryAcctRecordIdsAndSalaryItemIds(Collections.singleton(calculateParam.getSalaryAcctRecordId()), lockSalaryItemIds);
// List<SalaryAcctResultPO> 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<Long> formulaIds = SalaryEntityUtil.properties(salarySobItemPOS, SalarySobItemPO::getFormulaId);
formulaIds.addAll(SalaryEntityUtil.properties(salaryItemPOS, SalaryItemPO::getFormulaId));
formulaIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getFormulaId));
List<ExpressFormula> expressFormulas = getSalaryFormulaService(user).listExpressFormula(formulaIds);
// 本次运算的回算薪资项目所涉及的变量
Set<String> issuedFieldIds = new HashSet<>();
// 9、计算薪资项目的运算优先级
List<List<Long>> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds, user);
// 10、根据id查询其他合并计税的薪资核算记录
List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId());
// 11、查询本次核算人员
List<SalaryAcctEmployeePO> 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<List<SalaryAcctEmployeePO>> partition = Lists.partition(salaryAcctEmployeePOS, 5000);
// 12.1、监控子线程的任务执行
CountDownLatch childMonitor = new CountDownLatch(partition.size());
// 12.2、记录子线程的执行结果
BlockingDeque<SalaryAcctCalculateBO.Result> calculateResults = new LinkedBlockingDeque<>(partition.size());
// 12.3、生成本次运算的key
String calculateKey = UUID.randomUUID().toString();
// 12.4、是否采用系统算税
TaxDeclarationFunctionEnum taxDeclarationFunction = getSalarySysConfService(user).getTaxDeclaration();
// 12.5、多线程运算,运算结果存放在临时表中
for (List<SalaryAcctEmployeePO> 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<SalarySobBackItemPO> 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<Long> exceptItemIds = new ArrayList<>();
List<Long> 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<SalaryCheckResultPO> 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<SalaryAcctResultTempPO> 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<SalaryAcctResultPO> salaryAcctResultPOS = SalaryAcctResultBO.convert2ResultPO(salaryAcctResultTempPOS);
batchSave(salaryAcctResultPOS);
sw.stop();
new Thread() {
public void run() {
//保存核算报表数据
List<SalaryAcctResultReportPO> 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<SalaryAcctResultPO> listBySalaryAcctRecordIdsAndTaxAgentIds(Collection<Long> salaryAcctRecordIds, Collection<Long> 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<SalaryAcctEmployeePO> querySalaryAcctEmployee(SalaryAcctResultListContext salaryAcctResultListContext, SalaryAcctResultQueryParam queryParam, SalaryAcctRecordPO salaryAcctRecord) {
// // 构建薪资核算人员的查询参数
// SalaryAcctEmployeeQueryParam salaryAcctEmployeeListQueryParam = new SalaryAcctEmployeeQueryParam();
// BeanUtils.copyProperties(queryParam, salaryAcctEmployeeListQueryParam);
// // 查询薪资核算人员
// List<SalaryAcctEmployeePO> salaryAcctEmployees = getSalaryAcctEmployeeService(user).listByParam(salaryAcctEmployeeListQueryParam);
// // 查询相同税款所属期内的薪资核算人员
// List<SalaryAcctEmployeePO> sameTaxCycleSalaryAcctEmployees = salaryAcctEmployeeService
// .listSameTaxCycle(salaryAcctEmployees, SalaryDateUtil.getFormatYearMonth(salaryAcctRecord.getTaxCycle()));
// Set<String> 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<SalaryAcctEmployeePO> salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(updateParam.getSalaryAcctRecordId());
if (CollectionUtils.isEmpty(salaryAcctEmployees)) {
return;
}
// 查询薪资核算结果
// List<Long> salaryAcctEmployeeIds = SalaryEntityUtil.properties(salaryAcctEmployees, SalaryAcctEmployeePO::getId,Collectors.toList());
// List<SalaryAcctResultPO> salaryAcctResultValues = this.listBySalaryAcctEmployeeIds(salaryAcctEmployeeIds);
// Map<Long, SalaryAcctResultPO> salaryAcctResultValueMap = SalaryEntityUtil.convert2Map(salaryAcctResultValues, SalaryAcctResultPO::getSalaryAcctEmpId);
// 值可以锁定的薪资项目
// Set<Long> salaryItemIds = canLockSalaryItemIds(salaryAcctRecord.getSalarySobId());
// if (Objects.nonNull(updateParam.getSalaryItemId())) {
// if (!salaryItemIds.contains(updateParam.getSalaryItemId())) {
// return;
// }
// salaryItemIds = Collections.singleton(updateParam.getSalaryItemId());
// }
Set<Long> salaryItemIds;
if (CollectionUtils.isNotEmpty(updateParam.getSalaryItemIds())) {
salaryItemIds = updateParam.getSalaryItemIds();
} else {
salaryItemIds = Collections.singleton(updateParam.getSalaryItemId());
}
if (updateParam.getLockStatus() == LockStatusEnum.LOCK) {
Set<Long> lockSalaryItemIds = new HashSet<>();
lockSalaryItemIds.addAll(salaryAcctRecord.getLockSalaryItemIds());
lockSalaryItemIds.addAll(salaryItemIds);
salaryAcctRecord.setLockSalaryItemIds(new ArrayList<Long>(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<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultMapper().listSome(build);
// 回算前的薪资核算结果
salaryAcctResultPOS.forEach(salaryAcctResult -> salaryAcctResult.setOriginResultValue(salaryAcctResult.getResultValue()));
// 批量更新
batchUpdateOriginResultValue(salaryAcctResultPOS);
}
@Override
public List<SalaryAcctResultPO> listBySalaryAcctRecordIdsAndSalaryItemIds(Collection<Long> salaryAcctRecordIds, Collection<Long> salaryItemIds) {
if (CollectionUtils.isEmpty(salaryAcctRecordIds) || CollectionUtils.isEmpty(salaryItemIds)) {
return Collections.emptyList();
}
List<SalaryAcctResultPO> list = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordIds(salaryAcctRecordIds).salaryItemIds(salaryItemIds).build());
return encryptUtil.decryptList(list, SalaryAcctResultPO.class, user);
}
@Override
public List<SalaryAcctResultPO> listByAcctEmployeeIdsAndSalaryItemIds(List<Long> salaryAcctEmployeeIds, Collection<Long> salaryItemIds) {
if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) {
return Collections.emptyList();
}
List<List<Long>> partition = Lists.partition((List<Long>) salaryAcctEmployeeIds, 200);
List<SalaryAcctResultPO> 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<SalaryAcctResultPO> salaryAcctResultValues) {
int batchSize = 500;
List<List<SalaryAcctResultPO>> partition = Lists.partition(salaryAcctResultValues, batchSize);
for (List<SalaryAcctResultPO> subSalaryAcctResultValues : partition) {
getSalaryAcctResultMapper().batchUpdateOriginResultValue(subSalaryAcctResultValues);
}
}
@Override
public List<Long> listAcctEmpIdByAcctEmpId(List<Long> salaryAcctEmployeeIds) {
if (CollectionUtils.isEmpty(salaryAcctEmployeeIds)) {
return Collections.emptyList();
}
List<List<Long>> partition = Lists.partition((List<Long>) salaryAcctEmployeeIds, 1000);
List<Long> result = new ArrayList<>();
partition.forEach(empIds -> {
result.addAll(getSalaryAcctResultMapper().getAcctEmpIsExist(empIds));
});
return result;
}
private Set<Long> canLockSalaryItemIds(Long salarySobId) {
// 值可以锁定的薪资项目
Set<Long> salaryItemIds = Sets.newHashSet();
// 查询薪资核算记录所用的薪资账套的薪资项目
List<SalarySobItemDTO> 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<TaxAgentAdminPO> adminTaxAgentList = getTaxAgentAdminService(user).listByEmployeeId(Long.valueOf(user.getUID()));
Optional<TaxAgentAdminPO> canOperate = adminTaxAgentList.stream().filter(po -> NumberUtils.compare(taxAgentId, po.getTaxAgentId()) == 0).findFirst();
if (!canOperate.isPresent()) {
return false;
}
return true;
}
@Override
public Map<String, Object> 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<String, Object> sumMap = new HashMap<>();
Map<String, Long> fieldItemMap = new HashMap<>();
List<Long> 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<SalaryItemPO> itemList = getSalaryItemService(user).listByIds(salaryItemIds);
Map<Long, SalaryItemPO> salaryItemMap = SalaryEntityUtil.convert2Map(itemList, SalaryItemPO::getId);
List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
Map<Long, SalarySobItemPO> sobItemMap = SalaryEntityUtil.convert2Map(salarySobItemPOS, SalarySobItemPO::getSalaryItemId);
// 查询薪资核算结果
List<SalaryAcctResultPO> salaryAcctResultList = getSalaryAcctResultMapper().listSome(SalaryAcctResultPO.builder().salaryAcctRecordId(param.getSalaryAcctRecordId()).salaryItemIds(salaryItemIds).build());
encryptUtil.decryptList(salaryAcctResultList, SalaryAcctResultPO.class, user);
Map<Long, List<SalaryAcctResultPO>> 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<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
// 薪资账套中包含的薪资项目
List<Long> salarySobItemIds = salarySobItemPOS.stream().map(SalarySobItemPO::getSalaryItemId).collect(Collectors.toList());
if (!salarySobItemIds.contains(param.getSalaryItemId())) {
throw new SalaryRunTimeException("该账套不包含该薪资项目或已被删除,请先检查账套");
}
// 获取需要更新的核算人员信息
List<SalaryAcctEmployeePO> 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<Long> salaryAcctEmployeeIdList = SalaryEntityUtil.properties(salaryAcctEmployeePOList, SalaryAcctEmployeePO::getId, Collectors.toList());
// 查询薪资核算结果
List<SalaryAcctResultPO> resultPOS = listByAcctEmployeeIdsAndSalaryItemIds(salaryAcctEmployeeIdList, Collections.singleton(param.getSalaryItemId()));
Map<Long, SalaryAcctResultPO> salaryAcctResultPOMap = SalaryEntityUtil.convert2Map(resultPOS, SalaryAcctResultPO::getSalaryAcctEmpId);
List<DataCollectionEmployee> dataCollectionEmployees = getSalaryEmployeeService(user).listAllForReport();
Map<Long, DataCollectionEmployee> emps = SalaryEntityUtil.convert2Map(dataCollectionEmployees, DataCollectionEmployee::getEmployeeId);
List<SalaryAcctResultPO> needUpdateList = new ArrayList<>();
List<SalaryAcctResultPO> needInsertList = new ArrayList<>();
Date now = new Date();
List<SalaryAcctResultReportPO> 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<List<SalaryAcctResultPO>> 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<String, Object> fygsdReport(SalaryAcctRecordQueryParam param) {
if (param.getStartMonth() == null || param.getEndMonth() == null) {
throw new SalaryRunTimeException("报表参数错误");
}
RecordSet rs = new RecordSet();
Map<String, Object> resultMap = new HashMap<>();
// 获取薪资核算记录信息
Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents(Long.valueOf(user.getUID()));
List<Long> taxAgentIds = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
List<SalarySobPO> salarySobList = getSalarySobService(user).listByTaxAgentIds(taxAgentIds);
List<Long> salarySobIds = salarySobList.stream().map(SalarySobPO::getId).collect(Collectors.toList());
List<SalaryAcctRecordPO> 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<Long> salaryAcctRecordIds = salaryAcctRecordList.stream().map(SalaryAcctRecordPO::getId).collect(Collectors.toList());
List<SalaryAcctEmployeePO> salaryAcctEmployeeList = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordIds(salaryAcctRecordIds);
List<Long> employeeIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList());
// 获取这些员工的费用类型信息
List<GwFylxInfo> fylbInfoList = getGwEmpFylxInfo(employeeIds, rs, localDateRange);
List<GwFylbDataDTO> gwFylbDataDTOS = buildGwFylbData(fylbInfoList, localDateRange, employeeIds);
// 获取需要查询哪些薪资项目(有序)
List<GwSalaryItemRelation> itemRelationList = getGwReportItems(rs);
// 查询这些员工每个人每个费用类型下的人天数及薪资数据
Map<Long, Map<Integer, Map<String, String>>> salaryAcctEmpReportInfo = getGwReportInfoByAcctEmp(salaryAcctEmployeeList, gwFylbDataDTOS, itemRelationList, localDateRange, rs);
// 获取费用类型下拉框信息
Map<Integer, String> fylxMap = getFylxSelectItemMap(rs);
// 根据薪资账套分组
Map<Long, Set<Long>> acctEmpGroupBySob = SalaryEntityUtil.group2Map(salaryAcctEmployeeList, SalaryAcctEmployeePO::getSalarySobId, SalaryAcctEmployeePO::getId);
// 构建报表信息,计算小计
List<Map<String, String>> dataList = buildReportData(acctEmpGroupBySob, fylxMap, salaryAcctEmpReportInfo, itemRelationList, salarySobList);
// 构建表头
List<WeaTableColumn> 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<Map<String, String>> buildReportData(Map<Long, Set<Long>> acctEmpGroupBySob,
Map<Integer, String> fylxMap,
Map<Long, Map<Integer, Map<String, String>>> salaryAcctEmpReportInfo,
List<GwSalaryItemRelation> itemRelationList,
List<SalarySobPO> salarySobList) {
List<Map<String, String>> resultList = new ArrayList<>();
Set<Integer> fylxIds = fylxMap.keySet();
List<String> itemIdList = itemRelationList.stream().map(item -> item.getSalaryItemId().toString()).collect(Collectors.toList());
Map<Long, String> 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<Long, Set<Long>> entry : acctEmpGroupBySob.entrySet()){
// 该账套下的结果(用于计算小计)
List<Map<String, String>> resultListBySob = new ArrayList<>();
String sobName = salarySobNameMap.getOrDefault(entry.getKey(), "");
// 该分组下的薪资核算人员id
Set<Long> acctEmpIds = entry.getValue();
List<Map<Integer, Map<String, String>>> 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<Map<String, String>> 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<String, String> 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<String, String> xjMap = new HashMap<>();
// 薪资项目值
List<Map<String, String>> 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<Integer, String> getFylxSelectItemMap(RecordSet rs) {
Map<Integer, String> 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<Long, Map<Integer, Map<String, String>>> getGwReportInfoByAcctEmp(List<SalaryAcctEmployeePO> salaryAcctEmployeeList,
List<GwFylbDataDTO> gwFylbDataDTOS,
List<GwSalaryItemRelation> itemRelationList,
LocalDateRange localDateRange,
RecordSet rs) {
Map<Long, Map<Integer, Map<String, String>>> resultMap = new HashMap<>();
// 查询这个核算人员的薪资核算结果
if (CollectionUtils.isNotEmpty(salaryAcctEmployeeList) && CollectionUtils.isNotEmpty(itemRelationList)) {
List<Long> salaryAcctEmpIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getId).collect(Collectors.toList());
List<Long> salaryItemIds = itemRelationList.stream().map(GwSalaryItemRelation::getSalaryItemId).collect(Collectors.toList());
List<SalaryAcctResultPO> acctResultList = listByAcctEmployeeIdsAndSalaryItemIds(salaryAcctEmpIds, salaryItemIds);
Map<Long, List<SalaryAcctResultPO>> acctResultMap = SalaryEntityUtil.group2Map(acctResultList, SalaryAcctResultPO::getSalaryAcctEmpId);
// 获取这些员工的项目经历信息
List<GwXmjl> xmjlList = gwGetEmpXmjlInfo(rs, localDateRange, salaryAcctEmployeeList);
Map<Long, List<GwXmjl>> 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_bgsfy_select_id")).intValue();
Map<Long, GwFylbDataDTO> gwFylbDataMap = SalaryEntityUtil.convert2Map(gwFylbDataDTOS, GwFylbDataDTO::getEmployeeId);
for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctEmployeeList) {
Map<Integer, Map<String, String>> empFylbMap = new HashMap<Integer, Map<String, String>>();
// 获取该员工的费用类型信息
GwFylbDataDTO gwFylbDataDTO = gwFylbDataMap.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), GwFylbDataDTO.builder().fylbItemValues(Collections.emptyList()).build());
List<GwFylbItemDataDTO> fylbItemValues = gwFylbDataDTO.getFylbItemValues();
// 获取该员工薪资核算信息
List<SalaryAcctResultPO> salaryValueList = acctResultMap.get(salaryAcctEmployeePO.getId());
Map<Long, String> acctResultValueMap = SalaryEntityUtil.convert2Map(salaryValueList, SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue);
if (CollectionUtils.isNotEmpty(fylbItemValues)) {
// 存在费用类型信息
// 获取该员工的项目经历信息
List<GwXmjl> 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<String, String> empSalaryMap = new HashMap<String, String>();
empSalaryMap.put("empNums", "1.00");
// 获取薪资数据
for (Long salaryItemId : salaryItemIds) {
empSalaryMap.put(salaryItemId.toString(), acctResultValueMap.getOrDefault(salaryItemId, ""));
}
empFylbMap.put(fylx, empSalaryMap);
} else {
// 费用类型不是办公室费用、其他关系需要查项目经历中项目有几天,其余归类为办公室费用
// 获取薪资周期内有多少天是有项目经历的
Map<String, Integer> 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<String, String> empXmSalaryMap = new HashMap<String, String>();
empXmSalaryMap.put("empNums", baseDay.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
Map<String, String> empOfficeSalaryMap = new HashMap<String, String>();
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<String, Integer> xmDaysMap = gwGetDaysInRange(fylbItemData.getEffectiveDateRange().getFromDate(), fylbItemData.getEffectiveDateRange().getEndDate(), empXmjlList);
BigDecimal xmDays = new BigDecimal(xmDaysMap.get("xmDays"));
totalXmDays = totalXmDays.add(xmDays);
// 封装各个项目的天数和薪资(分段计算)
Map<String, String> empXmSalaryMap = new HashMap<String, String>();
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<String, String> empOfficeSalaryMap = new HashMap<String, String>();
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<String, String> empSalaryMap = new HashMap<String, String>();
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<String, Integer> gwGetDaysInRange(Date startDate, Date endDate, List<GwXmjl> xmjlList) {
Map<String, Integer> 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<GwSalaryItemRelation> getGwReportItems(RecordSet rs) {
List<GwSalaryItemRelation> resultList = new ArrayList<>();
rs.execute("select item.id,item.name,xsmc,px from uf_fygsdxzxm a " +
"left join hrsa_salary_item item on a.xzxm=item.name " +
"where item.delete_type=0 order by px");
while (rs.next()) {
String itemStr = rs.getString(1);
if (NumberUtils.isCreatable(itemStr)) {
GwSalaryItemRelation itemRelation = new GwSalaryItemRelation();
itemRelation.setSalaryItemId(Long.valueOf(itemStr));
itemRelation.setSalaryItemName(rs.getString(2));
itemRelation.setSalaryItemShowName(rs.getString("xsmc"));
itemRelation.setSortedId(rs.getInt("px"));
resultList.add(itemRelation);
}
}
return resultList;
}
/**
* 获取港湾员工项目经历信息
* @param localDateRange
* @param salaryAcctEmployeeList
* @return
*/
private List<GwXmjl> gwGetEmpXmjlInfo(RecordSet rs, LocalDateRange localDateRange, List<SalaryAcctEmployeePO> salaryAcctEmployeeList) {
String startDate = SalaryDateUtil.getFormatDate(localDateRange.getFromDate());
String endDate = SalaryDateUtil.getFormatDate(localDateRange.getEndDate());
List<Long> empIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList());
List<List<Long>> partition = Lists.partition(empIds, 800);
List<GwXmjl> 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<GwFylxInfo> getGwEmpFylxInfo(List<Long> employeeIds, RecordSet rs, LocalDateRange localDateRange) {
List<GwFylxInfo> resultList = new ArrayList<>();
if (CollectionUtils.isEmpty(employeeIds)) {
return resultList;
}
List<List<Long>> 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<GwFylbDataDTO> buildGwFylbData(List<GwFylxInfo> fylbInfoList,
LocalDateRange localDateRange,
List<Long> allEmployeeIds) {
// 获取离职员工的离职日期
List<DataCollectionEmployee> dismissEmpList = getSalaryEmployeeService(user).listDismissEmpByIds(allEmployeeIds);
Map<Long, String> dismissDateMap = SalaryEntityUtil.convert2Map(dismissEmpList, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getDismissdate);
Map<Long, List<GwFylxInfo>> fylbInfoMap = SalaryEntityUtil.group2Map(fylbInfoList, GwFylxInfo::getEmployeeId);
List<GwFylbDataDTO> list = new ArrayList<>();
allEmployeeIds.forEach(e -> {
GwFylbDataDTO gwFylbData = new GwFylbDataDTO();
gwFylbData.setEmployeeId(e);
// 获取该员工的费用类别信息
List<GwFylxInfo> 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<GwFylbItemDataDTO> 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;
}
}