Prechádzať zdrojové kódy

fix:新增自定义分析指标

Roc 1 rok pred
rodič
commit
f07e606622

+ 1 - 1
controllers/base_from_calculate.go

@@ -560,7 +560,7 @@ func (this *CalculateController) BatchSave() {
 		}
 	}
 
-	notNeedFromEdbSourceList := []int{utils.DATA_SOURCE_CALCULATE_KSZS, utils.DATA_SOURCE_CALCULATE_CORRELATION} // 不需要传入来源指标id的 指标类型
+	notNeedFromEdbSourceList := []int{utils.DATA_SOURCE_CALCULATE_KSZS, utils.DATA_SOURCE_CALCULATE_CORRELATION, utils.DATA_SOURCE_CALCULATE_ZDYFX} // 不需要传入来源指标id的 指标类型
 	if fromEdbInfoId <= 0 && !utils.InArrayByInt(notNeedFromEdbSourceList, req.Source) {
 		br.Msg = "请选择指标"
 		return

+ 3 - 1
models/base_from_calculate.go

@@ -600,6 +600,7 @@ type EdbInfoCalculateBatchSaveReq struct {
 	MoveType         int                            `description:"移动方式:1:领先(默认),2:滞后"`
 	MoveFrequency    string                         `description:"移动频度:天/周/月/季/年"`
 	Calendar         string                         `description:"公历/农历"`
+	Data             interface{}                    `description:"数据"`
 }
 
 // EdbInfoCalculateEdbInfoIdReq 新增/编辑请求 关联的指标列表
@@ -626,7 +627,8 @@ type EdbInfoCalculateBatchEditReq struct {
 		FromTag   string `description:"指标对应标签"`
 		MoveValue int    `description:"移动的值"`
 	}
-	Calendar string `description:"公历/农历" orm:"default(公历)"`
+	Calendar string      `description:"公历/农历" orm:"default(公历)"`
+	Data     interface{} `description:"数据"`
 }
 
 // CheckFormula2 校验公式是否正常(比如说除法的分母不能为0之类的,实际上就是用预设的字段数据做一次计算)

+ 4 - 0
models/common.go

@@ -7,7 +7,9 @@ type BaseEdbInfoInterface interface {
 	Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err error, errMsg string)
 	Edit(params EditCalculateBatchParams) (err error, errMsg string)
 	Refresh(params RefreshParams) (err error, errMsg string)
+	GetSource() int
 	GetSourceName() string
+	GetEdbType() int
 }
 
 // AddCalculateBatchParams 添加的请求参
@@ -50,6 +52,8 @@ func GetBaseEdbInfoModel(source int) (baseEdbInfoModel BaseEdbInfoInterface) {
 		baseEdbInfoModel = Percentile{}
 	case utils.DATA_SOURCE_CALCULATE_ZSXY:
 		baseEdbInfoModel = ExponentialSmoothing{}
+	case utils.DATA_SOURCE_CALCULATE_ZDYFX:
+		baseEdbInfoModel = CustomAnalysis{}
 	default:
 
 	}

+ 1 - 0
models/db.go

@@ -54,6 +54,7 @@ func init() {
 		new(EdbDataInsertConfig),
 		new(EdbAdjustConf), // 数据调整的配置
 		new(BaseFromMysteelChemicalClassify),
+		new(ExcelEdbMapping), //excel与指标的关系表
 	)
 
 	// 注册期货数据 数据表

+ 6 - 1
models/edb_data_calculate_ljz.go

@@ -67,7 +67,7 @@ func (obj Ljz) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err error,
 		MinValue:         0,
 		MaxValue:         0,
 		CalculateFormula: req.Formula,
-		EdbType:          2,
+		EdbType:          obj.GetEdbType(),
 		Sort:             0,
 		MoveType:         0,
 		MoveFrequency:    "",
@@ -274,6 +274,11 @@ func (obj Ljz) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_LJZ
 }
 
