Răsfoiți Sursa

feat:新增相关性计算的指标

Roc 2 ani în urmă
părinte
comite
686304b560
2 a modificat fișierele cu 554 adăugiri și 513 ștergeri
  1. 24 5
      controllers/base_from_calculate.go
  2. 530 508
      models/edb_data_calculate_correlation.go

+ 24 - 5
controllers/base_from_calculate.go

@@ -605,6 +605,7 @@ func (this *CalculateController) BatchSave() {
 	var sourName string
 	var edbInfoId int
 	var edbInfo *models.EdbInfo
+	var errMsg string
 	switch req.Source {
 	case utils.DATA_SOURCE_CALCULATE_LJZZY:
 		sourName = "累计值转月值"
@@ -776,7 +777,7 @@ func (this *CalculateController) BatchSave() {
 			return
 		}
 		sourName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION
-		edbInfo, err = models.AddCalculateKszs(&req, edbCode, uniqueCode, sysUserId, sysUserName)
+		edbInfo, err, errMsg = models.AddCalculateCorrelation(&req, edbCode, uniqueCode, sysUserId, sysUserName)
 	default:
 		br.Msg = "无效计算方式"
 		br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source)
@@ -784,7 +785,10 @@ func (this *CalculateController) BatchSave() {
 	}
 	if err != nil {
 		br.Msg = "生成" + sourName + "失败"
-		br.Msg = "生成" + sourName + "失败 Err:" + err.Error()
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "生成" + sourName + "失败 Err:" + err.Error()
 		return
 	}
 
@@ -817,7 +821,7 @@ func (this *CalculateController) BatchSave() {
 	}
 
 	// 更新指标最大最小值
-	err, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
+	err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -999,7 +1003,7 @@ func (this *CalculateController) BatchEdit() {
 		}
 	}
 
-	var sourName string
+	var sourName, errMsg string
 	var edbInfoId int
 
 	switch req.Source {
@@ -1153,6 +1157,16 @@ func (this *CalculateController) BatchEdit() {
 		}
 		sourName = utils.DATA_SOURCE_NAME_CALCULATE_KSZS
 		err = models.EditCalculateKszs(edbInfo, &req)
+	case utils.DATA_SOURCE_CALCULATE_CORRELATION:
+		//关联的指标信息
+		if len(req.EdbInfoIdArr) < 2 {
+			br.Msg = "指标数量不能小于2个,请重新选择"
+			br.ErrMsg = "指标数量不能小于2个,请重新选择"
+			br.IsSendEmail = false
+			return
+		}
+		sourName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION
+		err, errMsg = models.EditCalculateCorrelation(edbInfo, &req)
 	default:
 		br.Msg = "无效计算方式"
 		br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source)
@@ -1161,6 +1175,9 @@ func (this *CalculateController) BatchEdit() {
 	}
 	if err != nil {
 		br.Msg = "生成" + sourName + "失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
 		br.Msg = "生成" + sourName + "失败 Err:" + err.Error()
 		return
 	}
@@ -1193,7 +1210,7 @@ func (this *CalculateController) BatchEdit() {
 	}
 
 	// 更新指标最大最小值
-	err, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
+	err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -1567,6 +1584,8 @@ func (this *CalculateController) Refresh() {
 			errMsg = "RefreshAllCalculateKszs Err:" + err.Error()
 			break
 		}
+	case utils.DATA_SOURCE_CALCULATE_CORRELATION:
+		err, errMsg = models.RefreshAllCalculateCorrelation(edbInfo)
 	default:
 		br.Msg = "来源异常,请联系相关开发!"
 		br.ErrMsg = "来源异常,请联系相关开发"

+ 530 - 508
models/edb_data_calculate_correlation.go

@@ -1,510 +1,532 @@
 package models
 
