package logic import ( "errors" "eta/eta_index_lib/models" "eta/eta_index_lib/utils" "fmt" "strconv" "strings" "time" ) // AddPredictEdbInfo 新增预测指标 func AddPredictEdbInfo(sourceEdbInfoId, classifyId int, edbName, dataDateType string, ruleList []models.RuleConfig, minValue, maxValue float64, sysUserId int, sysUserName, lang string) (edbInfo *models.EdbInfo, err error, errMsg string) { var sourceEdbInfo *models.EdbInfo // 来源指标信息校验 { sourceEdbInfo, err = models.GetEdbInfoById(sourceEdbInfoId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "新增失败" err = errors.New("获取来源指标失败,Err:" + err.Error()) return } if sourceEdbInfo == nil { errMsg = "找不到该来源指标" err = errors.New(errMsg) return } //必须是普通的指标 if sourceEdbInfo.EdbInfoType != 0 { errMsg = "来源指标异常,不是普通的指标" err = errors.New(errMsg) return } //if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) { // errMsg = "预测指标只支持选择日度、周度、月度、年度的指标" // err = errors.New(errMsg) // return //} } var classifyInfo *models.EdbClassify // 来源分类信息校验 { classifyInfo, err = models.GetEdbClassifyById(classifyId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "新增失败" err = errors.New("获取预测指标分类失败,Err:" + err.Error()) return } if classifyInfo == nil { errMsg = "找不到该预测指标分类" err = errors.New(errMsg) return } //必须是预测指标分类 if classifyInfo.ClassifyType != 1 { errMsg = "预测指标分类异常,不是预测指标分类" err = errors.New(errMsg) return } } edbName = strings.Trim(edbName, " ") edbCode := sourceEdbInfo.EdbCode + "_" + time.Now().Format(utils.FormatShortDateTimeUnSpace) // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := CheckExistByEdbNameAndEdbInfoId(utils.PREDICT_EDB_INFO_TYPE, 0, edbName, lang) if err != nil { errMsg = "判断指标名称是否存在失败" err = errors.New("判断指标名称是否存在失败,Err:" + err.Error()) return } if existEdbName { errMsg = "指标名称已存在,请重新填写" err = errors.New(errMsg) return } timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) if dataDateType == `` { dataDateType = `自然日` } edbInfo = &models.EdbInfo{ //EdbInfoId: 0, EdbInfoType: 1, SourceName: "预测指标", Source: utils.DATA_SOURCE_PREDICT, EdbCode: edbCode, EdbName: edbName, EdbNameSource: edbName, Frequency: sourceEdbInfo.Frequency, Unit: sourceEdbInfo.Unit, StartDate: sourceEdbInfo.StartDate, ClassifyId: classifyId, SysUserId: sysUserId, SysUserRealName: sysUserName, UniqueCode: utils.MD5(utils.DATA_PREFIX + "_" + timestamp), CreateTime: time.Now(), ModifyTime: time.Now(), MinValue: minValue, MaxValue: maxValue, CalculateFormula: sourceEdbInfo.CalculateFormula, EdbType: 1, //Sort: sourceEdbInfo., LatestDate: sourceEdbInfo.LatestDate, LatestValue: sourceEdbInfo.LatestValue, MoveType: sourceEdbInfo.MoveType, MoveFrequency: sourceEdbInfo.MoveFrequency, NoUpdate: sourceEdbInfo.NoUpdate, ServerUrl: "", EdbNameEn: edbName, UnitEn: sourceEdbInfo.UnitEn, DataDateType: dataDateType, Sort: models.GetAddEdbMaxSortByClassifyId(classifyId, utils.PREDICT_EDB_INFO_TYPE), } // 关联关系表 calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0) fromEdbMap := make(map[int]int) // 源指标关联关系表 calculateMappingItem := &models.EdbInfoCalculateMapping{ //EdbInfoCalculateMappingId: 0, //EdbInfoId: 0, Source: edbInfo.Source, SourceName: edbInfo.SourceName, EdbCode: edbInfo.EdbCode, FromEdbInfoId: sourceEdbInfo.EdbInfoId, FromEdbCode: sourceEdbInfo.EdbCode, FromEdbName: sourceEdbInfo.EdbName, FromSource: sourceEdbInfo.Source, FromSourceName: sourceEdbInfo.SourceName, //FromTag: "", Sort: 1, CreateTime: time.Now(), ModifyTime: time.Now(), } fromEdbMap[sourceEdbInfoId] = sourceEdbInfoId calculateMappingList = append(calculateMappingList, calculateMappingItem) // 动态环差 计算列表 calculateRuleMap := make(map[int]models.CalculateRule, 0) // 预测指标配置 predictEdbConfList := make([]*models.PredictEdbConf, 0) for ruleIndex, v := range ruleList { // 预测指标配置 ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local) if tmpErr != nil { errMsg = "规则配置的截止日期异常,请重新填写" err = errors.New(errMsg) return } //1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据 // 环比、环差、动态环差、季节性、移动平均同比不支持年度 if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) { errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标" err = errors.New(errMsg) return } switch v.RuleType { case 8: //N期段线性外推值 valInt, tmpErr := strconv.Atoi(v.Value) if tmpErr != nil { errMsg = "N期段线性外推值的N值异常" err = errors.New(errMsg) return } if valInt <= 1 { errMsg = "N期段线性外推值的N值必须大于1" err = errors.New(errMsg) return } case 9: //9:动态环差 if v.Value == "" { errMsg = "请填写计算规则" err = errors.New(errMsg) return } formula := v.Value formula = strings.Replace(formula, "(", "(", -1) formula = strings.Replace(formula, ")", ")", -1) formula = strings.Replace(formula, ",", ",", -1) formula = strings.Replace(formula, "。", ".", -1) formula = strings.Replace(formula, "%", "*0.01", -1) v.Value = formula //检验公式 var formulaStr string var edbInfoIdBytes []string for _, tmpEdbInfoId := range v.EdbInfoIdArr { formulaStr += tmpEdbInfoId.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag) } formulaSlice, tErr := utils.CheckFormulaJson(formula) if tErr != nil { errMsg = "公式格式错误,请重新填写" err = errors.New(errMsg) return } for _, fm := range formulaSlice { formulaMap, e := utils.CheckFormula(fm) if e != nil { err = fmt.Errorf("公式错误,请重新填写") return } for _, f := range formulaMap { if !strings.Contains(formulaStr, f) { errMsg = "公式错误,请重新填写" err = errors.New(errMsg) return } } } //关联的指标信息 edbInfoList := make([]*models.EdbInfo, 0) // 动态环差规则 关系表 trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0) for k, tmpEdbInfoId := range v.EdbInfoIdArr { fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId) if tmpErr != nil { err = tmpErr if err.Error() == utils.ErrNoRow() { errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在" err = errors.New(errMsg) return } errMsg = "获取指标失败:Err:" + err.Error() err = errors.New(errMsg) return } edbInfoList = append(edbInfoList, fromEdbInfo) //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则) { if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok { fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId calculateMappingItem := &models.EdbInfoCalculateMapping{ EdbInfoCalculateMappingId: 0, EdbInfoId: 0, Source: utils.DATA_SOURCE_CALCULATE, SourceName: "指标运算", EdbCode: "", FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, //FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } calculateMappingList = append(calculateMappingList, calculateMappingItem) } } // 动态环差规则 关系表 tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{ //PredictEdbConfCalculateMappingId: 0, EdbInfoId: 0, ConfigId: 0, FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping) } for _, f := range formulaSlice { formulaMap, e := utils.CheckFormula(f) if e != nil { err = fmt.Errorf("公式错误,请重新填写") return } //预先计算,判断公式是否正常 ok, _ := models.CheckFormula2(edbInfoList, formulaMap, f, edbInfoIdBytes) if !ok { errMsg = "生成计算指标失败,请使用正确的计算公式" err = errors.New(errMsg) return } } calculateRuleMap[ruleIndex] = models.CalculateRule{ TrendsCalculateMappingList: trendsMappingList, EdbInfoList: edbInfoList, EdbInfoIdBytes: edbInfoIdBytes, Formula: formula, RuleType: v.RuleType, EndDate: v.EndDate, EdbInfoIdArr: v.EdbInfoIdArr, } case 14: //14:根据 一元线性拟合 规则获取预测数据 if v.Value == "" { errMsg = "请填写一元线性拟合规则" err = errors.New(errMsg) return } //关联的指标信息 edbInfoList := make([]*models.EdbInfo, 0) // 动态环差规则 关系表 trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0) for k, tmpEdbInfoId := range v.EdbInfoIdArr { fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId) if tmpErr != nil { err = tmpErr if err.Error() == utils.ErrNoRow() { errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在" err = errors.New(errMsg) return } errMsg = "获取指标失败:Err:" + err.Error() err = errors.New(errMsg) return } edbInfoList = append(edbInfoList, fromEdbInfo) //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则) { if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok { fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{ EdbInfoCalculateMappingId: 0, EdbInfoId: 0, Source: utils.DATA_SOURCE_CALCULATE, SourceName: "指标运算", EdbCode: "", FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, //FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem) } } // 动态环差规则 关系表 tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{ //PredictEdbConfCalculateMappingId: 0, EdbInfoId: 0, ConfigId: 0, FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping) } calculateRuleMap[ruleIndex] = models.CalculateRule{ TrendsCalculateMappingList: trendsMappingList, EdbInfoList: edbInfoList, //EdbInfoIdBytes: edbInfoIdBytes, //Formula: formula, RuleType: v.RuleType, EndDate: v.EndDate, EdbInfoIdArr: v.EdbInfoIdArr, } } tmpPredictEdbConf := &models.PredictEdbConf{ PredictEdbInfoId: 0, SourceEdbInfoId: sourceEdbInfoId, RuleType: v.RuleType, //FixedValue: v.Value, Value: v.Value, EndDate: ruleEndDate, ModifyTime: time.Now(), CreateTime: time.Now(), } edbInfo.EndDate = v.EndDate predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf) } err, errMsg = models.AddPredictEdb(edbInfo, calculateMappingList, predictEdbConfList, calculateRuleMap) return } // EditPredictEdbInfo 编辑预测指标 func EditPredictEdbInfo(edbInfoId, classifyId int, edbName, dataDateType string, ruleList []models.RuleConfig, minValue, maxValue float64, lang string) (edbInfo *models.EdbInfo, err error, errMsg string) { // 指标信息校验 { edbInfo, err = models.GetEdbInfoById(edbInfoId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "修改失败" err = errors.New("获取预测指标失败,Err:" + err.Error()) return } if edbInfo == nil { errMsg = "找不到该预测指标" err = errors.New(errMsg) return } //必须是普通的指标 if edbInfo.EdbInfoType != 1 { errMsg = "指标异常,不是预测指标" err = errors.New(errMsg) return } } var predictEdbConf *models.PredictEdbConf // 指标配置信息校验 { // 查找该预测指标配置 predictEdbConfList, tmpErr := models.GetPredictEdbConfListById(edbInfo.EdbInfoId) if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() { errMsg = "修改失败" err = errors.New("获取预测指标配置信息失败,Err:" + tmpErr.Error()) return } if len(predictEdbConfList) == 0 { errMsg = "找不到该预测指标配置" err = errors.New(errMsg) return } predictEdbConf = predictEdbConfList[0] } // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := CheckExistByEdbNameAndEdbInfoId(utils.PREDICT_EDB_INFO_TYPE, edbInfoId, edbName, lang) if err != nil { errMsg = "判断指标名称是否存在失败" err = errors.New("判断指标名称是否存在失败,Err:" + err.Error()) return } if existEdbName { errMsg = "指标名称已存在,请重新填写" err = errors.New(errMsg) return } if dataDateType == `` { dataDateType = `自然日` } switch lang { case utils.EnLangVersion: edbInfo.EdbNameEn = edbName default: edbInfo.EdbName = edbName } edbInfo.EdbNameSource = edbName edbInfo.ClassifyId = classifyId edbInfo.MinValue = minValue edbInfo.MaxValue = maxValue edbInfo.DataDateType = dataDateType edbInfo.ModifyTime = time.Now() updateEdbInfoCol := []string{"EdbName", "EdbNameEn", "EdbNameSource", "ClassifyId", "EndDate", "MinValue", "MaxValue", "DataDateType", "ModifyTime"} var sourceEdbInfo *models.EdbInfo // 来源指标信息校验 { sourceEdbInfo, err = models.GetEdbInfoById(predictEdbConf.SourceEdbInfoId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "新增失败" err = errors.New("获取来源指标失败,Err:" + err.Error()) return } if sourceEdbInfo == nil { errMsg = "找不到该来源指标" err = errors.New(errMsg) return } //必须是普通的指标 if sourceEdbInfo.EdbInfoType != 0 { errMsg = "来源指标异常,不是普通的指标" err = errors.New(errMsg) return } //if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) { // errMsg = "预测指标只支持选择日度、周度、月度、年度的指标" // err = errors.New(errMsg) // return //} } // 预测指标配置 // 关联关系表 calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0) fromEdbMap := make(map[int]int) // 源指标关联关系表 calculateMappingItem := &models.EdbInfoCalculateMapping{ //EdbInfoCalculateMappingId: 0, EdbInfoId: edbInfoId, Source: edbInfo.Source, SourceName: edbInfo.SourceName, EdbCode: edbInfo.EdbCode, FromEdbInfoId: sourceEdbInfo.EdbInfoId, FromEdbCode: sourceEdbInfo.EdbCode, FromEdbName: sourceEdbInfo.EdbName, FromSource: sourceEdbInfo.Source, FromSourceName: sourceEdbInfo.SourceName, //FromTag: "", Sort: 1, CreateTime: time.Now(), ModifyTime: time.Now(), } fromEdbMap[sourceEdbInfo.EdbInfoId] = sourceEdbInfo.EdbInfoId calculateMappingList = append(calculateMappingList, calculateMappingItem) // 动态环差 计算列表 calculateRuleMap := make(map[int]models.CalculateRule, 0) // 预测指标配置 predictEdbConfList := make([]*models.PredictEdbConf, 0) for ruleIndex, v := range ruleList { // 预测指标配置 ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local) if tmpErr != nil { errMsg = "规则配置的截止日期异常,请重新填写" err = errors.New(errMsg) return } //1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据 // 环比、环差、动态环差、季节性、移动平均同比不支持年度 if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) { errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标" err = errors.New(errMsg) return } switch v.RuleType { case 8: //N期段线性外推值 valInt, tmpErr := strconv.Atoi(v.Value) if tmpErr != nil { errMsg = "N期段线性外推值的N值异常" err = errors.New(errMsg) return } if valInt <= 1 { errMsg = "N期段线性外推值的N值必须大于1" err = errors.New(errMsg) return } case 9: //9:动态环差 if v.Value == "" { errMsg = "请填写计算规则" err = errors.New(errMsg) return } formula := v.Value formula = strings.Replace(formula, "(", "(", -1) formula = strings.Replace(formula, ")", ")", -1) formula = strings.Replace(formula, ",", ",", -1) formula = strings.Replace(formula, "。", ".", -1) formula = strings.Replace(formula, "%", "*0.01", -1) v.Value = formula //检验公式 var formulaStr string var edbInfoIdBytes []string for _, tmpEdbInfoId := range v.EdbInfoIdArr { formulaStr += tmpEdbInfoId.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag) } formulaSlice, tErr := utils.CheckFormulaJson(formula) if tErr != nil { errMsg = "公式格式错误,请重新填写" err = errors.New(errMsg) return } for _, fm := range formulaSlice { formulaMap, e := utils.CheckFormula(fm) if e != nil { err = fmt.Errorf("公式错误,请重新填写") return } for _, f := range formulaMap { if !strings.Contains(formulaStr, f) { errMsg = "公式错误,请重新填写" err = errors.New(errMsg) return } } } //关联的指标信息 edbInfoList := make([]*models.EdbInfo, 0) // 动态环差规则 关系表 trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0) for k, tmpEdbInfoId := range v.EdbInfoIdArr { fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId) if tmpErr != nil { err = tmpErr if err.Error() == utils.ErrNoRow() { errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在" err = errors.New(errMsg) return } errMsg = "获取指标失败:Err:" + err.Error() err = errors.New(errMsg) return } edbInfoList = append(edbInfoList, fromEdbInfo) //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则) { if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok { fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId calculateMappingItem := &models.EdbInfoCalculateMapping{ EdbInfoCalculateMappingId: 0, EdbInfoId: edbInfoId, Source: utils.DATA_SOURCE_CALCULATE, SourceName: "指标运算", EdbCode: "", FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, //FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } calculateMappingList = append(calculateMappingList, calculateMappingItem) } } // 动态环差规则 关系表 tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{ //PredictEdbConfCalculateMappingId: 0, EdbInfoId: edbInfoId, ConfigId: 0, FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping) } for _, f := range formulaSlice { formulaMap, e := utils.CheckFormula(f) if e != nil { err = fmt.Errorf("公式错误,请重新填写") return } //预先计算,判断公式是否正常 ok, _ := models.CheckFormula2(edbInfoList, formulaMap, f, edbInfoIdBytes) if !ok { errMsg = "生成计算指标失败,请使用正确的计算公式" err = errors.New(errMsg) return } } calculateRuleMap[ruleIndex] = models.CalculateRule{ TrendsCalculateMappingList: trendsMappingList, EdbInfoList: edbInfoList, EdbInfoIdBytes: edbInfoIdBytes, Formula: formula, RuleType: v.RuleType, EndDate: v.EndDate, EdbInfoIdArr: v.EdbInfoIdArr, } case 14: //14:根据 一元线性拟合 规则获取预测数据 if v.Value == "" { errMsg = "请填写一元线性拟合规则" err = errors.New(errMsg) return } //关联的指标信息 edbInfoList := make([]*models.EdbInfo, 0) // 动态环差规则 关系表 trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0) for k, tmpEdbInfoId := range v.EdbInfoIdArr { fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId) if tmpErr != nil { err = tmpErr if err.Error() == utils.ErrNoRow() { errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在" err = errors.New(errMsg) return } errMsg = "获取指标失败:Err:" + err.Error() err = errors.New(errMsg) return } edbInfoList = append(edbInfoList, fromEdbInfo) //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则) { if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok { fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{ EdbInfoCalculateMappingId: 0, EdbInfoId: 0, Source: utils.DATA_SOURCE_CALCULATE, SourceName: "指标运算", EdbCode: "", FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, //FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem) } } // 动态环差规则 关系表 tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{ //PredictEdbConfCalculateMappingId: 0, EdbInfoId: 0, ConfigId: 0, FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: tmpEdbInfoId.FromTag, Sort: k + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping) } calculateRuleMap[ruleIndex] = models.CalculateRule{ TrendsCalculateMappingList: trendsMappingList, EdbInfoList: edbInfoList, //EdbInfoIdBytes: edbInfoIdBytes, //Formula: formula, RuleType: v.RuleType, EndDate: v.EndDate, EdbInfoIdArr: v.EdbInfoIdArr, } } tmpPredictEdbConf := &models.PredictEdbConf{ PredictEdbInfoId: edbInfoId, SourceEdbInfoId: sourceEdbInfo.EdbInfoId, RuleType: v.RuleType, //FixedValue: v.Value, Value: v.Value, EndDate: ruleEndDate, ModifyTime: time.Now(), CreateTime: time.Now(), } edbInfo.EndDate = v.EndDate predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf) } err, errMsg = models.EditPredictEdb(edbInfo, updateEdbInfoCol, calculateMappingList, predictEdbConfList, calculateRuleMap) return } // RefreshPredictEdbInfo 更新基础预测指标规则中的动态数据 func RefreshPredictEdbInfo(edbInfoId int) (edbInfo *models.EdbInfo, err error, errMsg string) { // 指标信息校验 { edbInfo, err = models.GetEdbInfoById(edbInfoId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "刷新失败" err = errors.New("获取预测指标失败,Err:" + err.Error()) return } if edbInfo == nil { errMsg = "找不到该预测指标" err = nil return } //必须是普通的指标 if edbInfo.EdbInfoType != 1 { errMsg = "指标异常,不是预测指标" return } } // 配置 与 指标的 关联关系表 list, err := models.GetPredictEdbConfCalculateMappingListByEdbInfoId(edbInfoId) if err != nil { return } // 没有关联指标,不需要刷新 if len(list) <= 0 { return } // 配置关联的指标信息 predictEdbConfCalculateMappingListMap := make(map[int][]*models.PredictEdbConfCalculateMapping) configIdList := make([]int, 0) //关联配置id edbInfoIdList := make([]int, 0) //关联指标配置id edbInfoIdMap := make(map[int]int, 0) //关联指标配置map for _, v := range list { configList, ok := predictEdbConfCalculateMappingListMap[v.ConfigId] if !ok { configList = make([]*models.PredictEdbConfCalculateMapping, 0) configIdList = append(configIdList, v.ConfigId) } if _, ok := edbInfoIdMap[v.FromEdbInfoId]; !ok { edbInfoIdList = append(edbInfoIdList, v.FromEdbInfoId) } configList = append(configList, v) predictEdbConfCalculateMappingListMap[v.ConfigId] = configList } predictEdbConfList, err := models.GetPredictEdbConfListByConfigIdList(configIdList) if err != nil { errMsg = "刷新失败" err = errors.New("获取预测指标配置信息失败,Err:" + err.Error()) return } if len(predictEdbConfList) == 0 { errMsg = "找不到该预测指标配置" err = nil return } // 指标信息 edbInfoList, err := models.GetEdbInfoByIdList(edbInfoIdList) if err != nil { err = errors.New("获取关联指标失败,Err:" + err.Error()) return } // 指标信息map edbInfoListMap := make(map[int]*models.EdbInfo) for _, v := range edbInfoList { edbInfoListMap[v.EdbInfoId] = v } predictEdbConfAndDataList := make([]*models.PredictEdbConfAndData, 0) // 刷新所有的规则 for _, v := range predictEdbConfList { // 每次规则计算的时候,产生的临时数据 resultDataList := make([]*models.EdbInfoSearchData, 0) switch v.RuleType { case 9: //动态环差值 if v.Value == "" { errMsg = "请填写计算规则" return } // todo 动态环差的空值类型处理 formula := v.Value // 动态环差规则 关系表 trendsMappingList := predictEdbConfCalculateMappingListMap[v.ConfigId] // 关联标签 edbInfoIdArr := make([]models.EdbInfoFromTag, 0) //关联的指标信息 edbInfoList := make([]*models.EdbInfo, 0) for _, trendsMapping := range trendsMappingList { tmpEdbInfo, ok := edbInfoListMap[trendsMapping.FromEdbInfoId] if ok { edbInfoList = append(edbInfoList, tmpEdbInfo) } // 关联标签 edbInfoIdArr = append(edbInfoIdArr, models.EdbInfoFromTag{ EdbInfoId: trendsMapping.FromEdbInfoId, FromTag: trendsMapping.FromTag, }) } //检验公式 var formulaStr string var edbInfoIdBytes []string for _, tmpEdbInfoId := range edbInfoIdArr { formulaStr += tmpEdbInfoId.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag) } formulaSlice, tErr := utils.CheckFormulaJson(formula) if tErr != nil { errMsg = "公式格式错误,请重新填写" err = errors.New(errMsg) return } for _, fm := range formulaSlice { formulaMap, e := utils.CheckFormula(fm) if e != nil { err = fmt.Errorf("公式错误,请重新填写") return } for _, f := range formulaMap { if !strings.Contains(formulaStr, f) { errMsg = "公式错误,请重新填写" err = errors.New(errMsg) return } } //预先计算,判断公式是否正常 ok, _ := models.CheckFormula2(edbInfoList, formulaMap, fm, edbInfoIdBytes) if !ok { errMsg = "生成计算指标失败,请使用正确的计算公式" return } } rule := models.CalculateRule{ EdbInfoId: v.PredictEdbInfoId, ConfigId: v.ConfigId, TrendsCalculateMappingList: trendsMappingList, EdbInfoList: edbInfoList, EdbInfoIdBytes: edbInfoIdBytes, Formula: formula, RuleType: v.RuleType, EndDate: v.EndDate.Format(utils.FormatDate), EdbInfoIdArr: edbInfoIdArr, } resultDataList, err = models.RefreshCalculateByRuleBy9(rule) if err != nil { return } case 14: //14:根据 一元线性拟合 规则获取预测数据 if v.Value == "" { errMsg = "一元线性拟合规则信息未配置" return } err, errMsg = models.RefreshCalculateByRuleByLineNh(*edbInfo, predictEdbConfAndDataList, *v) if err != nil { return } } // 规则配置(含数据) tmpPredictEdbConfAndData := &models.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 } // checkExistByEdbName // @Description: 根据指标名称校验该指标是否存在库中 // @author: Roc // @datetime 2024-04-18 14:58:52 // @param edbInfoType int // @param edbName string // @param lang string // @return has bool // @return err error func checkExistByEdbName(edbInfoType int, edbName, lang string) (has bool, err error) { var condition string var pars []interface{} condition += " AND edb_info_type=? " pars = append(pars, edbInfoType) switch lang { case utils.EnLangVersion: condition += " AND edb_name_en = ? " default: condition += " AND edb_name=? " } pars = append(pars, edbName) count, err := models.GetEdbInfoCountByCondition(condition, pars) if err != nil { return } if count > 0 { has = true return } return } // checkExistByEdbNameAndEdbInfoId // @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标 // @author: Roc // @datetime 2024-04-18 15:00:19 // @param edbInfoType int // @param edbInfoId int // @param edbName string // @param lang string // @return has bool // @return err error func checkExistByEdbNameAndEdbInfoId(edbInfoType, edbInfoId int, edbName, lang string) (has bool, err error) { var condition string var pars []interface{} condition += " AND edb_info_type=? " pars = append(pars, edbInfoType) condition += " AND edb_info_id<>? " pars = append(pars, edbInfoId) switch lang { case utils.EnLangVersion: condition += " AND edb_name_en = ? " default: condition += " AND edb_name=? " } pars = append(pars, edbName) count, err := models.GetEdbInfoCountByCondition(condition, pars) if err != nil { return } if count > 0 { has = true return } return } // CheckExistByEdbNameAndEdbInfoId // @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标 // @author: Roc // @datetime 2024-04-18 15:01:44 // @param edbInfoType int // @param edbInfoId int // @param edbName string // @param lang string // @return has bool // @return err error func CheckExistByEdbNameAndEdbInfoId(edbInfoType, edbInfoId int, edbName, lang string) (has bool, err error) { // 指标没有入库的情况 if edbInfoId == 0 { return checkExistByEdbName(edbInfoType, edbName, lang) } //指标已经入库的情况 return checkExistByEdbNameAndEdbInfoId(edbInfoType, edbInfoId, edbName, lang) } // AddStaticPredictEdbInfo 新增静态指标数据 func AddStaticPredictEdbInfo(sourceEdbInfoId, classifyId int, edbName, frequency, unit string, sysUserId int, sysUserName, lang string) (edbInfo *models.EdbInfo, err error, errMsg string) { var sourceEdbInfo *models.EdbInfo // 来源指标信息校验 { sourceEdbInfo, err = models.GetEdbInfoById(sourceEdbInfoId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "新增失败" err = errors.New("获取来源指标失败,Err:" + err.Error()) return } if sourceEdbInfo == nil { errMsg = "找不到该来源指标" err = errors.New(errMsg) return } } var classifyInfo *models.EdbClassify // 来源分类信息校验 { classifyInfo, err = models.GetEdbClassifyById(classifyId) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "新增失败" err = errors.New("获取预测指标分类失败,Err:" + err.Error()) return } if classifyInfo == nil { errMsg = "找不到该预测指标分类" err = errors.New(errMsg) return } //必须是预测指标分类 if classifyInfo.ClassifyType != 1 { errMsg = "预测指标分类异常,不是预测指标分类" err = errors.New(errMsg) return } } edbName = strings.Trim(edbName, " ") edbCode := sourceEdbInfo.EdbCode + "_" + time.Now().Format(utils.FormatShortDateTimeUnSpace) // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := CheckExistByEdbNameAndEdbInfoId(utils.PREDICT_EDB_INFO_TYPE, 0, edbName, lang) if err != nil { errMsg = "判断指标名称是否存在失败" err = errors.New("判断指标名称是否存在失败,Err:" + err.Error()) return } if existEdbName { errMsg = "指标名称已存在,请重新填写" err = errors.New(errMsg) return } timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) edbInfo = &models.EdbInfo{ //EdbInfoId: 0, EdbInfoType: sourceEdbInfo.EdbInfoType, SourceName: sourceEdbInfo.SourceName, Source: sourceEdbInfo.Source, EdbCode: edbCode, EdbName: edbName, EdbNameSource: edbName, Frequency: frequency, Unit: unit, StartDate: sourceEdbInfo.StartDate, EndDate: sourceEdbInfo.EndDate, ClassifyId: classifyId, SysUserId: sysUserId, SysUserRealName: sysUserName, UniqueCode: utils.MD5(utils.DATA_PREFIX + "_" + timestamp), CreateTime: time.Now(), ModifyTime: time.Now(), MinValue: sourceEdbInfo.MinValue, MaxValue: sourceEdbInfo.MaxValue, EndValue: sourceEdbInfo.EndValue, CalculateFormula: sourceEdbInfo.CalculateFormula, EdbType: sourceEdbInfo.EdbType, //Sort: sourceEdbInfo., LatestDate: sourceEdbInfo.LatestDate, LatestValue: sourceEdbInfo.LatestValue, MoveType: sourceEdbInfo.MoveType, MoveFrequency: sourceEdbInfo.MoveFrequency, NoUpdate: sourceEdbInfo.NoUpdate, IsUpdate: sourceEdbInfo.IsUpdate, ServerUrl: "", EdbNameEn: edbName, UnitEn: sourceEdbInfo.UnitEn, DataDateType: sourceEdbInfo.DataDateType, Sort: models.GetAddEdbMaxSortByClassifyId(classifyId, utils.PREDICT_EDB_INFO_TYPE), IsStaticData: 1, } // 关联关系表 calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0) fromEdbMap := make(map[int]int) // 源指标关联关系表 calculateMappingItem := &models.EdbInfoCalculateMapping{ //EdbInfoCalculateMappingId: 0, //EdbInfoId: 0, Source: edbInfo.Source, SourceName: edbInfo.SourceName, EdbCode: edbInfo.EdbCode, FromEdbInfoId: sourceEdbInfo.EdbInfoId, FromEdbCode: sourceEdbInfo.EdbCode, FromEdbName: sourceEdbInfo.EdbName, FromSource: sourceEdbInfo.Source, FromSourceName: sourceEdbInfo.SourceName, //FromTag: "", Sort: 1, CreateTime: time.Now(), ModifyTime: time.Now(), } fromEdbMap[sourceEdbInfoId] = sourceEdbInfoId calculateMappingList = append(calculateMappingList, calculateMappingItem) newPredictEdbConfList := make([]*models.PredictEdbConf, 0) //查询原先的预测指标配置项 if sourceEdbInfo.EdbType == 1 { // 查找该预测指标配置 predictEdbConfList, tmpErr := models.GetPredictEdbConfListById(sourceEdbInfo.EdbInfoId) if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() { errMsg = "获取预测指标配置信息失败" err = errors.New("获取预测指标配置信息失败,Err:" + tmpErr.Error()) return } if len(predictEdbConfList) > 0 { // 遍历 for _, v := range predictEdbConfList { tmpPredictEdbConf := &models.PredictEdbConf{ PredictEdbInfoId: 0, SourceEdbInfoId: sourceEdbInfoId, RuleType: v.RuleType, FixedValue: v.FixedValue, Value: v.Value, EmptyType: v.EmptyType, MaxEmptyType: v.MaxEmptyType, EndDate: v.EndDate, ModifyTime: time.Now(), CreateTime: time.Now(), } newPredictEdbConfList = append(newPredictEdbConfList, tmpPredictEdbConf) } } } err, errMsg = models.AddPredictStaticEdb(edbInfo, sourceEdbInfo, calculateMappingList, newPredictEdbConfList) return }