package controllers import ( "encoding/json" "eta/eta_index_lib/logic" "eta/eta_index_lib/models" "eta/eta_index_lib/utils" "fmt" "strconv" "strings" "time" ) // PredictCalculateController 预测计算指标 type PredictCalculateController struct { BaseAuthController } // Save // @Title 新增/编辑预测指标运算接口 // @Description 新增预测指标运算接口 // @Success 200 {object} models.EdbInfoCalculateSaveReq // @router /save [post] func (this *PredictCalculateController) Save() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.EdbInfoCalculateSaveReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.EdbInfoId <= 0 { addPredictCalculate(br, req) } else { editPredictCalculate(br, req) } } // AddPredictCalculate 添加预测指标运算 func addPredictCalculate(br *models.BaseResponse, req models.EdbInfoCalculateSaveReq) { req.EdbName = strings.Trim(req.EdbName, " ") if req.EdbName == "" { br.Msg = "指标名称不能为空" return } if req.Frequency == "" { br.Msg = "频率不能为空" return } if req.Unit == "" { br.Msg = "单位不能为空" return } if req.ClassifyId <= 0 { br.Msg = "请选择分类" return } if len(req.EdbInfoIdArr) <= 0 { br.Msg = "请选择指标" return } if req.CalculateFormula == "" { br.Msg = "请填写指标" return } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("predict_edb_info:calculate:batch:save:", utils.DATA_SOURCE_PREDICT_CALCULATE, ":", req.EdbName) isExist := utils.Rc.IsExist(redisKey) if isExist { br.Msg = "指标正在处理,请勿重复提交" return } else { //设置3分钟缓存 utils.Rc.SetNX(redisKey, 1, time.Second*300) defer func() { _ = utils.Rc.Delete(redisKey) }() } calculateFormula := req.CalculateFormula calculateFormula = strings.Replace(calculateFormula, "(", "(", -1) calculateFormula = strings.Replace(calculateFormula, ")", ")", -1) calculateFormula = strings.Replace(calculateFormula, ",", ",", -1) calculateFormula = strings.Replace(calculateFormula, "。", ".", -1) if strings.Contains(req.CalculateFormula, "%") { calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1) } req.CalculateFormula = calculateFormula //检验公式 var formulaStr string var edbInfoIdBytes []string for _, v := range req.EdbInfoIdArr { formulaStr += v.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag) } formulaSlice, err := utils.CheckFormulaJson(req.CalculateFormula) if err != nil { br.Msg = "公式格式错误,请重新填写" return } for _, formula := range formulaSlice { formulaMap, e := utils.CheckFormula(formula) if e != nil { br.Msg = "公式错误,请重新填写" return } for _, v := range formulaMap { if !strings.Contains(formulaStr, v) { br.Msg = "公式错误,请重新填写" return } } } // 判断指标名称是否存在 { var condition string var pars []interface{} // 指标类型,0:普通指标,1:预测指标 condition += " AND edb_info_type=? AND edb_name=? " pars = append(pars, 1, req.EdbName) count, err := models.GetEdbInfoCountByCondition(condition, pars) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if count > 0 { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" return } } // 关联指标信息 edbInfoList := make([]*models.EdbInfo, 0) calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0) for k, v := range req.EdbInfoIdArr { fromEdbInfo, err := models.GetEdbInfoById(v.EdbInfoId) if err != nil { if err.Error() == utils.ErrNoRow() { br.Msg = "生成计算指标失败" br.Msg = "指标 " + strconv.Itoa(v.EdbInfoId) + " 不存在" return } br.Msg = "生成计算指标失败" br.Msg = "获取指标失败:Err:" + err.Error() return } edbInfoList = append(edbInfoList, fromEdbInfo) //关联关系表 { calculateMappingItem := &models.EdbInfoCalculateMapping{ CreateTime: time.Now(), ModifyTime: time.Now(), Sort: k + 1, //EdbCode: edbCode, //EdbInfoId: int(edbInfoId), FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: v.FromTag, Source: utils.DATA_SOURCE_PREDICT_CALCULATE, SourceName: "预测指标运算", } calculateMappingList = append(calculateMappingList, calculateMappingItem) } } for _, v := range formulaSlice { formulaMap, e := utils.CheckFormula(v) if e != nil { br.Msg = "公式错误,请重新填写" return } //预先计算,判断公式是否正常 ok, _ := models.CheckFormula2(edbInfoList, formulaMap, v, edbInfoIdBytes) if !ok { br.Msg = "生成计算指标失败,请使用正确的计算公式" return } } // 指标入库 randStr := utils.GetRandDigit(4) edbCode := `C2` + time.Now().Format("060102") + randStr timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp) edbInfo := &models.EdbInfo{ EdbInfoType: 1, Source: utils.DATA_SOURCE_PREDICT_CALCULATE, SourceName: "预测指标运算", EdbCode: edbCode, EdbName: req.EdbName, EdbNameSource: req.EdbName, Frequency: req.Frequency, Unit: req.Unit, ClassifyId: req.ClassifyId, SysUserId: req.AdminId, SysUserRealName: req.AdminName, CreateTime: time.Now(), ModifyTime: time.Now(), UniqueCode: uniqueCode, CalculateFormula: req.CalculateFormula, EdbType: 2, EmptyType: req.EmptyType, MaxEmptyType: req.MaxEmptyType, } edbInfoId, err := models.AddEdbInfo(edbInfo) if err != nil { br.Msg = "生成计算指标失败" br.Msg = "生成计算指标失败,AddEdbInfo Err:" + err.Error() return } edbInfo.EdbInfoId = int(edbInfoId) //处理同名指标 { edbNameList, err := models.GetEdbInfoByName(req.EdbName) if err != nil { br.Msg = "保存失败" br.ErrMsg = "获取指标信息失败,Err:" + err.Error() return } if len(edbNameList) >= 2 { for _, v := range edbNameList { edbName := v.EdbName + "(" + v.SourceName + ")" err = models.ModifyEdbInfoNameSource(edbName, v.EdbInfoId) if err != nil { br.Msg = "保存失败" br.ErrMsg = "修改指标名称失败,Err:" + err.Error() return } } } } //关联关系表入库 { if len(calculateMappingList) > 0 { for k, v := range calculateMappingList { v.EdbCode = edbInfo.EdbCode v.EdbInfoId = edbInfo.EdbInfoId calculateMappingList[k] = v } go models.AddEdbInfoCalculateMappingMulti(calculateMappingList) } } // 开始添加预测指标 latestDateStr, latestValue, err := models.AddPredictCalculateData(edbInfoList, edbInfo, edbCode, req.CalculateFormula, edbInfoIdBytes) if err != nil { br.Msg = "生成计算指标失败" br.Msg = "生成计算指标失败,Calculate Err:" + err.Error() return } // 更新指标最大最小值 err, errMsg := models.UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } resp := models.AddEdbInfoResp{ EdbInfoId: int(edbInfoId), UniqueCode: uniqueCode, } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // editPredictCalculate 编辑预测指标运算 func editPredictCalculate(br *models.BaseResponse, req models.EdbInfoCalculateSaveReq) { req.EdbName = strings.Trim(req.EdbName, " ") if req.EdbName == "" { br.Msg = "指标名称不能为空" return } if req.Frequency == "" { br.Msg = "频率不能为空" return } if req.Unit == "" { br.Msg = "单位不能为空" return } if req.ClassifyId <= 0 { br.Msg = "请选择分类" return } if len(req.EdbInfoIdArr) <= 0 { br.Msg = "请选择指标" return } if req.CalculateFormula == "" { br.Msg = "请填写指标" return } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("predict_edb_info:calculate:batch:save:", utils.DATA_SOURCE_PREDICT_CALCULATE, ":", req.EdbName) isExist := utils.Rc.IsExist(redisKey) if isExist { br.Msg = "指标正在处理,请勿重复提交" // return } else { //设置3分钟缓存 utils.Rc.SetNX(redisKey, 1, time.Second*300) defer func() { _ = utils.Rc.Delete(redisKey) }() } calculateFormula := req.CalculateFormula calculateFormula = strings.Replace(calculateFormula, "(", "(", -1) calculateFormula = strings.Replace(calculateFormula, ")", ")", -1) calculateFormula = strings.Replace(calculateFormula, ",", ",", -1) calculateFormula = strings.Replace(calculateFormula, "。", ".", -1) if strings.Contains(req.CalculateFormula, "%") { calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1) } req.CalculateFormula = calculateFormula //检验公式 var formulaStr string var edbInfoIdBytes []string for _, v := range req.EdbInfoIdArr { formulaStr += v.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag) } formulaSlice, err := utils.CheckFormulaJson(req.CalculateFormula) if err != nil { br.Msg = "公式格式错误,请重新填写" return } for _, formula := range formulaSlice { formulaMap, e := utils.CheckFormula(formula) if e != nil { br.Msg = "公式错误,请重新填写" return } for _, v := range formulaMap { if !strings.Contains(formulaStr, v) { br.Msg = "公式错误,请重新填写" return } } } // 获取计算指标信息 edbInfo, err := models.GetEdbInfoById(req.EdbInfoId) if err != nil { br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败,Err:" + err.Error() return } // 判断指标名称是否存在 { var condition string var pars []interface{} // 指标类型,0:普通指标,1:预测指标 condition += " AND edb_info_id !=? AND edb_info_type=? AND edb_name=? " pars = append(pars, edbInfo.EdbInfoId, edbInfo.EdbInfoType, req.EdbName) count, err := models.GetEdbInfoCountByCondition(condition, pars) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if count > 0 { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" return } } // 关联指标信息 edbInfoList := make([]*models.EdbInfo, 0) calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0) for k, v := range req.EdbInfoIdArr { fromEdbInfo, err := models.GetEdbInfoById(v.EdbInfoId) if err != nil { if err.Error() == utils.ErrNoRow() { br.Msg = "生成计算指标失败" br.Msg = "指标 " + strconv.Itoa(v.EdbInfoId) + " 不存在" return } br.Msg = "生成计算指标失败" br.Msg = "获取指标失败:Err:" + err.Error() return } edbInfoList = append(edbInfoList, fromEdbInfo) //关联关系表 { calculateMappingItem := &models.EdbInfoCalculateMapping{ CreateTime: time.Now(), ModifyTime: time.Now(), Sort: k + 1, EdbCode: edbInfo.EdbCode, EdbInfoId: edbInfo.EdbInfoId, FromEdbInfoId: fromEdbInfo.EdbInfoId, FromEdbCode: fromEdbInfo.EdbCode, FromEdbName: fromEdbInfo.EdbName, FromSource: fromEdbInfo.Source, FromSourceName: fromEdbInfo.SourceName, FromTag: v.FromTag, Source: utils.DATA_SOURCE_PREDICT_CALCULATE, SourceName: "预测指标运算", } calculateMappingList = append(calculateMappingList, calculateMappingItem) } } for _, v := range formulaSlice { formulaMap, e := utils.CheckFormula(v) if e != nil { br.Msg = "公式错误,请重新填写" return } //预先计算,判断公式是否正常 ok, _ := models.CheckFormula2(edbInfoList, formulaMap, v, edbInfoIdBytes) if !ok { br.Msg = "生成计算指标失败,请使用正确的计算公式" return } } //处理同名指标 { edbNameList, err := models.GetEdbInfoByName(req.EdbName) if err != nil { br.Msg = "保存失败" br.ErrMsg = "获取指标信息失败,Err:" + err.Error() return } if len(edbNameList) >= 2 { for _, v := range edbNameList { edbName := v.EdbName + "(" + v.SourceName + ")" err = models.ModifyEdbInfoNameSource(edbName, v.EdbInfoId) if err != nil { br.Msg = "保存失败" br.ErrMsg = "修改指标名称失败,Err:" + err.Error() return } } } } edbInfo.EdbName = req.EdbName edbInfo.Frequency = req.Frequency edbInfo.Unit = req.Unit edbInfo.ClassifyId = req.ClassifyId edbInfo.CalculateFormula = req.CalculateFormula edbInfo.EmptyType = req.EmptyType edbInfo.MaxEmptyType = req.MaxEmptyType err = models.EditPredictCalculate(edbInfo, calculateMappingList) if err != nil { br.Msg = "修改计算指标失败" br.Msg = "修改计算指标失败,Calculate Err:" + err.Error() return } // 开始添加预测指标 latestDateStr, latestValue, err := models.AddPredictCalculateData(edbInfoList, edbInfo, edbInfo.EdbCode, req.CalculateFormula, edbInfoIdBytes) if err != nil { br.Msg = "生成计算指标失败" br.Msg = "生成计算指标失败,Calculate Err:" + err.Error() return } // 更新指标最大最小值 err, errMsg := models.UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: edbInfo.UniqueCode, } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // CalculateBatchSave // @Title 累计值转月-同比值-同差等计算新增 // @Description 累计值转月-同比值-同差等计算新增接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /batch/save [post] func (this *PredictCalculateController) CalculateBatchSave() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.EdbInfoCalculateBatchSaveReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } req.EdbName = strings.Trim(req.EdbName, " ") if req.EdbName == "" { br.Msg = "指标名称不能为空" return } if req.Frequency == "" { br.Msg = "频率不能为空" return } if req.Unit == "" { br.Msg = "单位不能为空" return } if req.ClassifyId <= 0 { br.Msg = "请选择分类" return } // 基础指标id fromEdbInfoId := req.FromEdbInfoId notNeedFromEdbSourceList := []int{utils.DATA_SOURCE_PREDICT_CALCULATE_KSZS, utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC} // 不需要传入来源指标id的 指标类型 if fromEdbInfoId <= 0 && !utils.InArrayByInt(notNeedFromEdbSourceList, req.Source) { br.Msg = "请选择指标" return } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("edb_lib:predict_calculate:batch:save:", req.Source, ":", req.EdbName) isExist := utils.Rc.IsExist(redisKey) if isExist { br.Msg = "指标正在处理,请勿重复提交" return } else { //设置3分钟缓存 utils.Rc.SetNX(redisKey, 1, time.Second*300) defer func() { _ = utils.Rc.Delete(redisKey) }() } //加入缓存机制,避免创建同一个名称的指标 end var condition string var pars []interface{} condition += " AND edb_name=? " pars = append(pars, req.EdbName) if req.EdbInfoId > 0 { condition += " AND edb_info_id !=? " pars = append(pars, req.EdbInfoId) } count, err := models.GetEdbInfoCountByCondition(condition, pars) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if count > 0 { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" return } //生成指标编码 randStr := utils.GetRandDigit(4) edbCode := `C` + time.Now().Format("060102") + randStr timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp) adminId := req.AdminId adminName := req.AdminName var sourName string var errMsg string var edbInfo *models.EdbInfo var latestDateStr string // 最近实际数据的日期 var latestValue float64 // 最近实际数据的值 var formulaInt int var nhccDate models.NhccDate // 拟合残差的日期 switch req.Source { case utils.DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_PREDICT_CALCULATE_HBZ, utils.DATA_SOURCE_PREDICT_CALCULATE_HCZ, utils.DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_PREDICT_CALCULATE_CJJX: if req.Formula == "" { br.Msg = "请填写N值" return } formulaInt, _ = strconv.Atoi(req.Formula) if formulaInt <= 0 { br.Msg = "N值输入错误,请重新输入" return } /*case utils.DATA_SOURCE_PREDICT_CALCULATE_ZJPJ: //直接拼接指标 //校验时间格式 _, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local) if err != nil { br.Msg = "拼接日期有误,请重新输入" return }*/ case utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC: //拟合残差指标 //指标校验 if len(req.EdbInfoIdArr) != 2 { br.Msg = "选择的指标异常,请重新选择" return } fromEdbInfoId = req.EdbInfoIdArr[0].EdbInfoId //校验时间格式 //数据格式:2022-11-01,2022-11-10 timeList := strings.Split(req.Formula, ",") if len(timeList) != 2 { br.Msg = "选择时间有误,请重新输入" return } startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local) if err != nil { br.Msg = "开始日期有误,请重新输入" return } endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local) if err != nil { br.Msg = "结束日期有误,请重新输入" return } if utils.GetTimeSubDay(startDate, endDate) < 2 { br.Msg = "日期间隔不得少于两天" return } nhccDate.StartDate = startDate nhccDate.EndDate = endDate case utils.DATA_SOURCE_CALCULATE_ZSXY: // 指数修匀 if req.Formula == "" { br.Msg = "请填写alpha值" return } a, e := strconv.ParseFloat(req.Formula, 64) if e != nil { br.Msg = "alpha值输入错误, 请重新输入" return } if a <= 0 || a >= 1 { br.Msg = "alpha值输入错误, 请重新输入" return } } if err != nil { br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } // 来源预测指标信息 var fromEdbInfo *models.EdbInfo if fromEdbInfoId > 0 { fromEdbInfo, err = models.GetEdbInfoById(fromEdbInfoId) if err != nil { br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } if fromEdbInfo.EdbInfoType != 1 { br.Msg = "来源指标不是预测指标" br.ErrMsg = "来源指标不是预测指标" return } } var baseEdbInfoModel models.BasePredictEdbInfoInterface saveParams := models.BatchSaveCalculateBatchParams{ Req: req, FromEdbInfo: fromEdbInfo, EdbCode: edbCode, UniqueCode: uniqueCode, SysUserId: req.AdminId, SysUserRealName: req.AdminName, } if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_TBZ { if req.EdbInfoId <= 0 { if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != "无" { br.Msg = "单位只允许为无,禁止选择其他单位" return } } } if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_TCZ { if req.EdbInfoId <= 0 { if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != fromEdbInfo.Unit { br.Msg = "当前单位和原指标单位不一致" return } } sourName = "预测同差" edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateTcz(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS { sourName = "预测N数值移动平均计算" edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateNszydpjjs(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_BP { sourName = "预测变频" edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateBp(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_HBZ { checkDataList, tmpErr := models.GetPredictEdbDataListAllByStartDate(fromEdbInfo, 0, "") if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() { br.Msg = "判断环比值是否可计算失败" br.ErrMsg = "判断环比值是否可计算失败,Err:" + tmpErr.Error() return } for _, v := range checkDataList { if v.Value <= 0 { br.Msg = "原始数据中存在0或负数,该指标不能进行环比运算" br.ErrMsg = "原始数据中出现0和负值时,提示该指标不能进行环比运算" return } } sourName = "预测环比值" edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateHbz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_HCZ { sourName = "预测环差值" edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateHcz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_LJZZY { sourName = "预测累计值转月值" if fromEdbInfo.Frequency != "月度" { br.Msg = "请选择月度指标" return } edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateLjzzy(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT { sourName = "预测时间移位" edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateTimeShift(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_CJJX { sourName = "预测超季节性" edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateCjjx(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC { sourName = "预测拟合残差" secondEdbInfoReq := req.EdbInfoIdArr[1] secondEdbInfo, tmpErr := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId) if tmpErr != nil { br.Msg = "获取因变量的指标信息失败" br.ErrMsg = "获取因变量的指标信息失败:Err:" + tmpErr.Error() return } if fromEdbInfo.EdbInfoId == secondEdbInfo.EdbInfoId { br.Msg = "两个指标不允许为同一个" br.ErrMsg = "两个指标不允许为同一个" return } edbInfo, latestDateStr, latestValue, err = models.SavePredictCalculateNhcc(&req, fromEdbInfo, secondEdbInfo, edbCode, uniqueCode, nhccDate, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_JP { sourName = utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_JP edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateJp(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NH { sourName = utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_NH edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateNh(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, fromEdbInfo, edbCode, uniqueCode, adminId, adminName) } else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_KSZS { sourName = utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_KSZS edbInfo, latestDateStr, latestValue, err, errMsg = models.SavePredictCalculateKszs(req.EdbInfoId, req.ClassifyId, req.EdbName, req.Frequency, req.Unit, req.Formula, req.EdbInfoIdArr, edbCode, uniqueCode, adminId, adminName) } else { // 获取通用的数据源处理服务 baseEdbInfoModel = models.GetBasePredictEdbInfoModel(req.Source) // 没有找到的话,那么就直接返回报错吧 if baseEdbInfoModel == nil { br.Msg = "无效计算方式" br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source) return } sourName = baseEdbInfoModel.GetSourceName() if req.EdbInfoId <= 0 { edbInfo, latestDateStr, latestValue, err, errMsg = baseEdbInfoModel.Add(saveParams) } else { edbInfo, err = models.GetEdbInfoById(req.EdbInfoId) if err != nil { if err.Error() == utils.ErrNoRow() { br.Msg = "指标已被删除,请刷新页面" br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error() return } br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } saveParams.EdbInfo = edbInfo latestDateStr, latestValue, err, errMsg = baseEdbInfoModel.Edit(saveParams) } } if err != nil { br.Msg = "生成" + sourName + "失败" if errMsg != `` { br.Msg = errMsg } br.Msg = "生成" + sourName + "失败 Err:" + err.Error() return } if edbInfo == nil { br.Msg = "生成" + sourName + "失败" br.ErrMsg = "生成" + sourName + "失败,edbInfo is nil" return } //处理同名指标 { edbNameList, err := models.GetEdbInfoByName(req.EdbName) if err != nil { br.Msg = "保存失败" br.ErrMsg = "获取指标信息失败,Err:" + err.Error() return } if len(edbNameList) >= 2 { for _, v := range edbNameList { edbName := v.EdbName + "(" + v.SourceName + ")" err = models.ModifyEdbInfoNameSource(edbName, v.EdbInfoId) if err != nil { br.Msg = "保存失败" br.ErrMsg = "修改指标名称失败,Err:" + err.Error() return } } } } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyPredictEdbInfoMaxAndMinInfo(edbInfo, latestDateStr, latestValue) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: uniqueCode, } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // Refresh // @Title 刷新计算指标接口 // @Description 刷新计算指标接口 // @Success 200 {object} models.RefreshEdbInfoReq // @router /refresh [post] func (this *PredictCalculateController) Refresh() { br := new(models.BaseResponse).Init() var cacheKey string defer func() { this.Data["json"] = br this.ServeJSON() }() 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.GetEdbInfoById(req.EdbInfoId) if err != nil { br.Msg = "指标不存在!" br.ErrMsg = "指标不存在" return } cacheKey = utils.CACHE_EDB_DATA_REFRESH + strconv.Itoa(edbInfo.Source) + "_" + req.EdbCode if utils.Rc.IsExist(cacheKey) { br.Ret = 501 br.Success = true br.Msg = "系统处理中,请稍后重试" br.IsSendEmail = false return } utils.Rc.SetNX(cacheKey, 1, 1*time.Minute) defer func() { _ = utils.Rc.Delete(cacheKey) }() startDate := req.StartDate var errMsg string endDate := time.Now().Format(utils.FormatDate) edbInfoId := edbInfo.EdbInfoId source := edbInfo.Source var latestDateStr string // 最近实际数据的日期 var latestValue float64 // 最近实际数据的值 var baseEdbInfoModel models.BasePredictEdbInfoInterface refreshParams := models.RefreshParams{ EdbInfo: edbInfo, } switch source { case utils.DATA_SOURCE_PREDICT_CALCULATE_TBZ: //刷新同比值 calculateTbz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateTbz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } refreshParams.FromEdbInfo = fromEdbInfo refreshParams.StartDate = edbInfo.StartDate } switch source { case utils.DATA_SOURCE_PREDICT_CALCULATE: //startDate = edbInfo.StartDate //sTime, err := time.ParseInLocation(utils.FormatDate, edbInfo.EndDate, time.Local) //if err != nil { // return //} //startDate = sTime.Format(utils.FormatDate) startDate = "" var edbInfoIdBytes []string calculateMap, err := models.GetEdbInfoCalculateDetailList(edbInfo.EdbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateDetail Err:" + err.Error() break } var formulaStr string edbInfoList := make([]*models.EdbInfo, 0) for _, v := range calculateMap { formulaStr += v.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag) edbInfo, _ := models.GetEdbInfoById(v.FromEdbInfoId) edbInfoList = append(edbInfoList, edbInfo) } latestDateStr, latestValue, err = models.RefreshAllPredictCalculate(edbInfoList, edbInfo.EdbInfoId, source, edbInfo.SubSource, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, edbInfoIdBytes, edbInfo.EmptyType, edbInfo.MaxEmptyType) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshCalculate Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_TCZ: //同差值 calculateTcz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTczDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateTcz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } startDate = edbInfo.StartDate latestDateStr, latestValue, err = models.RefreshAllPredictCalculateTcz(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateTcz.EdbCode, startDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshCalculateTcz Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS: //N数值移动平均计算 calculateInfo, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTczDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateInfo.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } var formulaInt int formulaInt, _ = strconv.Atoi(calculateInfo.CalculateFormula) if formulaInt <= 0 { errMsg = "N值输入错误,请重新输入" break } startDate = edbInfo.StartDate latestDateStr, latestValue, err = models.RefreshAllPredictCalculateNszydpjjs(edbInfoId, source, edbInfo.SubSource, formulaInt, fromEdbInfo, calculateInfo.EdbCode, startDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateNszydpjjs Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_BP: //刷新变频 calculateTbz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateTbz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } endDate = time.Now().Format(utils.FormatDate) latestDateStr, latestValue, err = models.RefreshAllPredictCalculateBp(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateBp Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_HBZ: //刷新环比值 calculateTbz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateHbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateTbz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 endDate = time.Now().Format(utils.FormatDate) formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula) latestDateStr, latestValue, err = models.RefreshAllPredictCalculateHbz(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateHbz Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_HCZ: //刷新环差值 calculateTbz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateHczDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateTbz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 endDate = time.Now().Format(utils.FormatDate) formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula) latestDateStr, latestValue, err = models.RefreshAllPredictCalculateHcz(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateHcz Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZZY: //刷新累计值转月值 calculateLjzzy, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateLjzzyDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateLjzzy.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } endDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 latestDateStr, latestValue, err = models.RefreshAllPredictCalculateLjzzy(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateLjzzy.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateLjzzy Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT: calculate, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculate.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } //startDate = edbInfo.StartDate startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 endDate = time.Now().Format(utils.FormatDate) formulaInt, _ := strconv.Atoi(calculate.CalculateFormula) latestDateStr, latestValue, err = models.RefreshAllPredictCalculateTimeShift(edbInfoId, source, edbInfo.SubSource, formulaInt, calculate.MoveType, fromEdbInfo, calculate.EdbCode, startDate, endDate, calculate.MoveFrequency) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateTimeShift Err:" + err.Error() } case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZTBPJ: //刷新累计值同比拼接 latestDateStr, latestValue, err = models.RefreshAllPredictCalculateLjztbpj(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateLjztbpj Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_ZJPJ: //刷新直接拼接 latestDateStr, latestValue, err = models.RefreshAllPredictCalculateZjpj(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateZjpj Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_CJJX: //超季节性 calculateCjjx, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateNszydpjjsDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateCjjx.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula) startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 latestDateStr, latestValue, err = models.RefreshAllPredictCalculateCjjx(edbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, calculateCjjx.EdbCode, startDate, "", edbInfo.Calendar, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateCjjx Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC: //nhcc latestDateStr, latestValue, err = models.RefreshAllPredictCalculateNhcc(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateNhcc Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_JP: //降频 calculateInfo, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTczDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateInfo.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } latestDateStr, latestValue, err = models.RefreshAllPredictCalculateJp(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateInfo.EdbCode, edbInfo.Frequency, edbInfo.CalculateFormula) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateJp Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_NH: //年化 calculateInfo, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTczDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateInfo.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } latestDateStr, latestValue, err = models.RefreshAllPredictCalculateNh(edbInfoId, source, edbInfo.SubSource, fromEdbInfo, calculateInfo.EdbCode, edbInfo.Frequency, edbInfo.CalculateFormula) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateNh Err:" + err.Error() break } case utils.DATA_SOURCE_PREDICT_CALCULATE_KSZS: //扩散指数 latestDateStr, latestValue, err = models.RefreshAllPredictCalculateKszs(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPredictCalculateKszs Err:" + err.Error() break } default: // 获取通用的数据源处理服务 baseEdbInfoModel = models.GetBasePredictEdbInfoModel(source) // 没有找到的话,那么就直接返回报错吧 if baseEdbInfoModel == nil { br.Msg = "来源异常,请联系相关开发!" br.ErrMsg = "来源异常,请联系相关开发" return } latestDateStr, latestValue, err, errMsg = baseEdbInfoModel.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) br.Ret = 200 br.Success = true br.Msg = "获取成功" } // CalculateComputeCorrelation // @Title 拟合残差计算相关性接口 // @Description 拟合残差计算相关性接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /compute_correlation [post] func (this *PredictCalculateController) CalculateComputeCorrelation() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.EdbInfoCalculateBatchSaveReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if len(req.EdbInfoIdArr) != 2 { br.Msg = "选择的指标异常,请重新选择" return } //校验时间格式 //数据格式:2022-11-01,2022-11-10 timeList := strings.Split(req.Formula, ",") if len(timeList) != 2 { br.Msg = "选择时间有误,请重新输入" return } startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local) if err != nil { br.Msg = "开始日期有误,请重新输入" return } endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local) if err != nil { br.Msg = "结束日期有误,请重新输入" return } if utils.GetTimeSubDay(startDate, endDate) < 2 { br.Msg = "日期间隔不得少于两天" return } var nhccDate models.NhccDate // 拟合残差的日期 nhccDate.StartDate = startDate nhccDate.EndDate = endDate // 来源预测指标信息 fromEdbInfoId := req.EdbInfoIdArr[0].EdbInfoId if fromEdbInfoId <= 0 { br.Msg = "请选择指标" return } // 来源指标(自变量指标) fromEdbInfo, err := models.GetEdbInfoById(fromEdbInfoId) if err != nil { br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } if fromEdbInfo.EdbInfoType != 1 { br.Msg = "来源指标不是预测指标" br.ErrMsg = "来源指标不是预测指标" return } // 因变量指标 secondEdbInfoReq := req.EdbInfoIdArr[1] secondEdbInfo, tmpErr := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId) if tmpErr != nil { br.Msg = "获取因变量的指标信息失败" br.ErrMsg = "获取因变量的指标信息失败:Err:" + tmpErr.Error() return } if fromEdbInfo.EdbInfoId == secondEdbInfo.EdbInfoId { br.Msg = "两个指标不允许为同一个" br.ErrMsg = "两个指标不允许为同一个" return } rVal, err := models.CalculatePredictComputeCorrelation(&req, fromEdbInfo, secondEdbInfo, nhccDate) if err != nil { br.Msg = "计算失败" br.ErrMsg = "计算失败,ERR:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "计算成功" br.Data = rVal br.IsAddLog = true }