package com.engine.salary.service.impl; import com.engine.core.impl.Service; import com.engine.salary.encrypt.AESEncryptUtil; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryformula.ExpressFormula; import com.engine.salary.entity.salaryformula.po.FormulaVar; import com.engine.salary.enums.salaryformula.ReferenceTypeEnum; import com.engine.salary.formlua.core.QlExpress; import com.engine.salary.formlua.entity.parameter.DataType; import com.engine.salary.formlua.entity.standard.ExcelResult; import com.engine.salary.service.FormulaRunService; import com.engine.salary.sys.enums.OpenEnum; import com.engine.salary.util.JsonUtil; import com.ql.util.express.DefaultContext; import com.ql.util.express.ExpressRunner; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.util.StopWatch; import weaver.conn.RecordSet; import weaver.conn.RecordSetDataSource; import weaver.general.BaseBean; import weaver.general.Util; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j public class FormulaRunServiceImpl extends Service implements FormulaRunService { private static ExpressRunner runner = new ExpressRunner(true, false); private final BaseBean baseBean = new BaseBean(); private final Boolean isLog = "true".equals(baseBean.getPropValue("hrmSalary", "log")); //超时提醒 private final String formulaRunOvertimeThreshold = baseBean.getPropValue("hrmSalaryCustom", "formulaRunOvertimeThreshold"); QlExpress express = new QlExpress(); @Override public ExcelResult run(ExpressFormula expressFormula, List formulaVars, DataCollectionEmployee simpleEmployee) { ExcelResult result = new ExcelResult(false, "", "公式类型异常!"); if (StringUtils.isNotBlank(formulaRunOvertimeThreshold)) { 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(); long totalTimeMillis = stopWatch.getTotalTimeMillis(); result.setRunTime(totalTimeMillis); } else { if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.FORMULA) { result = runFormula(expressFormula, formulaVars); } if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.SQL) { result = runSQL(expressFormula, formulaVars); } } return result; } private ExcelResult runSQL(ExpressFormula expressFormula, List formulaVars) { if (isLog) { log.info("SQL ExpressFormula {}", expressFormula); } ExcelResult excelResult = new ExcelResult(); //解析配置,获取返回值、数据源 String extendParam = expressFormula.getExtendParam(); String sqlReturnKey = ""; String datasourceId = ""; String openDecrypt = ""; String result = ""; try { Map map = JsonUtil.parseMap(extendParam, String.class); //返回值配置 sqlReturnKey = map.getOrDefault("sqlReturnKey", ""); if (StringUtils.isNotBlank(sqlReturnKey)) { sqlReturnKey = sqlReturnKey.trim(); } //数据源配置 String datasourceJson = map.getOrDefault("datasource", ""); if (StringUtils.isNotBlank(datasourceJson)) { Map datasourceIdMap = JsonUtil.parseMap(datasourceJson, String.class); String datasourceIdNode = datasourceIdMap.getOrDefault("datasourceId", ""); if (StringUtils.isNotBlank(datasourceIdNode)) { datasourceId = datasourceIdNode; } } //是否需要解密 String decrypt = map.get("openDecrypt"); if (StringUtils.isNotBlank(decrypt)) { openDecrypt = decrypt.trim(); } //解析sql String sql = expressFormula.getFormulaRunScript(); for (FormulaVar formulaVar : formulaVars) { sql = sql.replaceAll(formulaVar.getFieldId(), "'" + formulaVar.getContent() + "'"); } if (isLog) { log.info("ExpressFormula sql run {}", sql); } 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); } } } else { RecordSet rs = new RecordSet(); if (rs.execute(sql)) { if (rs.next()) { result = rs.getString(sqlReturnKey); } } } 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; } } private ExcelResult runFormula(ExpressFormula expressFormula, List formulaVars) { if (isLog) { log.info("FORMULA ExpressFormula {} {}", expressFormula.getFormula(), expressFormula.getFormulaRunScript()); } //是否是自定义函数 boolean isCustomFunction = true; String extendParam = expressFormula.getExtendParam(); try { Map map = JsonUtil.parseMap(extendParam, String.class); //返回值配置 String isCustomFunctionNode = map.getOrDefault("isCustomFunction", ""); if (StringUtils.isNotBlank(isCustomFunctionNode)) { isCustomFunction = StringUtils.equals(isCustomFunctionNode.trim(), "1"); } } catch (Exception e) { log.error("express execute fail, extendParam parse fail {}", extendParam, e); } String formula = expressFormula.getFormulaRunScript(); ExcelResult execute = new ExcelResult(); if (isCustomFunction) { try { execute.setExpress(formula); DefaultContext context = new DefaultContext(); 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); } else { execute.setStatus(false); } } 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 { Map 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 if (v.getContent().startsWith("[") && v.getContent().endsWith("]")) { String content = v.getContent().substring(1); content = content.substring(0, content.length() - 1); context.put(v.getFieldId(), content.split(",")); } else { context.put(v.getFieldId(), v.getContent()); } }); execute = express.execute(formula, context); return execute; } } }