From 24a9ce77aefd93325cbc7b9e6296f0c62e25d079 Mon Sep 17 00:00:00 2001 From: lihongjie0209 Date: Sat, 31 Aug 2024 16:26:33 +0800 Subject: [PATCH] bugfix --- .../empSalary/dto/RecalculatePreviewDto.java | 6 + .../coal/empSalary/dto/SalaryItemData.java | 2 + .../empSalary/service/EmpSalaryService.java | 4 +- .../controller/EmpSalaryItemController.java | 5 +- .../empSalaryItem/dto/GenScriptRequest.java | 11 + .../service/EmpSalaryItemService.java | 270 +++++++++++++++++- 6 files changed, 286 insertions(+), 12 deletions(-) create mode 100644 src/main/java/cn/lihongjie/coal/empSalaryItem/dto/GenScriptRequest.java diff --git a/src/main/java/cn/lihongjie/coal/empSalary/dto/RecalculatePreviewDto.java b/src/main/java/cn/lihongjie/coal/empSalary/dto/RecalculatePreviewDto.java index ddf2f0c7..01074140 100644 --- a/src/main/java/cn/lihongjie/coal/empSalary/dto/RecalculatePreviewDto.java +++ b/src/main/java/cn/lihongjie/coal/empSalary/dto/RecalculatePreviewDto.java @@ -65,5 +65,11 @@ public class RecalculatePreviewDto implements SalaryItemData{ private BigDecimal kfheji; private BigDecimal sfheji; + private Map debug; + @Override + public void updateItems(Map ctx) { + SalaryItemData.super.updateItems(ctx); + this.debug = (Map) ctx.getOrDefault("debug", new HashMap<>()); + } } diff --git a/src/main/java/cn/lihongjie/coal/empSalary/dto/SalaryItemData.java b/src/main/java/cn/lihongjie/coal/empSalary/dto/SalaryItemData.java index aad7d883..ae1141f1 100644 --- a/src/main/java/cn/lihongjie/coal/empSalary/dto/SalaryItemData.java +++ b/src/main/java/cn/lihongjie/coal/empSalary/dto/SalaryItemData.java @@ -333,6 +333,8 @@ public interface SalaryItemData { this.setYfheji(getBigDeciaml(ctx, "yfheji")); this.setKfheji(getBigDeciaml(ctx, "kfheji")); this.setSfheji(getBigDeciaml(ctx, "sfheji")); + + } diff --git a/src/main/java/cn/lihongjie/coal/empSalary/service/EmpSalaryService.java b/src/main/java/cn/lihongjie/coal/empSalary/service/EmpSalaryService.java index 2567696a..76263475 100644 --- a/src/main/java/cn/lihongjie/coal/empSalary/service/EmpSalaryService.java +++ b/src/main/java/cn/lihongjie/coal/empSalary/service/EmpSalaryService.java @@ -486,7 +486,7 @@ public class EmpSalaryService extends BaseService ctx = buildPreviewCtx(dto, salary); @@ -769,6 +769,8 @@ public class EmpSalaryService extends BaseService()); + return ctxMap; } diff --git a/src/main/java/cn/lihongjie/coal/empSalaryItem/controller/EmpSalaryItemController.java b/src/main/java/cn/lihongjie/coal/empSalaryItem/controller/EmpSalaryItemController.java index 15c38054..d87b71d9 100644 --- a/src/main/java/cn/lihongjie/coal/empSalaryItem/controller/EmpSalaryItemController.java +++ b/src/main/java/cn/lihongjie/coal/empSalaryItem/controller/EmpSalaryItemController.java @@ -8,6 +8,7 @@ import cn.lihongjie.coal.base.dto.R; import cn.lihongjie.coal.common.Ctx; import cn.lihongjie.coal.empSalaryItem.dto.CreateEmpSalaryItemDto; import cn.lihongjie.coal.empSalaryItem.dto.EmpSalaryItemDto; +import cn.lihongjie.coal.empSalaryItem.dto.GenScriptRequest; import cn.lihongjie.coal.empSalaryItem.dto.UpdateEmpSalaryItemDto; import cn.lihongjie.coal.empSalaryItem.service.EmpSalaryItemService; @@ -52,8 +53,8 @@ public class EmpSalaryItemController { } @PostMapping("/genScriptWithCompileResult") - public Object genScriptWithCompileResult() { - return R.success(this.service.genScriptWithCompileResult(Ctx.currentUser().getOrganizationId())); + public Object genScriptWithCompileResult(GenScriptRequest request) { + return R.success(this.service.genScriptWithCompileResult(Ctx.currentUser().getOrganizationId(), request.isDebug())); } @PostMapping("/init") diff --git a/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/GenScriptRequest.java b/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/GenScriptRequest.java new file mode 100644 index 00000000..f7c1dcb2 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/GenScriptRequest.java @@ -0,0 +1,11 @@ +package cn.lihongjie.coal.empSalaryItem.dto; + +import lombok.Data; + +import java.util.*; + +@Data +public class GenScriptRequest { + + boolean debug = false; +} diff --git a/src/main/java/cn/lihongjie/coal/empSalaryItem/service/EmpSalaryItemService.java b/src/main/java/cn/lihongjie/coal/empSalaryItem/service/EmpSalaryItemService.java index f72010d3..4bc7aa00 100644 --- a/src/main/java/cn/lihongjie/coal/empSalaryItem/service/EmpSalaryItemService.java +++ b/src/main/java/cn/lihongjie/coal/empSalaryItem/service/EmpSalaryItemService.java @@ -18,6 +18,7 @@ import cn.lihongjie.coal.empSalarySysItem.service.EmpSalarySysItemService; import cn.lihongjie.coal.exception.BizException; import groovy.lang.Closure; +import groovy.lang.GString; import groovy.lang.Script; import io.vavr.Tuple; @@ -40,8 +41,9 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.CodeVisitorSupport; +import org.codehaus.groovy.ast.builder.AstBuilder; import org.codehaus.groovy.ast.builder.AstStringCompiler; -import org.codehaus.groovy.ast.expr.VariableExpression; +import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.control.CompilerConfiguration; import org.codehaus.groovy.control.customizers.SecureASTCustomizer; import org.jgrapht.alg.cycle.CycleDetector; @@ -58,7 +60,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.*; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -200,7 +204,7 @@ public class EmpSalaryItemService Arrays.asList( Object[].class, Arrays.class, - java.math.RoundingMode.class, + RoundingMode.class, Closure.class, Map.class, Object.class, @@ -214,9 +218,11 @@ public class EmpSalaryItemService LocalDateTime.class, LocalDate.class, LocalTime.class, - ZonedDateTime.class - + ZonedDateTime.class, + DateTimeFormatter.class, + GString.class )); + } }); } @@ -664,9 +670,9 @@ public class EmpSalaryItemService repository.save(item3); } - public Object genScriptWithCompileResult(String organizationId) { + public Object genScriptWithCompileResult(String organizationId, boolean debug) { - String script = genScript(organizationId); + String script = genScript(organizationId, debug); Exception exception = null; try { @@ -687,6 +693,10 @@ public class EmpSalaryItemService } public String genScript(String organizationId) { + return genScript(organizationId, true); + } + + public String genScript(String organizationId, boolean debug) { List items = this.findAll( @@ -751,6 +761,46 @@ public class EmpSalaryItemService sysItemScript.append("// 系统预设函数结束\n"); } + + if (debug) { + + sysItemScript.append( + """ + +def debugPrint(def x) { + + if (x == null) { + return "null" + } + + + if (x instanceof CharSequence) { + return "\\"" + x + "\\"" + + } else if (x instanceof Double) { + + return x.round(2) + + } else if (x instanceof BigDecimal) { + return x.round(2) + } else if (x instanceof Number) { + return x + } else if (x instanceof java.time.LocalDate) { + return x.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + } else if (x instanceof java.time.LocalDateTime) { + + return x.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + } else if (x instanceof java.time.YearMonth) { + return x.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM")) + } else { + return x.toString() + + } +} + +"""); + } + if (CollectionUtils.isNotEmpty(usedSysItems)) { sysItemScript.append("// 系统预设项目开始\n"); @@ -860,6 +910,12 @@ public class EmpSalaryItemService .append(" = (") .append(item.getFormula().trim()) .append(") ?: 0 ;\n"); + + if (debug) { + + script.append(genDebugStatement(item, sysItems, items)); + + } } script.append("// 工资项目结束\n"); @@ -870,6 +926,195 @@ public class EmpSalaryItemService return script.toString(); } + private String genDebugStatement( + EmpSalaryItemEntity item, + List sysItems, + List items) { + + AstBuilder astBuilder = new AstBuilder(); + + List astNodes = astBuilder.buildFromString(item.getFormula()); + + var sb = new StringBuilder(); + sb.append("\n"); + + sb.append("/**\n"); + sb.append(" * 调试信息"); + sb.append(" ") + .append(item.getCode()) + .append(" ") + .append(" ") + .append(item.getName()) + .append("\n"); + sb.append("*/"); + sb.append("\n"); + + sb.append("salary.debug.").append(item.getCode()).append(" = \""); + for (ASTNode astNode : astNodes) { + + astNode.visit( + new CodeVisitorSupport() { + + @Override + public void visitMethodCallExpression(MethodCallExpression call) { + + sb.append(call.getMethod().getText()); + sb.append("("); + + call.getArguments().visit(this); + + sb.append(")"); + } + + @Override + public void visitShortTernaryExpression( + ElvisOperatorExpression expression) { + + if (expression.getFalseExpression() + instanceof ConstantExpression falseExpression) { + + if (falseExpression.getText().equals("0")) { + + expression.getTrueExpression().visit(this); + } + } else if (expression.getTrueExpression() + instanceof ConstantExpression trueExpression) { + + if (trueExpression.getText().equals("0")) { + + expression.getFalseExpression().visit(this); + } + } else { + + super.visitShortTernaryExpression(expression); + } + } + + @Override + public void visitNotExpression(NotExpression expression) { + sb.append("!"); + super.visitNotExpression(expression); + } + + @Override + public void visitTupleExpression(TupleExpression expression) { + super.visitTupleExpression(expression); + } + + @Override + public void visitListExpression(ListExpression expression) { + + sb.append("["); + + expression + .getExpressions() + .forEach( + x -> { + x.visit(this); + sb.append(","); + }); + + if (sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length() - 1); + } + + sb.append("]"); + } + + @Override + public void visitConstantExpression(ConstantExpression expression) { + + sb.append(" "); + if (expression.getValue() instanceof String) { + sb.append("\\\"").append(expression.getValue()).append("\\\""); + } else { + sb.append(expression.getText()); + } + + sb.append(" "); + } + + @Override + public void visitVariableExpression(VariableExpression expression) { + + for (EmpSalarySysItemEntity sysItem : sysItems) { + + if (StringUtils.equals(sysItem.getCode(), expression.getName())) { + + sb.append(sysItem.getName()) + .append("(${debugPrint(") + .append(expression.getName()) + .append(")})"); + + return; + } + } + + super.visitVariableExpression(expression); + } + + @Override + public void visitBinaryExpression(BinaryExpression expression) { + + expression.getLeftExpression().visit(this); + + sb.append(" ").append(expression.getOperation().getText()).append(" "); + + expression.getRightExpression().visit(this); + } + + @Override + public void visitPropertyExpression(PropertyExpression expression) { + + if (expression + .getObjectExpression() + .getText() + .equalsIgnoreCase("salary")) { + + for (EmpSalaryItemEntity item : items) { + + if (StringUtils.equals( + item.getCode(), expression.getPropertyAsString())) { + + sb.append(item.getName()) + .append("(${debugPrint(") + .append("salary.") + .append(expression.getPropertyAsString()) + .append(")})"); + + return; + } + } + } + + super.visitPropertyExpression(expression); + } + + @Override + public void visitFieldExpression(FieldExpression expression) { + super.visitFieldExpression(expression); + } + + @Override + public void visitArgumentlistExpression(ArgumentListExpression expression) { + + List expressions = expression.getExpressions(); + for (int i = 0; i < expressions.size(); i++) { + Expression expressionExpression = expressions.get(i); + + expressionExpression.visit(this); + if (i != expressions.size() - 1) { + sb.append(","); + } + } + } + }); + } + + sb.append("\".toString()\n"); + return sb.toString(); + } + public List getItems(String organizationId) { return this.findAll( @@ -886,14 +1131,21 @@ public class EmpSalaryItemService }); } - public String computeCacheKey(String organizationId) { + public String computeCacheKey(String organizationId, boolean debug) { - return this.repository.computeCacheKey(organizationId); + return this.repository.computeCacheKey(organizationId) + "_" + debug; } public Script newScriptInstance(String organizationId) { + return newScriptInstance(organizationId, false); + } + + public Script newScriptInstance(String organizationId, boolean debug) { + + + return groovyScriptManager.newInstance( - computeCacheKey(organizationId), () -> genScript(organizationId)); + computeCacheKey(organizationId, debug), () -> genScript(organizationId, debug)); } }