|
@@ -8,12 +8,40 @@ import (
|
|
|
"eta/eta_api/services/data"
|
|
|
"eta/eta_api/utils"
|
|
|
"fmt"
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
+ "github.com/yidane/formula"
|
|
|
+ "sort"
|
|
|
+ "strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+type BaseCalculate struct {
|
|
|
+ DataList []*data_manage.EdbDataList
|
|
|
+ Frequency string `description:"需要转换的频度"`
|
|
|
+ Formula interface{}
|
|
|
+ Calendar string `description:"公历/农历"`
|
|
|
+ MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
|
|
|
+ MoveFrequency string `description:"移动频度"`
|
|
|
+ FromFrequency string `description:"来源的频度"`
|
|
|
+ Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+type Cell struct {
|
|
|
+ Column int `description:"行"`
|
|
|
+ Row int `description:"列"`
|
|
|
+ CellInfo request.MixedTableCellDataReq `description:"对应的单元格信息"`
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
-func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTableCellDataReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
|
|
|
+func GetMixedTableCellData(mixedTableReq request.MixedTableReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
|
|
|
+ cellRelationConf := mixedTableReq.CellRelation
|
|
|
+ config := mixedTableReq.Data
|
|
|
+
|
|
|
|
|
|
cellRelationConfMap := make(map[string]request.CellRelationConf)
|
|
|
cellRelationConfList := make([]request.CellRelationConf, 0)
|
|
@@ -98,20 +126,17 @@ func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTabl
|
|
|
config[k] = row
|
|
|
}
|
|
|
|
|
|
- type BaseCalculate struct {
|
|
|
- DataList []*data_manage.EdbDataList
|
|
|
- Frequency string `description:"需要转换的频度"`
|
|
|
- Formula interface{}
|
|
|
- Calendar string `description:"公历/农历"`
|
|
|
- MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
|
|
|
- MoveFrequency string `description:"移动频度"`
|
|
|
- FromFrequency string `description:"来源的频度"`
|
|
|
- Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
edbSourceDataMap := make(map[string]map[string]float64)
|
|
|
|
|
|
+
|
|
|
+ cellKeyVal := make(map[string]float64)
|
|
|
+
|
|
|
+
|
|
|
+ calculateCellMap := make(map[string]Cell)
|
|
|
+ calculateChainList := make([]string, 0)
|
|
|
+
|
|
|
+
|
|
|
for k, row := range config {
|
|
|
for i, cell := range row {
|
|
|
switch cell.DataType {
|
|
@@ -125,6 +150,7 @@ func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTabl
|
|
|
if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
|
|
|
tmpLenData := len(dateValList)
|
|
|
if tmpLenData > 0 {
|
|
|
+ cellKeyVal[cell.Uid] = dateValList[tmpLenData-1].Value
|
|
|
cell.ShowValue = utils.FormatTableDataShowValue(dateValList[tmpLenData-1].Value)
|
|
|
}
|
|
|
}
|
|
@@ -145,11 +171,37 @@ func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTabl
|
|
|
}
|
|
|
if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
|
|
|
|
|
|
+ cellKeyVal[cell.Uid] = val
|
|
|
cell.ShowValue = utils.FormatTableDataShowValue(val)
|
|
|
}
|
|
|
}
|
|
|
+ case request.CustomTextDT:
|
|
|
+ if cell.Value == `` {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ tmpDeci, tmpErr := decimal.NewFromString(cell.Value)
|
|
|
+ if tmpErr == nil {
|
|
|
+ tmpVal, _ := tmpDeci.Float64()
|
|
|
+ cellKeyVal[cell.Uid] = tmpVal
|
|
|
+
|
|
|
+ calculateCellMap[cell.Uid] = Cell{
|
|
|
+ Column: k,
|
|
|
+ Row: i,
|
|
|
+ CellInfo: cell,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ case request.FormulateCalculateDataDT:
|
|
|
+ calculateCellMap[cell.Uid] = Cell{
|
|
|
+ Column: k,
|
|
|
+ Row: i,
|
|
|
+ CellInfo: cell,
|
|
|
+ }
|
|
|
|
|
|
- case request.InsertEdbCalculateDataDT:
|
|
|
+ calculateChainList = append(calculateChainList, cell.Uid)
|
|
|
+
|
|
|
+ case request.InsertEdbCalculateDataDT:
|
|
|
|
|
|
var cellDateTime string
|
|
|
|
|
@@ -228,6 +280,7 @@ func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTabl
|
|
|
}
|
|
|
|
|
|
val := tmpDataMap[cellDateTime]
|
|
|
+ cellKeyVal[cell.Uid] = val
|
|
|
cell.ShowValue = utils.FormatTableDataShowValue(val)
|
|
|
}
|
|
|
|
|
@@ -236,11 +289,109 @@ func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTabl
|
|
|
config[k] = row
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ if len(calculateChainList) > 0 {
|
|
|
+ for _, cellKey := range calculateChainList {
|
|
|
+
|
|
|
+ cellPosition, ok := calculateCellMap[cellKey]
|
|
|
+ if !ok {
|
|
|
+ utils.FileLog.Error("找不到单元格位置:", cellKey)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ cell := config[cellPosition.Column][cellPosition.Row]
|
|
|
+ if cell.DataType != request.FormulateCalculateDataDT {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ val, tmpErr, has := getCalculateValueByCell(calculateCellMap, cellKey, cellKeyVal)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if !has {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ cellKeyVal[cell.Uid] = val
|
|
|
+ cell.ShowValue = utils.FormatTableDataShowValue(val)
|
|
|
+ config[cellPosition.Column][cellPosition.Row] = cell
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
newMixedTableCellDataList = config
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+func getCalculateValueByCell(calculateCellMap map[string]Cell, key string, cellKeyValMap map[string]float64) (val float64, err error, has bool) {
|
|
|
+
|
|
|
+ val, ok := cellKeyValMap[key]
|
|
|
+ if ok {
|
|
|
+ has = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ cell, ok := calculateCellMap[key]
|
|
|
+ if !ok {
|
|
|
+ err = errors.New("查找单元格" + key + "的数据失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ colData := cell.CellInfo
|
|
|
+
|
|
|
+
|
|
|
+ if colData.DataType != request.FormulateCalculateDataDT {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ tagList := make([]utils.CellPosition, 0)
|
|
|
+
|
|
|
+ var relationCellList []request.RelationCell
|
|
|
+ err = json.Unmarshal([]byte(colData.Extra), &relationCellList)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, relation := range relationCellList {
|
|
|
+
|
|
|
+ tmpVal, tmpErr, _ := getCalculateValueByCell(calculateCellMap, relation.Key, cellKeyValMap)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ cellKeyValMap[relation.Key] = tmpVal
|
|
|
+
|
|
|
+ rowInt, tmpErr := strconv.Atoi(relation.Row)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ tagList = append(tagList, utils.CellPosition{
|
|
|
+ Tag: relation.Tag,
|
|
|
+ Row: rowInt,
|
|
|
+ Value: tmpVal,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ val, _, err = calculateByCellList(strings.ToUpper(colData.Value), tagList)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ has = true
|
|
|
+ cellKeyValMap[key] = val
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -499,3 +650,82 @@ func handleSystemAppointDateT(appointDay, frequency string) (date string, err er
|
|
|
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func calculateByCellList(calculateFormula string, tagList []utils.CellPosition) (calVal float64, errMsg string, err error) {
|
|
|
+ if calculateFormula == "" {
|
|
|
+ errMsg = "公式异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ calculateFormula = strings.TrimPrefix(calculateFormula, "=")
|
|
|
+ calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
|
|
|
+ calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
|
|
|
+ calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
|
|
|
+ calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
|
|
|
+ calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
|
|
|
+
|
|
|
+ rowList := make([]int, 0)
|
|
|
+ rowListMap := make(map[int][]utils.CellPosition)
|
|
|
+ for _, v := range tagList {
|
|
|
+ tmpRowList, ok := rowListMap[v.Row]
|
|
|
+ if !ok {
|
|
|
+ rowList = append(rowList, v.Row)
|
|
|
+ tmpRowList = make([]utils.CellPosition, 0)
|
|
|
+ }
|
|
|
+ tmpRowList = append(tmpRowList, v)
|
|
|
+ rowListMap[v.Row] = tmpRowList
|
|
|
+ }
|
|
|
+
|
|
|
+ sort.Ints(rowList)
|
|
|
+
|
|
|
+ list := make([]utils.CellPosition, 0)
|
|
|
+ for _, row := range rowList {
|
|
|
+ list = append(list, rowListMap[row]...)
|
|
|
+ }
|
|
|
+
|
|
|
+ formulaFormStr := utils.ReplaceFormulaByCellList(list, calculateFormula)
|
|
|
+
|
|
|
+ if formulaFormStr == `` {
|
|
|
+ errMsg = "公式异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ expression := formula.NewExpression(formulaFormStr)
|
|
|
+ calResult, err := expression.Evaluate()
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "计算失败"
|
|
|
+ err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
|
|
|
+
|
|
|
+ if strings.Contains(err.Error(), "divide by zero") {
|
|
|
+ errMsg = "分母不能为0"
|
|
|
+ err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if calResult.IsNan() {
|
|
|
+ errMsg = "计算失败"
|
|
|
+ err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calVal, err = calResult.Float64()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
|
|
|
+
|
|
|
+ return
|
|
|
+}
|