浏览代码

Merge remote-tracking branch 'origin/11.3' into debug

Roc 2 年之前
父节点
当前提交
be4ee83028

+ 95 - 0
models/data_manage/predict_edb_conf_calculate_mapping.go

@@ -0,0 +1,95 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_chart_lib/utils"
+	"time"
+)
+
+// PredictEdbConfCalculateMapping 预测基础指标规则 与 计算预测指标关联关系表
+type PredictEdbConfCalculateMapping struct {
+	PredictEdbConfCalculateMappingId int       `orm:"column(predict_edb_conf_calculate_mapping_id);pk"`
+	EdbInfoId                        int       `description:"指标id"`
+	ConfigId                         int       `description:"配置id"`
+	FromEdbInfoId                    int       `description:"基础指标id"`
+	FromEdbCode                      string    `description:"基础指标编码"`
+	FromEdbName                      string    `description:"基础指标名称"`
+	FromSource                       int       `description:"基础指标来源"`
+	FromSourceName                   string    `description:"基础指标来源名称"`
+	FromTag                          string    `description:"来源指标标签"`
+	Sort                             int       `description:"计算指标名称排序"`
+	CreateTime                       time.Time `description:"创建时间"`
+	ModifyTime                       time.Time `description:"修改时间"`
+}
+
+// GetPredictEdbConfCalculateMappingListById 根据预测指标id获取预测指标配置的关联指标信息列表
+func GetPredictEdbConfCalculateMappingListById(edbInfoId int) (items []*PredictEdbConf, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM predict_edb_conf_calculate_mapping WHERE edb_info_id=? ORDER BY predict_edb_conf_calculate_mapping_id ASC`
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}
+
+// GetPredictEdbConfCalculateMappingListByConfigId 根据预测指标配置id获取预测指标配置的关联指标信息列表
+func GetPredictEdbConfCalculateMappingListByConfigId(edbInfoId, configId int) (items []*PredictEdbConf, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM predict_edb_conf_calculate_mapping WHERE edb_info_id=? AND config_id=? ORDER BY predict_edb_conf_calculate_mapping_id ASC`
+	_, err = o.Raw(sql, edbInfoId, configId).QueryRows(&items)
+	return
+}
+
+type PredictEdbConfCalculateMappingDetail struct {
+	PredictEdbConfCalculateMappingId int       `orm:"column(predict_edb_conf_calculate_mapping_id);pk"`
+	EdbInfoId                        int       `description:"指标id"`
+	ConfigId                         int       `description:"配置id"`
+	FromEdbInfoId                    int       `description:"基础指标id"`
+	FromEdbCode                      string    `description:"基础指标编码"`
+	FromEdbName                      string    `description:"基础指标名称"`
+	FromSource                       int       `description:"基础指标来源"`
+	FromSourceName                   string    `description:"基础指标来源名称"`
+	FromTag                          string    `description:"来源指标标签"`
+	Sort                             int       `description:"计算指标名称排序"`
+	CreateTime                       time.Time `description:"创建时间"`
+	ModifyTime                       time.Time `description:"修改时间"`
+	StartDate                        string    `description:"开始日期"`
+	EndDate                          string    `description:"结束日期"`
+	EdbType                          int       `description:"指标类型:1:基础指标,2:计算指标"`
+	EdbCode                          string    `description:"指标code"`
+}
+
+// GetPredictEdbConfCalculateMappingDetailListById 根据配置id获取 配置关联指标信息
+func GetPredictEdbConfCalculateMappingDetailListById(edbInfoId int) (list []*PredictEdbConfCalculateMappingDetail, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.predict_edb_conf_calculate_mapping_id,a.edb_info_id,a.from_edb_info_id,a.from_edb_code,a.from_source,a.from_source_name,a.sort,a.create_time,a.modify_time,a.from_tag,b.edb_name_source as from_edb_name,b.start_date,b.end_date,b.edb_type FROM predict_edb_conf_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id=? ORDER BY sort ASC `
+
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&list)
+	return
+}
+
+// GetPredictEdbConfCalculateMappingDetailListByConfigId 根据配置id和指标id获取 配置关联指标信息
+func GetPredictEdbConfCalculateMappingDetailListByConfigId(edbInfoId, configId int) (list []*PredictEdbConfCalculateMappingDetail, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.predict_edb_conf_calculate_mapping_id,a.edb_info_id,a.from_edb_info_id,a.from_edb_code,a.from_source,a.from_source_name,a.sort,a.create_time,a.modify_time,a.from_tag,b.edb_name_source as from_edb_name,b.start_date,b.end_date,b.edb_type FROM predict_edb_conf_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id=? AND a.config_id=?  ORDER BY sort ASC `
+
+	_, err = o.Raw(sql, edbInfoId, configId).QueryRows(&list)
+	return
+}
+
+// GetPredictEdbConfCalculateMappingDetailListByEdbInfoId 根据 关联指标id列表 来 获取 相关联的配置关联指标信息
+func GetPredictEdbConfCalculateMappingDetailListByEdbInfoId(fromEdbInfoIdList []int) (list []*PredictEdbConfCalculateMappingDetail, err error) {
+	num := len(fromEdbInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.predict_edb_conf_calculate_mapping_id,a.edb_info_id,a.from_edb_info_id,a.from_edb_code,a.from_source,a.from_source_name,a.sort,a.create_time,a.modify_time,a.from_tag,b.edb_name_source as from_edb_name,b.start_date,b.end_date,b.edb_type,b.edb_code FROM predict_edb_conf_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id in (` + utils.GetOrmInReplace(num) + `) GROUP BY a.edb_info_id ORDER BY sort ASC `
+
+	_, err = o.Raw(sql, fromEdbInfoIdList).QueryRows(&list)
+	return
+}

+ 36 - 0
models/data_manage/predict_edb_rule_data.go

@@ -0,0 +1,36 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// PredictEdbRuleData 预测指标,动态规则的计算数据
+type PredictEdbRuleData struct {
+	PredictEdbRuleDataId int `orm:"column(predict_edb_rule_data_id);pk"`
+	EdbInfoId            int
+	ConfigId             int
+	DataTime             string
+	Value                float64
+	CreateTime           time.Time
+	ModifyTime           time.Time
+	DataTimestamp        int64
+}
+
+// GetPredictEdbRuleDataList 根据基础预测指标id集合 获取 所有的普通指标列表数据
+func GetPredictEdbRuleDataList(edbInfoId, configId int, startDate, endDate string) (list []*PredictEdbRuleData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	var pars []interface{}
+	sql := ` SELECT * FROM predict_edb_rule_data WHERE edb_info_id = ? AND config_id = ? `
+	if startDate != "" {
+		sql += ` AND data_time>=? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		sql += ` AND data_time<=? `
+		pars = append(pars, endDate)
+	}
+	sql += ` ORDER BY data_time ASC `
+	_, err = o.Raw(sql, edbInfoId, configId, pars).QueryRows(&list)
+	return
+}

