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" "sort" "strconv" "strings" ) var ( BridgeApiJiaYueIndexDataUrl = "/api/index_data/jiayue/index_data" // 获取指标数据API BridgeApiJiaYueNewIndexUrl = "/api/index_data/jiayue/new_index" // 获取增量指标API BridgeApiJiaYueMenuListUrl = "/api/index_data/jiayue/menu_list" // 获取指标目录API ) // GetJiaYueIndexDataFromBridge 从桥接服务获取指标数据 func GetJiaYueIndexDataFromBridge(param models.BridgeJiaYueIndexDataParams) (indexData models.BridgeJiaYueIndexAndData, err error) { defer func() { if err != nil { b, _ := json.Marshal(param) tips := fmt.Sprintf("桥接服务-获取嘉悦指标数据失败, err: %s, params: %s", err.Error(), string(b)) utils.FileLog.Info(tips) go alarm_msg.SendAlarmMsg(tips, 3) } }() url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiJiaYueIndexDataUrl) data, e := json.Marshal(param) if e != nil { err = fmt.Errorf("data json marshal err: %s", e.Error()) return } body := ioutil.NopCloser(strings.NewReader(string(data))) 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.BridgeJiaYueResultIndexData) 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 } indexData = result.Data return } // GetJiaYueNewIndexFromBridge 从桥接服务获取增量指标 func GetJiaYueNewIndexFromBridge() (indexData []models.BridgeJiaYueIndexAndData, err error) { defer func() { if err != nil { tips := fmt.Sprintf("桥接服务-获取嘉悦增量指标失败, err: %s", err.Error()) utils.FileLog.Info(tips) go alarm_msg.SendAlarmMsg(tips, 3) } }() url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiJiaYueNewIndexUrl) 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.BridgeJiaYueResultNewIndexData) 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 } indexData = result.Data return } // GetJiaYueMenuListFromBridge 从桥接服务获取指标目录列表 func GetJiaYueMenuListFromBridge() (indexData []models.BridgeJiaYueIndexMenuData, err error) { defer func() { if err != nil { tips := fmt.Sprintf("桥接服务-获取嘉悦增量指标失败, err: %s", err.Error()) utils.FileLog.Info(tips) go alarm_msg.SendAlarmMsg(tips, 3) } }() url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiJiaYueMenuListUrl) 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.BridgeJiaYueResultMenuListData) 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 } indexData = result.Data return } // SyncJiaYueNewIndex 同步嘉悦增量指标 func SyncJiaYueNewIndex(item models.BridgeJiaYueIndexAndData, menus []models.BridgeJiaYueIndexMenuData) (err error) { defer func() { if err != nil { b, _ := json.Marshal(item) tips := fmt.Sprintf("SyncJiaYueNewIndex同步增量指标失败, Err: %s\nIndex: %s", err.Error(), string(b)) utils.FileLog.Info(tips) go alarm_msg.SendAlarmMsg(tips, 3) } }() subSource := utils.DATA_SUB_SOURCE_EDB // 校验指标来源 sourceId := models.EdbSourceExtendIdMap[item.SourceType] if sourceId <= 0 { utils.FileLog.Info(fmt.Sprintf("指标来源ID有误, 忽略同步, sourceId: %d; sourceType: %s", sourceId, item.SourceType)) return } edbSource := models.EdbSourceIdMap[sourceId] if edbSource == nil { utils.FileLog.Info(fmt.Sprintf("指标来源有误, sourceId: %d", sourceId)) return } sourceTableName := edbSource.TableName if sourceTableName == "" { utils.FileLog.Info(fmt.Sprintf("指标数据表有误, 忽略同步, sourceId: %d", sourceId)) return } // 指标编码 indexCode := "" if edbSource.EdbCodeRequired == 1 { indexCode = item.IndexCode } else { indexCode = strconv.Itoa(item.Id) } if indexCode == "" { utils.FileLog.Info("指标编码不存在") return } // 查询指标是否已存在, 存在则忽略 exist, e := models.GetEdbInfoByEdbCode(sourceId, indexCode) if e != nil && e.Error() != utils.ErrNoRow() { err = fmt.Errorf("查询指标是否存在失败, err: %s", e.Error()) return } if exist != nil && exist.EdbInfoId > 0 { utils.FileLog.Info(fmt.Sprintf("指标%s已存在, 忽略同步", indexCode)) return } // 从桥接服务获取指标和数据 var params models.BridgeJiaYueIndexDataParams params.IndexCode = indexCode params.SourceExtend = item.SourceType params.StartDate = utils.BASE_START_DATE params.EndDate = utils.BASE_END_DATE params.IndexCodeRequired = edbSource.EdbCodeRequired indexData, e := GetJiaYueIndexDataFromBridge(params) if e != nil { err = fmt.Errorf("GetJiaYueIndexDataFromBridge err: %s", e.Error()) return } // 没找到数据, 频度有误的忽略掉 if indexData.Id <= 0 { utils.FileLog.Info(fmt.Sprintf("SyncJiaYueNewIndex indexCode empty, IndexCode: %s", indexCode)) return } frequency := TransJiaYueFrequency(item.Frequency) if frequency == "" { utils.FileLog.Info(fmt.Sprintf("SyncJiaYueNewIndex frequency empty, Frequency: %s", item.Frequency)) return } // 获取指标目录对应的所有父级目录 parentId := 0 parentMenus := GetJiaYueParentMenusByMenu(indexData.MenuData, menus, 0) level := len(parentMenus) if level > 0 { // 将父级目录按照Level倒序排序(因为是从子目录往上找的, 所以Level最大的对应为顶级目录), 再进行遍历 sort.Slice(parentMenus, func(i, j int) bool { return parentMenus[i].Level > parentMenus[j].Level }) for _, p := range parentMenus { l := level - p.Level - 1 c, _, msg := models.SaveEdbClassify(p.Menu.Name, parentId, l, 0, utils.InitAdminId, utils.InitAdminName) if msg != "" { err = fmt.Errorf("SaveEdbClassify err: %s", msg) return } parentId = c.ClassifyId } } classify, _, msg := models.SaveEdbClassify(indexData.MenuData.Name, parentId, level, 0, utils.InitAdminId, utils.InitAdminName) if msg != "" { err = fmt.Errorf("SaveEdbClassify err: %s", msg) return } // 新增指标 addParams := new(models.AddEdbInfoParams) addParams.EdbCode = indexCode addParams.EdbName = item.IndexName addParams.Frequency = frequency addParams.Unit = item.Unit addParams.ClassifyId = classify.ClassifyId addParams.Source = sourceId adminId, _ := strconv.Atoi(utils.InitAdminId) edbInfo, e := models.EdbInfoAdd(addParams, "", adminId, utils.InitAdminName) if e != nil { err = fmt.Errorf("EdbInfoAdd err: %s", e.Error()) return } // 刷新指标数据 e = models.RefreshEdbDataFromJiaYue(sourceId, subSource, edbInfo.EdbInfoId, sourceTableName, edbInfo.EdbCode, params.StartDate, indexData.IndexData) if e != nil { err = fmt.Errorf("RefreshEdbDataFromJiaYue err: %s", e.Error()) return } // 更新指标最大最小值 e, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if e != nil { err = fmt.Errorf("UnifiedModifyEdbInfoMaxAndMinInfo err: %s, errMsg: %s", e.Error(), errMsg) return } // 更新ES go logic.UpdateEs(edbInfo.EdbInfoId) return } // TransJiaYueFrequency 频度转换 func TransJiaYueFrequency(origin string) string { mapping := map[string]string{ "日": "日度", "周": "周度", "旬": "旬度", "半月": "旬度", "月": "月度", "季": "季度", "半年": "半年度", "年": "年度", "日度": "日度", "周度": "周度", "旬度": "旬度", "月度": "月度", "季度": "季度", "半年度": "半年度", "年度": "年度", } return mapping[origin] } // GetJiaYueParentMenusByMenu 获取指定目录的父级目录 func GetJiaYueParentMenusByMenu(menu models.BridgeJiaYueIndexMenuData, menus []models.BridgeJiaYueIndexMenuData, level int) (results []models.BridgeJiaYueIndexMenuWithLevel) { results = make([]models.BridgeJiaYueIndexMenuWithLevel, 0) for _, m := range menus { if menu.ParentId == m.Id { results = append(results, models.BridgeJiaYueIndexMenuWithLevel{ Level: level, Menu: m, }) ps := GetJiaYueParentMenusByMenu(m, menus, level+1) if len(ps) > 0 { results = append(results, ps...) } } } return }