Browse Source

预测指标变频

xiexiaoyuan 2 years ago
parent
commit
526d8f4add

+ 21 - 0
controllers/base_from_predict_calculate.go

@@ -597,6 +597,9 @@ func (this *PredictCalculateController) CalculateBatchSave() {
 	} else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS {
 		sourName = "预测N数值移动平均计算"
 		edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateNszydpjjs(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_BP {
+		sourName = "预测变频"
+		edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateBp(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
 	} else {
 		br.Msg = "无效计算方式"
 		br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source)
@@ -799,6 +802,24 @@ func (this *PredictCalculateController) Refresh() {
 			errMsg = "RefreshAllPredictCalculateNszydpjjs Err:" + err.Error()
 			break
 		}
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_BP: //刷新变频
+		calculateTbz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId)
+		if err != nil {
+			errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error()
+			break
+		}
+		fromEdbInfo, err := models.GetEdbInfoById(calculateTbz.FromEdbInfoId)
+		if err != nil {
+			errMsg = "GetEdbInfoById Err:" + err.Error()
+			break
+		}
+		//startDate = edbInfo.StartDate
+		endDate := time.Now().Format(utils.FormatDate)
+		latestDateStr, latestValue, err = models.RefreshAllPredictCalculateBp(edbInfoId, source, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			errMsg = "RefreshAllPredictCalculateBp Err:" + err.Error()
+			break
+		}
 	default:
 		br.Msg = "来源异常,请联系相关开发!"
 		br.ErrMsg = "来源异常,请联系相关开发"

+ 18 - 0
models/edb_data_table.go

@@ -83,6 +83,24 @@ func GetEdbDataTableName(source int) (tableName string) {
 		tableName = "edb_data_predict_calculate_nszydpjjs"
 	case utils.DATA_SOURCE_CALCULATE_ADJUST:
 		tableName = "edb_data_calculate_adjust"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZZY:
+		tableName = "edb_data_predict_calculate_ljzzy"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT:
+		tableName = "edb_data_predict_calculate_time_shift"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_ZJPJ:
+		tableName = "edb_data_predict_calculate_zjpj"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZTBPJ:
+		tableName = "edb_data_predict_calculate_ljztbpj"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC:
+		tableName = "edb_data_predict_calculate_nhcc"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_CJJX:
+		tableName = "edb_data_predict_calculate_cjjx"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_HBZ:
+		tableName = "edb_data_predict_calculate_hbz"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_HCZ:
+		tableName = "edb_data_predict_calculate_hcz"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_BP:
+		tableName = "edb_data_predict_calculate_bp"
 	default:
 		tableName = ""
 	}

+ 383 - 0
models/predict_edb_data_calculate_bp.go

@@ -0,0 +1,383 @@
+package models
+
+import (
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// SavePredictCalculateBp 变频
+func SavePredictCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddPredictCalculateBp,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	if req.EdbInfoId <= 0 {
+		edbInfo = new(EdbInfo)
+	    edbInfo.EdbInfoType = 1
+		edbInfo.Source = utils.DATA_SOURCE_PREDICT_CALCULATE_BP
+		edbInfo.SourceName = "预测变频"
+		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 = sysUserId
+		edbInfo.SysUserRealName = sysUserRealName
+		edbInfo.CreateTime = time.Now()
+		edbInfo.ModifyTime = time.Now()
+		edbInfo.UniqueCode = uniqueCode
+		edbInfo.CalculateFormula = req.Formula
+		edbInfo.EdbType = 2
+		newEdbInfoId, tmpErr := to.Insert(edbInfo)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		edbInfo.EdbInfoId = int(newEdbInfoId)
+		//关联关系
+		{
+			calculateMappingItem := new(EdbInfoCalculateMapping)
+			calculateMappingItem.CreateTime = time.Now()
+			calculateMappingItem.ModifyTime = time.Now()
+			calculateMappingItem.Sort = 1
+			calculateMappingItem.EdbCode = edbCode
+			calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+			calculateMappingItem.FromSource = fromEdbInfo.Source
+			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+			calculateMappingItem.FromTag = ""
+			calculateMappingItem.Source = edbInfo.Source
+			calculateMappingItem.SourceName = edbInfo.SourceName
+			_, err = to.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+	} else {
+		edbInfo, err = GetEdbInfoById(req.EdbInfoId)
+		if err != nil {
+			return
+		}
+		//修改指标信息
+		edbInfo.EdbName = req.EdbName
+		edbInfo.EdbNameSource = req.EdbName
+		edbInfo.Frequency = req.Frequency
+		edbInfo.Unit = req.Unit
+		edbInfo.ClassifyId = req.ClassifyId
+		edbInfo.ModifyTime = time.Now()
+		_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "ModifyTime")
+		if err != nil {
+			return
+		}
+
+		//判断计算指标是否被更换
+		var existCondition string
+		var existPars []interface{}
+		existCondition += " AND edb_info_id=? AND from_edb_info_id=? "
+		existPars = append(existPars, edbInfo.EdbInfoId, req.FromEdbInfoId)
+
+		count, e := GetEdbInfoCalculateCountByCondition(existCondition, existPars)
+		if e != nil {
+			err = errors.New("判断指标是否改变失败,Err:" + e.Error())
+			return
+		}
+		if count > 0 { // 指标未被替换,无需重新计算
+			return
+		}
+
+		//删除,计算指标关联的,基础指标的关联关系
+		sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+		_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
+		if err != nil {
+			err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
+			return
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_predict_calculate_bp WHERE edb_info_id = ? `
+		_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
+		if err != nil {
+			return
+		}
+		//关联关系
+		{
+			calculateMappingItem := &EdbInfoCalculateMapping{
+				EdbInfoCalculateMappingId: 0,
+				EdbInfoId:                 edbInfo.EdbInfoId,
+				Source:                    utils.DATA_SOURCE_PREDICT_CALCULATE_BP,
+				SourceName:                "预测变频",
+				EdbCode:                   edbInfo.EdbCode,
+				FromEdbInfoId:             fromEdbInfo.EdbInfoId,
+				FromEdbCode:               fromEdbInfo.EdbCode,
+				FromEdbName:               fromEdbInfo.EdbName,
+				FromSource:                fromEdbInfo.Source,
+				FromSourceName:            fromEdbInfo.SourceName,
+				FromTag:                   "",
+				Sort:                      1,
+				CreateTime:                time.Now(),
+				ModifyTime:                time.Now(),
+			}
+			_, err = to.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	//计算数据
+	latestDateStr, latestValue, err = refreshAllPredictCalculateBp(to, edbInfo.EdbInfoId, edbInfo.Source, fromEdbInfo, edbInfo.EdbCode, "", "", 0)
+
+	return
+}
+
+func RefreshAllPredictCalculateBp(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (latestDateStr string, latestValue float64, err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllPredictCalculateBp,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 计算数据
+	latestDateStr, latestValue, err = refreshAllPredictCalculateBp(to, edbInfoId, source, fromEdbInfo, edbCode, startDate, endDate, 1)
+	return
+}
+
+// refreshAllPredictCalculateBp 刷新变频数据
+func refreshAllPredictCalculateBp(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string, order int) (latestDateStr string, latestValue float64, err error) {
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	// 获取关联指标数据
+	dataList, err := GetPredictEdbDataListAllByStartDate(fromEdbInfo, order, "")
+	if err != nil {
+		return
+	}
+	latestDateStr = fromEdbInfo.LatestDate
+
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	fromDataMap := make(map[string]float64)
+	//来源指指标数据
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+		fromDataMap[v.DataTime] = v.Value
+	}
+	fmt.Println("source:", source)
+
+	//获取变频指标所有数据
+	existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source)
+	if err != nil {
+		return
+	}
+	//计算指标的map
+	existDataMap := make(map[string]*EdbData, 0)
+
+	addSql := ` INSERT INTO edb_data_predict_calculate_bp(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+
+	var lastValue float64   //最后数据的值(float64)
+	var lastValueStr string //最后数据的值(string)
+	//待删除的日期
+	removeDateList := make([]string, 0)
+	if len(existDataList) > 0 {
+		//第一个已经入库的日期
+		firstExistDataTimeStr := existDataList[0].DataTime //计算指标数据第一条的日期字符串
+		if len(dateArr) > 0 {
+			firstFromDataTimeStr := dateArr[0]                                                             //来源数据第一条的日期字符串
+			firstExistDataTime, _ := time.Parse(utils.FormatDate, firstExistDataTimeStr)                   //计算指标数据第一条的日期(time类型)
+			firstFromDataTime, _ := time.Parse(utils.FormatDate, firstFromDataTimeStr)                     //来源数据第一条的日期(time类型)
+			nowDateStr := time.Now().Format(utils.FormatDate)                                              //当天日期字符串
+			nowDate, _ := time.ParseInLocation(utils.FormatDate, nowDateStr, firstFromDataTime.Location()) //当天日期(time类型)
+
+			lastValue = fromDataMap[firstFromDataTimeStr]
+			lastValueStr = decimal.NewFromFloat(lastValue).String()
+			//第一步: 判断来源指标的开始时间与计算指标的开始时间是否相等,相等的话,那么就不需要对两个时间之间的数据做处理
+			if firstExistDataTimeStr != firstFromDataTimeStr {
+				if firstExistDataTime.Before(firstFromDataTime) { //如果计算指标第一条数据的开始时间 早于 来源指标的第一条开始时间,那么需要对两个时间之间的计算指标数据做 删除处理
+					for _, v := range existDataList {
+						if v.DataTime == firstFromDataTimeStr {
+							if tmpLastValue, ok := fromDataMap[firstFromDataTimeStr]; ok { //来源指标当天的数据
+								lastValue = tmpLastValue
+								lastValueStr = decimal.NewFromFloat(lastValue).String()
+							}
+							break
+						}
+						removeDateList = append(removeDateList, v.DataTime)
+					}
+				} else {
+					for _, v := range dateArr { //如果计算指标第一条数据的开始时间 晚于 来源指标的第一条开始时间,那么需要对两个时间之间的计算指标数据做 新增处理
+						vDataTime, _ := time.Parse(utils.FormatDate, v) //当前日期(time类型)
+						if firstExistDataTime.Equal(vDataTime) || firstExistDataTime.Before(vDataTime) {
+							if tmpLastValue, ok := fromDataMap[v]; ok { //来源指标当天的数据
+								lastValue = tmpLastValue
+								lastValueStr = decimal.NewFromFloat(lastValue).String()
+							}
+							break
+						}
+
+						currentDate, _ := time.Parse(utils.FormatDate, v)
+						timestamp := currentDate.UnixNano() / 1e6
+						timestampStr := fmt.Sprintf("%d", timestamp)
+						addSql += GetAddSql(edbInfoIdStr, edbCode, v, timestampStr, lastValueStr)
+						// 实际数据的值
+						if fromEdbInfo.LatestDate == v {
+							latestValue = lastValue
+						}
+						isAdd = true
+					}
+				}
+			}
+
+			//第二步 剩余数据每天修改
+
+			day := int(nowDate.Sub(firstExistDataTime).Hours() / float64(24))
+
+			//第三步: 已经入库的数据处理
+			for _, v := range existDataList {
+				existDataMap[v.DataTime] = v
+			}
+
+			for k := day; k >= 0; k-- {
+				needDay := nowDate.AddDate(0, 0, -k)
+				needDayStr := needDay.Format(utils.FormatDate)
+				tmpExistData, ok := existDataMap[needDayStr]
+				if ok {
+					if tmpLastValue, ok := fromDataMap[tmpExistData.DataTime]; ok { //来源指标当天的数据
+						lastValue = tmpLastValue
+						//lastValueStr = decimal.NewFromFloat(lastValue).String()
+						lastValueStr = fmt.Sprintf("%.4f", lastValue)
+					}
+					if fromEdbInfo.LatestDate == tmpExistData.DataTime {
+						latestValue = lastValue
+					}
+					//如果对应的值不匹配
+					if tmpExistData.Value != lastValueStr {
+						err = ModifyEdbDataById(source, tmpExistData.EdbDataId, lastValueStr)
+						if err != nil {
+							return
+						}
+					}
+				} else {
+					timestamp := needDay.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					addSql += GetAddSql(edbInfoIdStr, edbCode, needDayStr, timestampStr, lastValueStr)
+					if fromEdbInfo.LatestDate == needDayStr {
+						latestValue = lastValue
+					}
+					isAdd = true
+				}
+			}
+		} else {
+			//如果没有来源指标数据,那么已经入库的计算指标数据需要全部删除
+			tableName := GetEdbDataTableName(source)
+			sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ?`, tableName)
+			_, err = to.Raw(sql, edbInfoId).Exec()
+			if err != nil {
+				err = fmt.Errorf("删除所有的变频指标数据失败,Err:" + err.Error())
+				return
+			}
+
+			//for _, v := range existDataList {
+			//	removeDateList = append(removeDateList, v.DataTime)
+			//}
+		}
+	} else {
+		existMap := make(map[string]string)
+		dataLen := len(dataList)
+
+		for i := 0; i < dataLen; i++ {
+			//当期
+			currentItem := dataList[i]
+			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+			var day int
+			var preItem *EdbInfoSearchData
+			var preDate time.Time
+			if i == 0 {
+				day = int(time.Now().Sub(currentDate).Hours() / float64(24))
+				preDate = time.Now()
+			} else {
+				j := i - 1
+				if j < dataLen {
+					preItem = dataList[j]
+					preDate, _ = time.Parse(utils.FormatDate, preItem.DataTime)
+					day = int(preDate.Sub(currentDate).Hours() / float64(24))
+					utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime + ";currentItem.DataTime" + currentItem.DataTime)
+				}
+			}
+			for k := 0; k <= day; k++ {
+				needDay := preDate.AddDate(0, 0, -k)
+				needDayStr := needDay.Format(utils.FormatDate)
+				existKey := edbCode + needDayStr
+				if _, ok := existMap[existKey]; !ok {
+					timestamp := needDay.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					valStr := decimal.NewFromFloat(currentItem.Value).String()
+					addSql += GetAddSql(edbInfoIdStr, edbCode, needDayStr, timestampStr, valStr)
+					if fromEdbInfo.LatestDate == needDayStr {
+						latestValue = currentItem.Value
+					}
+					isAdd = true
+				}
+				existMap[existKey] = needDayStr
+			}
+			existKey := edbCode + currentItem.DataTime
+			if _, ok := existMap[existKey]; !ok {
+				currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+				timestamp := currentDate.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				valStr := decimal.NewFromFloat(currentItem.Value).String()
+				addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, valStr)
+				if fromEdbInfo.LatestDate == currentItem.DataTime {
+					latestValue = currentItem.Value
+				}
+				isAdd = true
+			}
+			existMap[existKey] = currentItem.DataTime
+		}
+	}
+
+	// 删除不需要的指标数据
+	if len(removeDateList) > 0 {
+		removeDateStr := strings.Join(removeDateList, `","`)
+		removeDateStr = `"` + removeDateStr + `"`
+		//如果拼接指标变更了,那么需要删除所有的指标数据
+		tableName := GetEdbDataTableName(source)
+		sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
+
+		_, err = to.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			err = fmt.Errorf("删除不存在的变频指标数据失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = to.Raw(addSql).Exec()
+	}
+	return
+}

+ 10 - 1
utils/constants.go

@@ -68,7 +68,16 @@ const (
 	DATA_SOURCE_CALCULATE_NHCC                         //计算指标(拟合残差)->37
 	DATA_SOURCE_COM_TRADE                              //联合国商品贸易数据->38
 	DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS            //预测指标 - N数值移动平均计算 -> 39
-	DATA_SOURCE_CALCULATE_ADJUST                 //数据调整->40
+	DATA_SOURCE_CALCULATE_ADJUST                       //数据调整->40
+	DATA_SOURCE_PREDICT_CALCULATE_LJZZY                //预测指标 - 累计值转月->41
+	DATA_SOURCE_PREDICT_CALCULATE_HBZ                  //预测指标 - 环比值->42
+	DATA_SOURCE_PREDICT_CALCULATE_HCZ                  //预测指标 - 环差值->43
+	DATA_SOURCE_PREDICT_CALCULATE_BP                   //预测指标 - 变频->44
+	DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT           //预测指标 - 时间移位->45
+	DATA_SOURCE_PREDICT_CALCULATE_ZJPJ                 //预测指标 - 直接拼接->46
+	DATA_SOURCE_PREDICT_CALCULATE_LJZTBPJ              //预测指标 - 累计值同比拼接->47
+	DATA_SOURCE_PREDICT_CALCULATE_CJJX                 //预测指标 - 超季节性->48
+	DATA_SOURCE_PREDICT_CALCULATE_NHCC                 //预测指标 - 计算指标(拟合残差)->49
 )
 
 //基础数据初始化日期