2022-04-15 13:54:47 +08:00
|
|
|
package com.engine.salary.service.impl;
|
|
|
|
|
|
|
|
|
|
import com.engine.core.impl.Service;
|
2022-11-08 11:10:56 +08:00
|
|
|
import com.engine.salary.encrypt.AESEncryptUtil;
|
2022-04-15 13:54:47 +08:00
|
|
|
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
|
|
|
|
|
import com.engine.salary.entity.salaryformula.ExpressFormula;
|
|
|
|
|
import com.engine.salary.entity.salaryformula.po.FormulaVar;
|
2022-04-27 17:20:33 +08:00
|
|
|
import com.engine.salary.enums.salaryformula.ReferenceTypeEnum;
|
2023-04-19 19:28:05 +08:00
|
|
|
import com.engine.salary.formlua.core.QlExpress;
|
2022-04-20 19:23:16 +08:00
|
|
|
import com.engine.salary.formlua.entity.parameter.DataType;
|
2023-05-15 09:28:22 +08:00
|
|
|
import com.engine.salary.formlua.entity.standard.ExcelResult;
|
2022-04-15 13:54:47 +08:00
|
|
|
import com.engine.salary.service.FormulaRunService;
|
2022-11-08 11:10:56 +08:00
|
|
|
import com.engine.salary.sys.enums.OpenEnum;
|
2023-08-14 16:38:40 +08:00
|
|
|
import com.engine.salary.util.JsonUtil;
|
2022-04-18 14:45:12 +08:00
|
|
|
import com.ql.util.express.DefaultContext;
|
|
|
|
|
import com.ql.util.express.ExpressRunner;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2022-04-29 14:56:33 +08:00
|
|
|
import org.apache.commons.lang3.StringUtils;
|
2022-05-07 15:20:39 +08:00
|
|
|
import org.apache.commons.lang3.math.NumberUtils;
|
2023-08-31 14:39:58 +08:00
|
|
|
import org.springframework.util.StopWatch;
|
2022-04-29 14:56:33 +08:00
|
|
|
import weaver.conn.RecordSet;
|
2022-08-03 10:08:43 +08:00
|
|
|
import weaver.conn.RecordSetDataSource;
|
|
|
|
|
import weaver.general.BaseBean;
|
2023-05-15 09:28:22 +08:00
|
|
|
import weaver.general.Util;
|
2022-04-15 13:54:47 +08:00
|
|
|
|
2022-04-20 11:17:25 +08:00
|
|
|
import java.math.BigDecimal;
|
2023-04-19 19:28:05 +08:00
|
|
|
import java.util.HashMap;
|
2022-04-15 13:54:47 +08:00
|
|
|
import java.util.List;
|
2023-04-19 19:28:05 +08:00
|
|
|
import java.util.Map;
|
2022-04-15 13:54:47 +08:00
|
|
|
|
2022-04-18 14:45:12 +08:00
|
|
|
@Slf4j
|
2022-04-15 13:54:47 +08:00
|
|
|
public class FormulaRunServiceImpl extends Service implements FormulaRunService {
|
2022-04-24 17:42:32 +08:00
|
|
|
|
2022-04-29 14:56:33 +08:00
|
|
|
private static ExpressRunner runner = new ExpressRunner(true, false);
|
|
|
|
|
|
2022-08-03 10:08:43 +08:00
|
|
|
private final BaseBean baseBean = new BaseBean();
|
|
|
|
|
|
|
|
|
|
private final Boolean isLog = "true".equals(baseBean.getPropValue("hrmSalary", "log"));
|
2023-08-31 15:31:34 +08:00
|
|
|
//超时提醒
|
|
|
|
|
private final String formulaRunOvertimeThreshold = baseBean.getPropValue("hrmSalaryCustom", "formulaRunOvertimeThreshold");
|
2022-08-03 10:08:43 +08:00
|
|
|
|
2023-04-19 19:28:05 +08:00
|
|
|
QlExpress express = new QlExpress();
|
|
|
|
|
|
2022-04-24 17:42:32 +08:00
|
|
|
|
2022-04-15 13:54:47 +08:00
|
|
|
@Override
|
2023-05-15 09:28:22 +08:00
|
|
|
public ExcelResult run(ExpressFormula expressFormula, List<FormulaVar> formulaVars, DataCollectionEmployee simpleEmployee) {
|
2023-08-31 16:22:02 +08:00
|
|
|
ExcelResult result = new ExcelResult(false, "", "公式类型异常!");
|
2023-08-31 15:31:34 +08:00
|
|
|
if (StringUtils.isNotBlank(formulaRunOvertimeThreshold)) {
|
2023-08-31 14:39:58 +08:00
|
|
|
StopWatch stopWatch = new StopWatch();
|
|
|
|
|
stopWatch.start("run " + expressFormula.getName());
|
|
|
|
|
if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.FORMULA) {
|
|
|
|
|
result = runFormula(expressFormula, formulaVars);
|
|
|
|
|
}
|
|
|
|
|
if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.SQL) {
|
|
|
|
|
result = runSQL(expressFormula, formulaVars);
|
|
|
|
|
}
|
|
|
|
|
stopWatch.stop();
|
2023-08-31 15:31:34 +08:00
|
|
|
long totalTimeMillis = stopWatch.getTotalTimeMillis();
|
|
|
|
|
result.setRunTime(totalTimeMillis);
|
2023-08-31 14:39:58 +08:00
|
|
|
} else {
|
|
|
|
|
if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.FORMULA) {
|
|
|
|
|
result = runFormula(expressFormula, formulaVars);
|
|
|
|
|
}
|
|
|
|
|
if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.SQL) {
|
|
|
|
|
result = runSQL(expressFormula, formulaVars);
|
|
|
|
|
}
|
2022-04-29 14:56:33 +08:00
|
|
|
}
|
2023-08-31 14:39:58 +08:00
|
|
|
return result;
|
2022-04-29 14:56:33 +08:00
|
|
|
}
|
|
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
private ExcelResult runSQL(ExpressFormula expressFormula, List<FormulaVar> formulaVars) {
|
2022-08-03 10:08:43 +08:00
|
|
|
if (isLog) {
|
2022-11-04 10:42:05 +08:00
|
|
|
log.info("SQL ExpressFormula {}", expressFormula);
|
2022-08-03 10:08:43 +08:00
|
|
|
}
|
2023-05-15 09:28:22 +08:00
|
|
|
ExcelResult excelResult = new ExcelResult();
|
2022-08-03 10:08:43 +08:00
|
|
|
|
|
|
|
|
//解析配置,获取返回值、数据源
|
2022-05-08 12:34:05 +08:00
|
|
|
String extendParam = expressFormula.getExtendParam();
|
|
|
|
|
String sqlReturnKey = "";
|
2022-08-03 10:08:43 +08:00
|
|
|
String datasourceId = "";
|
2022-11-08 11:10:56 +08:00
|
|
|
String openDecrypt = "";
|
|
|
|
|
String result = "";
|
2022-04-29 14:56:33 +08:00
|
|
|
try {
|
2023-08-14 16:38:40 +08:00
|
|
|
Map<String, String> map = JsonUtil.parseMap(extendParam, String.class);
|
2022-08-03 10:08:43 +08:00
|
|
|
//返回值配置
|
2023-08-14 16:38:40 +08:00
|
|
|
sqlReturnKey = map.getOrDefault("sqlReturnKey", "");
|
|
|
|
|
if (StringUtils.isNotBlank(sqlReturnKey)) {
|
|
|
|
|
sqlReturnKey = sqlReturnKey.trim();
|
2022-04-29 14:56:33 +08:00
|
|
|
}
|
2022-08-03 10:08:43 +08:00
|
|
|
//数据源配置
|
2023-08-14 16:38:40 +08:00
|
|
|
String datasourceJson = map.getOrDefault("datasource", "");
|
|
|
|
|
if (StringUtils.isNotBlank(datasourceJson)) {
|
|
|
|
|
Map<String, String> datasourceIdMap = JsonUtil.parseMap(datasourceJson, String.class);
|
|
|
|
|
String datasourceIdNode = datasourceIdMap.getOrDefault("datasourceId","");
|
|
|
|
|
if (StringUtils.isNotBlank(datasourceIdNode)) {
|
|
|
|
|
datasourceId = datasourceIdNode;
|
2022-08-03 10:08:43 +08:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-08 11:10:56 +08:00
|
|
|
//是否需要解密
|
2023-08-14 16:38:40 +08:00
|
|
|
String decrypt = map.get("openDecrypt");
|
|
|
|
|
if (StringUtils.isNotBlank(decrypt)) {
|
|
|
|
|
openDecrypt = decrypt.trim();
|
2022-11-08 11:10:56 +08:00
|
|
|
}
|
2022-04-27 17:20:33 +08:00
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
//解析sql
|
|
|
|
|
String sql = expressFormula.getFormulaRunScript();
|
|
|
|
|
for (FormulaVar formulaVar : formulaVars) {
|
|
|
|
|
sql = sql.replaceAll(formulaVar.getFieldId(), "'" + formulaVar.getContent() + "'");
|
|
|
|
|
}
|
|
|
|
|
if (isLog) {
|
|
|
|
|
log.info("ExpressFormula sql run {}", sql);
|
|
|
|
|
}
|
2022-08-03 10:08:43 +08:00
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
excelResult.setExpress(sql);
|
|
|
|
|
|
|
|
|
|
//外部数据源
|
|
|
|
|
if (StringUtils.isNotBlank(datasourceId)) {
|
|
|
|
|
RecordSetDataSource rs = new RecordSetDataSource(datasourceId);
|
|
|
|
|
log.error("执行外部sql,{},datasourceId{}", sql, datasourceId);
|
|
|
|
|
if (rs.executeSql(sql)) {
|
|
|
|
|
if (rs.next()) {
|
|
|
|
|
result = rs.getString(sqlReturnKey);
|
|
|
|
|
}
|
2022-08-03 10:08:43 +08:00
|
|
|
}
|
2023-05-15 09:28:22 +08:00
|
|
|
} else {
|
|
|
|
|
RecordSet rs = new RecordSet();
|
|
|
|
|
if (rs.execute(sql)) {
|
|
|
|
|
if (rs.next()) {
|
|
|
|
|
result = rs.getString(sqlReturnKey);
|
|
|
|
|
}
|
2022-08-03 10:08:43 +08:00
|
|
|
}
|
2022-04-29 14:56:33 +08:00
|
|
|
}
|
2022-11-08 11:10:56 +08:00
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
if (OpenEnum.OPEN.getValue().equals(openDecrypt)) {
|
|
|
|
|
result = AESEncryptUtil.decrypt(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
excelResult.setStatus(true);
|
|
|
|
|
excelResult.setData(Util.null2String(result));
|
|
|
|
|
return excelResult;
|
|
|
|
|
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
log.error("express run err sql", e);
|
|
|
|
|
while (e.getCause() != null) {
|
|
|
|
|
e = e.getCause();
|
|
|
|
|
}
|
|
|
|
|
excelResult.setStatus(false);
|
|
|
|
|
excelResult.setErrorMsg(e.getMessage());
|
|
|
|
|
return excelResult;
|
2022-11-08 11:10:56 +08:00
|
|
|
}
|
2022-04-27 17:20:33 +08:00
|
|
|
}
|
|
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
private ExcelResult runFormula(ExpressFormula expressFormula, List<FormulaVar> formulaVars) {
|
2023-04-19 19:28:05 +08:00
|
|
|
|
2023-09-06 10:14:52 +08:00
|
|
|
if (isLog) {
|
|
|
|
|
log.info("FORMULA ExpressFormula {} {}", expressFormula.getFormula(), expressFormula.getFormulaRunScript());
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 19:28:05 +08:00
|
|
|
//是否是自定义函数
|
|
|
|
|
boolean isCustomFunction = true;
|
|
|
|
|
|
|
|
|
|
String extendParam = expressFormula.getExtendParam();
|
|
|
|
|
try {
|
2023-08-14 16:38:40 +08:00
|
|
|
Map<String, String> map = JsonUtil.parseMap(extendParam, String.class);
|
2023-04-19 19:28:05 +08:00
|
|
|
//返回值配置
|
2023-08-14 16:38:40 +08:00
|
|
|
String isCustomFunctionNode = map.getOrDefault("isCustomFunction", "");
|
|
|
|
|
if (StringUtils.isNotBlank(isCustomFunctionNode)) {
|
|
|
|
|
isCustomFunction = StringUtils.equals(isCustomFunctionNode.trim(), "1");
|
2023-04-19 19:28:05 +08:00
|
|
|
}
|
2023-08-14 16:38:40 +08:00
|
|
|
} catch (Exception e) {
|
2023-09-06 10:13:22 +08:00
|
|
|
log.error("express execute fail, extendParam parse fail {}", extendParam, e);
|
2023-04-19 19:28:05 +08:00
|
|
|
}
|
|
|
|
|
|
2022-05-08 12:34:05 +08:00
|
|
|
String formula = expressFormula.getFormulaRunScript();
|
2023-04-19 19:28:05 +08:00
|
|
|
|
2023-05-15 09:28:22 +08:00
|
|
|
ExcelResult execute = new ExcelResult();
|
|
|
|
|
if (isCustomFunction) {
|
|
|
|
|
try {
|
|
|
|
|
execute.setExpress(formula);
|
|
|
|
|
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
|
|
|
|
|
formulaVars.forEach(v -> {
|
|
|
|
|
if (isLog) {
|
|
|
|
|
log.info("FORMULA formulaVar {} - {}", v.getFieldId(), v.getContent());
|
|
|
|
|
}
|
|
|
|
|
if (DataType.NUMBER.equals(v.getFieldType()) && NumberUtils.isCreatable(v.getContent())) {
|
|
|
|
|
context.put(v.getFieldId(), new BigDecimal(v.getContent()));
|
|
|
|
|
} else {
|
|
|
|
|
context.put(v.getFieldId(), v.getContent());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
execute.setExpressContext(context);
|
|
|
|
|
Object data = runner.execute(formula, context, null, true, false);
|
|
|
|
|
|
|
|
|
|
if (data != null) {
|
|
|
|
|
execute.setData(data);
|
|
|
|
|
execute.setStatus(true);
|
2023-04-19 19:28:05 +08:00
|
|
|
} else {
|
2023-05-15 09:28:22 +08:00
|
|
|
execute.setStatus(false);
|
2023-04-19 19:28:05 +08:00
|
|
|
}
|
2023-05-15 09:28:22 +08:00
|
|
|
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
log.error("express run err isCustomFunction", e);
|
|
|
|
|
while (e.getCause() != null) {
|
|
|
|
|
e = e.getCause();
|
|
|
|
|
}
|
|
|
|
|
execute.setStatus(false);
|
|
|
|
|
execute.setErrorMsg(e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return execute;
|
|
|
|
|
} else {
|
2023-04-19 19:28:05 +08:00
|
|
|
Map<String, Object> context = new HashMap<>();
|
|
|
|
|
formulaVars.forEach(v -> {
|
|
|
|
|
if (isLog) {
|
|
|
|
|
log.info("FORMULA formulaVar {} - {}", v.getFieldId(), v.getContent());
|
|
|
|
|
}
|
|
|
|
|
if (DataType.NUMBER.equals(v.getFieldType()) && NumberUtils.isCreatable(v.getContent())) {
|
|
|
|
|
context.put(v.getFieldId(), new BigDecimal(v.getContent()));
|
|
|
|
|
} else {
|
|
|
|
|
context.put(v.getFieldId(), v.getContent());
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-05-15 09:28:22 +08:00
|
|
|
execute = express.execute(formula, context);
|
2023-04-19 19:28:05 +08:00
|
|
|
return execute;
|
|
|
|
|
}
|
2022-04-15 13:54:47 +08:00
|
|
|
}
|
|
|
|
|
}
|