+ 1 - 1
services/data/chart_info.go

@@ -448,7 +448,7 @@ func ChartInfoRefreshV2(chartInfoId int) (err error) {
 	}
 
 	// 批量刷新
-	err = EdbInfoRefreshAllFromBase(edbIdList, false)
+	err, errmsg = EdbInfoRefreshAllFromBase(edbIdList, false)
 	if err != nil {
 		return
 	}

+ 147 - 35
services/data/edb_info.go

@@ -10,12 +10,11 @@ import (
 	"time"
 )
 
-// EdbInfoRefreshAllFromBaseV3 全部刷新指标(切换到edb_lib服务)
+// EdbInfoRefreshAllFromBase 全部刷新指标(切换到edb_lib服务)
 // @author Roc
 // @datetime 2022-09-16 11:04:44
 // @description 将原有的单个指标刷新,调整为批量多个指标刷新
-func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error) {
-	var errmsg string
+func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error, errmsg string) {
 	defer func() {
 		if err != nil {
 			fmt.Println("EdbInfoRefreshAllFromBaseV2 Err:" + err.Error() + ";errmsg:" + errmsg)
@@ -25,7 +24,7 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 	}()
 
 	// 获取关联的基础指标
-	newBaseEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr, err, errmsg := getRefreshEdbInfoListByIds(edbInfoIdList)
+	newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr, err, errmsg := getRefreshEdbInfoListByIds(edbInfoIdList)
 	if err != nil {
 		return
 	}
@@ -41,15 +40,19 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 		//开始时间
 		startDate = ``
 		if refreshAll { //刷新所有数据,用开始时间作为起始日期去刷新
-			sTime, err := time.Parse(utils.FormatDate, bv.StartDate)
-			if err != nil {
-				return err
+			sTime, tmpErr := time.Parse(utils.FormatDate, bv.StartDate)
+			if tmpErr != nil {
+				err = tmpErr
+				errmsg = err.Error()
+				return
 			}
 			startDate = sTime.Format(utils.FormatDate)
 		} else {
-			sTime, err := time.Parse(utils.FormatDate, bv.EndDate)
-			if err != nil {
-				return err
+			sTime, tmpErr := time.Parse(utils.FormatDate, bv.EndDate)
+			if tmpErr != nil {
+				err = tmpErr
+				errmsg = err.Error()
+				return
 			}
 			frequency := bv.Frequency
 			var limitDay int
@@ -69,16 +72,18 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 			}
 			startDate = sTime.AddDate(0, 0, -limitDay).Format(utils.FormatDate)
 		}
-		result, err := RefreshEdbData(bv.EdbInfoId, bv.Source, bv.EdbCode, startDate)
-		if err != nil {
+		result, tmpErr := RefreshEdbData(bv.EdbInfoId, bv.Source, bv.EdbCode, startDate)
+		if tmpErr != nil {
+			err = tmpErr
 			fmt.Println(bv.EdbInfoId, "RefreshBaseEdbData err", time.Now())
-			errmsg = "RefreshBaseEdbData Err:" + err.Error()
-			return err
+			errmsg = "RefreshBaseEdbData Err:" + tmpErr.Error()
+			return
 		}
 		if result.Ret != 200 {
 			fmt.Println(bv.EdbInfoId, "RefreshBaseEdbData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
 			errmsg = fmt.Sprint(bv.EdbInfoId, "RefreshBaseEdbData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
-			return fmt.Errorf("刷新失败, err:", errmsg)
+			err = fmt.Errorf("刷新失败, err:", errmsg)
+			return
 		}
 
 		//maxAndMinItem, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
@@ -101,7 +106,7 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 	for _, v := range calculateArr {
 		edbInfo := newCalculateMap[v]
 		if edbInfo == nil {
-			return err
+			return
 		}
 		startDate = edbInfo.StartDate
 		source := edbInfo.Source
@@ -113,9 +118,11 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 				if refreshAll { //刷新所有数据,用开始时间作为起始日期去刷新
 					startDate = edbInfo.StartDate
 				} else {
-					sTime, err := time.Parse(utils.FormatDate, edbInfo.EndDate)
-					if err != nil {
-						return err
+					sTime, tmpErr := time.Parse(utils.FormatDate, edbInfo.EndDate)
+					if tmpErr != nil {
+						err = tmpErr
+						errmsg = tmpErr.Error()
+						return
 					}
 					frequency := edbInfo.Frequency
 					var limitDay int
@@ -138,16 +145,18 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 			}
 		}
 
-		result, err := RefreshEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
-		if err != nil {
+		result, tmpErr := RefreshEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
+		if tmpErr != nil {
+			err = tmpErr
 			fmt.Println(v, "RefreshEdbCalculateData err", time.Now())
-			errmsg = "RefreshEdbCalculateData Err:" + err.Error()
-			return err
+			errmsg = "RefreshEdbCalculateData Err:" + tmpErr.Error()
+			return
 		}
 		if result.Ret != 200 {
 			fmt.Println(v, "RefreshEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
 			errmsg = fmt.Sprint(v, "RefreshEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
-			return fmt.Errorf("刷新失败")
+			err = fmt.Errorf("刷新失败")
+			return
 		}
 	}
 
@@ -155,7 +164,7 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 	for _, v := range predictCalculateArr {
 		edbInfo := newPredictCalculateMap[v]
 		if edbInfo == nil {
-			return err
+			return
 		}
 		startDate = edbInfo.StartDate
 		source := edbInfo.Source
@@ -167,9 +176,11 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 				if refreshAll { //刷新所有数据,用开始时间作为起始日期去刷新
 					startDate = edbInfo.StartDate
 				} else {
-					sTime, err := time.Parse(utils.FormatDate, edbInfo.EndDate)
-					if err != nil {
-						return err
+					sTime, tmpErr := time.Parse(utils.FormatDate, edbInfo.EndDate)
+					if tmpErr != nil {
+						err = tmpErr
+						errmsg = tmpErr.Error()
+						return
 					}
 					frequency := edbInfo.Frequency
 					var limitDay int
@@ -192,23 +203,114 @@ func EdbInfoRefreshAllFromBase(edbInfoIdList []int, refreshAll bool) (err error)
 			}
 		}
 
-		result, err := RefreshPredictEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
-		if err != nil {
+		result, tmpErr := RefreshPredictEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
+		if tmpErr != nil {
+			err = tmpErr
+			fmt.Println(v, "RefreshPredictEdbCalculateData err", time.Now())
+			errmsg = "RefreshPredictEdbCalculateData Err:" + tmpErr.Error()
+			return
+		}
+		if result.Ret != 200 {
+			fmt.Println(v, "RefreshPredictEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
+			errmsg = fmt.Sprint(v, "RefreshPredictEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
+			err = fmt.Errorf("刷新失败")
+			return
+		}
+	}
+
+	// 4、更新动态环差值
+	{
+		predictEdbInfoIdList := make([]int, 0)
+		for _, v := range newBasePredictEdbInfoArr {
+			predictEdbInfoIdList = append(predictEdbInfoIdList, v.EdbInfoId)
+		}
+		fmt.Println("predictEdbConfCalculateMappingDetailList:", predictEdbInfoIdList)
+		predictEdbConfCalculateMappingDetailList, tmpErr := data_manage.GetPredictEdbConfCalculateMappingDetailListByEdbInfoId(predictEdbInfoIdList)
+		if tmpErr != nil {
+			err = tmpErr
+			errmsg = fmt.Sprint("更新动态环差值时,获取数据失败:" + err.Error())
+			return
+		}
+		for _, bv := range predictEdbConfCalculateMappingDetailList {
+			result, tmpErr := RefreshEdbData(bv.EdbInfoId, utils.DATA_SOURCE_PREDICT, bv.EdbCode, "")
+			if tmpErr != nil {
+				err = tmpErr
+				fmt.Println(bv.EdbInfoId, "RefreshBasePredictEdbData err", time.Now())
+				errmsg = "RefreshBasePredictEdbData Err:" + err.Error()
+				return
+			}
+			if result.Ret != 200 {
+				fmt.Println(bv.EdbInfoId, "RefreshBasePredictEdbData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
+				errmsg = fmt.Sprint(bv.EdbInfoId, "RefreshBasePredictEdbData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
+				err = errors.New("刷新失败:" + errmsg)
+				return
+			}
+			fmt.Println("end predictEdbConfCalculateMappingDetailList:", bv, time.Now())
+		}
+	}
+
+	//5、刷新相关预测计算指标
+	for _, v := range predictCalculateArr {
+		edbInfo := newPredictCalculateMap[v]
+		if edbInfo == nil {
+			return
+		}
+		startDate = edbInfo.StartDate
+		source := edbInfo.Source
+		if startDate == "" || startDate == "0000-00-00" { //如果没有开始日期,说明还没有计算出来数据,那么就往前面推40年吧(也意味着重新计算了)
+			startDate = time.Now().AddDate(-40, 0, 0).Format(utils.FormatDate)
+		} else {
+			if source == utils.DATA_SOURCE_PREDICT_CALCULATE {
+				startDate = ``
+				if refreshAll { //刷新所有数据,用开始时间作为起始日期去刷新
+					startDate = edbInfo.StartDate
+				} else {
+					sTime, tmpErr := time.Parse(utils.FormatDate, edbInfo.EndDate)
+					if tmpErr != nil {
+						err = tmpErr
+						errmsg = tmpErr.Error()
+						return
+					}
+					frequency := edbInfo.Frequency
+					var limitDay int
+					switch frequency {
+					case "日度":
+						limitDay = utils.DATA_REFRESH
+					case "周度":
+						limitDay = utils.DATA_REFRESH * 7
+					case "月度":
+						limitDay = utils.DATA_REFRESH * 30
+					case "季度":
+						limitDay = utils.DATA_REFRESH * 90
+					case "年度":
+						limitDay = utils.DATA_REFRESH * 365
+					default:
+						limitDay = utils.DATA_REFRESH
+					}
+					startDate = sTime.AddDate(0, 0, -limitDay).Format(utils.FormatDate)
+				}
+			}
+		}
+
+		result, tmpErr := RefreshPredictEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
+		if tmpErr != nil {
+			err = tmpErr
 			fmt.Println(v, "RefreshPredictEdbCalculateData err", time.Now())
-			errmsg = "RefreshPredictEdbCalculateData Err:" + err.Error()
-			return err
+			errmsg = "RefreshPredictEdbCalculateData Err:" + tmpErr.Error()
+			return
 		}
 		if result.Ret != 200 {
 			fmt.Println(v, "RefreshPredictEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
 			errmsg = fmt.Sprint(v, "RefreshPredictEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
-			return fmt.Errorf("刷新失败")
+			err = fmt.Errorf("刷新失败")
+			return
 		}
 	}
-	return err
+	return
 }
 
 // getRefreshEdbInfoList 获取待更新的指标(普通基础指标、普通运算指标,预测运算指标)
-func getRefreshEdbInfoListByIds(edbInfoIdList []int) (newBaseEdbInfoArr []*data_manage.EdbInfo, newCalculateMap, newPredictCalculateMap map[int]*data_manage.EdbInfo, calculateArr, predictCalculateArr []int, err error, errMsg string) {
+func getRefreshEdbInfoListByIds(edbInfoIdList []int) (newBaseEdbInfoArr, newBasePredictEdbInfoArr []*data_manage.EdbInfo, newCalculateMap, newPredictCalculateMap map[int]*data_manage.EdbInfo, calculateArr, predictCalculateArr []int, err error, errMsg string) {
 	calculateList, err := data_manage.GetEdbInfoAllCalculateByEdbInfoIdList(edbInfoIdList)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		err = errors.New("GetEdbInfoAllCalculate Err:" + err.Error())
@@ -436,6 +538,16 @@ func getRefreshEdbInfoListByIds(edbInfoIdList []int) (newBaseEdbInfoArr []*data_
 	// 普通计算指标的id
 	sort.Ints(calculateArr)
 
+	// 普通预测指标去重
+	newBasePredictEdbInfoArr = make([]*data_manage.EdbInfo, 0)
+	basePredictMap := make(map[int]int)
+	for _, v := range basePredictEdbInfoArr {
+		if _, ok := basePredictMap[v.EdbInfoId]; !ok {
+			newBasePredictEdbInfoArr = append(newBasePredictEdbInfoArr, v)
+		}
+		basePredictMap[v.EdbInfoId] = v.EdbInfoId
+	}
+
 	// 预测计算指标去重
 	newPredictCalculateMap = make(map[int]*data_manage.EdbInfo)
 	for _, v := range predictCalculateInfoArr {

+ 2 - 0
services/data/predict_edb_info.go

@@ -308,6 +308,8 @@ func GetChartPredictEdbInfoDataListByConfList(predictEdbConfList []*data_manage.
 				return
 			}
 			predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleNLinearRegression(predictEdbConf.PredictEdbInfoId, nValue, startDate, dataEndTime, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
+		case 9: //9:动态环差”预测规则;
+			predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleTrendsHC(predictEdbConf.PredictEdbInfoId, predictEdbConf.ConfigId, startDate, dataEndTime, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
 		}
 		//startDate = dataEndTime.AddDate(0, 0, 1)
 		startDate = dataEndTime

+ 73 - 0
services/data/predict_edb_info_rule.go

@@ -3,6 +3,7 @@ package data
 import (
 	"github.com/shopspring/decimal"
 	"hongze/hongze_chart_lib/models"
+	"hongze/hongze_chart_lib/models/data_manage"
 	"hongze/hongze_chart_lib/utils"
 	"time"
 )
@@ -581,3 +582,75 @@ func getLinearResult(s []Coordinate) (gradient, intercept float64) {
 
 	return
 }
+
+//	GetChartPredictEdbInfoDataListByRuleTrendsHC 根据动态环比增加值的计算规则获取预测数据
+// 研究员有对预测指标进行动态环差计算的需求,即预测指标使用环差规则进行预测时,环比增加值不是固定值,而是由几个预测指标计算得出的动态变化的值;
+//需求说明:
+//1、增加“动态环差”预测规则;
+//2、环比增加值在弹窗设置;
+//3、动态环差预测举例:
+//指标A实际最新数据为2022-10-27(100);
+//预测指标B预测数据为2022-10-28(240)、2022-10-29(300);
+//预测指标C预测数据为2022-10-28(260)、2022-10-29(310);
+//计算公式为B-C;
+//则指标A至2022-10-29的预测值为2022-10-28(100+(240-260)=80)、2022-10-29(80+(300-310)=90);
+//注:动态环比增加值的计算遵从计算指标的计算规则,即用于计算的指标若有部分指标缺少部分日期数据,则这部分日期数据不做计算,为空;若动态环比增加值某一天为空,则往前追溯最近一期有值的环比增加值作为该天的数值参与计算;
+func GetChartPredictEdbInfoDataListByRuleTrendsHC(edbInfoId, configId int, startDate, endDate time.Time, frequency string, realPredictEdbInfoData, predictEdbInfoData []*models.EdbDataList, existMap map[string]float64) (newPredictEdbInfoData []*models.EdbDataList, minValue, maxValue float64) {
+	allDataList := make([]*models.EdbDataList, 0)
+	allDataList = append(allDataList, realPredictEdbInfoData...)
+	allDataList = append(allDataList, predictEdbInfoData...)
+	newPredictEdbInfoData = predictEdbInfoData
+
+	lenAllData := len(allDataList)
+	if lenAllData <= 0 {
+		return
+	}
+
+	hcDataMap := make(map[string]float64) //规则计算的环差值map
+
+	//已经生成的动态数据
+	tmpPredictEdbRuleDataList, err := data_manage.GetPredictEdbRuleDataList(edbInfoId, configId, startDate.Format(utils.FormatDate), endDate.Format(utils.FormatDate))
+	if err != nil {
+		return
+	}
+	for _, v := range tmpPredictEdbRuleDataList {
+		hcDataMap[v.DataTime] = v.Value
+	}
+	dayList := getPredictEdbDayList(startDate, endDate, frequency)
+	for k, currentDate := range dayList {
+		// 最近一条数据
+		tmpLenAllDataList := len(allDataList)
+		lastValue := allDataList[tmpLenAllDataList-1].Value
+
+		// 动态环差值数据
+		currentDateStr := currentDate.Format(utils.FormatDate)
+		hcVal, ok := hcDataMap[currentDateStr]
+		if !ok {
+			continue
+		}
+		lastValueDecimal := decimal.NewFromFloat(lastValue)
+		hcValDecimal := decimal.NewFromFloat(hcVal)
+
+		val, _ := lastValueDecimal.Add(hcValDecimal).RoundCeil(4).Float64()
+
+		tmpData := &models.EdbDataList{
+			EdbDataId:     edbInfoId + 10000000000 + lenAllData + k,
+			EdbInfoId:     edbInfoId,
+			DataTime:      currentDateStr,
+			Value:         val,
+			DataTimestamp: (currentDate.UnixNano() / 1e6) + 1000, //前端需要让加1s,说是2022-09-01 00:00:00 这样的整点不合适
+		}
+		newPredictEdbInfoData = append(newPredictEdbInfoData, tmpData)
+		allDataList = append(allDataList, tmpData)
+		existMap[currentDateStr] = val
+
+		// 最大最小值
+		if val < minValue {
+			minValue = val
+		}
+		if val > maxValue {
+			maxValue = val
+		}
+	}
+	return
+}