浏览代码

Merge remote-tracking branch 'origin/master' into eta/1.8.4

# Conflicts:
#	routers/commentsRouter.go
#	routers/router.go
#	utils/common.go
#	utils/constants.go
Roc 11 月之前
父节点
当前提交
a9902b3be8

+ 273 - 0
controllers/base_from_bloomberg.go

@@ -0,0 +1,273 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_index_lib/logic"
+	"eta/eta_index_lib/models"
+	"eta/eta_index_lib/services"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"strconv"
+	"time"
+)
+
+// BloombergController Bloomberg
+type BloombergController struct {
+	BaseAuthController
+}
+
+// Add
+// @Title 新增彭博指标接口
+// @Description 新增彭博指标接口
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /add [post]
+func (this *BloombergController) Add() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		_ = utils.Rc.Delete(cacheKey)
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	source := utils.DATA_SOURCE_BLOOMBERG
+	var req models.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	if req.Source != source {
+		br.Msg = "数据源有误"
+		br.ErrMsg = fmt.Sprintf("数据源ID不匹配, Source: %d", req.Source)
+		return
+	}
+	cacheKey = utils.CACHE_EDB_DATA_ADD + strconv.Itoa(source) + "_" + req.EdbCode
+	if !utils.Rc.IsExist(cacheKey) {
+		utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+		err = models.AddEdbDataFromBloomberg(req.EdbCode)
+		if err != nil {
+			br.Msg = "获取指标信息失败!"
+			br.ErrMsg = "获取指标信息失败 AddEdbDataFromBloomberg,Err:" + err.Error()
+			return
+		}
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+	} else {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+	}
+}
+
+// Refresh
+// @Title 刷新彭博指标接口
+// @Description 刷新彭博指标接口
+// @Success 200 {object} models.RefreshEdbInfoReq
+// @router /refresh [post]
+func (this *BloombergController) Refresh() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		_ = utils.Rc.Delete(cacheKey)
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	source := utils.DATA_SOURCE_BLOOMBERG
+	var req models.RefreshEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	if req.EdbInfoId <= 0 {
+		br.Msg = "请输入指标ID!"
+		br.ErrMsg = "请输入指标ID"
+		return
+	}
+
+	// 获取指标详情
+	edbInfo, err := models.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if err != nil {
+		br.Msg = "指标不存在!"
+		br.ErrMsg = "指标不存在"
+		return
+	}
+	cacheKey = utils.CACHE_EDB_DATA_REFRESH + strconv.Itoa(source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	dataUpdateTime := time.Now().Format(utils.FormatDateTime)
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	err = models.RefreshEdbDataFromBloomberg(req.EdbInfoId, req.EdbCode, req.StartDate)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "刷新指标信息失败!"
+		br.ErrMsg = "刷新指标信息失败 RefreshEdbDataFromBloomberg,Err:" + err.Error()
+		return
+	}
+
+	// 更新指标最大最小值
+	erDataUpdateDate, err, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfoDataUpdate(edbInfo, dataUpdateTime)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+	// 添加指标刷新成功日志
+	if erDataUpdateDate != "" {
+		_ = services.AddEdbInfoUpdateLog(edbInfo.EdbInfoId, 1, "", 1, "", 0, 0)
+	} else {
+		_ = services.AddEdbInfoUpdateLog(edbInfo.EdbInfoId, 1, "", 2, "未刷新到数据", 0, 0)
+	}
+
+	// 更新ES
+	go logic.UpdateEs(edbInfo.EdbInfoId)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// PCSGRefreshDaily
+// @Title 中石油新加坡-刷新日度指标
+// @Description  中石油新加坡-刷新日度指标
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /pcsg/refresh_daily [post]
+func (this *BloombergController) PCSGRefreshDaily() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 获取数据
+	indexes, e := services.GetPCSGBloombergDailyFromBridge()
+	if e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "Bridge-获取PCSG彭博日度指标失败, Err: " + e.Error()
+		return
+	}
+	if len(indexes) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+
+	// 写入数据
+	if e = services.PCSGWrite2BaseBloomberg(indexes); e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "PCSG-写入Bloomberg数据源失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// PCSGRefreshWeekly
+// @Title 中石油新加坡-刷新周度指标
+// @Description  中石油新加坡-刷新周度指标
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /pcsg/refresh_weekly [post]
+func (this *BloombergController) PCSGRefreshWeekly() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 获取数据
+	indexes, e := services.GetPCSGBloombergWeeklyFromBridge()
+	if e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "Bridge-获取PCSG彭博周度指标失败, Err: " + e.Error()
+		return
+	}
+	if len(indexes) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+
+	// 写入数据
+	if e = services.PCSGWrite2BaseBloomberg(indexes); e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "PCSG-写入Bloomberg数据源失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// PCSGRefreshMonthly
+// @Title 中石油新加坡-刷新月度指标
+// @Description  中石油新加坡-刷新周度指标
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /pcsg/refresh_monthly [post]
+func (this *BloombergController) PCSGRefreshMonthly() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 获取数据
+	indexes, e := services.GetPCSGBloombergMonthlyFromBridge()
+	if e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "Bridge-获取PCSG彭博月度指标失败, Err: " + e.Error()
+		return
+	}
+	if len(indexes) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+
+	// 写入数据
+	if e = services.PCSGWrite2BaseBloomberg(indexes); e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "PCSG-写入Bloomberg数据源失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 20 - 0
controllers/base_from_predict.go

@@ -177,6 +177,26 @@ func (this *PredictController) Refresh() {
 		return
 	}
 
+	refreshParams := models.RefreshParams{
+		EdbInfo: edbInfo,
+	}
+
+	obj := new(models.PredictStandardBase)
+	latestDateStr, latestValue, err, errMsg := obj.Refresh(refreshParams)
+	if errMsg != `` {
+		br.Msg = "刷新指标失败!"
+		br.ErrMsg = "刷新指标失败,err:" + errMsg
+		return
+	}
+
+	// 更新指标最大最小值
+	err, errMsg = models.UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
 	// 更新ES
 	go logic.UpdateEs(edbInfo.EdbInfoId)
 

+ 347 - 0
models/base_from_bloomberg.go

