package services import ( "encoding/json" "errors" "eta_gn/eta_api/models/data_manage" excelModel "eta_gn/eta_api/models/data_manage/excel" "eta_gn/eta_api/models/data_manage/excel/request" "eta_gn/eta_api/services/alarm_msg" "eta_gn/eta_api/services/data" "eta_gn/eta_api/services/sandbox" "eta_gn/eta_api/utils" "fmt" "strconv" "time" ) // 全局的指标替换 func DealReplaceEdbCache() { var err error for { utils.Rc.Brpop(utils.CACHE_KEY_REPLACE_EDB, func(b []byte) { defer func() { if err != nil { utils.FileLog.Info("DealReplaceEdbCache err:" + err.Error()) go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg:"+err.Error(), 3) } }() record := new(data_manage.ReplaceEdbInfoItem) if err = json.Unmarshal(b, &record); err != nil { fmt.Println("json unmarshal wrong!") return } oldEdbInfo := record.OldEdbInfo newEdbInfo := record.NewEdbInfo utils.FileLog.Info(fmt.Sprintf("指标开始替换 DealReplaceEdbCache: 旧指标ID:%d,新指标ID:%d", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)) deleteCache := true setNxKey := fmt.Sprintf("EDB_INFO_REPLACE:%d-%d", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId) defer func() { if deleteCache { utils.Rc.Delete(setNxKey) } }() if !utils.Rc.SetNX(setNxKey, 1, 30*time.Minute) { deleteCache = false err = fmt.Errorf("替换表格中的指标失败旧指标:%d为新指标%d:正在处理中", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId) return } // 替换相关性图表配置 _, err = data_manage.ReplaceMultipleGraphConfigChartEdb(oldEdbInfo, newEdbInfo) if err != nil { err = fmt.Errorf("替换相关性图表配置失败,errmsg:%s", err.Error()) return } // 替换拟合方程指标 _, err = data_manage.ReplaceEdbInfoInLineEquationMultipleGraphConfig(oldEdbInfo, newEdbInfo) if err != nil { err = fmt.Errorf("替换拟合方程指标失败,errmsg:%s", err.Error()) return } // 替换表格中的指标 err = ReplaceEdbInExcel(oldEdbInfo, newEdbInfo) if err != nil { err = fmt.Errorf("替换表格中的指标失败,errmsg:%s", err.Error()) return } //替换逻辑图中的指标 err = sandbox.ReplaceEdbInSandbox(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId) if err != nil { err = fmt.Errorf("替换逻辑图中的指标失败,errmsg:%s", err.Error()) return } // todo 重置指标引用表 ReplaceEdbInRelation(oldEdbInfo, newEdbInfo) }) } } // ReplaceEdbInExcel 替换表格中的指标 func ReplaceEdbInExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) (err error) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg:"+err.Error(), 3) } }() //查询和指标相关的时间序列表格和混合表格 mappingList, err := excelModel.GetExcelEdbMappingByEdbInfoIdAndSource(oldEdbInfo.EdbInfoId, []int{utils.TIME_TABLE, utils.MIXED_TABLE}) if err != nil { err = fmt.Errorf("查询和指标相关的表格失败,错误:%s", err.Error()) return } updateList := make([]*excelModel.ExcelInfo, 0) // 循环列表,根据表格类型单独处理 for _, excelMapping := range mappingList { //查询和指标相关的混合表格 excelInfo, tmpErr := excelModel.GetExcelInfoById(excelMapping.ExcelInfoId) if tmpErr != nil { err = fmt.Errorf("查询和指标相关的混合表格失败,错误:%s", tmpErr.Error()) return } // 清除缓存 key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode if utils.Re == nil { _ = utils.Rc.Delete(key) } // 根据表格类型,调用不同的处理函数 switch excelMapping.Source { case utils.TIME_TABLE: // 时间序列表格 // 替换余额表格中的指标 newExcelInfo, e := replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo, excelInfo) if e != nil { err = fmt.Errorf("替换余额表格中的指标失败,错误:%s", e.Error()) return } updateList = append(updateList, newExcelInfo) case utils.MIXED_TABLE, utils.BALANCE_TABLE: // 替换余额表格中的指标 newExcelInfo, e := replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo, excelInfo) if e != nil { err = fmt.Errorf("替换余额表格中的指标失败,错误:%s", e.Error()) return } updateList = append(updateList, newExcelInfo) default: // 其他表格类型的处理逻辑 } } err = excelModel.ReplaceEdbInExcel(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, updateList) if err != nil { err = fmt.Errorf("替换表格中的指标失败,错误:%s", err.Error()) return } //todo 是否需要刷新表格中的指标数据 return } func replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) { newExcelInfo = excelInfo var mixedTableReq request.MixedTableReq err = json.Unmarshal([]byte(excelInfo.Content), &mixedTableReq) if err != nil { err = fmt.Errorf("表格json转结构体失败,Err:" + err.Error()) return } // 处理data configList := mixedTableReq.Data for ck, rowList := range configList { for rk, cell := range rowList { switch cell.DataType { case request.EdbDT: // 指标信息 if cell.EdbInfoId == oldEdbInfo.EdbInfoId { //更换成新指标ID configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId } case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值 if cell.EdbInfoId == oldEdbInfo.EdbInfoId { //更换成新指标ID configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId } case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值 var config request.CalculateConf err = json.Unmarshal([]byte(cell.Value), &config) if err != nil { return } if cell.EdbInfoId == oldEdbInfo.EdbInfoId { //更换成新指标ID configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId } if config.EdbInfoId == oldEdbInfo.EdbInfoId { config.EdbInfoId = newEdbInfo.EdbInfoId var configStr []byte configStr, err = json.Marshal(config) if err != nil { return } configList[ck][rk].Value = string(configStr) } case request.DateDT: // 日期类型 // 指标日期类型的单元格需要额外将指标id取出来 if cell.DataTimeType == request.EdbDateDT { var config request.EdbDateConf err = json.Unmarshal([]byte(cell.Value), &config) if err != nil { return } if config.EdbInfoId == oldEdbInfo.EdbInfoId { config.EdbInfoId = newEdbInfo.EdbInfoId var configStr []byte configStr, err = json.Marshal(config) if err != nil { return } configList[ck][rk].Value = string(configStr) } } } } } mixedTableReq.Data = configList var newContentByte []byte newContentByte, err = json.Marshal(mixedTableReq) if err != nil { return } // 生成的新内容替换原先的旧内容 excelInfo.Content = string(newContentByte) newExcelInfo = excelInfo return } func replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) { newExcelInfo = excelInfo var tableDataConfig request.TimeTableDataConfig err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig) if err != nil { err = errors.New("表格json转结构体失败,Err:" + err.Error()) return } if len(tableDataConfig.EdbInfoIdList) <= 0 { return } // 实际期数没有的情况下,直接返回吧 if tableDataConfig.Num <= 0 { return } // 先处理edbInfoList for k, id := range tableDataConfig.EdbInfoIdList { if id == oldEdbInfo.EdbInfoId { tableDataConfig.EdbInfoIdList[k] = newEdbInfo.EdbInfoId } } // 先处理tableEdbInfoList for k, tableEdbInfo := range tableDataConfig.TableEdbInfoList { if tableEdbInfo.EdbInfoId == oldEdbInfo.EdbInfoId { tableDataConfig.TableEdbInfoList[k].EdbInfoId = newEdbInfo.EdbInfoId } } var newContentByte []byte newContentByte, err = json.Marshal(tableDataConfig) if err != nil { return } // 生成的新内容替换原先的旧内容 excelInfo.Content = string(newContentByte) newExcelInfo = excelInfo return } func ReplaceEdbInRelation(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) { var err error var logMsg string var replaceTotal int defer func() { if err != nil { msg := fmt.Sprintf(" 替换指标引用表中的指标,并修改引用时间 replaceEdbInRelation err: %v", err) utils.FileLog.Info(msg) fmt.Println(msg) go alarm_msg.SendAlarmMsg(msg, 3) } if logMsg != `` { utils.FileLog.Info(fmt.Sprintf("替换指标引用表中的指标记录 替换总数%d,旧的指标id:%d,新的指标id:%d;涉及到的引用id:%s", replaceTotal, oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, logMsg)) } }() calculateEdbMappingListMap := make(map[int]*data_manage.EdbInfoCalculateMapping) calculateEdbMappingIdsMap := make(map[int][]int) childEdbMappingIds := make([]int, 0) //indexCodeList := make([]string, 0) //refreshIds := make([]int, 0) //分页查询,每次处理500条记录 pageSize := 500 // 替换直接引用中的指标 if newEdbInfo.EdbType == 2 { edbInfoList := make([]*data_manage.EdbInfo, 0) edbInfoList = append(edbInfoList, newEdbInfo) calculateEdbMappingListMap, calculateEdbMappingIdsMap, err = data.GetEdbListByEdbInfoId(edbInfoList) if err != nil { err = fmt.Errorf("查询指标关联指标列表失败 Err:%s", err) return } var ok bool childEdbMappingIds, ok = calculateEdbMappingIdsMap[newEdbInfo.EdbInfoId] if !ok { err = fmt.Errorf("查询%d指标关联指标列表为空", newEdbInfo.EdbInfoId) return } } total, err := data_manage.GetReplaceEdbInfoRelationTotal(oldEdbInfo.EdbInfoId) if err != nil { err = fmt.Errorf("查询引用表中关联的指标总数失败 err: %v", err) return } totalPage := 0 if total > 0 { totalPage = (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数 //查询图表列表 for i := 0; i < totalPage; i += 1 { startSize := i * pageSize list, e := data_manage.GetReplaceEdbInfoRelationList(oldEdbInfo.EdbInfoId, startSize, pageSize) if e != nil { err = fmt.Errorf("查询图表关联指标列表失败 Err:%s", e) return } if len(list) == 0 { break } replaceTotal1, logMsg1, e := replaceEdbInRelation(oldEdbInfo, newEdbInfo, list, childEdbMappingIds, calculateEdbMappingListMap) if e != nil { err = e return } replaceTotal += replaceTotal1 logMsg += logMsg1 } } // 更新间接引用中的指标 //查询相关的记录总数 total, err = data_manage.GetReplaceChildEdbInfoRelationTotal(oldEdbInfo.EdbInfoId) if err != nil { if utils.IsErrNoRow(err) { err = nil } else { err = fmt.Errorf("查询引用表中关联的指标总数失败 err: %v", err) return } } if total > 0 { totalPage = (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数 //查询列表 for i := 0; i < totalPage; i += 1 { startSize := i * pageSize tmpList, e := data_manage.GetReplaceChildEdbInfoRelationList(oldEdbInfo.EdbInfoId, startSize, pageSize) if e != nil { err = fmt.Errorf("查询图表关联指标列表失败 Err:%s", e) return } // 查询直接引用 relationIds := make([]int, 0) for _, v := range tmpList { relationIds = append(relationIds, v.ParentRelationId) } if len(relationIds) > 0 { list, e := data_manage.GetEdbInfoRelationByRelationIds(relationIds) if e != nil { err = fmt.Errorf("查询图表关联指标列表失败 Err:%s", e) return } //查询直接引用指标关联关系 edbInfoListMap := make(map[int]struct{}) edbInfoIds := make([]int, 0) for _, v := range list { if _, ok := edbInfoListMap[v.EdbInfoId]; !ok { edbInfoListMap[v.EdbInfoId] = struct{}{} edbInfoIds = append(edbInfoIds, v.EdbInfoId) } } edbInfoList := make([]*data_manage.EdbInfo, 0) if len(edbInfoIds) > 0 { // 查询指标信息 edbInfoList, err = data_manage.GetEdbInfoByIdList(edbInfoIds) if err != nil { err = fmt.Errorf("查询指标信息失败 Err:%s", err) return } } calculateEdbMappingListMap, calculateEdbMappingIdsMap, err = data.GetEdbListByEdbInfoId(edbInfoList) if err != nil { err = fmt.Errorf("查询指标关联指标列表失败 Err:%s", err) return } //如何过滤掉只有间接引用,没有直接引用的 replaceTotal1, logMsg1, e := UpdateSecondEdbInRelation(list, calculateEdbMappingListMap, calculateEdbMappingIdsMap, edbInfoList) if e != nil { err = e return } replaceTotal += replaceTotal1 logMsg += logMsg1 } } } return } // 完成直接引用中的指标替换工程 func replaceEdbInRelation(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, list []*data_manage.EdbInfoRelation, childEdbMappingIds []int, calculateEdbMappingListMap map[int]*data_manage.EdbInfoCalculateMapping) (replaceTotal int, logMsg string, err error) { replaceEdbIds := make([]int, 0) indexCodeList := make([]string, 0) addList := make([]*data_manage.EdbInfoRelation, 0) refreshIds := make([]int, 0) nowTime := time.Now() for _, v := range list { replaceEdbIds = append(replaceEdbIds, v.EdbInfoRelationId) if newEdbInfo.EdbType == 2 { for _, childEdbMappingId := range childEdbMappingIds { childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId] if !ok2 { continue } if childEdbMapping.FromSource == utils.DATA_SOURCE_MYSTEEL_CHEMICAL { indexCodeList = append(indexCodeList, childEdbMapping.FromEdbCode) } tmp1 := &data_manage.EdbInfoRelation{ ReferObjectId: v.ReferObjectId, ReferObjectType: v.ReferObjectType, ReferObjectSubType: v.ReferObjectSubType, EdbInfoId: childEdbMapping.FromEdbInfoId, EdbName: childEdbMapping.FromEdbName, Source: childEdbMapping.FromSource, EdbCode: childEdbMapping.FromEdbCode, CreateTime: nowTime, ModifyTime: nowTime, RelationTime: nowTime, RelationType: 1, RootEdbInfoId: newEdbInfo.EdbInfoId, ChildEdbInfoId: childEdbMapping.EdbInfoId, } tmp1.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp1.RootEdbInfoId, tmp1.ReferObjectId, tmp1.ReferObjectType, tmp1.ReferObjectSubType) addList = append(addList, tmp1) refreshIds = append(refreshIds, childEdbMapping.FromEdbInfoId) // todo 防止重复 } } logMsg += strconv.Itoa(v.EdbInfoRelationId) + ";" } if len(replaceEdbIds) > 0 { err = data_manage.ReplaceRelationEdbInfoId(oldEdbInfo, newEdbInfo, replaceEdbIds, addList, refreshIds, indexCodeList) if err != nil { logMsg = "" err = fmt.Errorf("替换指标引用表中的指标ID失败 Err:%s", err) return } replaceTotal = len(replaceEdbIds) } return } func UpdateSecondEdbInRelation(list []*data_manage.EdbInfoRelation, calculateEdbMappingListMap map[int]*data_manage.EdbInfoCalculateMapping, calculateEdbMappingIdsMap map[int][]int, edbInfoList []*data_manage.EdbInfo) (replaceTotal int, logMsg string, err error) { nowTime := time.Now() edbInfoRelationIds := make([]int, 0) indexCodeList := make([]string, 0) addList := make([]*data_manage.EdbInfoRelation, 0) refreshIds := make([]int, 0) edbInfoMap := make(map[int]*data_manage.EdbInfo) for _, v := range edbInfoList { edbInfoMap[v.EdbInfoId] = v } // 查询所有的直接引用,删除所有的间接引用,添加所有直接引用的间接引用 for _, v := range list { if v.RelationType == 0 { edbInfoRelationIds = append(edbInfoRelationIds, v.EdbInfoRelationId) edbInfo, ok := edbInfoMap[v.EdbInfoId] if !ok { err = fmt.Errorf("查询指标信息失败 EdbInfoId:%d", v.EdbInfoId) return } if edbInfo.EdbType == 2 { //计算指标 childEdbMappingIds, ok := calculateEdbMappingIdsMap[edbInfo.EdbInfoId] if !ok { err = fmt.Errorf("查询%d指标关联指标列表为空", edbInfo.EdbInfoId) return } for _, childEdbMappingId := range childEdbMappingIds { childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId] if !ok2 { continue } if childEdbMapping.FromSource == utils.DATA_SOURCE_MYSTEEL_CHEMICAL { indexCodeList = append(indexCodeList, childEdbMapping.FromEdbCode) } tmp1 := &data_manage.EdbInfoRelation{ ReferObjectId: v.ReferObjectId, ReferObjectType: v.ReferObjectType, ReferObjectSubType: v.ReferObjectSubType, EdbInfoId: childEdbMapping.FromEdbInfoId, EdbName: childEdbMapping.FromEdbName, Source: childEdbMapping.FromSource, EdbCode: childEdbMapping.FromEdbCode, CreateTime: nowTime, ModifyTime: nowTime, RelationTime: nowTime, RelationType: 1, RootEdbInfoId: edbInfo.EdbInfoId, ChildEdbInfoId: childEdbMapping.EdbInfoId, } tmp1.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp1.RootEdbInfoId, tmp1.ReferObjectId, tmp1.ReferObjectType, tmp1.ReferObjectSubType) addList = append(addList, tmp1) refreshIds = append(refreshIds, childEdbMapping.FromEdbInfoId) } } logMsg += strconv.Itoa(v.EdbInfoRelationId) + ";" } } if len(edbInfoRelationIds) > 0 { err = data_manage.UpdateSecondRelationEdbInfoId(edbInfoRelationIds, addList, refreshIds, indexCodeList) if err != nil { logMsg = "" err = fmt.Errorf("替换指标引用表中的指标ID失败 Err:%s", err) return } replaceTotal = len(edbInfoRelationIds) } return }