From bd38f11889ea66f8432022f89d53ad278663dbc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E6=B6=9B?= <15850646081@163.com> Date: Tue, 26 Nov 2024 11:44:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=A0=B8=E7=AE=97=E4=BC=98=E5=85=88=E7=BA=A7=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../salaryacct/bo/SalaryAcctCalculateBO.java | 2 +- .../entity/salaryacct/bo/SalaryCalcItem.java | 59 ++++++ .../salaryacct/bo/SalaryCalcItemGraph.java | 195 ++++++++++++++++++ .../entity/salarysob/po/SalarySobItemPO.java | 7 + .../salaryacct/SalaryAcctManager.java | 19 +- .../common/constant/SalaryConstant.java | 31 +++ .../impl/SalaryAcctCalculateServiceImpl.java | 156 +++++++------- .../impl/SalaryAcctResultServiceImpl.java | 16 +- 8 files changed, 401 insertions(+), 84 deletions(-) create mode 100644 src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItem.java create mode 100644 src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java diff --git a/src/com/engine/salary/entity/salaryacct/bo/SalaryAcctCalculateBO.java b/src/com/engine/salary/entity/salaryacct/bo/SalaryAcctCalculateBO.java index e0a777bcd..94e8971e0 100644 --- a/src/com/engine/salary/entity/salaryacct/bo/SalaryAcctCalculateBO.java +++ b/src/com/engine/salary/entity/salaryacct/bo/SalaryAcctCalculateBO.java @@ -61,7 +61,7 @@ public class SalaryAcctCalculateBO { /** * 本次运算的薪资项目(已排好运算优先级) */ - private List> salaryItemIdWithPriorityList; + private List salaryItemIdWithPriorityList; /** * 本次运算涉及的所有公式 diff --git a/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItem.java b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItem.java new file mode 100644 index 000000000..42df567df --- /dev/null +++ b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItem.java @@ -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; + +/** + * 薪资核算涉及的薪资项目 + *

Copyright: Copyright (c) 2023

+ *

Company: 泛微软件

+ * + * @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; + + +} diff --git a/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java new file mode 100644 index 000000000..7e8e3690e --- /dev/null +++ b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java @@ -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; + +/** + * 对薪资核算时涉及的薪资项目进行排序 + *

Copyright: Copyright (c) 2023

+ *

Company: 泛微软件

+ * + * @author qiantao + * @version 1.0 + **/ +public class SalaryCalcItemGraph { + + private List nodes; + private Map items; + + /** + * 根据薪资账套的薪资项目、公式详情构建实例 + * + * @param salarySobItems 薪资账套的薪资项目 + * @param expressFormulas 公式详情 + */ + public SalaryCalcItemGraph(List salarySobItems, List salaryItemPOS, List expressFormulas) { + Map salaryItemMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getCode); + Map expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId); + Map> formulaVarMap = ExpressFormulaBO.buildFormulaVar(expressFormulas); + // key:薪资项目的code,value:薪资项目的po + Map codeKeySalaryItemPOMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getId); + salarySobItems.forEach(salarySobItem -> salarySobItem.setSalaryItemCode(codeKeySalaryItemPOMap.get(salarySobItem.getSalaryItemId()).getCode())); + Map salarySobItemMap = SalaryEntityUtil.convert2Map(salarySobItems, SalarySobItemPO::getSalaryItemCode); + + Map 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 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 sort() { + // 循环遍历所有顶点 + for (SalaryCalcItemGraphNode node : nodes) { + // 循环遍历每个顶点的邻居 + for (SalaryCalcItemGraphNode destNode : node.getDestNodes()) { + // 维护每个顶点的入度 + destNode.setInDegree(destNode.getInDegree() + 1); + } + } + + // 创建一个队列 + LinkedTransferQueue queue = new LinkedTransferQueue<>(); + + // 再次循环所有顶点 + for (SalaryCalcItemGraphNode node : nodes) { + // 若该顶点入度为0,则加入队列 + if (node.getInDegree() == 0) { + queue.offer(node); + } + } + + // 存储结果的列表 + List 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 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 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<>(); + } + } +} diff --git a/src/com/engine/salary/entity/salarysob/po/SalarySobItemPO.java b/src/com/engine/salary/entity/salarysob/po/SalarySobItemPO.java index 011f992c4..377590cc9 100644 --- a/src/com/engine/salary/entity/salarysob/po/SalarySobItemPO.java +++ b/src/com/engine/salary/entity/salarysob/po/SalarySobItemPO.java @@ -57,6 +57,13 @@ public class SalarySobItemPO { @XStreamAsAttribute private Long salaryItemId; + /** + * 薪资项目的code + */ + private String salaryItemCode; + + + /** * 薪资账套薪资项目分组id */ diff --git a/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java b/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java index 289b898bd..22f7d879c 100644 --- a/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java +++ b/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java @@ -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.SalaryCalcItemGraph; 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 issuedFieldIds = new HashSet<>(); // 9、计算薪资项目的运算优先级 - List> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds); +// List> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds); + List temp = salarySobBackItems.stream() + .map(e -> { + SalarySobItemPO salarySobItem = new SalarySobItemPO(); + BeanUtils.copyProperties(e, salarySobItem); + return salarySobItem; + }).collect(Collectors.toList()); + salarySobItemPOS.addAll(temp); + + SalaryCalcItemGraph salaryCalcItemGraph = new SalaryCalcItemGraph(salarySobItemPOS, salaryItemPOS, expressFormulas); + List salaryCalcItems = salaryCalcItemGraph.sort(); + List salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList()); + // 10、根据id查询其他合并计税的薪资核算记录 List otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId()); // 11、查询本次核算人员 diff --git a/src/com/engine/salary/report/common/constant/SalaryConstant.java b/src/com/engine/salary/report/common/constant/SalaryConstant.java index b6af93d9d..4e3a32a5f 100644 --- a/src/com/engine/salary/report/common/constant/SalaryConstant.java +++ b/src/com/engine/salary/report/common/constant/SalaryConstant.java @@ -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"; } diff --git a/src/com/engine/salary/service/impl/SalaryAcctCalculateServiceImpl.java b/src/com/engine/salary/service/impl/SalaryAcctCalculateServiceImpl.java index d4563d8d2..4c013b55a 100644 --- a/src/com/engine/salary/service/impl/SalaryAcctCalculateServiceImpl.java +++ b/src/com/engine/salary/service/impl/SalaryAcctCalculateServiceImpl.java @@ -216,91 +216,89 @@ public class SalaryAcctCalculateServiceImpl extends Service implements SalaryAcc formulaVarValues.addAll(empInfo); Map formulaVarValueMap = SalaryEntityUtil.convert2Map(formulaVarValues, CalculateFormulaVarBO.FormulaVarValue::getFieldId, CalculateFormulaVarBO.FormulaVarValue::getFieldValue); // 按照计算好的优先级计算薪资项目的值 - for (List 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(); diff --git a/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java b/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java index 67e873658..a6c50ea49 100644 --- a/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java +++ b/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java @@ -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; @@ -827,7 +828,20 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe // 本次运算的回算薪资项目所涉及的变量 Set issuedFieldIds = new HashSet<>(); // 9、计算薪资项目的运算优先级 - List> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds); +// List> salarySobItemsWithPriority = SalaryAcctCalculatePriorityBO.calculatePriority(salarySobItemPOS, salaryItemPOS, expressFormulas, salarySobBackItems, issuedFieldIds); + List temp = salarySobBackItems.stream() + .map(e -> { + SalarySobItemPO salarySobItem = new SalarySobItemPO(); + BeanUtils.copyProperties(e, salarySobItem); + return salarySobItem; + }).collect(Collectors.toList()); + salarySobItemPOS.addAll(temp); + + SalaryCalcItemGraph salaryCalcItemGraph = new SalaryCalcItemGraph(salarySobItemPOS, salaryItemPOS, expressFormulas); + List salaryCalcItems = salaryCalcItemGraph.sort(); + List salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList()); + + // 10、根据id查询其他合并计税的薪资核算记录 List otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(salaryAcctRecordPO.getId()); // 11、查询本次核算人员 From ce34e86724e9251183ac746fbc400a43740bb6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E6=B6=9B?= <15850646081@163.com> Date: Tue, 26 Nov 2024 11:45:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E9=98=B2=E6=AD=A2=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...{SalaryCalcItemGraph.java => SalaryCalcItemGraphTemp.java} | 4 ++-- .../salary/maintainer/salaryacct/SalaryAcctManager.java | 4 ++-- .../salary/service/impl/SalaryAcctResultServiceImpl.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/com/engine/salary/entity/salaryacct/bo/{SalaryCalcItemGraph.java => SalaryCalcItemGraphTemp.java} (98%) diff --git a/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraphTemp.java similarity index 98% rename from src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java rename to src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraphTemp.java index 7e8e3690e..67cbef8f4 100644 --- a/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraph.java +++ b/src/com/engine/salary/entity/salaryacct/bo/SalaryCalcItemGraphTemp.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; * @author qiantao * @version 1.0 **/ -public class SalaryCalcItemGraph { +public class SalaryCalcItemGraphTemp { private List nodes; private Map items; @@ -35,7 +35,7 @@ public class SalaryCalcItemGraph { * @param salarySobItems 薪资账套的薪资项目 * @param expressFormulas 公式详情 */ - public SalaryCalcItemGraph(List salarySobItems, List salaryItemPOS, List expressFormulas) { + public SalaryCalcItemGraphTemp(List salarySobItems, List salaryItemPOS, List expressFormulas) { Map salaryItemMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getCode); Map expressFormulaMap = SalaryEntityUtil.convert2Map(expressFormulas, ExpressFormula::getId); Map> formulaVarMap = ExpressFormulaBO.buildFormulaVar(expressFormulas); diff --git a/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java b/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java index 22f7d879c..5a2715720 100644 --- a/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java +++ b/src/com/engine/salary/maintainer/salaryacct/SalaryAcctManager.java @@ -7,7 +7,7 @@ import com.engine.salary.entity.datacollection.dto.AttendQuoteFieldListDTO; 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.SalaryCalcItemGraph; +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; @@ -295,7 +295,7 @@ public class SalaryAcctManager extends Service { }).collect(Collectors.toList()); salarySobItemPOS.addAll(temp); - SalaryCalcItemGraph salaryCalcItemGraph = new SalaryCalcItemGraph(salarySobItemPOS, salaryItemPOS, expressFormulas); + SalaryCalcItemGraphTemp salaryCalcItemGraph = new SalaryCalcItemGraphTemp(salarySobItemPOS, salaryItemPOS, expressFormulas); List salaryCalcItems = salaryCalcItemGraph.sort(); List salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList()); diff --git a/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java b/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java index a6c50ea49..09007cb09 100644 --- a/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java +++ b/src/com/engine/salary/service/impl/SalaryAcctResultServiceImpl.java @@ -837,7 +837,7 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe }).collect(Collectors.toList()); salarySobItemPOS.addAll(temp); - SalaryCalcItemGraph salaryCalcItemGraph = new SalaryCalcItemGraph(salarySobItemPOS, salaryItemPOS, expressFormulas); + SalaryCalcItemGraphTemp salaryCalcItemGraph = new SalaryCalcItemGraphTemp(salarySobItemPOS, salaryItemPOS, expressFormulas); List salaryCalcItems = salaryCalcItemGraph.sort(); List salarySobItemsWithPriority = SalaryEntityUtil.properties(salaryCalcItems, SalaryCalcItem::getSalaryItemId, Collectors.toList());