2023-04-23 16:27:11 +08:00
|
|
|
|
package com.engine.salary.maintainer.salaryacct;
|
|
|
|
|
|
|
|
|
|
|
|
import com.engine.common.util.ServiceUtil;
|
|
|
|
|
|
import com.engine.core.impl.Service;
|
|
|
|
|
|
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
|
|
|
|
|
|
import com.engine.salary.entity.datacollection.dto.AttendQuoteFieldListDTO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryacct.bo.SalaryAcctCalculateBO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryacct.bo.SalaryAcctCalculatePriorityBO;
|
2023-06-06 10:30:49 +08:00
|
|
|
|
import com.engine.salary.entity.progress.ProgressDTO;
|
2023-04-23 16:27:11 +08:00
|
|
|
|
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultTempPO;
|
|
|
|
|
|
import com.engine.salary.entity.salaryformula.ExpressFormula;
|
|
|
|
|
|
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
|
|
|
|
|
|
import com.engine.salary.entity.salarysob.dto.SalarySobCycleDTO;
|
|
|
|
|
|
import com.engine.salary.entity.salarysob.po.SalarySobAdjustRulePO;
|
|
|
|
|
|
import com.engine.salary.entity.salarysob.po.SalarySobBackItemPO;
|
|
|
|
|
|
import com.engine.salary.entity.salarysob.po.SalarySobItemPO;
|
|
|
|
|
|
import com.engine.salary.entity.salarysob.po.SalarySobPO;
|
|
|
|
|
|
import com.engine.salary.exception.SalaryRunTimeException;
|
|
|
|
|
|
import com.engine.salary.mapper.salaryacct.SalaryAcctResultMapper;
|
|
|
|
|
|
import com.engine.salary.service.*;
|
|
|
|
|
|
import com.engine.salary.service.impl.*;
|
|
|
|
|
|
import com.engine.salary.util.SalaryEntityUtil;
|
|
|
|
|
|
import com.engine.salary.util.SalaryI18nUtil;
|
|
|
|
|
|
import com.engine.salary.util.db.MapperProxyFactory;
|
2023-04-23 18:00:30 +08:00
|
|
|
|
import com.engine.salary.util.valid.ValidUtil;
|
2023-04-23 16:27:11 +08:00
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
|
|
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.lang.math.NumberUtils;
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
2023-04-23 18:00:30 +08:00
|
|
|
|
import org.springframework.beans.BeanUtils;
|
2023-04-23 16:27:11 +08:00
|
|
|
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
|
|
|
|
|
import weaver.hrm.User;
|
|
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
import java.util.concurrent.BlockingDeque;
|
|
|
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
|
|
import java.util.concurrent.LinkedBlockingDeque;
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 薪资核算维护类
|
|
|
|
|
|
* <p>Copyright: Copyright (c) 2022</p>
|
|
|
|
|
|
* <p>Company: 泛微软件</p>
|
|
|
|
|
|
*
|
|
|
|
|
|
* @author qiantao
|
|
|
|
|
|
* @version 1.0
|
|
|
|
|
|
**/
|
|
|
|
|
|
@Slf4j
|
|
|
|
|
|
public class SalaryAcctManager extends Service {
|
|
|
|
|
|
private SalaryAcctResultMapper getSalaryAcctResultMapper() {
|
|
|
|
|
|
return MapperProxyFactory.getProxy(SalaryAcctResultMapper.class);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private SalaryAcctResultService getSalaryAcctResultService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalaryAcctResultServiceImpl.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 SalaryAcctCalculateService getSalaryAcctCalculateService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalaryAcctCalculateServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-06 10:30:49 +08:00
|
|
|
|
private ProgressService getSalaryAcctProgressService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(ProgressServiceImpl.class, user);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DataSourceTransactionManager dataSourceTransactionManager;
|
|
|
|
|
|
|
|
|
|
|
|
private SalaryAcctResultTempService getSalaryAcctResultTempService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalaryAcctResultTempServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
// private LoggerTemplate salaryAcctRecordLoggerTemplate;
|
|
|
|
|
|
|
|
|
|
|
|
private SIAccountService getSIAccountService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SIAccountServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private AttendQuoteFieldService getAttendQuoteFieldService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(AttendQuoteFieldServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private SalaryAcctReportService getSalaryAcctReportService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalaryAcctReportServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private SalarySobItemGroupService getSalarySobItemGroupService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalarySobItemGroupServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private SalarySobBackItemService getSalarySobBackItemService(User user) {
|
|
|
|
|
|
return ServiceUtil.getService(SalarySobBackItemServiceImpl.class, user);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 补充核算
|
|
|
|
|
|
* 核算已归档后,需要重新核算某一项
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void supplementAcctRecord(SalaryAcctSupplementParam param) {
|
2023-04-23 18:00:30 +08:00
|
|
|
|
ValidUtil.doValidator(param);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
|
2023-04-23 18:00:30 +08:00
|
|
|
|
|
2023-04-25 17:08:42 +08:00
|
|
|
|
//待补算的记录
|
|
|
|
|
|
List<SalaryAcctRecordPO> salaryAcctRecordPOS = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
if (StringUtils.equals(param.getType(), "sob")) {
|
|
|
|
|
|
|
|
|
|
|
|
List<Long> salarySobIds = param.getSalarySobIds();
|
|
|
|
|
|
|
|
|
|
|
|
if (CollectionUtils.isEmpty(salarySobIds)) {
|
|
|
|
|
|
throw new SalaryRunTimeException("补算账套为空!");
|
|
|
|
|
|
}
|
|
|
|
|
|
//获取账套下面所有的核算记录
|
|
|
|
|
|
salaryAcctRecordPOS = getSalaryAcctRecordService(user).listBySalarySobIds(salarySobIds);
|
|
|
|
|
|
|
|
|
|
|
|
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
|
|
|
|
|
|
throw new SalaryRunTimeException("账套下不存在核算记录");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else if (StringUtils.equals(param.getType(), "record")) {
|
|
|
|
|
|
|
|
|
|
|
|
List<Long> salaryAcctRecordIds = param.getSalaryAcctRecordIds();
|
|
|
|
|
|
|
|
|
|
|
|
salaryAcctRecordPOS = getSalaryAcctRecordService(user).listByIds(salaryAcctRecordIds);
|
|
|
|
|
|
|
|
|
|
|
|
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
|
|
|
|
|
|
throw new SalaryRunTimeException("核算记录不存在");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new SalaryRunTimeException("补算方式异常!");
|
2023-04-23 18:00:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-25 17:08:42 +08:00
|
|
|
|
salaryAcctRecordPOS.forEach(salaryAcctRecordPO -> {
|
|
|
|
|
|
param.setSalaryAcctRecordId(salaryAcctRecordPO.getId());
|
|
|
|
|
|
calculate(param);
|
|
|
|
|
|
});
|
2023-04-23 16:27:11 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2023-04-23 18:00:30 +08:00
|
|
|
|
* 补算
|
2023-04-23 16:27:11 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @param calculateParam 薪资核算的参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void calculate(SalaryAcctSupplementParam calculateParam) {
|
2023-04-23 18:00:30 +08:00
|
|
|
|
log.info("补算开始{}", calculateParam);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
|
2023-04-25 17:08:42 +08:00
|
|
|
|
//核算记录
|
|
|
|
|
|
Long salaryAcctRecordId = calculateParam.getSalaryAcctRecordId();
|
|
|
|
|
|
|
2023-04-23 16:27:11 +08:00
|
|
|
|
//当前登陆人员
|
|
|
|
|
|
DataCollectionEmployee simpleEmployee = new DataCollectionEmployee();
|
|
|
|
|
|
simpleEmployee.setEmployeeId((long) user.getUID());
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否正在核算中
|
2023-06-06 10:30:49 +08:00
|
|
|
|
ProgressDTO salaryAcctProgressDTO = getSalaryAcctProgressService(user).getProgress("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
if (Objects.nonNull(salaryAcctProgressDTO) && salaryAcctProgressDTO.isStatus() && Optional.ofNullable(salaryAcctProgressDTO.getProgress()).orElse(BigDecimal.ZERO).compareTo(BigDecimal.ONE) < 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 初始化进度
|
2023-06-06 10:30:49 +08:00
|
|
|
|
ProgressDTO initProgress = new ProgressDTO()
|
2023-04-23 16:27:11 +08:00
|
|
|
|
.setTitle(SalaryI18nUtil.getI18nLabel(97515, "核算中"))
|
|
|
|
|
|
.setTitleLabelId(97515L)
|
|
|
|
|
|
.setTotalQuantity(NumberUtils.INTEGER_ONE)
|
|
|
|
|
|
.setCalculatedQuantity(NumberUtils.INTEGER_ZERO)
|
|
|
|
|
|
.setProgress(BigDecimal.ZERO)
|
|
|
|
|
|
.setStatus(true)
|
|
|
|
|
|
.setMessage(StringUtils.EMPTY);
|
2023-04-25 17:08:42 +08:00
|
|
|
|
getSalaryAcctProgressService(user).initProgress("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId, initProgress);
|
|
|
|
|
|
calculate(calculateParam, simpleEmployee);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void calculate(SalaryAcctSupplementParam calculateParam, DataCollectionEmployee simpleEmployee) {
|
2023-04-25 17:08:42 +08:00
|
|
|
|
Long salaryAcctRecordId = calculateParam.getSalaryAcctRecordId();
|
2023-04-23 16:27:11 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 1、查询薪资核算记录
|
2023-04-25 17:08:42 +08:00
|
|
|
|
SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
if (Objects.isNull(salaryAcctRecordPO)) {
|
|
|
|
|
|
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
|
|
|
|
|
|
}
|
|
|
|
|
|
//查询对应账套
|
|
|
|
|
|
SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
|
|
|
|
|
|
if (Objects.isNull(salarySobPO)) {
|
|
|
|
|
|
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资账套不存在或已被删除"));
|
|
|
|
|
|
}
|
|
|
|
|
|
// 2、查询薪资核算记录的薪资周期、考勤周期等
|
2023-04-25 17:08:42 +08:00
|
|
|
|
SalarySobCycleDTO salarySobCycleDTO = getSalaryAcctRecordService(user).getSalarySobCycleById(salaryAcctRecordId);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 3、查询薪资核算记录所用薪资账套的薪资项目副本
|
|
|
|
|
|
List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
|
|
|
|
|
|
if (CollectionUtils.isEmpty(salarySobItemPOS)) {
|
|
|
|
|
|
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(99151, "当前所用的薪资账套未选择任何薪资项目,无法核算"));
|
|
|
|
|
|
}
|
|
|
|
|
|
// 回算薪资项目
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
2023-04-28 14:37:59 +08:00
|
|
|
|
// //核算锁定值
|
|
|
|
|
|
// List<Long> lockSalaryItemIds = salaryAcctRecordPO.getLockSalaryItemIds();
|
|
|
|
|
|
// Map<String, SalaryAcctResultPO> acctResults = new HashMap<>();
|
|
|
|
|
|
// if (CollectionUtils.isNotEmpty(lockSalaryItemIds)) {
|
|
|
|
|
|
// List<SalaryAcctResultPO> acctResultPOS = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecordId));
|
|
|
|
|
|
// 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));
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
//将除重新核算的项目外的所有的值都锁定
|
|
|
|
|
|
List<Long> salaryItemIds = calculateParam.getSalaryItemIds();
|
|
|
|
|
|
List<Long> lockSalaryItemIds = salaryItemPOS.stream().map(SalaryItemPO::getId).filter(id -> !salaryItemIds.contains(id)).collect(Collectors.toList());
|
2023-04-23 16:27:11 +08:00
|
|
|
|
Map<String, SalaryAcctResultPO> acctResults = new HashMap<>();
|
|
|
|
|
|
if (CollectionUtils.isNotEmpty(lockSalaryItemIds)) {
|
2023-04-25 17:08:42 +08:00
|
|
|
|
List<SalaryAcctResultPO> acctResultPOS = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecordId));
|
2023-04-23 16:27:11 +08:00
|
|
|
|
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));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-28 14:37:59 +08:00
|
|
|
|
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 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);
|
|
|
|
|
|
// 10、根据id查询其他合并计税的薪资核算记录
|
|
|
|
|
|
List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId());
|
|
|
|
|
|
// 11、查询本次核算人员
|
2023-04-23 18:00:30 +08:00
|
|
|
|
List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salaryAcctRecordPO.getId());
|
2023-04-23 16:27:11 +08:00
|
|
|
|
if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
|
|
|
|
|
|
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(103378, "薪资核算人员不能为空"));
|
|
|
|
|
|
}
|
|
|
|
|
|
// 11.1、初始化进度
|
2023-06-06 10:30:49 +08:00
|
|
|
|
ProgressDTO initProgress = new ProgressDTO().setTitle(SalaryI18nUtil.getI18nLabel(97515, "核算中")).setTitleLabelId(97515L).setTotalQuantity(salaryAcctEmployeePOS.size() * 2 + 1).setCalculatedQuantity(0).setProgress(BigDecimal.ZERO).setStatus(true).setMessage(StringUtils.EMPTY);
|
2023-04-25 17:08:42 +08:00
|
|
|
|
getSalaryAcctProgressService(user).initProgress("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId, initProgress);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 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、多线程运算,运算结果存放在临时表中
|
|
|
|
|
|
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);
|
|
|
|
|
|
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();
|
|
|
|
|
|
// 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("|"));
|
2023-04-25 17:08:42 +08:00
|
|
|
|
getSalaryAcctProgressService(user).fail("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId, errorMsg);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 删除薪资核算临时存储表中的数据
|
|
|
|
|
|
getSalaryAcctResultTempService(user).deleteByCalculateKey(calculateKey);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 15、处理核算结果临时表数据
|
|
|
|
|
|
handleSalaryAcctResultTemp(calculateParam, calculateKey);
|
|
|
|
|
|
|
2023-04-25 17:08:42 +08:00
|
|
|
|
getSalaryAcctProgressService(user).finish("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId, true);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.info("薪资核算出错:{}", e.getMessage(), e);
|
2023-04-25 17:08:42 +08:00
|
|
|
|
getSalaryAcctProgressService(user).fail("SUPPLEMENT_ACCT_PROGRESS_" + salaryAcctRecordId, SalaryI18nUtil.getI18nLabel(99642, "薪资核算出错") + ": " + e.getMessage());
|
2023-04-23 16:27:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理薪资核算临时存储表中的数据
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param calculateParam
|
|
|
|
|
|
* @param calculateKey
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void handleSalaryAcctResultTemp(SalaryAcctSupplementParam calculateParam, String calculateKey) {
|
|
|
|
|
|
// 查询薪资核算结果的临时存储
|
|
|
|
|
|
List<SalaryAcctResultTempPO> salaryAcctResultTempPOS = getSalaryAcctResultTempService(user).listByCalculateKey(calculateKey);
|
|
|
|
|
|
// 删除原来的薪资核算结果
|
2023-04-23 18:00:30 +08:00
|
|
|
|
List<Long> salaryItemIds = calculateParam.getSalaryItemIds();
|
|
|
|
|
|
getSalaryAcctResultMapper().deleteBySalaryAcctRecordIdAndSalaryItemIds(calculateParam.getSalaryAcctRecordId(), salaryItemIds);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 保存薪资的薪资核算结果
|
2023-04-25 17:08:42 +08:00
|
|
|
|
List<SalaryAcctResultPO> salaryAcctResultPOS = salaryAcctResultTempPOS.stream()
|
|
|
|
|
|
.filter(salaryAcctResultTempPO -> salaryItemIds.contains(salaryAcctResultTempPO.getSalaryItemId()))
|
|
|
|
|
|
.map(e -> {
|
|
|
|
|
|
SalaryAcctResultPO salaryAcctResult = new SalaryAcctResultPO();
|
|
|
|
|
|
BeanUtils.copyProperties(e, salaryAcctResult);
|
|
|
|
|
|
return salaryAcctResult;
|
|
|
|
|
|
}).collect(Collectors.toList());
|
2023-04-23 18:00:30 +08:00
|
|
|
|
getSalaryAcctResultService(user).batchSave(salaryAcctResultPOS);
|
2023-04-23 16:27:11 +08:00
|
|
|
|
// 删除薪资核算临时存储表中的数据
|
|
|
|
|
|
getSalaryAcctResultTempService(user).deleteByCalculateKey(calculateKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|