package services
import (
"context"
"encoding/json"
"eta/eta_forum_task/models"
"eta/eta_forum_task/services/alarm_msg"
"eta/eta_forum_task/services/eta_forum"
"eta/eta_forum_task/utils"
"fmt"
"strconv"
"time"
)
func EtaForumChartUpdate(cont context.Context) (err error) {
err = ChartInfoSaveBatch()
return
}
// UpdateChart 更新社区里的图表接口
func UpdateChart(chartInfoId int) (err error, errMsg string) {
// 设置缓存 防止重复更新
cacheKey := "eta_forum_task:UpdateChart:" + strconv.Itoa(chartInfoId)
if utils.Rc.Get(cacheKey) != nil {
err = fmt.Errorf("系统处理中,请稍后重试!")
return
}
utils.Rc.SetNX(cacheKey, 1, 10*time.Minute)
defer func() {
if err != nil {
go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新图表至社区失败:Err:%v,ErrMsg:%s", err, errMsg), 3)
}
utils.Rc.Delete(cacheKey)
}()
// 查询图表信息
chartInfo, err := models.GetChartInfoById(chartInfoId)
if err != nil {
if err.Error() == utils.ErrNoRow() {
errMsg = "图表不存在"
err = fmt.Errorf(errMsg)
return
}
errMsg = "获取图表信息失败"
err = fmt.Errorf("获取图表信息失败,Err:" + err.Error())
return
}
if chartInfo.ForumChartInfoId <= 0 {
return
}
//查询图表指标
//获取原图表关联的指标信息列表
chartMappingList, err := models.GetChartMappingList(chartInfoId)
if err != nil {
errMsg = "获取图表关联的指标信息失败"
err = fmt.Errorf("获取图表关联的指标信息失败,Err:" + err.Error())
return
}
edbIds := make([]int, 0)
edbInfoStr := ""
for _, v := range chartMappingList {
edbIds = append(edbIds, v.EdbInfoId)
edbInfoStr += strconv.Itoa(v.EdbInfoId) + ","
}
chartSeriesList := make([]*models.ChartSeries, 0)
chartSeriesEdbList := make([]*models.ChartSeriesEdbMapping, 0)
if chartInfo.ChartType == utils.CHART_TYPE_SECTION_COMBINE {
chartSeriesList, err = models.GetChartSeriesByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表关联的系列信息失败"
err = fmt.Errorf("获取图表关联的系列信息失败,Err:" + err.Error())
return
}
chartSeriesEdbList, err = models.GetChartSeriesEdbByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表关联的系列指标信息失败"
err = fmt.Errorf("获取图表关联的系列指标信息失败,Err:" + err.Error())
return
}
}
var (
edbInfoList []*models.EdbInfo
edbMappingList []*models.EdbInfoCalculateMapping
edbInfoDataList []*eta_forum.AddEdbDataReq
)
//查询指标详情
isGetEdbData := false
// 查询投研资源库里的图表和指标绑定关系
oldEdbInfoStr, err := models.GetEdbInfoIdsByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取投研资源库里的图表和指标绑定关系失败"
err = fmt.Errorf("获取投研资源库里的图表和指标绑定关系失败,Err:" + err.Error())
return
}
if oldEdbInfoStr != edbInfoStr { // 图表更换过指标需要重新获取指标数据
isGetEdbData = true
}
edbInfoList, edbMappingList, edbInfoDataList, err = GetEdbListByEdbInfoId(edbIds, isGetEdbData)
if err != nil {
errMsg = "获取指标详情失败"
err = fmt.Errorf("获取指标详情失败,Err:" + err.Error())
return
}
descriptionList, err, errMsg := getChartDescriptionWithAdminNameByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表简介失败"
err = fmt.Errorf("获取图表简介失败,Err:" + err.Error())
return
}
req := new(eta_forum.ChartSaveLibReq)
req.ChartInfo = chartInfo
req.ChartInfo.ChartInfoId = chartInfo.ForumChartInfoId
req.ChartEdbMapping = chartMappingList
req.EdbInfoList = edbInfoList
req.EdbInfoDataList = edbInfoDataList
req.EdbInfoCalculateMapping = edbMappingList
req.ChartSeries = chartSeriesList
req.ChartSeriesEdbMapping = chartSeriesEdbList
req.Description = descriptionList
// 查询创建者信息
creatorInfo, _ := models.GetSysUserById(chartInfo.SysUserId)
if creatorInfo != nil {
req.CreatorInfo = creatorInfo
}
// 添加计算指标
reqJson, err := json.Marshal(req)
if err != nil {
errMsg = "参数解析异常"
err = fmt.Errorf("参数解析异常,Err:" + err.Error())
return
}
respItem, err := eta_forum.ChartUpdateLib(string(reqJson))
if err != nil {
errMsg = "更新失败"
err = fmt.Errorf("上传失败,Err:" + err.Error())
return
}
if respItem.Ret != 200 {
errMsg = "更新失败"
err = fmt.Errorf(respItem.ErrMsg)
return
}
// 更新投研资源库里的图表和指标绑定关系
err = models.UpdateForumChartEdbMapping(chartInfoId, edbInfoStr)
if err != nil {
errMsg = "更新投研资源库里的图表和指标绑定关系失败"
err = fmt.Errorf("更新投研资源库里的图表和指标绑定关系失败,Err:" + err.Error())
return
}
return
}
func GetEdbListByEdbInfoId(edbInfoIds []int, isGetEdbData bool) (edbInfoList []*models.EdbInfo, edbMappingList []*models.EdbInfoCalculateMapping, edbInfoDataList []*eta_forum.AddEdbDataReq, err error) {
//查询指标信息
//查询指标映射
//查询所有指标数据
//查询这个指标相关的mapping信息放到数组里,
//将得到的指标ID信息放到数组里
chartEdbInfoIdMap := make(map[int]struct{}) //只查询图表上直接相关的指标数据
hasFindMap := make(map[int]struct{})
edbInfoIdMap := make(map[int]struct{})
edbMappingList = make([]*models.EdbInfoCalculateMapping, 0)
edbMappingMap := make(map[int]struct{})
for _, edbInfoId := range edbInfoIds {
chartEdbInfoIdMap[edbInfoId] = struct{}{}
edbMappingList, err = traceEdbInfoByEdbInfoId(edbInfoId, hasFindMap, edbInfoIdMap, edbMappingList, edbMappingMap)
if err != nil {
return
}
}
// 指标信息map
edbInfoIdList := make([]int, 0)
for k, _ := range edbInfoIdMap {
edbInfoIdList = append(edbInfoIdList, k)
}
edbInfoList, err = models.GetEdbInfoByIdList(edbInfoIdList)
if err != nil {
err = fmt.Errorf("traceEdbInfoByEdbInfoId GetEdbInfoByIdList err: %s", err.Error())
return
}
if isGetEdbData {
for _, v := range edbInfoList {
if _, ok := chartEdbInfoIdMap[v.EdbInfoId]; !ok {
continue
}
var dataList []*models.EdbDataBase
if v.Source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
dataList, err = models.GetEdbDataBaseMongoByEdbInfoId(v.EdbInfoId, v.Source, v.SubSource)
} else if v.Source == utils.DATA_SOURCE_THS && v.SubSource == utils.DATA_SUB_SOURCE_HIGH_FREQUENCY && utils.UseMongo {
dataList, err = models.GetThsHfEdbDataBaseMongoByEdbInfoId(v.EdbInfoId, v.Source, v.SubSource)
} else {
dataList, err = models.GetEdbDataBaseByEdbInfoId(v.EdbInfoId, v.Source, v.SubSource)
}
if err != nil {
err = fmt.Errorf("查询指标数据失败 Err: %s", err.Error())
return
}
tmp := new(eta_forum.AddEdbDataReq)
tmp.EdbCode = v.EdbCode
tmp.EdbType = v.EdbType
tmp.DataList = dataList
edbInfoDataList = append(edbInfoDataList, tmp)
}
}
return
}
// traceEdbInfoByEdbInfoId 指标追溯
func traceEdbInfoByEdbInfoId(edbInfoId int, hasFindMap map[int]struct{}, edbInfoIdMap map[int]struct{}, edbMappingList []*models.EdbInfoCalculateMapping, edbMappingMap map[int]struct{}) (newEdbMappingList []*models.EdbInfoCalculateMapping, err error) {
newEdbMappingList = edbMappingList
_, ok := hasFindMap[edbInfoId]
if ok {
return
}
if _, ok1 := edbInfoIdMap[edbInfoId]; !ok1 {
edbInfoIdMap[edbInfoId] = struct{}{}
}
edbInfoMappingList, e := models.GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId)
if e != nil {
err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoId err: %s", e.Error())
return
}
if len(edbInfoMappingList) > 0 {
fromEdbInfoIdList := make([]int, 0)
for _, v := range edbInfoMappingList {
fromEdbInfoIdList = append(fromEdbInfoIdList, v.FromEdbInfoId)
if _, ok1 := edbInfoIdMap[v.FromEdbInfoId]; !ok1 {
edbInfoIdMap[v.FromEdbInfoId] = struct{}{}
}
if _, ok2 := edbMappingMap[v.EdbInfoCalculateMappingId]; !ok2 {
edbMappingMap[v.EdbInfoCalculateMappingId] = struct{}{}
tmp := &models.EdbInfoCalculateMapping{
EdbInfoCalculateMappingId: v.EdbInfoCalculateMappingId,
EdbInfoId: v.EdbInfoId,
Source: v.Source,
SourceName: v.SourceName,
EdbCode: v.EdbCode,
FromEdbInfoId: v.FromEdbInfoId,
FromEdbCode: v.FromEdbCode,
FromEdbName: v.FromEdbName,
FromSource: v.FromSource,
FromSourceName: v.FromSourceName,
FromTag: v.FromTag,
Sort: v.Sort,
CreateTime: v.CreateTime,
ModifyTime: v.ModifyTime,
}
newEdbMappingList = append(newEdbMappingList, tmp)
}
if edbInfoId != v.FromEdbInfoId && (v.FromEdbType == 2 || v.FromEdbInfoType == 1) {
// 查过了就不查了
if _, ok2 := hasFindMap[v.FromEdbInfoId]; !ok2 {
newEdbMappingList, e = traceEdbInfoByEdbInfoId(v.FromEdbInfoId, hasFindMap, edbInfoIdMap, newEdbMappingList, edbMappingMap)
if e != nil {
err = fmt.Errorf("traceEdbInfoByEdbInfoId err: %s", e.Error())
return
}
}
}
hasFindMap[v.FromEdbInfoId] = struct{}{}
}
}
hasFindMap[edbInfoId] = struct{}{}
return
}
// 批量上传图表分类信息
func ChartInfoSaveBatch() (err error) {
var tmpErr []error
cacheKey := "eta_forum_task:ChartInfoSaveBatchAdmin"
if !utils.Rc.SetNX(cacheKey, 1, 30*time.Minute) {
err = fmt.Errorf("系统处理中,请稍后重试!")
return
}
defer func() {
utils.Rc.Delete(cacheKey)
stack := ""
if err != nil {
stack = fmt.Sprintln(stack + err.Error())
}
if len(tmpErr) > 0 {
for _, v := range tmpErr {
stack = fmt.Sprintln(stack + v.Error())
}
}
if stack != "" {
utils.FileLog.Error("批量上传资源库图表信息失败"+"
"+stack)
go alarm_msg.SendAlarmMsg("批量上传资源库图表信息失败"+"
"+stack, 3)
}
}()
// 已上架的图表都更新,批量更新图表信息
condition := " and source=1 and forum_chart_info_id > 0 and resource_status =1"
// 查询需要更新的图表信息总数
total, err := models.GetChartInfoCountByCondition(condition, []interface{}{})
if err != nil {
return
}
if total > 0 {
// 批量上传图表信息
offset := 0
pageSize := 100
success := 0
// 循环更新100个图表数据
for i := 0; offset < total; i++ {
// 查询需要更新的图表信息
chartInfos, e := models.GetChartInfoListByCondition(condition, []interface{}{}, offset, pageSize)
if e != nil {
err = fmt.Errorf("查询需要更新的图表信息失败: %v", e)
return
}
if len(chartInfos) == 0 {
break
}
// 循环更新图表数据
for _, chartInfo := range chartInfos {
var er error
var msg string
// 更新图表数据
er, msg = UpdateChart(chartInfo.ChartInfoId)
if er != nil {
er = fmt.Errorf("图表ID %d, 更新图表数据失败: %s, %v", chartInfo.ChartInfoId, msg, er)
tmpErr = append(tmpErr, er)
continue
}
success += 1
}
offset = (i + 1) * pageSize
}
utils.FileLog.Info("更新图表数据完成, 更新图表数据总数:", success)
}
sysUser, err := models.GetSysUserByAdminName("admin")
if err != nil {
err = fmt.Errorf("获取系统用户失败,Err:" + err.Error())
return
}
// 获取精选资源分类已经上架的分类
classifyCondition := " AND source=? and is_selected=1 and resource_status=1 "
var classifyPars []interface{}
classifyPars = append(classifyPars, utils.CHART_SOURCE_DEFAULT)
classifyList, err := models.GetChartClassifyListByCondition(classifyCondition, classifyPars)
if err != nil {
return
}
chartClassifyIdList := make([]string, 0)
for _, v := range classifyList {
chartClassifyIdList = append(chartClassifyIdList, strconv.Itoa(v.ChartClassifyId))
}
if len(chartClassifyIdList) == 0 {
return
}
// 批量上传图表信息
condition = " and source=1 and forum_chart_info_id = 0 and chart_classify_id in ("+utils.GetOrmInReplace(len(chartClassifyIdList))+") and resource_status !=2"
// 查询需要更新的图表信息总数
total, err = models.GetChartInfoCountByCondition(condition, []interface{}{chartClassifyIdList})
if err != nil {
return
}
if total == 0 {
return
}
// 批量上传图表信息
offset := 0
pageSize := 100
success := 0
// 循环更新100个图表数据
for i := 0; offset < total; i++ {
// 查询需要更新的图表信息
chartInfos, e := models.GetChartInfoListByCondition(condition, []interface{}{chartClassifyIdList}, offset, pageSize)
if e != nil {
err = fmt.Errorf("查询需要更新的图表信息失败: %v", e)
return
}
if len(chartInfos) == 0 {
break
}
// 循环更新图表数据
for _, chartInfo := range chartInfos {
var er error
var msg string
// 上传图表数据
er, msg = UploadChart(chartInfo.ChartInfoId, "", sysUser)
if er != nil {
er = fmt.Errorf("图表ID %d, 上传图表数据失败: %s, %v", chartInfo.ChartInfoId, msg, er)
tmpErr = append(tmpErr, er)
continue
}
success += 1
}
offset = (i + 1) * pageSize
}
utils.FileLog.Info("上传图表数据完成, 上传图表数据总数:", success)
// 更新指标数据
utils.Rc.LPush(utils.CACHE_KEY_EDB_DATA_UPDATE_LOG, []byte("1"))
return
}
// UploadChart 上传图表接口
func UploadChart(chartInfoId int, description string, uploaderInfo *models.Admin) (err error, errMsg string) {
// 设置缓存 防止重复上传
cacheKey := "eta_forum_task:UploadChart:" + strconv.Itoa(chartInfoId)
if utils.Rc.Get(cacheKey) != nil {
err = fmt.Errorf("系统处理中,请稍后重试!")
return
}
utils.Rc.SetNX(cacheKey, 1, 10*time.Minute)
defer func() {
if err != nil {
go alarm_msg.SendAlarmMsg(fmt.Sprintf("上传图表至社区失败:Err:%v,ErrMsg:%s", err, errMsg), 3)
}
utils.Rc.Delete(cacheKey)
}()
// 查询图表信息
chartInfo, err := models.GetChartInfoById(chartInfoId)
if err != nil {
if err.Error() == utils.ErrNoRow() {
errMsg = "图表不存在"
err = fmt.Errorf(errMsg)
return
}
errMsg = "获取图表信息失败"
err = fmt.Errorf("获取图表信息失败,Err:" + err.Error())
return
}
if chartInfo.ForumChartInfoId > 0 {
errMsg = "该图表已上传至社区,无法再次上传"
err = fmt.Errorf(errMsg)
return
}
//查询图表主题
//查询图表指标
//获取原图表关联的指标信息列表
chartMappingList, err := models.GetChartMappingList(chartInfoId)
if err != nil {
errMsg = "获取图表关联的指标信息失败"
err = fmt.Errorf("获取图表关联的指标信息失败,Err:" + err.Error())
return
}
edbIds := make([]int, 0)
edbInfoStr := ""
for _, v := range chartMappingList {
edbIds = append(edbIds, v.EdbInfoId)
edbInfoStr += strconv.Itoa(v.EdbInfoId) + ","
}
chartSeriesList := make([]*models.ChartSeries, 0)
chartSeriesEdbList := make([]*models.ChartSeriesEdbMapping, 0)
if chartInfo.ChartType == utils.CHART_TYPE_SECTION_COMBINE {
chartSeriesList, err = models.GetChartSeriesByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表关联的系列信息失败"
err = fmt.Errorf("获取图表关联的系列信息失败,Err:" + err.Error())
return
}
chartSeriesEdbList, err = models.GetChartSeriesEdbByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表关联的系列指标信息失败"
err = fmt.Errorf("获取图表关联的系列指标信息失败,Err:" + err.Error())
return
}
}
var (
edbInfoList []*models.EdbInfo
edbMappingList []*models.EdbInfoCalculateMapping
edbInfoDataList []*eta_forum.AddEdbDataReq
)
//查询指标详情
edbInfoList, edbMappingList, edbInfoDataList, err = GetEdbListByEdbInfoId(edbIds, true)
if err != nil {
errMsg = "获取指标详情失败"
err = fmt.Errorf("获取指标详情失败,Err:" + err.Error())
return
}
descriptionList, err, errMsg := getChartDescriptionWithAdminNameByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表简介失败"
err = fmt.Errorf("获取图表简介失败,Err:" + err.Error())
return
}
req := new(eta_forum.ChartSaveLibReq)
req.ChartInfo = chartInfo
req.ChartEdbMapping = chartMappingList
req.EdbInfoList = edbInfoList
req.EdbInfoDataList = edbInfoDataList
req.EdbInfoCalculateMapping = edbMappingList
req.Description = descriptionList
req.ChartSeries = chartSeriesList
req.ChartSeriesEdbMapping = chartSeriesEdbList
// 查询创建者信息
creatorInfo, _ := models.GetSysUserById(chartInfo.SysUserId)
if creatorInfo != nil {
req.CreatorInfo = creatorInfo
}
req.UploaderInfo = uploaderInfo
// 添加计算指标
reqJson, err := json.Marshal(req)
if err != nil {
errMsg = "参数解析异常"
err = fmt.Errorf("参数解析异常,Err:" + err.Error())
return
}
respItem, err := eta_forum.ChartSaveLib(string(reqJson))
if err != nil {
errMsg = "上传失败"
err = fmt.Errorf("上传失败,Err:" + err.Error())
return
}
if respItem.Ret != 200 {
errMsg = "上传失败"
err = fmt.Errorf(respItem.ErrMsg)
return
}
if respItem.Data != nil && respItem.Data.ChartInfoId != 0 {
// 更新社区返回的图表ID
err = models.SetForumChartInfoId(chartInfoId, respItem.Data.ChartInfoId, utils.ChartClassifyResourceStatusUp)
if err != nil {
errMsg = "更新图表ID失败"
err = fmt.Errorf("更新图表ID失败,Err:" + err.Error())
return
}
// 新增投研资源库里的图表和指标绑定关系
err = models.AddForumChartEdbMapping(chartInfoId, edbInfoStr)
if err != nil {
errMsg = "新增投研资源库里的图表和指标绑定关系失败"
err = fmt.Errorf("新增投研资源库里的图表和指标绑定关系失败,Err:" + err.Error())
return
}
}
return
}
func getChartDescriptionWithAdminNameByChartInfoId(chartInfoId int) (list []*models.ChartDescriptionReq, err error, errMsg string) {
descriptionList, err := models.GetChartDescriptionByChartInfoId(chartInfoId)
if err != nil {
errMsg = "获取图表简介失败"
err = fmt.Errorf("获取图表简介失败,Err:" + err.Error())
return
}
// 查询创建者信息
adminIdList := make([]int, 0)
for _, v := range descriptionList {
adminIdList = append(adminIdList, v.SysUserId)
}
adminList, err := models.GetAdminListByIdList(adminIdList)
if err != nil {
errMsg = "获取创建者信息失败"
err = fmt.Errorf("获取创建者信息失败,Err:" + err.Error())
return
}
adminMap := make(map[int]string)
for _, v := range adminList {
adminMap[v.AdminId] = v.AdminName
}
for _, v := range descriptionList {
adminName, ok := adminMap[v.SysUserId]
if !ok {
adminName = ""
}
list = append(list, &models.ChartDescriptionReq{
Id: v.Id,
ChartInfoId: v.ChartInfoId,
Description: v.Description,
AdminName: adminName,
SysUserId: v.SysUserId,
SysUserRealName: v.SysUserRealName,
ModifyTime: v.ModifyTime,
CreateTime: v.CreateTime,
})
}
return
}