+// GetEdbType 获取指标类型
+func (obj Ljz) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 func (obj Ljz) refresh(to orm.TxOrmer, edbInfoId, source int, edbInfo, fromEdbInfo *EdbInfo, edbCode, startDate string) (err error) {
 	dataTableName := GetEdbDataTableName(source)
 	edbInfoIdStr := strconv.Itoa(edbInfoId)

+ 6 - 1
models/edb_data_calculate_ljznczj.go

@@ -67,7 +67,7 @@ func (obj LjzNczj) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err er
 		MinValue:         0,
 		MaxValue:         0,
 		CalculateFormula: req.Formula,
-		EdbType:          2,
+		EdbType:          obj.GetEdbType(),
 		Sort:             0,
 		MoveType:         0,
 		MoveFrequency:    "",
@@ -274,6 +274,11 @@ func (obj LjzNczj) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_LJZNCZJ
 }
 
+// GetEdbType 获取指标类型
+func (obj LjzNczj) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 func (obj LjzNczj) refresh(to orm.TxOrmer, edbInfoId, source int, edbInfo, fromEdbInfo *EdbInfo, edbCode, startDate string) (err error) {
 	dataTableName := GetEdbDataTableName(source)
 	edbInfoIdStr := strconv.Itoa(edbInfoId)

+ 6 - 1
models/edb_data_calculate_ljzzj.go

@@ -55,7 +55,7 @@ func (obj Ljzzj) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err erro
 	edbInfo.ModifyTime = time.Now()
 	edbInfo.UniqueCode = params.UniqueCode
 	edbInfo.CalculateFormula = req.Formula
-	edbInfo.EdbType = 2
+	edbInfo.EdbType = obj.GetEdbType()
 	newEdbInfoId, tmpErr := to.Insert(edbInfo)
 	if tmpErr != nil {
 		err = tmpErr
@@ -231,6 +231,11 @@ func (obj Ljzzj) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_LJZZJ
 }
 
+// GetEdbType 获取指标类型
+func (obj Ljzzj) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 func (obj Ljzzj) refresh(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode string) (err error) {
 	dataTableName := GetEdbDataTableName(source)
 	edbInfoIdStr := strconv.Itoa(edbInfoId)

+ 6 - 1
models/edb_data_calculate_percentile.go

@@ -51,7 +51,7 @@ func (obj Percentile) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err
 	edbInfo.ModifyTime = time.Now()
 	edbInfo.UniqueCode = params.UniqueCode
 	edbInfo.CalculateFormula = req.Formula
-	edbInfo.EdbType = 2
+	edbInfo.EdbType = obj.GetEdbType()
 	newEdbInfoId, tmpErr := to.Insert(edbInfo)
 	if tmpErr != nil {
 		err = tmpErr
@@ -229,6 +229,11 @@ func (obj Percentile) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_PERCENTILE
 }
 
+// GetEdbType 获取指标类型
+func (obj Percentile) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 // PercentileConfig 百分位的配置
 type PercentileConfig struct {
 	CalculateValue int    `description:"时间长度期数"`

+ 6 - 1
models/edb_data_calculate_standard_deviation.go

@@ -50,7 +50,7 @@ func (obj StandardDeviation) Add(params AddCalculateBatchParams) (edbInfo *EdbIn
 	edbInfo.ModifyTime = time.Now()
 	edbInfo.UniqueCode = params.UniqueCode
 	edbInfo.CalculateFormula = req.Formula
-	edbInfo.EdbType = 2
+	edbInfo.EdbType = obj.GetEdbType()
 	newEdbInfoId, tmpErr := to.Insert(edbInfo)
 	if tmpErr != nil {
 		err = tmpErr
@@ -228,6 +228,11 @@ func (obj StandardDeviation) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_STANDARD_DEVIATION
 }
 
+// GetEdbType 获取指标类型
+func (obj StandardDeviation) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 func (obj StandardDeviation) refresh(to orm.TxOrmer, edbInfo, fromEdbInfo *EdbInfo, edbCode string) (err error) {
 	edbInfoId := edbInfo.EdbInfoId
 	dataTableName := GetEdbDataTableName(edbInfo.Source)

+ 278 - 0
models/edb_data_calculate_zdyfx.go

@@ -0,0 +1,278 @@
+package models
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// CustomAnalysis 自定义分析
+type CustomAnalysis struct{}
+
+// CustomAnalysisData 自定义分析的数据
+type CustomAnalysisData struct {
+	ExcelInfoId int `description:"excel的id"`
+	DateList    []string
+	DataList    []float64
+}
+
+// Add 添加
+func (obj CustomAnalysis) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err error, errMsg string) {
+	req := params.Req
+	edbCode := params.EdbCode
+
+	// 自定义分析的数据集
+	jsonByte, err := json.Marshal(req.Data)
+	if err != nil {
+		return
+	}
+	var customAnalysisData CustomAnalysisData
+	err = json.Unmarshal(jsonByte, &customAnalysisData)
+	if err != nil {
+		return
+	}
+
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+			fmt.Println(reflect.TypeOf(obj).Name(), ";Add,Err:"+err.Error())
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	edbInfo = new(EdbInfo)
+	edbInfo.Source = obj.GetSource()
+	edbInfo.SourceName = obj.GetSourceName()
+	edbInfo.EdbCode = edbCode
+	edbInfo.EdbName = req.EdbName
+	edbInfo.EdbNameSource = req.EdbName
+	edbInfo.Frequency = req.Frequency
+	edbInfo.Unit = req.Unit
+	edbInfo.ClassifyId = req.ClassifyId
+	edbInfo.SysUserId = params.SysUserId
+	edbInfo.SysUserRealName = params.SysUserRealName
+	edbInfo.CreateTime = time.Now()
+	edbInfo.ModifyTime = time.Now()
+	edbInfo.UniqueCode = params.UniqueCode
+	edbInfo.CalculateFormula = req.Formula
+	edbInfo.EdbType = 2
+	newEdbInfoId, tmpErr := to.Insert(edbInfo)
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	edbInfo.EdbInfoId = int(newEdbInfoId)
+
+	//关联关系
+	{
+		excelEdbMappingItem := new(ExcelEdbMapping)
+		excelEdbMappingItem.CreateTime = time.Now()
+		excelEdbMappingItem.ModifyTime = time.Now()
+		excelEdbMappingItem.ExcelInfoId = customAnalysisData.ExcelInfoId
+		excelEdbMappingItem.EdbInfoId = edbInfo.EdbInfoId
+		_, err = to.Insert(excelEdbMappingItem)
+		if err != nil {
+			return
+		}
+	}
+
+	//计算数据
+	err = obj.refresh(to, edbInfo, customAnalysisData.DateList, customAnalysisData.DataList)
+
+	return
+}
+
+// Edit 编辑
+func (obj CustomAnalysis) Edit(params EditCalculateBatchParams) (err error, errMsg string) {
+	req := params.Req
+	edbInfo := params.EdbInfo
+
+	// 自定义分析的数据集
+	jsonByte, err := json.Marshal(req.Data)
+	if err != nil {
+		return
+	}
+	var customAnalysisData CustomAnalysisData
+	err = json.Unmarshal(jsonByte, &customAnalysisData)
+	if err != nil {
+		return
+	}
+
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+			fmt.Println(reflect.TypeOf(obj).Name(), ";Edit,Err:"+err.Error())
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	edbInfo.EdbName = req.EdbName
+	edbInfo.EdbNameSource = req.EdbName
+	edbInfo.Frequency = req.Frequency
+	edbInfo.Unit = req.Unit
+	edbInfo.ClassifyId = req.ClassifyId
+	edbInfo.CalculateFormula = req.Formula
+	edbInfo.ModifyTime = time.Now()
+	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime")
+	if err != nil {
+		return
+	}
+
+	// 只有excel的id有传递,同时有数据的情况下,才去做处理
+	if customAnalysisData.ExcelInfoId > 0 && len(customAnalysisData.DateList) > 0 && len(customAnalysisData.DataList) > 0 {
+		//判断计算指标是否被更换
+		excelEdbMapping, tmpErr := GetExcelEdbMappingByEdbInfoId(edbInfo.EdbInfoId)
+		if tmpErr != nil {
+			err = errors.New("获取excel与指标的关系失败,Err:" + tmpErr.Error())
+			return
+		}
+		if excelEdbMapping.ExcelInfoId != customAnalysisData.ExcelInfoId {
+			errMsg = `excel与指标关系异常`
+			err = errors.New(errMsg)
+			return
+		}
+
+		//计算数据
+		err = obj.refresh(to, edbInfo, customAnalysisData.DateList, customAnalysisData.DataList)
+	}
+
+	return
+}
+
+// Refresh 刷新
+func (obj CustomAnalysis) Refresh(params RefreshParams) (err error, errMsg string) {
+
+	return
+}
+
+// GetSource 获取来源编码id
+func (obj CustomAnalysis) GetSource() int {
+	return utils.DATA_SOURCE_CALCULATE_ZDYFX
+}
+
+// GetSourceName 获取来源名称
+func (obj CustomAnalysis) GetSourceName() string {
+	return utils.DATA_SOURCE_NAME_CALCULATE_ZDYFX
+}
+
+// GetEdbType 获取指标类型
+func (obj CustomAnalysis) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
+func (obj CustomAnalysis) refresh(to orm.TxOrmer, edbInfo *EdbInfo, dateList []string, dataList []float64) (err error) {
+	edbInfoId := edbInfo.EdbInfoId
+	dataTableName := GetEdbDataTableName(edbInfo.Source)
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+	if len(dateList) != len(dataList) {
+		err = errors.New("数据集与日期集不匹配")
+		return
+	}
+
+	//获取指标所有数据
+	existDataList := make([]*EdbData, 0)
+	sql := `SELECT * FROM %s WHERE edb_info_id=? `
+	sql = fmt.Sprintf(sql, dataTableName)
+	_, err = to.Raw(sql, edbInfoId).QueryRows(&existDataList)
+	if err != nil {
+		return err
+	}
+	existDataMap := make(map[string]string)
+	removeDataTimeMap := make(map[string]int) //需要移除的日期数据
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v.Value
+		removeDataTimeMap[v.DataTime] = 1
+	}
+	needAddDateMap := make(map[time.Time]int)
+
+	addSql := ` INSERT INTO ` + dataTableName + `(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+
+	for i, currDateStr := range dateList {
+		currVal := dataList[i] // 当前日期对应的值
+
+		currTime, tmpErr := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 当前的实际值
+		saveValue := decimal.NewFromFloat(currVal).Round(4).String()
+
+		existVal, ok := existDataMap[currDateStr]
+		// 如果库中已经存在该数据的话,那么就进行值的变更操作
+		if ok {
+			//校验待删除日期数据里面是否存在该元素,如果存在的话,那么移除该日期
+			delete(removeDataTimeMap, currDateStr)
+
+			if existVal != saveValue {
+				sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+				sql = fmt.Sprintf(sql, dataTableName)
+				_, err = to.Raw(sql, saveValue, edbInfoId, currDateStr).Exec()
+				if err != nil {
+					return
+				}
+			}
+
+			continue
+		}
+
+		// 库中不存在该日期的数据
+		timestamp := currTime.UnixNano() / 1e6
+		timeStr := fmt.Sprintf("%d", timestamp)
+		if _, existOk := needAddDateMap[currTime]; !existOk {
+			addSql += GetAddSql(edbInfoIdStr, edbInfo.EdbCode, currDateStr, timeStr, saveValue)
+			isAdd = true
+		}
+		needAddDateMap[currTime] = 1
+	}
+
+	//删除已经不存在的指标数据(由于该指标当日的数据删除了)
+	{
+		removeDateList := make([]string, 0)
+		for dateTime := range removeDataTimeMap {
+			removeDateList = append(removeDateList, dateTime)
+		}
+		removeNum := len(removeDateList)
+		if removeNum > 0 {
+			sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (`+utils.GetOrmInReplace(removeNum)+`) `, dataTableName)
+			_, err = to.Raw(sql, edbInfo.EdbInfoId, removeDateList).Exec()
+			if err != nil {
+				fmt.Println(reflect.TypeOf(obj).Name(), " add data ;delete Err", err.Error())
+				err = fmt.Errorf("删除不存在的指标数据失败,Err:" + err.Error())
+				return
+			}
+		}
+	}
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = to.Raw(addSql).Exec()
+		if err != nil {
+			fmt.Println(reflect.TypeOf(obj).Name(), " add data Err", err.Error())
+			return
+		}
+	}
+	return
+}

