Browse Source

Merge branch 'feature/eta1.2.0_edb_calculate' into debug

xyxie 1 year ago
parent
commit
72e0172f7e

+ 30 - 36
controllers/data_manage/predict_edb_info.go

@@ -1487,7 +1487,7 @@ func (this *PredictEdbInfoController) ChartDataList() {
 		switch v.RuleType {
 		case 9:
 			// 获取计算参数
-			formula, edbInfoList, edbInfoIdBytes, err, errMsg := data.GetCalculateByRuleByNineParams(v)
+			/*formula, edbInfoList, edbInfoIdBytes, err, errMsg := data.GetCalculateByRuleByNineParams(v)
 			if err != nil {
 				br.Msg = "计算失败"
 				if errMsg != "" {
@@ -1504,7 +1504,20 @@ func (this *PredictEdbInfoController) ChartDataList() {
 				br.ErrMsg = err.Error()
 				br.IsSendEmail = false
 				return
+			}*/
+			reqJson, err := json.Marshal(v)
+			respItem, err := data.PredictCalculateByNinePreview(string(reqJson))
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = respItem.Msg
+				br.ErrMsg = respItem.ErrMsg
+				return
 			}
+			tmpDataList = respItem.Data.DataList
 		}
 		tmpPredictEdbConfAndData := data_manage.PredictEdbConfAndData{
 			ConfigId:         0,
@@ -1643,7 +1656,6 @@ func (this *PredictEdbInfoController) PredictRuleCalculateByNine() {
 		this.ServeJSON()
 	}()
 	sysUser := this.SysUser
-	time.Now().AddDate(0, -1, -1).Format(utils.FormatDate)
 	if sysUser == nil {
 		br.Msg = "请登录"
 		br.ErrMsg = "请登录,SysUser Is Empty"
@@ -1652,49 +1664,31 @@ func (this *PredictEdbInfoController) PredictRuleCalculateByNine() {
 	}
 	var req request.RuleConfig
 	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
-
-	// 获取计算参数
-	formula, edbInfoList, edbInfoIdBytes, err, errMsg := data.GetCalculateByRuleByNineParams(req)
 	if err != nil {
-		br.Msg = "计算失败"
-		if errMsg != "" {
-			br.Msg = errMsg
-		}
-		br.Msg = err.Error()
-		br.IsSendEmail = false
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-	// 获取计算数据
-	dataList, err := data.CalculateByRuleByNine(formula, edbInfoList, edbInfoIdBytes, req.EmptyType, req.MaxEmptyType)
+	// 添加计算指标
+	reqJson, err := json.Marshal(req)
 	if err != nil {
-		br.Msg = "数据计算失败"
-		br.ErrMsg = "数据计算失败:Err:" + err.Error()
-		br.IsSendEmail = false
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
 
-	latestDate := time.Now()
-	for _, v := range edbInfoList {
-		tmpLatestDate, err := time.ParseInLocation(utils.FormatDate, v.LatestDate, time.Local)
-		if err != nil {
-			continue
-		}
-		if tmpLatestDate.Before(latestDate) {
-			latestDate = tmpLatestDate
-		}
-	}
-
-	newDataList := make([]*data_manage.EdbDataList, 0)
-	lenData := len(dataList)
-	if lenData > 0 {
-		for i := lenData - 1; i >= 0; i-- {
-			newDataList = append(newDataList, dataList[i])
-		}
+	respItem, err := data.PredictCalculateByNinePreview(string(reqJson))
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
 	}
-	resp := response.PredictRuleCalculateByNineResp{
-		LatestDate: latestDate.Format(utils.FormatDate),
-		DataList:   newDataList,
+	if respItem.Ret != 200 {
+		br.Msg = respItem.Msg
+		br.ErrMsg = respItem.ErrMsg
+		return
 	}
+	resp := respItem.Data
 
 	br.Ret = 200
 	br.Success = true

+ 1 - 1
models/data_manage/response/predit_edb_info.go

@@ -46,5 +46,5 @@ type PredictEdbInfoChartDataResp struct {
 // PredictRuleCalculateByNineResp 获取预测指标规则9的绘图数据返回
 type PredictRuleCalculateByNineResp struct {
 	LatestDate string
-	DataList   interface{}
+	DataList   []*data_manage.EdbDataList
 }

+ 22 - 0
services/data/base_edb_lib.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/response"
 	"eta/eta_api/utils"
 	"fmt"
 	"io/ioutil"
@@ -116,6 +117,27 @@ func SaveBasePredictEdbData(edbInfoCalculateBatchSaveReqStr string) (resp *AddPr
 	return
 }
 
+type PredictRuleCalculateByNineRespResponse struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data        response.PredictRuleCalculateByNineResp
+	Success     bool `description:"true 执行成功,false 执行失败"`
+	IsSendEmail bool `json:"-" description:"true 发送邮件,false 不发送邮件"`
+	IsAddLog    bool `json:"-" description:"true 新增操作日志,false 不新增操作日志" `
+}
+
+// PredictCalculateByNinePreview 预测指标动态环差演算
+func PredictCalculateByNinePreview(RuleConfigReqStr string) (resp *PredictRuleCalculateByNineRespResponse, err error) {
+	_, resultByte, err := postAddEdbData(RuleConfigReqStr, "predict/calculate_by_nine/preview")
+	err = json.Unmarshal(resultByte, &resp)
+	if err != nil {
+		return
+	}
+	return
+}
+
 // SavePredictEdbData 新增/编辑预测指标运算
 func SavePredictEdbData(edbInfoCalculateBatchSaveReqStr string) (resp *AddPredictEdbDataResponse, err error) {
 	_, resultByte, err := postAddEdbData(edbInfoCalculateBatchSaveReqStr, "predict_calculate/save")

+ 1 - 47
services/data/edb_info_calculate.go

@@ -10,14 +10,13 @@ import (
 	"github.com/yidane/formula"
 	"math"
 	"regexp"
-	"sort"
 	"strconv"
 	"strings"
 	"time"
 )
 
 func CheckFormula(formula string) map[string]string {
-	mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN"}
+	mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN", "EXP"}
 
 	str := strings.ToUpper(formula)
 	for _, v := range mathFormula {
@@ -39,56 +38,11 @@ func CheckFormula(formula string) map[string]string {
 	return byteMap
 }
 
-// CheckFormula2 校验公式是否正常(比如说除法的分母不能为0之类的,实际上就是用预设的字段数据做一次计算)
-func CheckFormula2(edbInfoArr []*data_manage.EdbInfo, formulaMap map[string]string, formulaStr string, edbInfoIdBytes []string) (ok bool, err error) {
-	valArr := make(map[int]float64)
-	for _, v := range edbInfoArr {
-		valArr[v.EdbInfoId] = 100
-	}
-	formulaStr = strings.ToUpper(formulaStr)
-	formulaFormStr := ReplaceFormula(edbInfoArr, valArr, formulaMap, formulaStr, edbInfoIdBytes)
-	if formulaFormStr == "" {
-		return
-	}
-	expression := formula.NewExpression(formulaFormStr)
-	_, err = expression.Evaluate()
-	if err != nil {
-	} else {
-		ok = true
-	}
-	return
-}
-
 type FormulaListItem struct {
 	Formula string `json:"f"`
 	Date    string `json:"d"`
 }
 
-// HandleFormulaJson 处理计算公式json串是否异常
-func HandleFormulaJson(formula string, startDate string) (dateSlice []string, formulaMap map[string]string, err error) {
-	list := make([]FormulaListItem, 0)
-	err = json.Unmarshal([]byte(formula), &list)
-	if err != nil {
-		err = fmt.Errorf("公式串解析失败: json.Unmarshal Err: %v", err)
-		return
-	}
-	formulaMap = make(map[string]string)
-	dateSlice = make([]string, 0)
-	// 日期排序
-	for k, v := range list {
-		if k == 0 { // 首个日期均为起始日
-			v.Date = startDate
-		}
-		formulaMap[v.Date] = v.Formula
-		dateSlice = append(dateSlice, v.Date)
-	}
-	sort.Slice(dateSlice, func(i, j int) bool {
-		return dateSlice[i] > dateSlice[j]
-	})
-
-	return
-}
-
 // CheckFormulaJson 检测计算公式json串是否异常
 func CheckFormulaJson(formula string) (formulaSlice []string, err error) {
 	list := make([]FormulaListItem, 0)

+ 0 - 204
services/data/predict_edb_info.go

@@ -9,7 +9,6 @@ import (
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/shopspring/decimal"
-	"github.com/yidane/formula"
 	"strconv"
 	"strings"
 	"time"
@@ -1127,209 +1126,6 @@ func GetPredictCalculateDataListByPredictEdbInfo(edbInfo *data_manage.EdbInfo, s
 	return
 }
 
-// GetCalculateByRuleByNineParams 获取预测规则9的计算参数
-func GetCalculateByRuleByNineParams(req request.RuleConfig) (formula string, edbInfoList []*data_manage.EdbInfo, edbInfoIdBytes []string, err error, errMsg string) {
-	formula = req.Value
-	formula = strings.Replace(formula, "(", "(", -1)
-	formula = strings.Replace(formula, ")", ")", -1)
-	formula = strings.Replace(formula, ",", ",", -1)
-	formula = strings.Replace(formula, "。", ".", -1)
-	formula = strings.Replace(formula, "%", "*0.01", -1)
-
-	//检验公式
-	var checkFormulaStr string
-	for _, tmpEdbInfoId := range req.EdbInfoIdArr {
-		checkFormulaStr += tmpEdbInfoId.FromTag + ","
-		edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
-	}
-	formulaMap := CheckFormula(formula)
-	for _, tmpFormula := range formulaMap {
-		if !strings.Contains(checkFormulaStr, tmpFormula) {
-			errMsg = "公式错误,请重新填写"
-			return
-		}
-	}
-
-	//关联的指标信息
-	edbInfoList = make([]*data_manage.EdbInfo, 0)
-
-	for _, tmpEdbInfoId := range req.EdbInfoIdArr {
-		fromEdbInfo, tmpErr := data_manage.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
-		if tmpErr != nil {
-			if tmpErr.Error() == utils.ErrNoRow() {
-				err = errors.New("指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在")
-			} else {
-				err = errors.New("获取指标失败:Err:" + tmpErr.Error())
-			}
-			errMsg = "数据计算失败"
-			return
-		}
-		edbInfoList = append(edbInfoList, fromEdbInfo)
-	}
-	ok, _ := CheckFormula2(edbInfoList, formulaMap, formula, edbInfoIdBytes)
-	if !ok {
-		errMsg = "生成计算指标失败,请使用正确的计算公式"
-		err = errors.New(errMsg)
-	}
-	return
-}
-
-// CalculateByRuleByNine 动态环差规则计算入库
-func CalculateByRuleByNine(formulaStr string, edbInfoList []*data_manage.EdbInfo, edbInfoIdBytes []string, emptyType, maxEmptyType int) (dataList []*data_manage.EdbDataList, err error) {
-	realSaveDataMap := make(map[string]map[int]float64)
-	saveDataMap := make(map[string]map[int]float64)
-	dateList := make([]string, 0) //日期
-
-	// 最小的结束日期 , 最晚的数据开始日期
-	var minLatestDate, maxStartDate time.Time
-	formulaStr = strings.ToUpper(formulaStr)
-	// 获取关联指标数据
-	for edbInfoIndex, v := range edbInfoList {
-		sourceDataList, _, _, tmpErr, _ := GetPredictDataListByPredictEdbInfo(v, "", "", false)
-		if tmpErr != nil {
-			err = tmpErr
-			return
-		}
-		dataMap := make(map[string]float64)
-		lenData := len(sourceDataList)
-		for _, dv := range sourceDataList {
-			// 实际数据
-			if val, ok := realSaveDataMap[dv.DataTime]; ok {
-				if _, ok := val[v.EdbInfoId]; !ok {
-					val[v.EdbInfoId] = dv.Value
-				}
-			} else {
-				temp := make(map[int]float64)
-				temp[v.EdbInfoId] = dv.Value
-				realSaveDataMap[dv.DataTime] = temp
-			}
-
-			// saveDataMap 待计算的数据
-			if val, ok := saveDataMap[dv.DataTime]; ok {
-				if _, ok := val[v.EdbInfoId]; !ok {
-					val[v.EdbInfoId] = dv.Value
-				}
-			} else {
-				temp2 := make(map[int]float64)
-				temp2[v.EdbInfoId] = dv.Value
-				saveDataMap[dv.DataTime] = temp2
-			}
-
-			// 以第一个指标的日期作为基准日期
-			if edbInfoIndex == 0 {
-				dateList = append(dateList, dv.DataTime)
-			}
-
-			if lenData > 0 {
-				tmpLatestDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[lenData-1].DataTime, time.Local)
-				if minLatestDate.IsZero() || minLatestDate.After(tmpLatestDate) {
-					minLatestDate = tmpLatestDate
-				}
-
-				tmpStartDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[0].DataTime, time.Local)
-				if maxStartDate.IsZero() || maxStartDate.Before(tmpStartDate) {
-					maxStartDate = tmpStartDate
-				}
-			}
-		}
-		item := new(CalculateItems)
-		item.EdbInfoId = v.EdbInfoId
-		item.DataMap = dataMap
-	}
-
-	// todo 数据处理,将日期内不全的数据做填补
-	handleDateSaveDataMap(dateList, realSaveDataMap, saveDataMap, edbInfoList, emptyType)
-	// 添加数据
-	dataList = make([]*data_manage.EdbDataList, 0)
-
-	// 计算规则
-	formulaDateSlice, formulaDateMap, err := HandleFormulaJson(formulaStr, maxStartDate.Format(utils.FormatDate))
-	if err != nil {
-		return
-	}
-	existDataMap := make(map[string]string)
-	// 判断是否特殊处理max和min函数
-	/*maxDealFlag := false
-	if emptyType == 4 && maxEmptyType == 2 {
-		maxDealFlag = true
-	}*/
-	for k, date := range dateList {
-		sv := saveDataMap[date]
-		// 当空值处理类型选择了不计算时,只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值
-		if emptyType == 1 {
-			if len(sv) != len(edbInfoList) {
-				continue
-			}
-		}
-		//fmt.Println(sk, sv)
-		// 根据时间范围,选择对应的公式
-		formulaMap := make(map[string]string)
-		formulaStr = ""
-		for _, fv := range formulaDateSlice {
-			if date >= fv {
-				if f, ok := formulaDateMap[fv]; ok {
-					formulaStr = f
-					formulaMap = CheckFormula(formulaStr)
-				}
-				break
-			}
-		}
-		if formulaStr == "" {
-			continue
-		}
-		/*svMax := make(map[int]float64)
-		if maxDealFlag {
-			// 特殊处理max和min函数,如果原本的值为空,则选择空值参与运算
-			if svMaxData, ok := realSaveDataMap[date]; ok {
-				svMax = svMaxData
-			}
-		}
-		*/
-		//fmt.Println(date, sv)
-
-		formulaFormStr := ReplaceFormula(edbInfoList, sv, formulaMap, formulaStr, edbInfoIdBytes)
-		if formulaFormStr == `` {
-			//计算公式异常,那么就移除该指标
-			continue
-		}
-
-		//fmt.Println(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
-		expression := formula.NewExpression(formulaFormStr)
-		calResult, tmpErr := expression.Evaluate()
-		if tmpErr != nil {
-			// 分母为0的报错
-			if strings.Contains(tmpErr.Error(), "divide by zero") {
-				continue
-			}
-			err = errors.New("计算失败:Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
-			return
-		}
-		calVal, tmpErr := calResult.Float64()
-		if tmpErr != nil {
-			err = errors.New("计算失败:获取计算值失败 Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
-			fmt.Println(err)
-			return
-		}
-
-		saveValue, _ := decimal.NewFromFloat(calVal).RoundCeil(4).Float64() //utils.SubFloatToString(calVal, 4)
-		dataTime, _ := time.Parse(utils.FormatDate, date)
-		timestamp := dataTime.UnixNano() / 1e6
-
-		if _, existOk := existDataMap[date]; !existOk {
-			tmpPredictEdbRuleData := &data_manage.EdbDataList{
-				EdbDataId:     k,
-				EdbInfoId:     0,
-				DataTime:      date,
-				DataTimestamp: timestamp,
-				Value:         saveValue,
-			}
-			dataList = append(dataList, tmpPredictEdbRuleData)
-		}
-		existDataMap[date] = date
-	}
-	return
-}
-
 // ModifyPredictEdbBaseInfoBySourceEdb  根据来源ETA指标修改预测指标的基础信息
 func ModifyPredictEdbBaseInfoBySourceEdb(sourceEDdbInfo *data_manage.EdbInfo) {
 	list, err := data_manage.GetGroupPredictEdbBySourceEdbInfoId(sourceEDdbInfo.EdbInfoId)