Merge branch 'feature/重置排序-业务线' into custom/爱信(中国)投资有限公司
This commit is contained in:
commit
61418516af
|
|
@ -61,7 +61,7 @@ public class SalaryAcctCalculateBO {
|
|||
/**
|
||||
* 本次运算的薪资项目(已排好运算优先级)
|
||||
*/
|
||||
private List<List<Long>> salaryItemIdWithPriorityList;
|
||||
private List<Long> salaryItemIdWithPriorityList;
|
||||
|
||||
/**
|
||||
* 本次运算涉及的所有公式
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package com.engine.salary.entity.salaryacct.bo;
|
||||
|
||||
import com.engine.salary.entity.salaryformula.ExpressFormula;
|
||||
import com.engine.salary.enums.SalaryRoundingModeEnum;
|
||||
import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 薪资核算涉及的薪资项目
|
||||
* <p>Copyright: Copyright (c) 2023</p>
|
||||
* <p>Company: 泛微软件</p>
|
||||
*
|
||||
* @author qiantao
|
||||
* @version 1.0
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class SalaryCalcItem {
|
||||
|
||||
/**
|
||||
* 薪资项目id
|
||||
*/
|
||||
private Long salaryItemId;
|
||||
/**
|
||||
* 薪资项目编号
|
||||
*/
|
||||
private String salaryItemCode;
|
||||
/**
|
||||
* 所得项目
|
||||
*/
|
||||
private String incomeCategory;
|
||||
/**
|
||||
* 薪资档案引用。0:薪资档案未引用、1:薪资档案引用
|
||||
* 为处理历史数据而留,不再使用
|
||||
*/
|
||||
@Deprecated
|
||||
private Integer useInEmployeeSalary;
|
||||
/**
|
||||
* 字段类型
|
||||
* @see SalaryDataTypeEnum
|
||||
*/
|
||||
private String dataType;
|
||||
/**
|
||||
* 舍入规则
|
||||
* @see SalaryRoundingModeEnum
|
||||
*/
|
||||
private Integer roundingMode;
|
||||
/**
|
||||
* 小数位数
|
||||
*/
|
||||
private Integer pattern;
|
||||
/**
|
||||
* 公式
|
||||
*/
|
||||
private ExpressFormula expressFormula;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
package com.engine.salary.entity.salaryacct.bo;
|
||||
|
||||
import com.engine.salary.entity.salaryformula.ExpressFormula;
|
||||
import com.engine.salary.entity.salaryformula.po.FormulaVar;
|
||||
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
|
||||
import com.engine.salary.entity.salarysob.po.SalarySobItemPO;
|
||||
import com.engine.salary.enums.salaryformula.SalaryFormulaReferenceEnum;
|
||||
import com.engine.salary.exception.SalaryRunTimeException;
|
||||
import com.engine.salary.report.common.constant.SalaryConstant;
|
||||
import com.engine.salary.util.SalaryEntityUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对薪资核算时涉及的薪资项目进行排序
|
||||
* <p>Copyright: Copyright (c) 2023</p>
|
||||
* <p>Company: 泛微软件</p>
|
||||
*
|
||||
* @author qiantao
|
||||
* @version 1.0
|
||||
**/
|
||||
public class SalaryCalcItemGraphTemp {
|
||||
|
||||
private List<SalaryCalcItemGraphNode> nodes;
|
||||
private Map<Long, String> items;
|
||||
|
||||
/**
|
||||
* 根据薪资账套的薪资项目、公式详情构建实例
|
||||
*
|
||||
* @param salarySobItems 薪资账套的薪资项目
|
||||
* @param expressFormulas 公式详情
|
||||
*/
|
||||
public SalaryCalcItemGraphTemp(List<SalarySobItemPO> salarySobItems, List<SalaryItemPO> salaryItemPOS, List<ExpressFormula> expressFormulas) {
|
||||
Map<String, SalaryItemPO> salaryItemMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getCode);
|
||||
Map<Long, ExpressFormula> expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId);
|
||||
Map<Long, List<FormulaVar>> formulaVarMap = ExpressFormulaBO.buildFormulaVar(expressFormulas);
|
||||
// key:薪资项目的code,value:薪资项目的po
|
||||
Map<Long, SalaryItemPO> codeKeySalaryItemPOMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getId);
|
||||
salarySobItems.forEach(salarySobItem -> salarySobItem.setSalaryItemCode(codeKeySalaryItemPOMap.get(salarySobItem.getSalaryItemId()).getCode()));
|
||||
Map<String, SalarySobItemPO> salarySobItemMap = SalaryEntityUtil.convert2Map(salarySobItems, SalarySobItemPO::getSalaryItemCode);
|
||||
|
||||
Map<Long, SalaryCalcItemGraphNode> nodeMap = new HashMap<>();
|
||||
for (SalarySobItemPO salarySobItem : salarySobItems) {
|
||||
ExpressFormula expressFormula = expressFormulaMap.get(salarySobItem.getFormulaId());
|
||||
SalaryCalcItemGraphNode node = nodeMap.computeIfAbsent(salarySobItem.getSalaryItemId(), key -> new SalaryCalcItemGraphNode(salarySobItem, expressFormula));
|
||||
List<FormulaVar> formulaVars = expressFormula == null ? Collections.emptyList() : formulaVarMap.getOrDefault(expressFormula.getId(), Collections.emptyList());
|
||||
for (FormulaVar formulaVar : formulaVars) {
|
||||
if (StringUtils.isNotEmpty(formulaVar.getFieldId()) && StringUtils.startsWith(formulaVar.getFieldId(), SalaryFormulaReferenceEnum.SALARY_ITEM.getValue() + SalaryConstant.FORMULA_VAR_SEPARATOR)) {
|
||||
String salaryItemCode = formulaVar.getFieldId().split(SalaryConstant.FORMULA_VAR_SEPARATOR)[1];
|
||||
SalarySobItemPO subSalarySobItem = salarySobItemMap.get(salaryItemCode);
|
||||
if (subSalarySobItem == null) {
|
||||
SalaryItemPO salaryItemPO = salaryItemMap.get(salaryItemCode);
|
||||
if (salaryItemPO == null) {
|
||||
continue;
|
||||
} else {
|
||||
subSalarySobItem = SalarySobItemPO.builder().salaryItemId(salaryItemPO.getId()).salaryItemCode(salaryItemPO.getCode()).build();
|
||||
}
|
||||
}
|
||||
ExpressFormula subExpressFormula = expressFormulaMap.get(subSalarySobItem.getFormulaId());
|
||||
SalarySobItemPO finalSubSalarySobItem = subSalarySobItem;
|
||||
SalaryCalcItemGraphNode destNode = nodeMap.computeIfAbsent(subSalarySobItem.getSalaryItemId(), key -> new SalaryCalcItemGraphNode(finalSubSalarySobItem, subExpressFormula));
|
||||
node.getDestNodes().add(destNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.nodes = Lists.newArrayList(nodeMap.values());
|
||||
this.items = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getId, SalaryItemPO::getName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对薪资核算时涉及的薪资项目进行排序
|
||||
* 对于一次薪资核算而言,不同的薪资项目之间可能会存在引用。
|
||||
* 例如「绩效工资=绩效比例*(基本工资+岗位工资)」,在计算「绩效工资」前需要先计算出「绩效比例」、「基本工资」、「岗位工资」
|
||||
* 所以薪资核算前需要对所涉及的所有薪资项目进行一个计算排序
|
||||
* 对薪资项目的排序就相当于是对一个「有向无环的图」进行拓扑排序,一个薪资项目就相当于图中的一个「顶点」
|
||||
* 具体算法如下:
|
||||
* 1、根据「薪资账套的薪资项目」、「公式详情」构建出所有的「顶点」
|
||||
* 2、将所有顶点的入度都初始化为0
|
||||
* 3、遍历所有的顶点,计算每个顶点的入度
|
||||
* 4、创建一个队列,将所有入度为0的顶点都存入队列
|
||||
* 5、每次从队列中取出一个点,将该点存入结果集合中,并将该顶点的所有邻接点的入度减1。如果邻接点的入度变为了0,将其加入队列中
|
||||
* 6、重复步骤5,直到队列空了
|
||||
*
|
||||
* @return 排好序的薪资项目id
|
||||
*/
|
||||
public List<SalaryCalcItem> sort() {
|
||||
// 循环遍历所有顶点
|
||||
for (SalaryCalcItemGraphNode node : nodes) {
|
||||
// 循环遍历每个顶点的邻居
|
||||
for (SalaryCalcItemGraphNode destNode : node.getDestNodes()) {
|
||||
// 维护每个顶点的入度
|
||||
destNode.setInDegree(destNode.getInDegree() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建一个队列
|
||||
LinkedTransferQueue<SalaryCalcItemGraphNode> queue = new LinkedTransferQueue<>();
|
||||
|
||||
// 再次循环所有顶点
|
||||
for (SalaryCalcItemGraphNode node : nodes) {
|
||||
// 若该顶点入度为0,则加入队列
|
||||
if (node.getInDegree() == 0) {
|
||||
queue.offer(node);
|
||||
}
|
||||
}
|
||||
|
||||
// 存储结果的列表
|
||||
List<SalaryCalcItem> result = new ArrayList<>();
|
||||
// 循环直到队列为空
|
||||
while (!queue.isEmpty()) {
|
||||
// 取出队列头部的顶点编号
|
||||
SalaryCalcItemGraphNode node = queue.poll();
|
||||
// 将该顶点加入到结果列表中
|
||||
result.add(node.getSalaryCalcItem());
|
||||
// 标记该顶点已被访问
|
||||
node.setVisited(true);
|
||||
|
||||
// 遍历该顶点的邻居
|
||||
for (SalaryCalcItemGraphNode destNode : node.getDestNodes()) {
|
||||
// 若该邻居未被访问过
|
||||
if (!destNode.isVisited()) {
|
||||
// 将该邻居的入度减一
|
||||
destNode.setInDegree(destNode.getInDegree() - 1);
|
||||
// 若该邻居入度已经变为0
|
||||
if (destNode.getInDegree() == 0) {
|
||||
// 将该邻居加入到队列中
|
||||
queue.offer(destNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 倒序
|
||||
Collections.reverse(result);
|
||||
if (!Objects.equals(result.size(), nodes.size())) {
|
||||
|
||||
List<Long> resultIds = SalaryEntityUtil.properties(result, SalaryCalcItem::getSalaryItemId, Collectors.toList());
|
||||
String errItemName = nodes.stream()
|
||||
.map(SalaryCalcItemGraphNode::getSalaryCalcItem)
|
||||
.map(SalaryCalcItem::getSalaryItemId)
|
||||
.filter(itemId -> !resultIds.contains(itemId))
|
||||
.map(itemId -> items.getOrDefault(itemId, ""))
|
||||
.collect((Collectors.joining(",", "[", "]")));
|
||||
|
||||
throw new SalaryRunTimeException("薪资项目:" + errItemName + "存在闭环!");
|
||||
}
|
||||
// 返回结果列表
|
||||
return result;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class SalaryCalcItemGraphNode {
|
||||
|
||||
/**
|
||||
* 薪资项目的id
|
||||
*/
|
||||
private SalaryCalcItem salaryCalcItem;
|
||||
|
||||
/**
|
||||
* 入度
|
||||
*/
|
||||
private int inDegree;
|
||||
|
||||
/**
|
||||
* 是否已被访问
|
||||
*/
|
||||
private boolean visited;
|
||||
|
||||
/**
|
||||
* 当前顶点的邻居
|
||||
*/
|
||||
private List<SalaryCalcItemGraphNode> destNodes;
|
||||
|
||||
public SalaryCalcItemGraphNode(SalarySobItemPO salarySobItem, ExpressFormula expressFormula) {
|
||||
SalaryCalcItem salaryCalcItem = new SalaryCalcItem();
|
||||
salaryCalcItem.setSalaryItemId(salarySobItem.getSalaryItemId());
|
||||
salaryCalcItem.setSalaryItemCode(salarySobItem.getSalaryItemCode());
|
||||
// salaryCalcItem.setIncomeCategory(salarySobItem.getIncomeCategory());
|
||||
// salaryCalcItem.setUseInEmployeeSalary(salarySobItem.getUseInEmployeeSalary());
|
||||
// salaryCalcItem.setDataType(salarySobItem.getDataType());
|
||||
salaryCalcItem.setRoundingMode(salarySobItem.getRoundingMode());
|
||||
salaryCalcItem.setPattern(salarySobItem.getPattern());
|
||||
salaryCalcItem.setExpressFormula(expressFormula);
|
||||
this.salaryCalcItem = salaryCalcItem;
|
||||
this.inDegree = 0;
|
||||
this.visited = false;
|
||||
this.destNodes = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +57,13 @@ public class SalarySobItemPO {
|
|||
@XStreamAsAttribute
|
||||
private Long salaryItemId;
|
||||
|
||||
/**
|
||||
* 薪资项目的code
|
||||
*/
|
||||
private String salaryItemCode;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 薪资账套薪资项目分组id
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ 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;
|
||||
import com.engine.salary.entity.progress.ProgressDTO;
|
||||
import com.engine.salary.entity.salaryacct.bo.SalaryAcctCalculateBO;
|
||||
import com.engine.salary.entity.salaryacct.bo.SalaryCalcItem;
|
||||
import com.engine.salary.entity.salaryacct.bo.SalaryCalcItemGraphTemp;
|
||||
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
|
||||
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
|
||||
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
|
||||
|
|
@ -285,7 +286,19 @@ public class SalaryAcctManager extends Service {
|
|||
// 本次运算的回算薪资项目所涉及的变量
|
||||
Set<String> issuedFieldIds = new HashSet<>();
|
||||
// 9、计算薪资项目的运算优先级
|
||||
List<List<Long>> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds);
|
||||
// List<List<Long>> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds);
|
||||
List<SalarySobItemPO> temp = salarySobBackItems.stream()
|
||||
.map(e -> {
|
||||
SalarySobItemPO salarySobItem = new SalarySobItemPO();
|
||||
BeanUtils.copyProperties(e, salarySobItem);
|
||||
return salarySobItem;
|
||||
}).collect(Collectors.toList());
|
||||
salarySobItemPOS.addAll(temp);
|
||||
|
||||
SalaryCalcItemGraphTemp salaryCalcItemGraph = new SalaryCalcItemGraphTemp(salarySobItemPOS, salaryItemPOS, expressFormulas);
|
||||
List<SalaryCalcItem> salaryCalcItems = salaryCalcItemGraph.sort();
|
||||
List<Long> salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList());
|
||||
|
||||
// 10、根据id查询其他合并计税的薪资核算记录
|
||||
List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId());
|
||||
// 11、查询本次核算人员
|
||||
|
|
|
|||
|
|
@ -9,4 +9,35 @@ public class SalaryConstant {
|
|||
* 列表中薪资项目动态列后缀标识
|
||||
*/
|
||||
public static final String DYNAMIC_SUFFIX = "_salaryItem";
|
||||
|
||||
/**
|
||||
* 模块标识
|
||||
*/
|
||||
public static final String MODULE = "hrmsalary";
|
||||
|
||||
/**
|
||||
* 公共租户标识
|
||||
*/
|
||||
public static final String DEFAULT_TENANT_KEY = "all_teams";
|
||||
/**
|
||||
* 通用的分隔符
|
||||
*/
|
||||
public static final String COMMON_SEPARATOR = "-";
|
||||
/**
|
||||
* 下划线
|
||||
*/
|
||||
public static final String FORMULA_VAR_SEPARATOR = "_";
|
||||
/**
|
||||
* 下划线分隔符
|
||||
*/
|
||||
public static final String UNDERLINE_SEPARATOR = "_";
|
||||
/**
|
||||
* 完整主域名
|
||||
*/
|
||||
public static final String PRIMARY_DOMAIN = "primary.domain";
|
||||
|
||||
/**
|
||||
* 图片公共地址
|
||||
*/
|
||||
public static final String IMG_URL = "/papi/file/preview?type=imgs&fileId=%s&random=123456";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,91 +224,89 @@ public class SalaryAcctCalculateServiceImpl extends Service implements SalaryAcc
|
|||
formulaVarValues.addAll(empInfo);
|
||||
Map<String, String> formulaVarValueMap = SalaryEntityUtil.convert2Map(formulaVarValues, CalculateFormulaVarBO.FormulaVarValue::getFieldId, CalculateFormulaVarBO.FormulaVarValue::getFieldValue);
|
||||
// 按照计算好的优先级计算薪资项目的值
|
||||
for (List<Long> salaryItemIds : salaryAcctCalculateBO.getSalaryItemIdWithPriorityList()) {
|
||||
for (Long salaryItemId : salaryAcctCalculateBO.getSalaryItemIdWithPriorityList()) {
|
||||
// 同一运算优先级下的薪资项目逐个独立运算
|
||||
for (Long salaryItemId : salaryItemIds) {
|
||||
String resultValue;
|
||||
SalaryItemPO salaryItemPO = salaryItemMap.get(salaryItemId);
|
||||
ExpressFormula expressFormula;
|
||||
String defaultValue;
|
||||
if (salarySobBackItemMap.containsKey(salaryItemId)) {
|
||||
// 如果薪资账套的回算项目中重新定义了回算项目公式,则使用薪资账套下的公式
|
||||
SalarySobBackItemPO salarySobBackItemPO = salarySobBackItemMap.get(salaryItemId);
|
||||
expressFormula = expressFormulaMap.get(salarySobBackItemPO.getFormulaId());
|
||||
defaultValue = salarySobBackItemPO.getDefaultValue();
|
||||
} else if (salaryItemIdKeySalarySobItemPOMap.containsKey(salaryItemId)) {
|
||||
// 如果薪资账套下重新定义了薪资项目的公式,则使用薪资账套下的公式,否则使用薪资项目本身的公式
|
||||
SalarySobItemPO salarySobItemPO = salaryItemIdKeySalarySobItemPOMap.get(salaryItemId);
|
||||
expressFormula = expressFormulaMap.get(salarySobItemPO.getFormulaId());
|
||||
defaultValue = salarySobItemPO.getDefaultValue();
|
||||
} else {
|
||||
expressFormula = expressFormulaMap.get(salaryItemPO.getFormulaId());
|
||||
defaultValue = salaryItemPO.getDefaultValue();
|
||||
String resultValue;
|
||||
SalaryItemPO salaryItemPO = salaryItemMap.get(salaryItemId);
|
||||
ExpressFormula expressFormula;
|
||||
String defaultValue;
|
||||
if (salarySobBackItemMap.containsKey(salaryItemId)) {
|
||||
// 如果薪资账套的回算项目中重新定义了回算项目公式,则使用薪资账套下的公式
|
||||
SalarySobBackItemPO salarySobBackItemPO = salarySobBackItemMap.get(salaryItemId);
|
||||
expressFormula = expressFormulaMap.get(salarySobBackItemPO.getFormulaId());
|
||||
defaultValue = salarySobBackItemPO.getDefaultValue();
|
||||
} else if (salaryItemIdKeySalarySobItemPOMap.containsKey(salaryItemId)) {
|
||||
// 如果薪资账套下重新定义了薪资项目的公式,则使用薪资账套下的公式,否则使用薪资项目本身的公式
|
||||
SalarySobItemPO salarySobItemPO = salaryItemIdKeySalarySobItemPOMap.get(salaryItemId);
|
||||
expressFormula = expressFormulaMap.get(salarySobItemPO.getFormulaId());
|
||||
defaultValue = salarySobItemPO.getDefaultValue();
|
||||
} else {
|
||||
expressFormula = expressFormulaMap.get(salaryItemPO.getFormulaId());
|
||||
defaultValue = salaryItemPO.getDefaultValue();
|
||||
}
|
||||
if (Objects.nonNull(expressFormula)) {
|
||||
// 运行公式
|
||||
ExcelResult result = runExpressFormula(expressFormula, formulaVarValueMap, simpleEmployee);
|
||||
resultValue = result.getData2String();
|
||||
//公式异常信息
|
||||
if (!result.isStatus()) {
|
||||
String username = empInfo.stream().filter(emp -> StringUtils.equals("employeeInfo_username", emp.getFieldId())).findFirst().map(CalculateFormulaVarBO.FormulaVarValue::getFieldValue).orElse("");
|
||||
String errorMsg = String.format("%s的%s核算异常,原因:%s \r\n", username, salaryItemPO.getName(), result.getErrorMsg());
|
||||
noticeMsg.append(errorMsg);
|
||||
}
|
||||
if (Objects.nonNull(expressFormula)) {
|
||||
// 运行公式
|
||||
ExcelResult result = runExpressFormula(expressFormula, formulaVarValueMap, simpleEmployee);
|
||||
resultValue = result.getData2String();
|
||||
//公式异常信息
|
||||
if (!result.isStatus()) {
|
||||
String username = empInfo.stream().filter(emp -> StringUtils.equals("employeeInfo_username", emp.getFieldId())).findFirst().map(CalculateFormulaVarBO.FormulaVarValue::getFieldValue).orElse("");
|
||||
String errorMsg = String.format("%s的%s核算异常,原因:%s \r\n", username, salaryItemPO.getName(), result.getErrorMsg());
|
||||
noticeMsg.append(errorMsg);
|
||||
}
|
||||
//提醒运行超时
|
||||
if (StringUtils.isNotBlank(formulaRunOvertimeThreshold) && result.getRunTime() > Long.parseLong(formulaRunOvertimeThreshold)) {
|
||||
String username = empInfo.stream().filter(emp -> StringUtils.equals("employeeInfo_username", emp.getFieldId())).findFirst().map(CalculateFormulaVarBO.FormulaVarValue::getFieldValue).orElse("");
|
||||
String errorMsg = String.format("%s的%s核算超时,耗时:%s毫秒 \r\n", username, salaryItemPO.getName(), result.getRunTime());
|
||||
noticeMsg.append(errorMsg);
|
||||
}
|
||||
} else {
|
||||
// 处理取值类型为“输入/导入”的薪资项目
|
||||
String key = SalaryFormulaReferenceEnum.SALARY_ITEM.getValue() + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItemPO.getCode();
|
||||
resultValue = formulaVarValueMap.getOrDefault(key, StringUtils.EMPTY);
|
||||
if (StrUtil.isBlank(resultValue)) {
|
||||
resultValue = Util.null2String(defaultValue);
|
||||
}
|
||||
//提醒运行超时
|
||||
if (StringUtils.isNotBlank(formulaRunOvertimeThreshold) && result.getRunTime() > Long.parseLong(formulaRunOvertimeThreshold)) {
|
||||
String username = empInfo.stream().filter(emp -> StringUtils.equals("employeeInfo_username", emp.getFieldId())).findFirst().map(CalculateFormulaVarBO.FormulaVarValue::getFieldValue).orElse("");
|
||||
String errorMsg = String.format("%s的%s核算超时,耗时:%s毫秒 \r\n", username, salaryItemPO.getName(), result.getRunTime());
|
||||
noticeMsg.append(errorMsg);
|
||||
}
|
||||
// 处理薪资档案
|
||||
if (Objects.equals(salaryItemPO.getUseInEmployeeSalary(), NumberUtils.INTEGER_ONE)) {
|
||||
String key = SalaryFormulaReferenceEnum.SALARY_ARCHIVES.getValue() + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItemPO.getCode();
|
||||
resultValue = formulaVarValueMap.getOrDefault(key, StringUtils.EMPTY);
|
||||
}
|
||||
// 处理合并计税
|
||||
resultValue = handleConsolidatedTax(resultValue, salaryItemPO, salaryAcctCalculateBO, otherSalaryAcctEmployeePOMap.get(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId()), otherSalaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId()));
|
||||
|
||||
// 处理小数点
|
||||
resultValue = SalaryAcctFormulaBO.roundResultValue(resultValue, salaryItemPO, salarySobBackItems, salarySobBackItemMap, salaryItemIdKeySalarySobItemPOMap);
|
||||
|
||||
//是否锁定
|
||||
if (lockItems != null && lockItems.contains(salaryItemId)) {
|
||||
resultValue = empItemValueMap.getOrDefault(salaryAcctEmployeePOId + "_" + salaryItemId, StringUtils.EMPTY);
|
||||
}
|
||||
// 将已经计算过的薪资项目的值转换成公式变量的值添加到集合中
|
||||
} else {
|
||||
// 处理取值类型为“输入/导入”的薪资项目
|
||||
String key = SalaryFormulaReferenceEnum.SALARY_ITEM.getValue() + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItemPO.getCode();
|
||||
formulaVarValueMap.put(key, resultValue);
|
||||
// 值保存薪资账套下的薪资项目的核算结果
|
||||
if (salaryItemIdKeySalarySobItemPOMap.containsKey(salaryItemId) || salarySobBackItemIds.contains(salaryItemId)) {
|
||||
// 转换成薪资核算结果po
|
||||
SalaryAcctResultTempPO salaryAcctResultTempPO = new SalaryAcctResultTempPO()
|
||||
.setSalaryAcctRecordId(salaryAcctEmployeePO.getSalaryAcctRecordId())
|
||||
.setSalaryAcctEmpId(salaryAcctEmployeePOId)
|
||||
.setEmployeeId(salaryAcctEmployeePO.getEmployeeId())
|
||||
.setTaxAgentId(salaryAcctEmployeePO.getTaxAgentId())
|
||||
.setSalarySobId(salaryAcctEmployeePO.getSalarySobId())
|
||||
.setSalaryItemId(salaryItemPO.getId())
|
||||
.setResultValue(resultValue)
|
||||
.setOriginResultValue(salaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId() + "-" + salaryItemId) == null
|
||||
? StringUtils.EMPTY : salaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId() + "-" + salaryItemId))
|
||||
.setCalculateKey(salaryAcctCalculateBO.getCalculateKey())
|
||||
.setCreator((long) user.getUID())
|
||||
.setCreateTime(now)
|
||||
.setUpdateTime(now)
|
||||
.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
|
||||
.setDeleteType(0);
|
||||
salaryAcctResultTempPOS.add(salaryAcctResultTempPO);
|
||||
resultValue = formulaVarValueMap.getOrDefault(key, StringUtils.EMPTY);
|
||||
if (StrUtil.isBlank(resultValue)) {
|
||||
resultValue = Util.null2String(defaultValue);
|
||||
}
|
||||
}
|
||||
// 处理薪资档案
|
||||
if (Objects.equals(salaryItemPO.getUseInEmployeeSalary(), NumberUtils.INTEGER_ONE)) {
|
||||
String key = SalaryFormulaReferenceEnum.SALARY_ARCHIVES.getValue() + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItemPO.getCode();
|
||||
resultValue = formulaVarValueMap.getOrDefault(key, StringUtils.EMPTY);
|
||||
}
|
||||
// 处理合并计税
|
||||
resultValue = handleConsolidatedTax(resultValue, salaryItemPO, salaryAcctCalculateBO, otherSalaryAcctEmployeePOMap.get(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId()), otherSalaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId()));
|
||||
|
||||
// 处理小数点
|
||||
resultValue = SalaryAcctFormulaBO.roundResultValue(resultValue, salaryItemPO, salarySobBackItems, salarySobBackItemMap, salaryItemIdKeySalarySobItemPOMap);
|
||||
|
||||
//是否锁定
|
||||
if (lockItems != null && lockItems.contains(salaryItemId)) {
|
||||
resultValue = empItemValueMap.getOrDefault(salaryAcctEmployeePOId + "_" + salaryItemId, StringUtils.EMPTY);
|
||||
}
|
||||
// 将已经计算过的薪资项目的值转换成公式变量的值添加到集合中
|
||||
String key = SalaryFormulaReferenceEnum.SALARY_ITEM.getValue() + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + salaryItemPO.getCode();
|
||||
formulaVarValueMap.put(key, resultValue);
|
||||
// 值保存薪资账套下的薪资项目的核算结果
|
||||
if (salaryItemIdKeySalarySobItemPOMap.containsKey(salaryItemId) || salarySobBackItemIds.contains(salaryItemId)) {
|
||||
// 转换成薪资核算结果po
|
||||
SalaryAcctResultTempPO salaryAcctResultTempPO = new SalaryAcctResultTempPO()
|
||||
.setSalaryAcctRecordId(salaryAcctEmployeePO.getSalaryAcctRecordId())
|
||||
.setSalaryAcctEmpId(salaryAcctEmployeePOId)
|
||||
.setEmployeeId(salaryAcctEmployeePO.getEmployeeId())
|
||||
.setTaxAgentId(salaryAcctEmployeePO.getTaxAgentId())
|
||||
.setSalarySobId(salaryAcctEmployeePO.getSalarySobId())
|
||||
.setSalaryItemId(salaryItemPO.getId())
|
||||
.setResultValue(resultValue)
|
||||
.setOriginResultValue(salaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId() + "-" + salaryItemId) == null
|
||||
? StringUtils.EMPTY : salaryAcctResultPOMap.get(salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId() + "-" + salaryItemId))
|
||||
.setCalculateKey(salaryAcctCalculateBO.getCalculateKey())
|
||||
.setCreator((long) user.getUID())
|
||||
.setCreateTime(now)
|
||||
.setUpdateTime(now)
|
||||
.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
|
||||
.setDeleteType(0);
|
||||
salaryAcctResultTempPOS.add(salaryAcctResultTempPO);
|
||||
}
|
||||
}
|
||||
}
|
||||
sw.stop();
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ 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.beans.BeanUtils;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.util.StopWatch;
|
||||
import weaver.general.BaseBean;
|
||||
|
|
@ -841,7 +842,20 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe
|
|||
// 本次运算的回算薪资项目所涉及的变量
|
||||
Set<String> issuedFieldIds = new HashSet<>();
|
||||
// 9、计算薪资项目的运算优先级
|
||||
List<List<Long>> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds);
|
||||
// List<List<Long>> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds);
|
||||
List<SalarySobItemPO> temp = salarySobBackItems.stream()
|
||||
.map(e -> {
|
||||
SalarySobItemPO salarySobItem = new SalarySobItemPO();
|
||||
BeanUtils.copyProperties(e, salarySobItem);
|
||||
return salarySobItem;
|
||||
}).collect(Collectors.toList());
|
||||
salarySobItemPOS.addAll(temp);
|
||||
|
||||
SalaryCalcItemGraphTemp salaryCalcItemGraph = new SalaryCalcItemGraphTemp(salarySobItemPOS, salaryItemPOS, expressFormulas);
|
||||
List<SalaryCalcItem> salaryCalcItems = salaryCalcItemGraph.sort();
|
||||
List<Long> salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList());
|
||||
|
||||
|
||||
// 10、根据id查询其他合并计税的薪资核算记录
|
||||
List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId());
|
||||
// 11、查询本次核算人员
|
||||
|
|
|
|||
Loading…
Reference in New Issue