This commit is contained in:
2024-08-31 16:26:33 +08:00
parent e75aacdf76
commit 24a9ce77ae
6 changed files with 286 additions and 12 deletions

View File

@@ -65,5 +65,11 @@ public class RecalculatePreviewDto implements SalaryItemData{
private BigDecimal kfheji;
private BigDecimal sfheji;
private Map<String, Object> debug;
@Override
public void updateItems(Map<String, Object> ctx) {
SalaryItemData.super.updateItems(ctx);
this.debug = (Map<String, Object>) ctx.getOrDefault("debug", new HashMap<>());
}
}

View File

@@ -333,6 +333,8 @@ public interface SalaryItemData {
this.setYfheji(getBigDeciaml(ctx, "yfheji"));
this.setKfheji(getBigDeciaml(ctx, "kfheji"));
this.setSfheji(getBigDeciaml(ctx, "sfheji"));
}

View File

@@ -486,7 +486,7 @@ public class EmpSalaryService extends BaseService<EmpSalaryEntity, EmpSalaryRepo
EmpSalaryEntity salary = this.get(dto.getId());
Script scriptObj = empSalaryItemService.newScriptInstance(batch.getOrganizationId());
Script scriptObj = empSalaryItemService.newScriptInstance(batch.getOrganizationId(), true);
Map<String, Object> ctx = buildPreviewCtx(dto, salary);
@@ -769,6 +769,8 @@ public class EmpSalaryService extends BaseService<EmpSalaryEntity, EmpSalaryRepo
dto.overWriteSalaryItem(ctxMap);
ctxMap.put("debug", new HashMap<>());
return ctxMap;
}

View File

@@ -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")

View File

@@ -0,0 +1,11 @@
package cn.lihongjie.coal.empSalaryItem.dto;
import lombok.Data;
import java.util.*;
@Data
public class GenScriptRequest {
boolean debug = false;
}

View File

@@ -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<EmpSalaryItemEntity> 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<EmpSalarySysItemEntity> sysItems,
List<EmpSalaryItemEntity> items) {
AstBuilder astBuilder = new AstBuilder();
List<ASTNode> 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<Expression> 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<EmpSalaryItemEntity> 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));
}
}