+ 6 - 1
models/edb_data_calculate_zsxy.go

@@ -49,7 +49,7 @@ func (obj ExponentialSmoothing) Add(params AddCalculateBatchParams) (edbInfo *Ed
 	edbInfo.ModifyTime = time.Now()
 	edbInfo.UniqueCode = params.UniqueCode
 	edbInfo.CalculateFormula = req.Formula
-	edbInfo.EdbType = 2
+	edbInfo.EdbType = obj.GetEdbType()
 	newEdbInfoId, tmpErr := to.Insert(edbInfo)
 	if tmpErr != nil {
 		err = tmpErr
@@ -226,6 +226,11 @@ func (obj ExponentialSmoothing) GetSourceName() string {
 	return utils.DATA_SOURCE_NAME_CALCULATE_ZSXY
 }
 
+// GetEdbType 获取指标类型
+func (obj ExponentialSmoothing) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}
+
 func (obj ExponentialSmoothing) refresh(to orm.TxOrmer, edbInfo, fromEdbInfo *EdbInfo, edbCode string) (err error) {
 	edbInfoId := edbInfo.EdbInfoId
 	dataTableName := GetEdbDataTableName(edbInfo.Source)

+ 2 - 0
models/edb_data_table.go

@@ -149,6 +149,8 @@ func GetEdbDataTableName(source int) (tableName string) {
 		tableName = "edb_data_calculate_zsxy" // 指数修匀->72
 	case utils.DATA_SOURCE_PREDICT_CALCULATE_ZSXY:
 		tableName = "edb_data_predict_calculate_zsxy" // 预测指数修匀->73
+	case utils.DATA_SOURCE_CALCULATE_ZDYFX:
+		tableName = "edb_data_calculate_zdyfx" // 自定义分析->74
 	default:
 		tableName = ""
 	}

+ 38 - 0
models/excel_edb_mapping.go

@@ -0,0 +1,38 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ExcelEdbMapping excel与指标的关系表
+type ExcelEdbMapping struct {
+	ExcelEdbMappingId int       `orm:"column(excel_edb_mapping_id);pk"`
+	ExcelInfoId       int       `description:"excel的id"`
+	EdbInfoId         int       `description:"计算指标id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+}
+
+// AddExcelEdbMappingMulti 批量添加excel与指标的关系
+func AddExcelEdbMappingMulti(items []*ExcelEdbMapping) (err error) {
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+// Add 添加excel与指标的关系
+func (e *ExcelEdbMapping) Add() (err error) {
+	o := orm.NewOrm()
+	_, err = o.Insert(e)
+	return
+}
+
+// GetExcelEdbMappingByEdbInfoId 根据指标id获取配置关系
+func GetExcelEdbMappingByEdbInfoId(edbInfoId int) (item *ExcelEdbMapping, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT *  FROM excel_edb_mapping WHERE 1=1 AND edb_info_id = ? `
+
+	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	return
+}

+ 8 - 0
utils/constants.go

@@ -94,6 +94,7 @@ const (
 	DATA_SOURCE_FUBAO                                           //富宝数据->71
 	DATA_SOURCE_CALCULATE_ZSXY                                  // 指数修匀->72
 	DATA_SOURCE_PREDICT_CALCULATE_ZSXY                          // 预测指数修匀->73
+	DATA_SOURCE_CALCULATE_ZDYFX                                 // 自定义分析->74
 )
 
 // 指标来源的中文展示
@@ -171,6 +172,7 @@ const (
 	DATA_SOURCE_NAME_FUBAO                                = `富宝数据`              //富宝数据->71
 	DATA_SOURCE_NAME_CALCULATE_ZSXY                       = `指数修匀`              //指数修匀->72
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_ZSXY               = `预测指数修匀`            //预测指数修匀->73
+	DATA_SOURCE_NAME_CALCULATE_ZDYFX                      = `自定义分析`             //自定义分析->74
 )
 
 // 基础数据初始化日期
@@ -233,3 +235,9 @@ var FrequencyDaysMap = map[string]int{
 var (
 	HZ_TRIAL_BUSSINESS_CODE = "E2023080700" //商家试用平台
 )
+
+// 指标类型:1:基础指标,2:计算指标
+const (
+	DEFAULT_EDB_TYPE   = 1 //基础指标
+	CALCULATE_EDB_TYPE = 2 //计算指标
+)