@@ -0,0 +1,347 @@
+package models
+
+import (
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BaseFromBloombergIndex Bloomberg原始指标
+type BaseFromBloombergIndex struct {
+	BaseFromBloombergIndexId int       `orm:"column(base_from_bloomberg_index_id);pk"`
+	IndexCode                string    `description:"指标编码"`
+	IndexName                string    `description:"指标名称"`
+	Unit                     string    `description:"单位"`
+	Source                   int       `description:"来源"`
+	Frequency                string    `description:"频度"`
+	StartDate                time.Time `description:"开始时间"`
+	EndDate                  time.Time `description:"结束时间"`
+	Describe                 string    `description:"描述"`
+	Sort                     int       `description:"排序"`
+	IsStop                   int       `description:"是否停更:0-否;1-停更"`
+	EdbExist                 int       `description:"指标库是否已添加:0-否;1-是"`
+	TerminalCode             string    `description:"所属终端编码"`
+	FilePath                 string    `description:"文件存储路径"`
+	CreateTime               time.Time `description:"创建时间"`
+	ModifyTime               time.Time `description:"修改时间"`
+}
+
+func (m *BaseFromBloombergIndex) TableName() string {
+	return "base_from_bloomberg_index"
+}
+
+func (m *BaseFromBloombergIndex) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.BaseFromBloombergIndexId = int(id)
+	return
+}
+
+func GetBaseFromBloombergIndexByCode(indexCode string) (item *BaseFromBloombergIndex, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM base_from_bloomberg_index WHERE index_code = ? LIMIT 1`
+	err = o.Raw(sql, indexCode).QueryRow(&item)
+	return
+}
+
+// BaseFromBloombergData Bloomberg原始数据
+type BaseFromBloombergData struct {
+	BaseFromBloombergDataId  int       `orm:"column(base_from_bloomberg_data_id);pk"`
+	BaseFromBloombergIndexId int       `description:"指标ID"`
+	IndexCode                string    `description:"指标编码"`
+	DataTime                 time.Time `description:"数据日期"`
+	Value                    float64   `description:"数据值"`
+	CreateTime               time.Time `description:"创建时间"`
+	ModifyTime               time.Time `description:"修改时间"`
+	DataTimestamp            int       `description:"数据日期时间戳"`
+}
+
+func (m *BaseFromBloombergData) TableName() string {
+	return "base_from_bloomberg_data"
+}
+
+func GetBaseFromBloombergDataByCondition(condition string, pars []interface{}) (items []*BaseFromBloombergData, err error) {
+	sub := `SELECT * FROM base_from_bloomberg_data WHERE 1=1  `
+	o := orm.NewOrm()
+	if condition != "" {
+		sub += condition
+	}
+	sql := `SELECT * FROM (` + sub + ` HAVING 1 ORDER BY modify_time DESC) tmp GROUP BY data_time ORDER BY data_time DESC `
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func MultiInsertOrUpdateBaseFromBloombergData(inserts, updates []*BaseFromBloombergData) (err error) {
+	o := orm.NewOrm()
+	if len(inserts) > 0 {
+		_, e := o.InsertMulti(len(inserts), inserts)
+		if e != nil {
+			err = fmt.Errorf("insert multi err: %s", e.Error())
+			return
+		}
+	}
+	if len(updates) > 0 {
+		p, e := o.Raw("UPDATE base_from_bloomberg_data SET value = ?, modify_time = NOW() WHERE index_code = ? AND data_time = ?").Prepare()
+		if e != nil {
+			err = fmt.Errorf("prepare err: %s", e.Error())
+			return
+		}
+		defer func() {
+			_ = p.Close()
+		}()
+		for _, v := range updates {
+			_, e = p.Exec(v.Value, v.IndexCode, v.DataTime.Format(utils.FormatDate))
+			if e != nil {
+				err = fmt.Errorf("update err: %s", e.Error())
+				return
+			}
+		}
+	}
+	return
+}
+
+func GetBaseFromBloombergIndexMinMax(indexCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date,MIN(value) AS min_value,MAX(value) AS max_value FROM base_from_bloomberg_data WHERE index_code = ? `
+	err = o.Raw(sql, indexCode).QueryRow(&item)
+	if err != nil {
+		return
+	}
+
+	// 获取最新值
+	var lastVal float64
+	sql = ` SELECT value AS latest_value FROM base_from_bloomberg_data WHERE index_code = ? ORDER BY data_time DESC LIMIT 1 `
+	err = o.Raw(sql, indexCode).QueryRow(&lastVal)
+	if err != nil {
+		return
+	}
+	item.LatestValue = lastVal
+	return
+}
+
+func ModifyBaseFromBloombergIndexMinMax(indexCode string, item *EdbInfoMaxAndMinInfo) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE base_from_bloomberg_index SET start_date = ?, end_date = ?, modify_time = NOW() WHERE index_code = ? `
+	_, err = o.Raw(sql, item.MinDate, item.MaxDate, indexCode).Exec()
+	return
+}
+
+type BloombergData struct {
+	InputValue float64 `orm:"column(value)" description:"值"`
+	DataTime   string  `orm:"column(data_time)" description:"日期"`
+}
+
+func GetBloombergDataByCondition(condition string, pars []interface{}) (item []*BloombergData, err error) {
+	sql1 := ` SELECT * FROM base_from_bloomberg_data WHERE 1=1  `
+	o := orm.NewOrm()
+	if condition != "" {
+		sql1 += condition
+	}
+	sql := `select * from (` + sql1 + ` having 1 order by modify_time DESC ) tmp GROUP BY data_time ORDER BY data_time DESC `
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}
+
+// AddEdbDataFromBloomberg 新增Bloomberg指标数据
+func AddEdbDataFromBloomberg(edbCode string) (err error) {
+	o := orm.NewOrm()
+
+	var condition string
+	var pars []interface{}
+
+	if edbCode != "" {
+		condition += " AND index_code = ? "
+		pars = append(pars, edbCode)
+	}
+
+	bloombergDataList, err := GetBloombergDataByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	dataLen := len(bloombergDataList)
+
+	existMap := make(map[string]string)
+	if dataLen > 0 {
+		var isAdd bool
+		addSql := ` INSERT INTO edb_data_bloomberg (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+		for i := 0; i < dataLen; i++ {
+			item := bloombergDataList[i]
+			eDate := item.DataTime
+			sValue := utils.SubFloatToString(item.InputValue, 4)
+			if sValue != "" {
+				if _, ok := existMap[eDate]; !ok {
+					dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
+					if err != nil {
+						return err
+					}
+					timestamp := dataTime.UnixNano() / 1e6
+					timeStr := fmt.Sprintf("%d", timestamp)
+					addSql += GetAddSql("0", edbCode, eDate, timeStr, sValue)
+					isAdd = true
+				}
+			}
+			existMap[eDate] = eDate
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			utils.FileLog.Info("addSql:" + addSql)
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return
+}
+
+// RefreshEdbDataFromBloomberg 刷新Bloomberg指标数据
+func RefreshEdbDataFromBloomberg(edbInfoId int, edbCode, startDate string) (err error) {
+	source := utils.DATA_SOURCE_BLOOMBERG
+	subSource := utils.DATA_SUB_SOURCE_EDB
+
+	o := orm.NewOrm()
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	//计算数据
+	var condition string
+	var pars []interface{}
+
+	if edbCode != "" {
+		condition += " AND index_code=? "
+		pars = append(pars, edbCode)
+	}
+
+	if startDate != "" {
+		condition += " AND data_time>=? "
+		pars = append(pars, startDate)
+	}
+
+	bloombergDataList, err := GetBloombergDataByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	// 真实数据的最大日期  , 插入规则配置的日期
+	var realDataMaxDate, edbDataInsertConfigDate time.Time
+	var edbDataInsertConfig *EdbDataInsertConfig
+	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
+	{
+		edbDataInsertConfig, err = GetEdbDataInsertConfigByEdbId(edbInfoId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			return
+		}
+		if edbDataInsertConfig != nil {
+			edbDataInsertConfigDate = edbDataInsertConfig.Date
+		}
+	}
+
+	var existCondition string
+	var existPars []interface{}
+
+	existCondition += " AND edb_info_id=? "
+	existPars = append(existPars, edbInfoId)
+	if startDate != "" {
+		existCondition += " AND data_time>=? "
+		existPars = append(existPars, startDate)
+	}
+	//获取指标所有数据
+	existList, err := GetEdbDataByCondition(source, subSource, existCondition, existPars)
+	if err != nil {
+		return err
+	}
+	existMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range existList {
+		existMap[v.DataTime] = v
+	}
+
+	addSql := ` INSERT INTO edb_data_bloomberg(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	addMap := make(map[string]string)
+	for _, v := range bloombergDataList {
+		item := v
+		eDate := item.DataTime
+		sValue := utils.SubFloatToString(item.InputValue, 4)
+
+		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
+		if err != nil {
+			return err
+		}
+		if findItem, ok := existMap[v.DataTime]; !ok {
+			if sValue != "" {
+				timestamp := dataTime.UnixNano() / 1e6
+				timeStr := fmt.Sprintf("%d", timestamp)
+				saveValue := sValue
+
+				if _, addOk := addMap[eDate]; !addOk {
+					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, saveValue)
+					isAdd = true
+				}
+			}
+		} else {
+			if findItem != nil && utils.SubFloatToString(findItem.Value, 4) != sValue {
+				err = ModifyEdbDataById(source, subSource, findItem.EdbDataId, sValue)
+				if err != nil {
+					return err
+				}
+			}
+		}
+		addMap[v.DataTime] = v.DataTime
+
+		// 下面代码主要目的是处理掉手动插入的数据判断
+		{
+			if realDataMaxDate.IsZero() || dataTime.After(realDataMaxDate) {
+				realDataMaxDate = dataTime
+			}
+			if edbDataInsertConfigDate.IsZero() || dataTime.Equal(edbDataInsertConfigDate) {
+				isFindConfigDateRealData = true
+			}
+		}
+	}
+
+	// 处理手工数据补充的配置
+	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, subSource, existMap, isFindConfigDateRealData)
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
+// BridgePCSGBloombergResultData 中石油新加坡-指标接口响应体
+type BridgePCSGBloombergResultData struct {
+	Code int                                `json:"code" description:"状态码"`
+	Msg  string                             `json:"msg" description:"提示信息"`
+	Data []BaseFromBloombergApiIndexAndData `json:"data" description:"返回数据"`
+}
+
+// BaseFromBloombergApiIndexAndData Bloomberg原始指标及数据
+type BaseFromBloombergApiIndexAndData struct {
+	BaseFromBloombergIndexId int                             `description:"指标ID"`
+	IndexCode                string                          `description:"指标编码"`
+	IndexName                string                          `description:"指标名称"`
+	Unit                     string                          `description:"单位"`
+	Source                   string                          `description:"来源"`
+	Frequency                string                          `description:"频度"`
+	CreateTime               time.Time                       `description:"创建时间"`
+	ModifyTime               time.Time                       `description:"修改时间"`
+	Data                     []BaseFromBloombergApiIndexData `description:"数据列表"`
+}
+
+// BaseFromBloombergApiIndexData Bloomberg原始指标数据
+type BaseFromBloombergApiIndexData struct {
+	DataTime time.Time `description:"数据日期"`
+	Value    float64   `description:"数据值"`
+}

+ 0 - 26
models/base_from_business.go

@@ -2,7 +2,6 @@ package models
 
 import (
 	"eta/eta_index_lib/utils"
-	"fmt"
 	"time"
 
 	"github.com/beego/beego/v2/client/orm"
@@ -87,31 +86,6 @@ func (m *BaseFromBusinessIndex) Update(cols []string) (err error) {
 	return
 }
 
-// GetNoMergeIndexByFrequencyCount 获取未合并的指标总数量
-func (m *BaseFromBusinessIndex) GetNoMergeIndexByFrequencyCount(frequency string) (total int64, err error) {
-	o := orm.NewOrm()
-	sql := `SELECT count(1) AS total FROM base_from_business_index WHERE frequency = ? AND merge_file_path = '' AND index_name NOT LIKE "%停%"  `
-	err = o.Raw(sql, frequency).QueryRow(&total)
-
-	return
-}
-
-// GetIndexRefreshMethanolByTimely 获取需要及时刷新的文件
-func (m *BaseFromBusinessIndex) GetIndexRefreshMethanolByTimely() (items []*BaseFromBusinessIndex, err error) {
-	o := orm.NewOrm()
-	sql := `SELECT * FROM base_from_business_index WHERE merge_file_path <> '' AND is_refresh = 1 GROUP BY merge_file_path`
-	_, err = o.Raw(sql).QueryRows(&items)
-	return
-}
-
-func (m *BaseFromBusinessIndex) GetIndexRefreshWeek(nowWeekZn, startTime, endTime string) (items []*BaseFromBusinessIndex, err error) {
-	where := `update_week = ? AND ((update_time >= ? AND update_time <= ?) OR (update_time2 >= ? AND update_time2 <= ?)) `
-	o := orm.NewOrm()
-	sql := fmt.Sprintf(`SELECT * FROM base_from_business_index WHERE %s `, where)
-	_, err = o.Raw(sql, nowWeekZn, startTime, endTime, startTime, endTime).QueryRows(&items)
-	return
-}
-
 func (m *BaseFromBusinessIndex) UpdateIndex(item *BaseFromBusinessIndex, updateCols []string) (err error) {
 	if item == nil {
 		return

+ 2 - 0
models/db.go

@@ -132,6 +132,8 @@ func initBaseIndex() {
 		new(BaseFromMtjhIndex),
 		new(BaseFromFenweiIndex),
 		new(BaseFromFenweiData),
+		new(BaseFromBloombergIndex),
+		new(BaseFromBloombergData),
 	)
 }
 

+ 2 - 0
models/edb_data_table.go

@@ -162,6 +162,8 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		tableName = "edb_data_calculate_zdyfx" // 自定义分析->74
 	case utils.DATA_SOURCE_CALCULATE_RJZ: //日均值75
 		tableName = "edb_data_calculate_rjz"
+	case utils.DATA_SOURCE_PREDICT: // 基础预测指标->30
+		tableName = "edb_data_predict_base"
 	default:
 		edbSource := EdbSourceIdMap[source]
 		if edbSource != nil {

+ 5 - 2
models/edb_info.go

@@ -458,8 +458,11 @@ func UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo *EdbInfo) (err error, errMsg stri
 			}
 		}
 	}
-	// 修改关联的预测指标
-	go ModifyPredictEdbInfoMaxAndMinInfoBySourceEdbInfoId(edbInfo.EdbInfoId, maxAndMinItem)
+
+	// 刷新关联的预测指标
+	go RefreshPredictStandardBaseByGeneralEdbInfoId(edbInfo.EdbInfoId)
+
+	//go ModifyPredictEdbInfoMaxAndMinInfoBySourceEdbInfoId(edbInfo.EdbInfoId, maxAndMinItem)
 	return
 }
 

+ 0 - 263
models/predict_edb_conf.go

@@ -152,269 +152,6 @@ func AddPredictEdbConf(item *PredictEdbConf) (lastId int64, err error) {
 	return
 }
 
-// AddPredictEdb 添加预测指标
-// edbInfo, calculateMappingList, predictEdbConfList,calculateRule9List,trendsMappingList
-func AddPredictEdb(item *EdbInfo, calculateMappingList []*EdbInfoCalculateMapping, predictEdbConfList []*PredictEdbConf, calculateRuleMap map[int]CalculateRule) (err error, errMsg string) {
-	o := orm.NewOrm()
-	tx, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			tx.Rollback()
-		} else {
-			err = tx.Commit()
-		}
-	}()
-	// 新增预测指标
-	edbInfoId, err := tx.Insert(item)
-	if err != nil {
-		return
-	}
-	item.EdbInfoId = int(edbInfoId)
-
-	// 新增预测指标的关联关系
-	lenCalculateMapping := len(calculateMappingList)
-	if lenCalculateMapping > 0 {
-		for _, calculateMappingItem := range calculateMappingList {
-			calculateMappingItem.EdbInfoId = item.EdbInfoId
-			calculateMappingItem.EdbCode = item.EdbCode
-		}
-		_, err = tx.InsertMulti(lenCalculateMapping, calculateMappingList)
-		if err != nil {
-			return
-		}
-	}
-
-	predictEdbConfAndDataList := make([]*PredictEdbConfAndData, 0)
-
-	// 新增预测指标配置
-	for k, v := range predictEdbConfList {
-		v.PredictEdbInfoId = item.EdbInfoId
-		configId, tmpErr := tx.Insert(v)
-		if tmpErr != nil {
-			err = tmpErr
-			return
-		}
-		v.ConfigId = int(configId)
-
-		// 每次规则计算的时候,产生的临时数据
-		resultDataList := make([]*EdbInfoSearchData, 0)
-		switch v.RuleType {
-		case 9: //动态环差规则
-			calculateRule := calculateRuleMap[k]
-			calculateRule.ConfigId = v.ConfigId
-			calculateRule.EdbInfoId = v.PredictEdbInfoId
-
-			// 指标与规则的动态数据生成入库
-			resultDataList, err = CalculateByRuleBy9(tx, calculateRule)
-			if err != nil {
-				return
-			}
-
-			// 规则与指标的关系入库
-			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
-			if lenTrendsCalculateMapping > 0 {
-				for _, vv := range calculateRule.TrendsCalculateMappingList {
-					vv.EdbInfoId = item.EdbInfoId
-					vv.ConfigId = v.ConfigId
-				}
-				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
-				if err != nil {
-					return
-				}
-			}
-		case 14: //14:根据 一元线性拟合 规则获取预测数据
-			calculateRule := calculateRuleMap[k]
-			calculateRule.ConfigId = v.ConfigId
-			calculateRule.EdbInfoId = v.PredictEdbInfoId
-
-			// 指标与规则的动态数据(拟合数据)生成入库
-			err, errMsg = CalculateByRuleByRuleLineNh(tx, *item, predictEdbConfAndDataList, *v)
-			if err != nil {
-				return
-			}
-
-			// 规则与指标的关系入库
-			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
-			if lenTrendsCalculateMapping > 0 {
-				for _, vv := range calculateRule.TrendsCalculateMappingList {
-					vv.EdbInfoId = item.EdbInfoId
-					vv.ConfigId = v.ConfigId
-				}
-				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
-				if err != nil {
-					return
-				}
-			}
-
-		}
-
-		// 规则配置(含数据)
-		tmpPredictEdbConfAndData := &PredictEdbConfAndData{
-			ConfigId:         0,
-			PredictEdbInfoId: 0,
-			SourceEdbInfoId:  v.SourceEdbInfoId,
-			RuleType:         v.RuleType,
-			FixedValue:       v.FixedValue,
-			Value:            v.Value,
-			EndDate:          v.EndDate,
-			ModifyTime:       v.ModifyTime,
-			CreateTime:       v.CreateTime,
-			DataList:         resultDataList,
-		}
-		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
-	}
-	return
-}
-
-// EditPredictEdb 修改预测指标
-func EditPredictEdb(edbInfo *EdbInfo, updateEdbInfoCol []string, calculateMappingList []*EdbInfoCalculateMapping, predictEdbConfList []*PredictEdbConf, calculateRuleMap map[int]CalculateRule) (err error, errMsg string) {
-	o := orm.NewOrm()
-	tx, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			tx.Rollback()
-		} else {
-			err = tx.Commit()
-		}
-	}()
-	// 修改预测指标
-	_, err = tx.Update(edbInfo, updateEdbInfoCol...)
-	if err != nil {
-		return
-	}
-
-	// 先删除原有的预测指标 与 其他指标的 关联关系
-	sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ?`
-	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	// 先删除原有的配置
-	sql = ` DELETE FROM predict_edb_conf WHERE predict_edb_info_id = ?`
-	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	// 删除基础预测指标 规则配置 与 其他指标的 关联关系
-	sql = ` DELETE FROM predict_edb_conf_calculate_mapping WHERE edb_info_id = ?`
-	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	// 删除基础预测指标 规则配置 生成的动态数据值
-	sql = ` DELETE FROM predict_edb_rule_data WHERE edb_info_id = ?`
-	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	// 新增预测指标的关联关系
-	lenCalculateMapping := len(calculateMappingList)
-	if lenCalculateMapping > 0 {
-		for _, calculateMappingItem := range calculateMappingList {
-			calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
-			calculateMappingItem.EdbCode = edbInfo.EdbCode
-		}
-		_, err = tx.InsertMulti(lenCalculateMapping, calculateMappingList)
-		if err != nil {
-			return
-		}
-	}
-
-	calculateRuleIndex := 0 // 预测计算规则下标
-	predictEdbConfAndDataList := make([]*PredictEdbConfAndData, 0)
-
-	// 新增预测指标配置
-	for confIndex, v := range predictEdbConfList {
-		configId, tmpErr := tx.Insert(v)
-		if tmpErr != nil {
-			err = tmpErr
-			return
-		}
-		v.ConfigId = int(configId)
-		// 每次规则计算的时候,产生的临时数据
-		resultDataList := make([]*EdbInfoSearchData, 0)
-
-		switch v.RuleType {
-		case 9: //动态环差规则
-			calculateRule := calculateRuleMap[confIndex]
-			calculateRule.ConfigId = v.ConfigId
-			calculateRule.EdbInfoId = v.PredictEdbInfoId
-
-			// 指标与规则的动态数据生成入库
-			resultDataList, err = CalculateByRuleBy9(tx, calculateRule)
-			if err != nil {
-				return
-			}
-
-			// 规则与指标的关系入库
-			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
-			if lenTrendsCalculateMapping > 0 {
-				for _, vv := range calculateRule.TrendsCalculateMappingList {
-					vv.EdbInfoId = edbInfo.EdbInfoId
-					vv.ConfigId = v.ConfigId
-				}
-				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
-				if err != nil {
-					return
-				}
-			}
-		case 14: //14:根据 一元线性拟合 规则获取预测数据
-			calculateRule := calculateRuleMap[confIndex]
-			calculateRule.ConfigId = v.ConfigId
-			calculateRule.EdbInfoId = v.PredictEdbInfoId
-
-			// 指标与规则的动态数据(拟合数据)生成入库
-			err, errMsg = CalculateByRuleByRuleLineNh(tx, *edbInfo, predictEdbConfAndDataList, *v)
-			if err != nil {
-				return
-			}
-
-			// 规则与指标的关系入库
-			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
-			if lenTrendsCalculateMapping > 0 {
-				for _, vv := range calculateRule.TrendsCalculateMappingList {
-					vv.EdbInfoId = edbInfo.EdbInfoId
-					vv.ConfigId = v.ConfigId
-				}
-				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
-				if err != nil {
-					return
-				}
-			}
-
-		}
-
-		calculateRuleIndex++
-
-		// 规则配置(含数据)
-		tmpPredictEdbConfAndData := &PredictEdbConfAndData{
-			ConfigId:         0,
-			PredictEdbInfoId: 0,
-			SourceEdbInfoId:  v.SourceEdbInfoId,
-			RuleType:         v.RuleType,
-			FixedValue:       v.FixedValue,
-			Value:            v.Value,
-			EndDate:          v.EndDate,
-			ModifyTime:       v.ModifyTime,
-			CreateTime:       v.CreateTime,
-			DataList:         resultDataList,
-		}
-		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
-	}
-
-	return
-}
-
 // GetPredictEdbInfoAllCalculate 根据基础预测指标id集合 获取 所有的普通指标列表数据
 func GetPredictEdbInfoAllCalculate(edbInfoIdList []int) (list []*EdbInfo, err error) {
 	num := len(edbInfoIdList)

+ 563 - 0
models/predict_edb_data_base.go

@@ -0,0 +1,563 @@
+package models
+
+import (
+	"errors"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// PredictStandardBase 基础预测指标
+type PredictStandardBase struct {
+}
+
+// AddPredictEdb 添加预测指标
+// edbInfo, calculateMappingList, predictEdbConfList,calculateRule9List,trendsMappingList
+func AddPredictEdb(item *EdbInfo, calculateMappingList []*EdbInfoCalculateMapping, predictEdbConfList []*PredictEdbConf, calculateRuleMap map[int]CalculateRule) (err error, errMsg string) {
+	var latestDateStr string
+	var latestValue float64
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			err = tx.Commit()
+
+			// 更新指标最大最小值
+			go UnifiedModifyPredictEdbInfoMaxAndMinInfo(item, latestDateStr, latestValue)
+		}
+	}()
+	// 新增预测指标
+	edbInfoId, err := tx.Insert(item)
+	if err != nil {
+		return
+	}
+	item.EdbInfoId = int(edbInfoId)
+
+	// 新增预测指标的关联关系
+	lenCalculateMapping := len(calculateMappingList)
+	if lenCalculateMapping > 0 {
+		for _, calculateMappingItem := range calculateMappingList {
+			calculateMappingItem.EdbInfoId = item.EdbInfoId
+			calculateMappingItem.EdbCode = item.EdbCode
+		}
+		_, err = tx.InsertMulti(lenCalculateMapping, calculateMappingList)
+		if err != nil {
+			return
+		}
+	}
+
+	predictEdbConfAndDataList := make([]*PredictEdbConfAndData, 0)
+
+	// 新增预测指标配置
+	for k, v := range predictEdbConfList {
+		v.PredictEdbInfoId = item.EdbInfoId
+		configId, tmpErr := tx.Insert(v)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		v.ConfigId = int(configId)
+
+		// 每次规则计算的时候,产生的临时数据
+		resultDataList := make([]*EdbInfoSearchData, 0)
+		switch v.RuleType {
+		case 9: //动态环差规则
+			calculateRule := calculateRuleMap[k]
+			calculateRule.ConfigId = v.ConfigId
+			calculateRule.EdbInfoId = v.PredictEdbInfoId
+
+			// 指标与规则的动态数据生成入库
+			resultDataList, err = CalculateByRuleBy9(tx, calculateRule)
+			if err != nil {
+				return
+			}
+
+			// 规则与指标的关系入库
+			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
+			if lenTrendsCalculateMapping > 0 {
+				for _, vv := range calculateRule.TrendsCalculateMappingList {
+					vv.EdbInfoId = item.EdbInfoId
+					vv.ConfigId = v.ConfigId
+				}
+				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
+				if err != nil {
+					return
+				}
+			}
+		case 14: //14:根据 一元线性拟合 规则获取预测数据
+			calculateRule := calculateRuleMap[k]
+			calculateRule.ConfigId = v.ConfigId
+			calculateRule.EdbInfoId = v.PredictEdbInfoId
+
+			// 指标与规则的动态数据(拟合数据)生成入库
+			err, errMsg = CalculateByRuleByRuleLineNh(tx, *item, predictEdbConfAndDataList, *v)
+			if err != nil {
+				return
+			}
+
+			// 规则与指标的关系入库
+			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
+			if lenTrendsCalculateMapping > 0 {
+				for _, vv := range calculateRule.TrendsCalculateMappingList {
+					vv.EdbInfoId = item.EdbInfoId
+					vv.ConfigId = v.ConfigId
+				}
+				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
+				if err != nil {
+					return
+				}
+			}
+
+		}
+
+		// 规则配置(含数据)
+		tmpPredictEdbConfAndData := &PredictEdbConfAndData{
+			ConfigId:         0,
+			PredictEdbInfoId: 0,
+			SourceEdbInfoId:  v.SourceEdbInfoId,
+			RuleType:         v.RuleType,
+			FixedValue:       v.FixedValue,
+			Value:            v.Value,
+			EndDate:          v.EndDate,
+			ModifyTime:       v.ModifyTime,
+			CreateTime:       v.CreateTime,
+			DataList:         resultDataList,
+		}
+		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
+	}
+
+	// 重新预测数据
+	obj := new(PredictStandardBase)
+	latestDateStr, latestValue, err, errMsg = obj.refresh(tx, item, predictEdbConfAndDataList, item.EdbCode, "")
+
+	return
+}
+
+// EditPredictEdb 修改预测指标
+func EditPredictEdb(edbInfo *EdbInfo, updateEdbInfoCol []string, calculateMappingList []*EdbInfoCalculateMapping, predictEdbConfList []*PredictEdbConf, calculateRuleMap map[int]CalculateRule) (err error, errMsg string) {
+	var latestDateStr string
+	var latestValue float64
+
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			err = tx.Commit()
+
+			// 更新指标最大最小值
+			go UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue)
+		}
+	}()
+	// 修改预测指标
+	_, err = tx.Update(edbInfo, updateEdbInfoCol...)
+	if err != nil {
+		return
+	}
+
+	// 先删除原有的预测指标 与 其他指标的 关联关系
+	sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ?`
+	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 先删除原有的配置
+	sql = ` DELETE FROM predict_edb_conf WHERE predict_edb_info_id = ?`
+	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 删除基础预测指标 规则配置 与 其他指标的 关联关系
+	sql = ` DELETE FROM predict_edb_conf_calculate_mapping WHERE edb_info_id = ?`
+	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 删除基础预测指标 规则配置 生成的动态数据值
+	sql = ` DELETE FROM predict_edb_rule_data WHERE edb_info_id = ?`
+	_, err = tx.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 新增预测指标的关联关系
+	lenCalculateMapping := len(calculateMappingList)
+	if lenCalculateMapping > 0 {
+		for _, calculateMappingItem := range calculateMappingList {
+			calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+			calculateMappingItem.EdbCode = edbInfo.EdbCode
+		}
+		_, err = tx.InsertMulti(lenCalculateMapping, calculateMappingList)
+		if err != nil {
+			return
+		}
+	}
+
+	calculateRuleIndex := 0 // 预测计算规则下标
+	predictEdbConfAndDataList := make([]*PredictEdbConfAndData, 0)
+
+	// 新增预测指标配置
+	for confIndex, v := range predictEdbConfList {
+		configId, tmpErr := tx.Insert(v)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		v.ConfigId = int(configId)
+		// 每次规则计算的时候,产生的临时数据
+		resultDataList := make([]*EdbInfoSearchData, 0)
+
+		switch v.RuleType {
+		case 9: //动态环差规则
+			calculateRule := calculateRuleMap[confIndex]
+			calculateRule.ConfigId = v.ConfigId
+			calculateRule.EdbInfoId = v.PredictEdbInfoId
+
+			// 指标与规则的动态数据生成入库
+			resultDataList, err = CalculateByRuleBy9(tx, calculateRule)
+			if err != nil {
+				return
+			}
+
+			// 规则与指标的关系入库
+			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
+			if lenTrendsCalculateMapping > 0 {
+				for _, vv := range calculateRule.TrendsCalculateMappingList {
+					vv.EdbInfoId = edbInfo.EdbInfoId
+					vv.ConfigId = v.ConfigId
+				}
+				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
+				if err != nil {
+					return
+				}
+			}
+		case 14: //14:根据 一元线性拟合 规则获取预测数据
+			calculateRule := calculateRuleMap[confIndex]
+			calculateRule.ConfigId = v.ConfigId
+			calculateRule.EdbInfoId = v.PredictEdbInfoId
+
+			// 指标与规则的动态数据(拟合数据)生成入库
+			err, errMsg = CalculateByRuleByRuleLineNh(tx, *edbInfo, predictEdbConfAndDataList, *v)
+			if err != nil {
+				return
+			}
+
+			// 规则与指标的关系入库
+			lenTrendsCalculateMapping := len(calculateRule.TrendsCalculateMappingList)
+			if lenTrendsCalculateMapping > 0 {
+				for _, vv := range calculateRule.TrendsCalculateMappingList {
+					vv.EdbInfoId = edbInfo.EdbInfoId
+					vv.ConfigId = v.ConfigId
+				}
+				_, err = tx.InsertMulti(lenTrendsCalculateMapping, calculateRule.TrendsCalculateMappingList)
+				if err != nil {
+					return
+				}
+			}
+
+		}
+
+		calculateRuleIndex++
+
+		// 规则配置(含数据)
+		tmpPredictEdbConfAndData := &PredictEdbConfAndData{
+			ConfigId:         0,
+			PredictEdbInfoId: 0,
+			SourceEdbInfoId:  v.SourceEdbInfoId,
+			RuleType:         v.RuleType,
+			FixedValue:       v.FixedValue,
+			Value:            v.Value,
+			EndDate:          v.EndDate,
+			ModifyTime:       v.ModifyTime,
+			CreateTime:       v.CreateTime,
+			DataList:         resultDataList,
+		}
+		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
+	}
+
+	// 重新预测数据
+	obj := new(PredictStandardBase)
+	latestDateStr, latestValue, err, errMsg = obj.refresh(tx, edbInfo, predictEdbConfAndDataList, edbInfo.EdbCode, "")
+
+	return
+}
+
+// Add 添加
+func (obj PredictStandardBase) Add(params BatchSaveCalculateBatchParams) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error, errMsg string) {
+	err = errors.New("暂不支持该方法")
+	return
+}
+
+// Edit 编辑
+func (obj PredictStandardBase) Edit(params BatchSaveCalculateBatchParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	err = errors.New("暂不支持该方法")
+	return
+}
+
+// Refresh 刷新
+func (obj PredictStandardBase) Refresh(params RefreshParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	edbInfo := params.EdbInfo
+	if edbInfo == nil {
+		errMsg = `错误的指标`
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 查找该预测指标配置
+	predictEdbConfList, err := GetPredictEdbConfAndDataListById(edbInfo.EdbInfoId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		errMsg = "获取预测指标配置信息失败"
+		return
+	}
+	if len(predictEdbConfList) == 0 {
+		errMsg = "获取预测指标配置信息失败"
+		err = errors.New(errMsg)
+		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(), ";Refresh,Err:"+err.Error())
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 重新预测数据
+	latestDateStr, latestValue, err, errMsg = obj.refresh(to, edbInfo, predictEdbConfList, edbInfo.EdbCode, "")
+
+	return
+}
+
+// GetSource 获取来源编码id
+func (obj PredictStandardBase) GetSource() int {
+	return utils.DATA_SOURCE_PREDICT
+}
+
+// GetSourceName 获取来源名称
+func (obj PredictStandardBase) GetSourceName() string {
+	return utils.DATA_SOURCE_NAME_PREDICT
+}
+
+func (obj PredictStandardBase) refresh(to orm.TxOrmer, edbInfo *EdbInfo, predictEdbConfAndDataList []*PredictEdbConfAndData, edbCode, startDate string) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	edbInfoId := edbInfo.EdbInfoId
+	dataTableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+	// 获取标准差图表的指标数据
+	fromDataList, fromEdbInfo, err, errMsg := obj.GetCalculateDataList(edbInfo, predictEdbConfAndDataList, 1, startDate)
+	if err != nil {
+		return
+	}
+	latestDateStr = fromEdbInfo.LatestDate
+
+	//获取指标所有数据
+	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
+	}
+	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 _, tmpData := range fromDataList {
+		currDateStr := tmpData.DataTime
+		currTime, tmpErr := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 当前的实际值
+		saveValue := decimal.NewFromFloat(tmpData.Value).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, 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
+		}
+	}
+
+	//确定实际数据的最终值
+	{
+		finalLast, tmpErr := GetFinalLastByTo(to, edbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo.LatestDate)
+		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+			return
+		}
+		if tmpErr == nil {
+			latestDateStr = finalLast.DataTime
+			latestValue = finalLast.Value
+		}
+	}
+
+	return
+}
+
+// GetCalculateDataList
+// @Description: 获取计算后的数据
+// @author: Roc
+// @receiver obj
+// @datetime 2024-04-24 10:42:51
+// @param edbInfo *EdbInfo
+// @param predictEdbConfList []*PredictEdbConfAndData
+// @param order int order:1升序,其余值为降序
+// @param startDate string
+// @return dataList []*EdbInfoSearchData
+// @return sourceEdbInfoItem *EdbInfo
+// @return err error
+// @return errMsg string
+func (obj PredictStandardBase) GetCalculateDataList(edbInfo *EdbInfo, predictEdbConfList []*PredictEdbConfAndData, order int, startDate string) (dataList []*EdbInfoSearchData, sourceEdbInfoItem *EdbInfo, err error, errMsg string) {
+	if len(predictEdbConfList) == 0 {
+		errMsg = "获取预测指标配置信息失败"
+		err = errors.New(errMsg)
+		return
+	}
+	predictEdbConf := predictEdbConfList[0]
+
+	// 来源指标
+	sourceEdbInfoItem, err = GetEdbInfoById(predictEdbConf.SourceEdbInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "找不到来源指标信息"
+			err = errors.New(errMsg)
+		}
+		return
+	}
+
+	dataList, err, errMsg = GetPredictDataListByPredictEdbConfList(edbInfo, sourceEdbInfoItem, predictEdbConfList, order, startDate)
+
+	return
+}
+
+// RefreshPredictStandardBaseByGeneralEdbInfoId
+// @Description:  根据普通指标id刷新预测标准基础数据
+// @author: Roc
+// @datetime 2024-04-24 13:40:59
+// @param sourceEdbInfoId int
+// @return err error
+func RefreshPredictStandardBaseByGeneralEdbInfoId(sourceEdbInfoId int) {
+	errList := make([]string, 0)
+	defer func() {
+		if len(errList) > 0 {
+			fmt.Println(errList)
+			utils.FileLog.Info("RefreshPredictStandardBaseByGeneralEdbInfoId更新失败,来源ID: ErrMsg:" + strings.Join(errList, "\n"))
+		}
+	}()
+	o := orm.NewOrm()
+	var list []*PredictEdbConf
+	sql := ` SELECT * FROM predict_edb_conf WHERE source_edb_info_id=? `
+	total, err := o.Raw(sql, sourceEdbInfoId).QueryRows(&list)
+	if err != nil {
+		errList = append(errList, fmt.Sprintf("根据来源换指标id获取配置项失败,来源指标ID:%d;err:%s", sourceEdbInfoId, err.Error()))
+		return
+	}
+
+	if total > 0 {
+		idList := make([]int, 0)
+		for _, v := range list {
+			idList = append(idList, v.PredictEdbInfoId)
+			edbInfo, tmpErr := GetEdbInfoById(v.PredictEdbInfoId)
+			if tmpErr != nil {
+				errList = append(errList, fmt.Sprintf("获取预测指标配置信息失败,预测指标配置ID:%d;err:%s", v.PredictEdbInfoId, tmpErr.Error()))
+				continue
+			}
+			refreshParams := RefreshParams{
+				EdbInfo: edbInfo,
+			}
+			obj := new(PredictStandardBase)
+			latestDateStr, latestValue, tmpErr, errMsg := obj.Refresh(refreshParams)
+			if tmpErr != nil {
+				errList = append(errList, fmt.Sprintf("更新失败,预测指标配置ID:%d;err:%s;errMsg:%s", v.PredictEdbInfoId, tmpErr.Error(), errMsg))
+				continue
+			}
+
+			// 更新指标最大最小值
+			tmpErr, errMsg = UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue)
+			if tmpErr != nil {
+				errList = append(errList, fmt.Sprintf("更新指标最大最小值失败,预测指标配置ID:%d;err:%s;errMsg:%s", v.PredictEdbInfoId, tmpErr.Error(), errMsg))
+				continue
+			}
+		}
+	}
+
+	return
+}

+ 5 - 0
models/predict_edb_info_rule.go

@@ -1492,6 +1492,11 @@ func GetChartPredictEdbInfoDataListByRuleAnnualValueInversion(edbInfoId int, con
 	newPredictEdbInfoData = predictEdbInfoData
 	index := len(allDataList)
 
+	// 没有数据,直接返回
+	if index <= 0 {
+		return
+	}
+
 	// 配置的年度值
 	yearValueConfig := annualValueInversionConf.Value
 

+ 5 - 0
routers/router.go

@@ -244,6 +244,11 @@ func init() {
 				&controllers.EdbRefreshController{},
 			),
 		),
+		beego.NSNamespace("/bloomberg",
+			beego.NSInclude(
+				&controllers.BloombergController{},
+			),
+		),
 		beego.NSNamespace("/business_index",
 			beego.NSInclude(
 				&controllers.BusinessIndexController{},

+ 313 - 0
services/base_from_pcsg.go

@@ -0,0 +1,313 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_index_lib/logic"
+	"eta/eta_index_lib/models"
+	"eta/eta_index_lib/services/alarm_msg"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+	"time"
+)
+
+var (
+	BridgeApiPCSGBloombergDailyUrl   = "/api/pcsg/bloomberg/daily_index"   // 日度指标API
+	BridgeApiPCSGBloombergWeeklyUrl  = "/api/pcsg/bloomberg/weekly_index"  // 周度指标API
+	BridgeApiPCSGBloombergMonthlyUrl = "/api/pcsg/bloomberg/monthly_index" // 月度指标API
+)
+
+// GetPCSGBloombergDailyFromBridge 获取彭博日度指标
+func GetPCSGBloombergDailyFromBridge() (indexes []models.BaseFromBloombergApiIndexAndData, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("GetPCSGBloombergDailyFromBridge-获取彭博日度指标失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiPCSGBloombergDailyUrl)
+	body := ioutil.NopCloser(strings.NewReader(""))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := ioutil.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgePCSGBloombergResultData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexes = result.Data
+	return
+}
+
+// GetPCSGBloombergWeeklyFromBridge 获取彭博周度指标
+func GetPCSGBloombergWeeklyFromBridge() (indexes []models.BaseFromBloombergApiIndexAndData, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("GetPCSGBloombergWeeklyFromBridge-获取彭博周度指标失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiPCSGBloombergWeeklyUrl)
+	body := ioutil.NopCloser(strings.NewReader(""))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := ioutil.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgePCSGBloombergResultData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexes = result.Data
+	return
+}
+
+// GetPCSGBloombergMonthlyFromBridge 获取彭博月度指标
+func GetPCSGBloombergMonthlyFromBridge() (indexes []models.BaseFromBloombergApiIndexAndData, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("GetPCSGBloombergMonthlyFromBridge-获取彭博月度指标失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiPCSGBloombergMonthlyUrl)
+	body := ioutil.NopCloser(strings.NewReader(""))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := ioutil.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgePCSGBloombergResultData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexes = result.Data
+	return
+}
+
+// PCSGWrite2BaseBloomberg 写入彭博数据源
+func PCSGWrite2BaseBloomberg(indexes []models.BaseFromBloombergApiIndexAndData) (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("PCSGWrite2BaseBloomberg-写入彭博数据源失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	for _, v := range indexes {
+		if v.IndexCode == "" {
+			continue
+		}
+
+		// 指标是否存在
+		index, e := models.GetBaseFromBloombergIndexByCode(v.IndexCode)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = fmt.Errorf("获取Bloomberg原始指标失败, err: %s", e.Error())
+			return
+		}
+
+		// 新增指标
+		if index == nil {
+			newIndex := new(models.BaseFromBloombergIndex)
+			newIndex.IndexCode = v.IndexCode
+			newIndex.IndexName = v.IndexName
+			newIndex.Unit = v.Unit
+			newIndex.Source = utils.DATA_SOURCE_BLOOMBERG
+			newIndex.Frequency = v.Frequency
+			newIndex.CreateTime = time.Now().Local()
+			newIndex.ModifyTime = time.Now().Local()
+			if e = newIndex.Create(); e != nil {
+				err = fmt.Errorf("新增Bloomberg原始指标失败, err: %s", e.Error())
+				return
+			}
+			index = newIndex
+		}
+
+		// 更新指标数据
+		var cond string
+		var pars []interface{}
+		cond += ` AND index_code = ? `
+		pars = append(pars, v.IndexCode)
+		indexData, e := models.GetBaseFromBloombergDataByCondition(cond, pars)
+		if e != nil {
+			err = fmt.Errorf("获取Bloomberg历史数据失败, err: %s", e.Error())
+			return
+		}
+		dateExist := make(map[string]*models.BaseFromBloombergData)
+		if len(indexData) > 0 {
+			for _, d := range indexData {
+				strDate := d.DataTime.Format(utils.FormatDate)
+				dateExist[strDate] = d
+			}
+		}
+
+		// 筛选新增/更新数据
+		updateData := make([]*models.BaseFromBloombergData, 0)
+		insertData := make([]*models.BaseFromBloombergData, 0)
+		for _, d := range v.Data {
+			strDate := d.DataTime.Format(utils.FormatDate)
+			originData := dateExist[strDate]
+			if originData != nil {
+				if utils.FloatAlmostEqual(originData.Value, d.Value) {
+					continue
+				}
+				originData.Value = d.Value
+				originData.ModifyTime = time.Now().Local()
+				updateData = append(updateData, originData)
+			} else {
+				newData := new(models.BaseFromBloombergData)
+				newData.BaseFromBloombergIndexId = index.BaseFromBloombergIndexId
+				newData.IndexCode = index.IndexCode
+				newData.DataTime = d.DataTime
+				newData.Value = d.Value
+				newData.CreateTime = time.Now()
+				newData.ModifyTime = time.Now()
+				timestamp := d.DataTime.UnixNano() / 1e6
+				newData.DataTimestamp = int(timestamp)
+				insertData = append(insertData, newData)
+			}
+		}
+		if e = models.MultiInsertOrUpdateBaseFromBloombergData(insertData, updateData); e != nil {
+			err = fmt.Errorf("新增/更新Bloomberg指标数据失败, err: %s", e.Error())
+			return
+		}
+
+		// 更新指标开始结束时间
+		minMax, e := models.GetBaseFromBloombergIndexMinMax(index.IndexCode)
+		if e == nil && minMax != nil {
+			e = models.ModifyBaseFromBloombergIndexMinMax(index.IndexCode, minMax)
+			if e != nil {
+				err = fmt.Errorf("更新Bloomberg开始结束时间失败, err: %s", e.Error())
+				return
+			}
+		}
+
+		// 同步刷新指标库
+		go func() {
+			edb, e := models.GetEdbInfoByEdbCode(utils.DATA_SOURCE_BLOOMBERG, index.IndexCode)
+			if e != nil && e.Error() != utils.ErrNoRow() {
+				utils.FileLog.Info("获取Bloomberg指标库信息失败, err: " + e.Error())
+				return
+			}
+			if edb != nil {
+				logic.RefreshBaseEdbInfo(edb, ``)
+			}
+		}()
+	}
+	return
+}

+ 6 - 0
utils/common.go

@@ -1219,6 +1219,12 @@ func DealExcelDate(date string) (newDate time.Time, err error) {
 	return
 }
 
+// FloatAlmostEqual 判断两个浮点数是否相等
+func FloatAlmostEqual(a, b float64) bool {
+	epsilon := 1e-9 // 容差值
+	return math.Abs(a-b) <= epsilon
+}
+
 // VerifyFrequency
 // @Description: 校验频度是否合规
 // @author: Roc

+ 2 - 1
utils/constants.go

@@ -108,7 +108,8 @@ const (
 	DATA_SOURCE_MTJH          = 80 // 煤炭江湖->80
 	DATA_SOURCE_CALCULATE_SUM = 81
 	DATA_SOURCE_CALCULATE_AVG = 82
-	DATA_SOURCE_BUSINESS      = 83 // 来源于外部数据
+	DATA_SOURCE_BLOOMBERG     = 83 // bloomberg彭博数据
+	DATA_SOURCE_BUSINESS      = 84 // 来源于外部数据
 )
 
 // 指标来源的中文展示

+ 3 - 3
utils/redis/cluster_redis.go

@@ -149,12 +149,12 @@ func (rc *ClusterRedisClient) Put(key string, val interface{}, timeout time.Dura
 // @param timeout
 // @return bool
 func (rc *ClusterRedisClient) SetNX(key string, val interface{}, timeout time.Duration) bool {
-	result, err := rc.redisClient.SetEX(context.TODO(), key, val, timeout).Result()
-	if err != nil || result != "OK" {
+	result, err := rc.redisClient.SetNX(context.TODO(), key, val, timeout).Result()
+	if err != nil {
 		return false
 	}
 
-	return true
+	return result
 }
 
 // Delete

+ 3 - 3
utils/redis/standalone_redis.go

@@ -141,12 +141,12 @@ func (rc *StandaloneRedisClient) Put(key string, val interface{}, timeout time.D
 // @param timeout
 // @return bool
 func (rc *StandaloneRedisClient) SetNX(key string, val interface{}, timeout time.Duration) bool {
-	result, err := rc.redisClient.SetEX(context.TODO(), key, val, timeout).Result()
-	if err != nil || result != "OK" {
+	result, err := rc.redisClient.SetNX(context.TODO(), key, val, timeout).Result()
+	if err != nil {
 		return false
 	}
 
-	return true
+	return result
 }
 
 // Delete