-//
-//import (
-//	"encoding/json"
-//	"errors"
-//	"fmt"
-//	"github.com/beego/beego/v2/client/orm"
-//	"github.com/shopspring/decimal"
-//	"hongze/hongze_edb_lib/utils"
-//	"strconv"
-//	"strings"
-//	"time"
-//)
-//
-//// AddCalculateCorrelation 扩散指数
-//func AddCalculateCorrelation(req *EdbInfoCalculateBatchSaveReq, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfo *EdbInfo, err error) {
-//	o := orm.NewOrm()
-//	to, err := o.Begin()
-//	if err != nil {
-//		return
-//	}
-//	defer func() {
-//		if err != nil {
-//			fmt.Println("AddCalculateCorrelation,Err:" + err.Error())
-//			_ = to.Rollback()
-//		} else {
-//			_ = to.Commit()
-//		}
-//	}()
-//	if req.EdbInfoId > 0 {
-//		err = errors.New("无法新增")
-//		return
-//	}
-//
-//	edbInfo = new(EdbInfo)
-//	edbInfo.Source = utils.DATA_SOURCE_CALCULATE_CORRELATION
-//	edbInfo.SourceName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION
-//	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)
-//
-//	//关联关系
-//	tagMap := make(map[string]int)
-//	relationEdbInfoList := make([]*EdbInfo, 0)
-//	calculateMappingItemList := make([]*EdbInfoCalculateMapping, 0)
-//	for _, v := range req.EdbInfoIdArr {
-//		tmpEdbInfo, tmpErr := GetEdbInfoById(v.EdbInfoId)
-//		if tmpErr != nil {
-//			err = tmpErr
-//			return
-//		}
-//		relationEdbInfoList = append(relationEdbInfoList, tmpEdbInfo)
-//
-//		calculateMappingItem := new(EdbInfoCalculateMapping)
-//		calculateMappingItem.CreateTime = time.Now()
-//		calculateMappingItem.ModifyTime = time.Now()
-//		calculateMappingItem.Sort = 1
-//		calculateMappingItem.EdbCode = edbCode
-//		calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
-//		calculateMappingItem.FromEdbInfoId = tmpEdbInfo.EdbInfoId
-//		calculateMappingItem.FromEdbCode = tmpEdbInfo.EdbCode
-//		calculateMappingItem.FromEdbName = tmpEdbInfo.EdbName
-//		calculateMappingItem.FromSource = tmpEdbInfo.Source
-//		calculateMappingItem.FromSourceName = tmpEdbInfo.SourceName
-//		calculateMappingItem.FromTag = v.FromTag
-//		calculateMappingItem.Source = edbInfo.Source
-//		calculateMappingItem.SourceName = edbInfo.SourceName
-//		calculateMappingItemList = append(calculateMappingItemList, calculateMappingItem)
-//
-//		tagMap[v.FromTag] = v.EdbInfoId
-//	}
-//	_, err = to.InsertMulti(len(calculateMappingItemList), calculateMappingItemList)
-//	if err != nil {
-//		return
-//	}
-//
-//	//计算数据
-//	err = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, relationEdbInfoList, edbInfo.EdbCode, edbInfo.CalculateFormula, tagMap)
-//
-//	return
-//}
-//
-//// EditCalculateCorrelation 修改扩散指数数据
-//func EditCalculateCorrelation(edbInfo *EdbInfo, req *EdbInfoCalculateBatchEditReq) (err error) {
-//	o := orm.NewOrm()
-//	to, err := o.Begin()
-//	if err != nil {
-//		return
-//	}
-//	defer func() {
-//		if err != nil {
-//			fmt.Println("EditCalculateCorrelation,Err:" + err.Error())
-//			_ = to.Rollback()
-//		} 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
-//	}
-//
-//	//删除,计算指标关联的,基础指标的关联关系
-//	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
-//	}
-//	//清空原有数据
-//	tableName := GetEdbDataTableName(edbInfo.Source)
-//	sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
-//	_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
-//	if err != nil {
-//		return
-//	}
-//
-//	//关联关系
-//	tagMap := make(map[string]int)
-//	relationEdbInfoList := make([]*EdbInfo, 0)
-//	calculateMappingItemList := make([]*EdbInfoCalculateMapping, 0)
-//	for _, v := range req.EdbInfoIdArr {
-//		tmpEdbInfo, tmpErr := GetEdbInfoById(v.EdbInfoId)
-//		if tmpErr != nil {
-//			err = tmpErr
-//			return
-//		}
-//		relationEdbInfoList = append(relationEdbInfoList, tmpEdbInfo)
-//
-//		calculateMappingItem := new(EdbInfoCalculateMapping)
-//		calculateMappingItem.CreateTime = time.Now()
-//		calculateMappingItem.ModifyTime = time.Now()
-//		calculateMappingItem.Sort = 1
-//		calculateMappingItem.EdbCode = edbInfo.EdbCode
-//		calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
-//		calculateMappingItem.FromEdbInfoId = tmpEdbInfo.EdbInfoId
-//		calculateMappingItem.FromEdbCode = tmpEdbInfo.EdbCode
-//		calculateMappingItem.FromEdbName = tmpEdbInfo.EdbName
-//		calculateMappingItem.FromSource = tmpEdbInfo.Source
-//		calculateMappingItem.FromSourceName = tmpEdbInfo.SourceName
-//		calculateMappingItem.FromTag = v.FromTag
-//		calculateMappingItem.Source = edbInfo.Source
-//		calculateMappingItem.SourceName = edbInfo.SourceName
-//		calculateMappingItemList = append(calculateMappingItemList, calculateMappingItem)
-//
-//		tagMap[v.FromTag] = v.EdbInfoId
-//	}
-//	_, err = to.InsertMulti(len(calculateMappingItemList), calculateMappingItemList)
-//	if err != nil {
-//		return
-//	}
-//
-//	//计算数据
-//	err = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, relationEdbInfoList, edbInfo.EdbCode, edbInfo.CalculateFormula, tagMap)
-//
-//	return
-//}
-//
-//func RefreshAllCalculateCorrelation(edbInfo *EdbInfo) (err error) {
-//	edbInfoCalculateDetailList, err := GetEdbInfoCalculateDetailList(edbInfo.EdbInfoId)
-//	if err != nil {
-//		return
-//	}
-//	tagMap := make(map[string]int)
-//	relationEdbInfoList := make([]*EdbInfo, 0)
-//	for _, v := range edbInfoCalculateDetailList {
-//		tagMap[v.FromTag] = v.FromEdbInfoId
-//		fromEdbInfo, _ := GetEdbInfoById(v.FromEdbInfoId)
-//		relationEdbInfoList = append(relationEdbInfoList, fromEdbInfo)
-//	}
-//	o := orm.NewOrm()
-//	to, err := o.Begin()
-//	if err != nil {
-//		return
-//	}
-//	defer func() {
-//		if err != nil {
-//			fmt.Println("RefreshAllCalculateCorrelation,Err:" + err.Error())
-//			_ = to.Rollback()
-//		} else {
-//			_ = to.Commit()
-//		}
-//	}()
-//
-//	// 计算数据
-//	err = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, relationEdbInfoList, edbInfo.EdbCode, edbInfo.CalculateFormula, tagMap)
-//
-//	return
-//}
-//
-//// CorrelationConfig 扩散指数配置
-//type CorrelationConfig struct {
-//	DateType  int      `description:"扩散指标日期;1:全部指标日期并集;2:部分指标日期并集"`
-//	CheckList []string `description:"选中的数据,A,B,C"`
-//}
-//
-//type EdbCalculateFormula struct {
-//	BaseCalculateValue int    `description:"基础计算窗口"`
-//	BaseCalculateUnit  string `description:"基础计算频度"`
-//	LeadValue          int    `description:"领先期数"`
-//	LeadUnit           string `description:"频度"`
-//	CalculateValue     int    `description:"计算窗口"`
-//	CalculateUnit      string `description:"计算频度"`
-//}
-//
-//// refreshAllCalculateCorrelation 刷新扩散指数数据
-//func refreshAllCalculateCorrelation(to orm.TxOrmer, edbInfoId, source int, edbInfoA, edbInfoB *EdbInfo, relationEdbInfoList []*EdbInfo, edbCode, calculateFormula string, tagMap map[string]int) (err error, errMsg string) {
-//	edbInfoIdStr := strconv.Itoa(edbInfoId)
-//	tableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_CORRELATION)
-//
-//	// 获取扩散指标关联的指标id
-//	checkEdbInfoIdMap := make(map[int]int)
-//	{
-//		var config CorrelationConfig
-//		err = json.Unmarshal([]byte(calculateFormula), &config)
-//		if err != nil {
-//			return
-//		}
-//		if config.DateType == 1 {
-//			for _, tmpEdbInfoId := range tagMap {
-//				checkEdbInfoIdMap[tmpEdbInfoId] = tmpEdbInfoId
-//			}
-//		} else {
-//			for _, v := range config.CheckList {
-//				if tmpEdbInfoId, ok := tagMap[v]; ok {
-//					checkEdbInfoIdMap[tmpEdbInfoId] = tmpEdbInfoId
-//				}
-//			}
-//		}
-//	}
-//
-//	//获取扩散指数指标所有数据
-//	existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source)
-//	if err != nil {
-//		return
-//	}
-//	//计算指标的map
-//	existDataMap := make(map[string]*EdbData, 0)
-//	removeDateMap := make(map[string]string)
-//	for _, v := range existDataList {
-//		existDataMap[v.DataTime] = v
-//		removeDateMap[v.DataTime] = ``
-//	}
-//	var correlationConf EdbCalculateFormula
-//	err = json.Unmarshal([]byte(calculateFormula), &calculateFormula)
-//	if err != nil {
-//		return
-//	}
-//	frequencyDaysMap := map[string]int{
-//		"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
-//	}
-//	moveUnitDays, ok := frequencyDaysMap[correlationConf.CalculateUnit]
-//	if !ok {
-//		errMsg = `错误的分析周期`
-//		err = errors.New(errMsg)
-//		return
-//	}
-//	startDate := time.Now().AddDate(0, 0, -correlationConf.CalculateValue*moveUnitDays).Format(utils.FormatDate)
-//	endDate := time.Now().Format(utils.FormatDate)
-//	correlationChartDataMap, err := GetRollingCorrelationChartDataByEdbInfo(edbInfoA, edbInfoB, correlationConf.LeadValue, correlationConf.LeadUnit, correlationConf.CalculateValue, correlationConf.CalculateUnit, startDate, endDate)
-//
-//	addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
-//	var isAdd bool
-//
-//	for currDateStr, val := range correlationChartDataMap {
-//		currDate, tmpErr := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
-//		if tmpErr != nil {
-//			err = tmpErr
-//			return
-//		}
-//		currVal, _ := decimal.NewFromFloat(val).Round(4).Float64()
-//
-//		// 判断扩散指数指标是否存在数据
-//		if existData, ok := existDataMap[currDateStr]; ok {
-//			// 处理扩散指数数据的值
-//			existValStr := existData.Value
-//			existValDeci, tmpErr := decimal.NewFromString(existValStr)
-//			if tmpErr != nil {
-//				err = tmpErr
-//				return
-//			}
-//			existVal, _ := existValDeci.Round(4).Float64()
-//			// 判断扩散指数数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
-//			if existVal != currVal {
-//				err = ModifyEdbDataById(source, existData.EdbDataId, fmt.Sprint(currVal))
-//				if err != nil {
-//					return
-//				}
-//			}
-//		} else {
-//			// 直接入库
-//			timestamp := currDate.UnixNano() / 1e6
-//			timestampStr := fmt.Sprintf("%d", timestamp)
-//			addSql += GetAddSql(edbInfoIdStr, edbCode, currDateStr, timestampStr, fmt.Sprint(currVal))
-//			isAdd = true
-//		}
-//
-//		delete(removeDateMap, currDateStr)
-//	}
-//
-//	// 数据入库
-//	{
-//
-//		if isAdd {
-//			addSql = strings.TrimRight(addSql, ",")
-//			_, err = to.Raw(addSql).Exec()
-//		}
-//
-//		// 移除不存在的日期数据
-//		if len(removeDateMap) > 0 {
-//			removeDateList := make([]string, 0) //需要移除的日期
-//			for k := range removeDateMap {
-//				removeDateList = append(removeDateList, k)
-//			}
-//			removeDateStr := strings.Join(removeDateList, `","`)
-//			removeDateStr = `"` + removeDateStr + `"`
-//			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
-//			}
-//		}
-//	}
-//
-//	return
-//}
-//
-//// GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
-//func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *EdbInfo, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate string) (dateData map[string]float64, err error) {
-//	yData := make([]float64, 0)
-//
-//	baseEdbInfo := edbInfoMappingA
-//	changeEdbInfo := edbInfoMappingB
-//
-//	// 获取时间基准指标在时间区间内的值
-//	aDataList := make([]*EdbInfoSearchData, 0)
-//	switch baseEdbInfo.EdbInfoType {
-//	case 0:
-//		var condition string
-//		var pars []interface{}
-//		condition += " AND edb_info_id=? "
-//		pars = append(pars, baseEdbInfo.EdbInfoId)
-//
-//		//获取来源指标的数据
-//		aDataList, err = GetEdbDataListAll(condition, pars, baseEdbInfo.Source, 1)
-//	case 1:
-//		aDataList, err = GetPredictEdbDataListAllByStartDate(baseEdbInfo, 1, "")
-//	default:
-//		err = errors.New(fmt.Sprint("获取失败,指标base类型异常", baseEdbInfo.EdbInfoType))
-//	}
-//
-//	// 获取变频指标所有日期的值, 插值法完善数据
-//	bDataList := make([]*EdbInfoSearchData, 0)
-//	switch changeEdbInfo.EdbInfoType {
-//	case 0:
-//		var condition string
-//		var pars []interface{}
-//		condition += " AND edb_info_id=? "
-//		pars = append(pars, changeEdbInfo.EdbInfoId)
-//
-//		//获取来源指标的数据
-//		bDataList, err = GetEdbDataListAll(condition, pars, changeEdbInfo.Source, 1)
-//	case 1:
-//		bDataList, err = GetPredictEdbDataListAllByStartDate(changeEdbInfo, 1, "")
-//	default:
-//		err = errors.New(fmt.Sprint("获取失败,指标change类型异常", baseEdbInfo.EdbInfoType))
-//		return
-//	}
-//
-//	// 数据平移变频指标领先/滞后的日期(单位天)
-//	frequencyDaysMap := map[string]int{
-//		"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
-//	}
-//	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
-//	//baseDataList := make([]*data_manage.EdbDataList, 0)
-//	baseDataMap := make(map[string]float64)
-//	changeDataList := make([]*EdbInfoSearchData, 0)
-//	changeDataMap := make(map[string]float64)
-//
-//	// A指标不管三七二十一,先变个频再说
-//	{
-//		_, e := HandleDataByLinearRegression(aDataList, baseDataMap)
-//		if e != nil {
-//			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
-//			return
-//		}
-//		//baseDataList = tmpNewChangeDataList
-//	}
-//	// A指标不管三七二十一,先变个频再说
-//	{
-//		tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
-//		if e != nil {
-//			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
-//			return
-//		}
-//		changeDataList = tmpNewChangeDataList
-//
-//		// 平移下日期
-//		moveUnitDays := frequencyDaysMap[leadUnit]
-//		_, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
-//	}
-//
-//	// 计算计算时,需要多少个日期内数据
-//	calculateDay := frequencyDaysMap[calculateUnit] * calculateValue
-//
-//	// 计算 每个日期的相关性值
-//	{
-//		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
-//		endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
-//
-//		for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
-//			coordinateData := make([]utils.Coordinate, 0)
-//			// 取出对应的基准日期的值
-//			for i := 0; i < calculateDay; i++ {
-//				iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
-//				tmpCoordinate := utils.Coordinate{
-//					X: baseDataMap[iDay],
-//					Y: changeDataMap[iDay],
-//				}
-//				coordinateData = append(coordinateData, tmpCoordinate)
-//			}
-//
-//			// 公式计算出领先/滞后频度对应点的相关性系数
-//			var ratio float64
-//			if len(coordinateData) > 0 {
-//				ratio = utils.ComputeCorrelation(coordinateData)
-//			}
-//			yData = append(yData, ratio)
-//			dateData[currDay.AddDate(0, 0, calculateDay).Format(utils.FormatDate)] = ratio
-//		}
-//	}
-//	return
-//}
-//
-//// MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
-//func MoveDataDaysToNewDataList(dataList []*EdbInfoSearchData, moveDay int) (newDataList []EdbInfoSearchData, dateDataMap map[string]float64) {
-//	dateMap := make(map[time.Time]float64)
-//	var minDate, maxDate time.Time
-//	dateDataMap = make(map[string]float64)
-//
-//	for _, v := range dataList {
-//		currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
-//		if minDate.IsZero() || currDate.Before(minDate) {
-//			minDate = currDate
-//		}
-//		if maxDate.IsZero() || currDate.After(maxDate) {
-//			maxDate = currDate
-//		}
-//		dateMap[currDate] = v.Value
-//	}
-//
-//	// 处理领先、滞后数据
-//	newDateMap := make(map[time.Time]float64)
-//	for currDate, value := range dateMap {
-//		newDate := currDate.AddDate(0, 0, moveDay)
-//		newDateMap[newDate] = value
-//	}
-//	minDate = minDate.AddDate(0, 0, moveDay)
-//	maxDate = maxDate.AddDate(0, 0, moveDay)
-//
-//	// 获取日期相差日
-//	dayNum := utils.GetTimeSubDay(minDate, maxDate)
-//
-//	for i := 0; i <= dayNum; i++ {
-//		currDate := minDate.AddDate(0, 0, i)
-//		tmpValue, ok := newDateMap[currDate]
-//		if !ok {
-//			//找不到数据,那么就用前面的数据吧
-//			if len(newDataList)-1 < 0 {
-//				tmpValue = 0
-//			} else {
-//				tmpValue = newDataList[len(newDataList)-1].Value
-//			}
-//		}
-//		tmpData := EdbInfoSearchData{
-//			DataTime: currDate.Format(utils.FormatDate),
-//			Value:    tmpValue,
-//		}
-//		dateDataMap[tmpData.DataTime] = tmpData.Value
-//		newDataList = append(newDataList, tmpData)
-//	}
-//	return
-//}
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// AddCalculateCorrelation 扩散指数
+func AddCalculateCorrelation(req *EdbInfoCalculateBatchSaveReq, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfo *EdbInfo, err error, errMsg string) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateCorrelation,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	if req.EdbInfoId > 0 {
+		err = errors.New("无法新增")
+		return
+	}
+
+	edbInfo = new(EdbInfo)
+	edbInfo.Source = utils.DATA_SOURCE_CALCULATE_CORRELATION
+	edbInfo.SourceName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION
+	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)
+
+	var edbInfoA, edbInfoB *EdbInfo
+	//关联关系
+	calculateMappingItemList := make([]*EdbInfoCalculateMapping, 0)
+	for _, v := range req.EdbInfoIdArr {
+		tmpEdbInfo, tmpErr := GetEdbInfoById(v.EdbInfoId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		if v.FromTag == `A` {
+			edbInfoA = tmpEdbInfo
+		}
+		if v.FromTag == `B` {
+			edbInfoB = tmpEdbInfo
+		}
+
+		calculateMappingItem := new(EdbInfoCalculateMapping)
+		calculateMappingItem.CreateTime = time.Now()
+		calculateMappingItem.ModifyTime = time.Now()
+		calculateMappingItem.Sort = 1
+		calculateMappingItem.EdbCode = edbCode
+		calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+		calculateMappingItem.FromEdbInfoId = tmpEdbInfo.EdbInfoId
+		calculateMappingItem.FromEdbCode = tmpEdbInfo.EdbCode
+		calculateMappingItem.FromEdbName = tmpEdbInfo.EdbName
+		calculateMappingItem.FromSource = tmpEdbInfo.Source
+		calculateMappingItem.FromSourceName = tmpEdbInfo.SourceName
+		calculateMappingItem.FromTag = v.FromTag
+		calculateMappingItem.Source = edbInfo.Source
+		calculateMappingItem.SourceName = edbInfo.SourceName
+		calculateMappingItemList = append(calculateMappingItemList, calculateMappingItem)
+	}
+
+	if edbInfoA == nil || edbInfoB == nil {
+		errMsg = "指标异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	if edbInfoA.EdbInfoId == edbInfoB.EdbInfoId {
+		errMsg = "两个指标不允许为同一个"
+		err = errors.New(errMsg)
+		return
+	}
+
+	_, err = to.InsertMulti(len(calculateMappingItemList), calculateMappingItemList)
+	if err != nil {
+		return
+	}
+
+	//计算数据
+	err, errMsg = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfoA, edbInfoB, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+// EditCalculateCorrelation 修改扩散指数数据
+func EditCalculateCorrelation(edbInfo *EdbInfo, req *EdbInfoCalculateBatchEditReq) (err error, errMsg string) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EditCalculateCorrelation,Err:" + err.Error())
+			_ = to.Rollback()
+		} 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
+	}
+
+	//删除,计算指标关联的,基础指标的关联关系
+	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
+	}
+	//清空原有数据
+	tableName := GetEdbDataTableName(edbInfo.Source)
+	sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
+	_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	var edbInfoA, edbInfoB *EdbInfo
+	//关联关系
+	calculateMappingItemList := make([]*EdbInfoCalculateMapping, 0)
+	for _, v := range req.EdbInfoIdArr {
+		tmpEdbInfo, tmpErr := GetEdbInfoById(v.EdbInfoId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		if v.FromTag == `A` {
+			edbInfoA = tmpEdbInfo
+		}
+		if v.FromTag == `B` {
+			edbInfoB = tmpEdbInfo
+		}
+
+		calculateMappingItem := new(EdbInfoCalculateMapping)
+		calculateMappingItem.CreateTime = time.Now()
+		calculateMappingItem.ModifyTime = time.Now()
+		calculateMappingItem.Sort = 1
+		calculateMappingItem.EdbCode = edbInfo.EdbCode
+		calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+		calculateMappingItem.FromEdbInfoId = tmpEdbInfo.EdbInfoId
+		calculateMappingItem.FromEdbCode = tmpEdbInfo.EdbCode
+		calculateMappingItem.FromEdbName = tmpEdbInfo.EdbName
+		calculateMappingItem.FromSource = tmpEdbInfo.Source
+		calculateMappingItem.FromSourceName = tmpEdbInfo.SourceName
+		calculateMappingItem.FromTag = v.FromTag
+		calculateMappingItem.Source = edbInfo.Source
+		calculateMappingItem.SourceName = edbInfo.SourceName
+		calculateMappingItemList = append(calculateMappingItemList, calculateMappingItem)
+
+	}
+
+	if edbInfoA == nil || edbInfoB == nil {
+		errMsg = "指标异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	if edbInfoA.EdbInfoId == edbInfoB.EdbInfoId {
+		errMsg = "两个指标不允许为同一个"
+		err = errors.New(errMsg)
+		return
+	}
+	_, err = to.InsertMulti(len(calculateMappingItemList), calculateMappingItemList)
+	if err != nil {
+		return
+	}
+
+	//计算数据
+	err, errMsg = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfoA, edbInfoB, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+func RefreshAllCalculateCorrelation(edbInfo *EdbInfo) (err error, errMsg string) {
+	edbInfoCalculateDetailList, err := GetEdbInfoCalculateDetailList(edbInfo.EdbInfoId)
+	if err != nil {
+		return
+	}
+	var edbInfoA, edbInfoB *EdbInfo
+	for _, v := range edbInfoCalculateDetailList {
+		tmpEdbInfo, _ := GetEdbInfoById(v.FromEdbInfoId)
+		if v.FromTag == `A` {
+			edbInfoA = tmpEdbInfo
+		}
+		if v.FromTag == `B` {
+			edbInfoB = tmpEdbInfo
+		}
+	}
+
+	if edbInfoA == nil || edbInfoB == nil {
+		errMsg = "指标异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	if edbInfoA.EdbInfoId == edbInfoB.EdbInfoId {
+		errMsg = "两个指标不允许为同一个"
+		err = errors.New(errMsg)
+		return
+	}
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateCorrelation,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 计算数据
+	err, errMsg = refreshAllCalculateCorrelation(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfoA, edbInfoB, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+// CorrelationConfig 扩散指数配置
+type CorrelationConfig struct {
+	DateType  int      `description:"扩散指标日期;1:全部指标日期并集;2:部分指标日期并集"`
+	CheckList []string `description:"选中的数据,A,B,C"`
+}
+
+type EdbCalculateFormula struct {
+	BaseCalculateValue int    `description:"基础计算窗口"`
+	BaseCalculateUnit  string `description:"基础计算频度"`
+	LeadValue          int    `description:"领先期数"`
+	LeadUnit           string `description:"频度"`
+	CalculateValue     int    `description:"计算窗口"`
+	CalculateUnit      string `description:"计算频度"`
+}
+
+// refreshAllCalculateCorrelation 刷新扩散指数数据
+func refreshAllCalculateCorrelation(to orm.TxOrmer, edbInfoId, source int, edbInfoA, edbInfoB *EdbInfo, edbCode, calculateFormula string) (err error, errMsg string) {
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	tableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_CORRELATION)
+
+	//获取扩散指数指标所有数据
+	existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source)
+	if err != nil {
+		return
+	}
+	//计算指标的map
+	existDataMap := make(map[string]*EdbData, 0)
+	removeDateMap := make(map[string]string)
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v
+		removeDateMap[v.DataTime] = ``
+	}
+	var correlationConf EdbCalculateFormula
+	fmt.Println("calculateFormula:", calculateFormula)
+	err = json.Unmarshal([]byte(calculateFormula), &correlationConf)
+	if err != nil {
+		return
+	}
+	frequencyDaysMap := map[string]int{
+		"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
+	}
+	moveUnitDays, ok := frequencyDaysMap[correlationConf.CalculateUnit]
+	if !ok {
+		errMsg = `错误的分析周期`
+		err = errors.New(errMsg)
+		return
+	}
+	startDate := time.Now().AddDate(0, 0, -correlationConf.CalculateValue*moveUnitDays).Format(utils.FormatDate)
+	endDate := time.Now().Format(utils.FormatDate)
+	correlationChartDataMap, err := GetRollingCorrelationChartDataByEdbInfo(edbInfoA, edbInfoB, correlationConf.LeadValue, correlationConf.LeadUnit, correlationConf.CalculateValue, correlationConf.CalculateUnit, startDate, endDate)
+
+	addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+
+	for currDateStr, val := range correlationChartDataMap {
+		currDate, tmpErr := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		currVal, _ := decimal.NewFromFloat(val).Round(4).Float64()
+
+		// 判断扩散指数指标是否存在数据
+		if existData, ok := existDataMap[currDateStr]; ok {
+			// 处理扩散指数数据的值
+			existValStr := existData.Value
+			existValDeci, tmpErr := decimal.NewFromString(existValStr)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			existVal, _ := existValDeci.Round(4).Float64()
+			// 判断扩散指数数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
+			if existVal != currVal {
+				err = ModifyEdbDataById(source, existData.EdbDataId, fmt.Sprint(currVal))
+				if err != nil {
+					return
+				}
+			}
+		} else {
+			// 直接入库
+			timestamp := currDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+			addSql += GetAddSql(edbInfoIdStr, edbCode, currDateStr, timestampStr, fmt.Sprint(currVal))
+			isAdd = true
+		}
+
+		delete(removeDateMap, currDateStr)
+	}
+
+	// 数据入库
+	{
+
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = to.Raw(addSql).Exec()
+		}
+
+		// 移除不存在的日期数据
+		if len(removeDateMap) > 0 {
+			removeDateList := make([]string, 0) //需要移除的日期
+			for k := range removeDateMap {
+				removeDateList = append(removeDateList, k)
+			}
+			removeDateStr := strings.Join(removeDateList, `","`)
+			removeDateStr = `"` + removeDateStr + `"`
+			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
+			}
+		}
+	}
+
+	return
+}
+
+// GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
+func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *EdbInfo, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate string) (dateData map[string]float64, err error) {
+	dateData = make(map[string]float64)
+	baseEdbInfo := edbInfoMappingA
+	changeEdbInfo := edbInfoMappingB
+
+	// 获取时间基准指标在时间区间内的值
+	aDataList := make([]*EdbInfoSearchData, 0)
+	switch baseEdbInfo.EdbInfoType {
+	case 0:
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id=? "
+		pars = append(pars, baseEdbInfo.EdbInfoId)
+
+		//获取来源指标的数据
+		aDataList, err = GetEdbDataListAll(condition, pars, baseEdbInfo.Source, 1)
+	case 1:
+		aDataList, err = GetPredictEdbDataListAllByStartDate(baseEdbInfo, 1, "")
+	default:
+		err = errors.New(fmt.Sprint("获取失败,指标base类型异常", baseEdbInfo.EdbInfoType))
+	}
+
+	// 获取变频指标所有日期的值, 插值法完善数据
+	bDataList := make([]*EdbInfoSearchData, 0)
+	switch changeEdbInfo.EdbInfoType {
+	case 0:
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id=? "
+		pars = append(pars, changeEdbInfo.EdbInfoId)
+
+		//获取来源指标的数据
+		bDataList, err = GetEdbDataListAll(condition, pars, changeEdbInfo.Source, 1)
+	case 1:
+		bDataList, err = GetPredictEdbDataListAllByStartDate(changeEdbInfo, 1, "")
+	default:
+		err = errors.New(fmt.Sprint("获取失败,指标change类型异常", baseEdbInfo.EdbInfoType))
+		return
+	}
+
+	// 数据平移变频指标领先/滞后的日期(单位天)
+	frequencyDaysMap := map[string]int{
+		"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
+	}
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	//baseDataList := make([]*data_manage.EdbDataList, 0)
+	baseDataMap := make(map[string]float64)
+	changeDataList := make([]*EdbInfoSearchData, 0)
+	changeDataMap := make(map[string]float64)
+
+	// A指标不管三七二十一,先变个频再说
+	{
+		_, e := HandleDataByLinearRegression(aDataList, baseDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		//baseDataList = tmpNewChangeDataList
+	}
+	// A指标不管三七二十一,先变个频再说
+	{
+		tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		changeDataList = tmpNewChangeDataList
+
+		// 平移下日期
+		moveUnitDays := frequencyDaysMap[leadUnit]
+		_, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
+	}
+
+	// 计算计算时,需要多少个日期内数据
+	calculateDay := frequencyDaysMap[calculateUnit] * calculateValue
+
+	// 计算 每个日期的相关性值
+	{
+		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+
+		for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
+			coordinateData := make([]utils.Coordinate, 0)
+			// 取出对应的基准日期的值
+			for i := 0; i < calculateDay; i++ {
+				iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
+				tmpCoordinate := utils.Coordinate{
+					X: baseDataMap[iDay],
+					Y: changeDataMap[iDay],
+				}
+				coordinateData = append(coordinateData, tmpCoordinate)
+			}
+
+			// 公式计算出领先/滞后频度对应点的相关性系数
+			var ratio float64
+			if len(coordinateData) > 0 {
+				ratio = utils.ComputeCorrelation(coordinateData)
+			}
+			dateData[currDay.AddDate(0, 0, calculateDay).Format(utils.FormatDate)] = ratio
+		}
+	}
+	return
+}
+
+// MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
+func MoveDataDaysToNewDataList(dataList []*EdbInfoSearchData, moveDay int) (newDataList []EdbInfoSearchData, dateDataMap map[string]float64) {
+	dateMap := make(map[time.Time]float64)
+	var minDate, maxDate time.Time
+	dateDataMap = make(map[string]float64)
+
+	for _, v := range dataList {
+		currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+		if minDate.IsZero() || currDate.Before(minDate) {
+			minDate = currDate
+		}
+		if maxDate.IsZero() || currDate.After(maxDate) {
+			maxDate = currDate
+		}
+		dateMap[currDate] = v.Value
+	}
+
+	// 处理领先、滞后数据
+	newDateMap := make(map[time.Time]float64)
+	for currDate, value := range dateMap {
+		newDate := currDate.AddDate(0, 0, moveDay)
+		newDateMap[newDate] = value
+	}
+	minDate = minDate.AddDate(0, 0, moveDay)
+	maxDate = maxDate.AddDate(0, 0, moveDay)
+
+	// 获取日期相差日
+	dayNum := utils.GetTimeSubDay(minDate, maxDate)
+
+	for i := 0; i <= dayNum; i++ {
+		currDate := minDate.AddDate(0, 0, i)
+		tmpValue, ok := newDateMap[currDate]
+		if !ok {
+			//找不到数据,那么就用前面的数据吧
+			if len(newDataList)-1 < 0 {
+				tmpValue = 0
+			} else {
+				tmpValue = newDataList[len(newDataList)-1].Value
+			}
+		}
+		tmpData := EdbInfoSearchData{
+			DataTime: currDate.Format(utils.FormatDate),
+			Value:    tmpValue,
+		}
+		dateDataMap[tmpData.DataTime] = tmpData.Value
+		newDataList = append(newDataList, tmpData)
+	}
+	return
+}