package com.engine.salary.entity.salaryacct.bo; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.engine.salary.constant.SalaryFormulaFieldConstant; import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.enums.SalaryFormulaReferenceEnum; import com.engine.salary.util.SalaryEntityUtil; import com.google.common.collect.Maps; import com.weaver.excel.formula.api.entity.ExpressFormula; import com.weaver.excel.formula.api.entity.FormulaVar; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @description: 薪资核算公式 * @author: xiajun * @modified By: xiajun * @date: Created in 6/2/22 10:33 PM * @version:v1.0 */ public class ExpressFormulaBO { /** * 公式中变量的fieldId的正则表达式 */ private static final String SALARY_REGEX = "(\\w+)" + SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR + "(\\w+)"; /** * 解析公式中变量的fieldId的正则表达式 */ private static final Pattern SALARY_PATTERN = Pattern.compile(SALARY_REGEX); /** * 解析公式中的变量 * * @param expressFormulas 公式详情 * @return */ public static Map> buildFormulaVar(List expressFormulas) { if (CollectionUtils.isEmpty(expressFormulas)) { return Collections.emptyMap(); } Map> resultMap = Maps.newHashMapWithExpectedSize(expressFormulas.size()); for (ExpressFormula expressFormula : expressFormulas) { if (StringUtils.isEmpty(expressFormula.getParameter())) { continue; } JSONObject paramJson = JSON.parseObject(expressFormula.getParameter()); if (paramJson != null) { JSONArray paramArray = paramJson.getJSONArray("formulavars"); if (paramArray != null) { List formulaVars = paramArray.toJavaList(FormulaVar.class); resultMap.put(expressFormula.getId(), formulaVars); } } } return resultMap; } /** * 给公式中的变量填入值 * * @param expressFormulas * @param salaryItems * @param acctResults * @return */ public static Map> buildFormulaVar4Check(List expressFormulas, List salaryItems, List acctResults) { if (CollectionUtils.isEmpty(expressFormulas)) { return Collections.emptyMap(); } Map salaryItemCodeMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getId, SalaryItemPO::getCode); Map acctResultMap = SalaryEntityUtil.convert2Map(acctResults, e -> salaryItemCodeMap.getOrDefault(e.getSalaryItemId(), ""), SalaryAcctResultPO::getResultValue); Map> formulaVarMap = buildFormulaVar(expressFormulas); formulaVarMap.forEach((k, v) -> { for (FormulaVar formulaVar : v) { Matcher matcher = SALARY_PATTERN.matcher(formulaVar.getFieldId()); if (matcher.find()) { SalaryFormulaReferenceEnum referenceEnum = SalaryFormulaReferenceEnum.parseByValue(matcher.group(1)); if (referenceEnum == SalaryFormulaReferenceEnum.SALARY_ITEM) { formulaVar.setContent(acctResultMap.getOrDefault(matcher.group(2), "")); } } } }); return formulaVarMap; } /** * 给公式中的变量填入值 * * @param expressFormula 公式 * @param formulaVarValueMap 公式变量的值 * @return */ public static List buildFormulaVar4Accounting(ExpressFormula expressFormula, Map formulaVarValueMap) { List formulaVars = Collections.emptyList(); // 公式异常 if (Objects.isNull(expressFormula) || StringUtils.isEmpty(expressFormula.getParameter())) { return Collections.emptyList(); } JSONObject paramJson = JSON.parseObject(expressFormula.getParameter()); if (paramJson != null) { JSONArray paramArray = paramJson.getJSONArray("formulavars"); if (paramArray != null) { formulaVars = paramArray.toJavaList(FormulaVar.class); for (FormulaVar formulaVar : formulaVars) { // 公式变量的值 String formulaVarValue = formulaVarValueMap.getOrDefault(formulaVar.getFieldId(), StringUtils.EMPTY); // 如果公式的返回值类型为number,公式中的变量的值如果为空,公式运行的时候会报错,所以需要替换成0 if (StringUtils.isEmpty(formulaVarValue) && "number".equals(expressFormula.getReturnType())) { formulaVarValue = BigDecimal.ZERO.toPlainString(); } formulaVar.setContent(formulaVarValue); } } } return formulaVars; } }