package controllers import ( "encoding/json" "errors" "eta_gn/eta_index_lib/logic" "eta_gn/eta_index_lib/models" "eta_gn/eta_index_lib/services" "eta_gn/eta_index_lib/utils" "fmt" "strconv" "strings" "sync" "time" ) // CalculateController 计算指标 type CalculateController struct { BaseAuthController } // Add // @Title 新增计算指标接口 // @Description 新增计算指标接口 // @Success 200 {object} models.EdbInfoCalculateSaveReq // @router /add [post] func (this *CalculateController) Add() { 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 } 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("edb_lib:edb_info:calculate:add:", utils.DATA_SOURCE_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) }() } // 新增 edbInfo, uniqueCode, err, errMsg := services.EdbCalculateAdd(req, this.Lang) if err != nil { br.Msg = err.Error() br.ErrMsg = errMsg return } //处理同名指标 { edbNameList, e := models.GetEdbInfoByName(req.EdbName) if e != nil { err = fmt.Errorf("保存失败") errMsg = "获取指标信息失败,Err:" + e.Error() return } if len(edbNameList) >= 2 { for _, v := range edbNameList { edbName := v.EdbName + "(" + v.SourceName + ")" err = models.ModifyEdbInfoNameSource(edbName, v.EdbInfoId) if err != nil { errMsg = "修改指标名称失败,Err:" + err.Error() err = fmt.Errorf("保存失败") return } } } } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if err != nil { return } // 判断是否需要禁用 go services.DisableEdbInfoNoUpdate(edbInfo) resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: uniqueCode, } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // Edit // @Title 编辑计算指标接口 // @Description 编辑计算指标接口 // @Success 200 {object} models.EdbInfoCalculateSaveReq // @router /edit [post] func (this *CalculateController) Edit() { 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 { br.Msg = "参数错误" br.ErrMsg = "指标ID:" + strconv.Itoa(req.EdbInfoId) 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 } if len(req.EdbInfoIdArr) <= 0 { br.Msg = "请选择指标" return } if req.CalculateFormula == "" { br.Msg = "请填写指标公式" return } //todo 校验空值类型,max、min空值类型 //todo req.EdbInfoIdArr根据tag排序,排成A,B,AB,这种格式 calculateFormula := req.CalculateFormula calculateFormula = strings.Replace(calculateFormula, "(", "(", -1) calculateFormula = strings.Replace(calculateFormula, ")", ")", -1) calculateFormula = strings.Replace(calculateFormula, ",", ",", -1) calculateFormula = strings.Replace(calculateFormula, "。", ".", -1) calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1) req.CalculateFormula = calculateFormula fmt.Println("calculateFormula:" + calculateFormula) //判断是否重复指标 edbInfoMap := make(map[int]string) //移除研究员选择指标中的未使用的指标 { //转大写的计算公式 upperCalculateFormulaStr := strings.ToUpper(req.CalculateFormula) //用到的指标 newEdbInfoIdArr := make([]models.EdbInfoFromTag, 0) for _, tmpEdbInfo := range req.EdbInfoIdArr { _, ok := edbInfoMap[tmpEdbInfo.EdbInfoId] if ok { br.Msg = "选择指标失败,请勿选择重复指标!" return } edbInfoMap[tmpEdbInfo.EdbInfoId] = tmpEdbInfo.FromTag upperFromTag := strings.ToUpper(tmpEdbInfo.FromTag) if strings.Contains(upperCalculateFormulaStr, upperFromTag) { newEdbInfoIdArr = append(newEdbInfoIdArr, tmpEdbInfo) } } req.EdbInfoIdArr = newEdbInfoIdArr } // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := logic.CheckExistByEdbNameAndEdbInfoId(0, req.EdbInfoId, req.EdbName, this.Lang) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if existEdbName { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" br.IsSendEmail = false return } //判断公式,指标是否有改动 edbInfoDetail, err := models.GetEdbInfoById(req.EdbInfoId) if err != nil { br.Msg = "修改失败" br.Msg = "获取指标信息失败,GetEdbInfoById Err:" + err.Error() return } if edbInfoDetail == nil { br.Msg = "修改失败" br.Msg = "指标信息不存在,EdbInfoId:" + strconv.Itoa(req.EdbInfoId) return } // 记录指标原始的基本信息 oldEdbName := edbInfoDetail.EdbName oldFrequency := edbInfoDetail.Frequency oldUnit := edbInfoDetail.Unit var needCalculate bool if edbInfoDetail.CalculateFormula != req.CalculateFormula || edbInfoDetail.EmptyType != req.EmptyType || edbInfoDetail.MaxEmptyType != req.MaxEmptyType || edbInfoDetail.Extra != req.Extra { needCalculate = true } //检验公式 var formulaStr string var edbInfoIdBytes []string var edbInfoIdArr []string for _, v := range req.EdbInfoIdArr { formulaStr += v.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag) edbInfoIdArr = append(edbInfoIdArr, strconv.Itoa(v.EdbInfoId)) if v.EdbInfoId == req.EdbInfoId { br.Msg = "计算指标中包含此指标,不能修改" return } } if needCalculate == false { edbInfoIdStr := strings.Join(edbInfoIdArr, ",") fromEdbInfoId, err := models.GetCalculateEdbInfo(req.EdbInfoId) if err != nil { br.Msg = "修改失败" br.Msg = "获取数据失败,GetCalculateEdbInfo:" + err.Error() return } if edbInfoIdStr != fromEdbInfoId { needCalculate = true } } 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 } } } // 额外赋值 switch this.Lang { case utils.EnLangVersion: req.EdbNameEn = req.EdbName req.UnitEn = req.Unit req.EdbName = edbInfoDetail.EdbName req.Unit = edbInfoDetail.Unit default: req.EdbNameEn = edbInfoDetail.EdbNameEn req.UnitEn = edbInfoDetail.UnitEn } //重新计算 err, errMsg := models.EditCalculateInfo(edbInfoDetail, req, formulaSlice, edbInfoIdBytes, needCalculate) if err != nil { br.Msg = "生成计算指标失败" if errMsg != `` { br.Msg = errMsg } br.Msg = "生成计算指标失败,AddEdbInfo Err:" + err.Error() return } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfoDetail) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } // 记录基础信息变更日志 oldEdbInfo := new(models.EdbInfo) oldEdbInfo.EdbInfoId = edbInfoDetail.EdbInfoId oldEdbInfo.EdbName = oldEdbName oldEdbInfo.Frequency = oldFrequency oldEdbInfo.Unit = oldUnit newEdbInfoEditRecord := new(models.EdbInfoEditRecord) newEdbInfoEditRecord.EdbName = req.EdbName newEdbInfoEditRecord.Frequency = req.Frequency newEdbInfoEditRecord.Unit = req.Unit newEdbInfoEditRecord.OperateUserId = req.AdminId newEdbInfoEditRecord.OperateUserRealName = req.AdminName err = services.AddEditEdbInfoRcord(oldEdbInfo, newEdbInfoEditRecord) if err != nil { br.Msg = "记录基础信息变更日志失败" br.ErrMsg = err.Error() return } resp := models.AddEdbInfoResp{ EdbInfoId: edbInfoDetail.EdbInfoId, UniqueCode: edbInfoDetail.UniqueCode, } // 重置计算指标中的引用关系 go services.ResetEdbRelation(edbInfoDetail.EdbInfoId) br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // BatchSave // @Title 累计值转月-同比值-同差等计算新增 // @Description 累计值转月-同比值-同差等计算新增接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /batch/save [post] func (this *CalculateController) BatchSave() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } 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 var formulaInt int var nhccDate models.NhccDate // 拟合残差的日期 switch req.Source { case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SOURCE_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_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_CALCULATE_ZJPJ: //直接拼接指标 //校验时间格式 _, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local) if err != nil { br.Msg = "拼接日期有误,请重新输入" return } case utils.DATA_SOURCE_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_JP: if req.Formula != "期末值" && req.Formula != "平均值" { br.Msg = "数据取值类型错误:" + req.Formula return } 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 } } notNeedFromEdbSourceList := []int{utils.DATA_SOURCE_CALCULATE_KSZS, utils.DATA_SOURCE_CALCULATE_CORRELATION, utils.DATA_SOURCE_CALCULATE_ZDYFX} // 不需要传入来源指标id的 指标类型 if fromEdbInfoId <= 0 && !utils.InArrayByInt(notNeedFromEdbSourceList, req.Source) { br.Msg = "请选择指标" return } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("edb_lib:edb_info: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 // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := logic.CheckExistByEdbNameAndEdbInfoId(0, req.EdbInfoId, req.EdbName, this.Lang) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if existEdbName { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" br.IsSendEmail = false return } // 来源指标 var fromEdbInfo *models.EdbInfo if fromEdbInfoId > 0 { fromEdbInfo, err = models.GetEdbInfoById(fromEdbInfoId) if err != nil { br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } } //生成指标编码 edbCode, err := utils.GenerateEdbCode(1, "") if err != nil { br.Msg = "指标生成失败" br.ErrMsg = "指标编码生成失败,Err:" + err.Error() return } timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp) sysUserId := req.AdminId sysUserName := req.AdminName var sourName string var edbInfoId int var edbInfo *models.EdbInfo var errMsg string var baseEdbInfoModel models.BaseEdbInfoInterface addParam := models.AddCalculateBatchParams{ Req: &req, FromEdbInfo: fromEdbInfo, EdbCode: edbCode, UniqueCode: uniqueCode, SysUserId: sysUserId, SysUserRealName: sysUserName, } switch req.Source { case utils.DATA_SOURCE_CALCULATE_LJZZY: sourName = "累计值转月值" if fromEdbInfo.Frequency != "月度" { br.Msg = "请选择月度指标" return } edbInfo, err = models.AddCalculateLjzzy(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_TBZ: if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != "无" { br.Msg = "单位只允许为无,禁止选择其他单位" return } sourName = "同比值" edbInfo, err = models.AddCalculateTbz(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_TCZ: if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != fromEdbInfo.Unit { br.Msg = "当前单位和原指标单位不一致" return } sourName = "同差值" edbInfo, err = models.AddCalculateTcz(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS: sourName = "N数值移动平均计算" edbInfo, err = models.AddCalculateNszydpjjs(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName, formulaInt) case utils.DATA_SOURCE_CALCULATE_HBZ: checkCount, tmpErr := models.GetLteZeroEdbDataCount(fromEdbInfo.Source, fromEdbInfo.SubSource, fromEdbInfoId) if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() { br.Msg = "判断环比值是否可计算失败" br.ErrMsg = "判断环比值是否可计算失败,Err:" + tmpErr.Error() return } if checkCount > 0 { br.Msg = "原始数据中存在0或负数,该指标不能进行环比运算" br.ErrMsg = "原始数据中出现0和负值时,提示该指标不能进行环比运算" return } sourName = "环比值" edbInfo, err = models.AddCalculateHbz(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName, formulaInt) case utils.DATA_SOURCE_CALCULATE_HCZ: sourName = "环差值" edbInfo, err = models.AddCalculateHcz(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName, formulaInt) case utils.DATA_SOURCE_CALCULATE_BP: sourName = utils.DATA_SOURCE_NAME_CALCULATE_BP edbInfo, err = models.AddCalculateBp(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_TIME_SHIFT: sourName = "时间移位" edbInfo, err = models.AddCalculateTimeShift(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_ZJPJ: sourName = "直接拼接" if len(req.EdbInfoIdArr) != 1 { br.Msg = "请传入拼接日期之后的指标" br.ErrMsg = "请传入拼接日期之后的指标" return } secondEdbInfoReq := req.EdbInfoIdArr[0] 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, err = models.AddCalculateZjpj(&req, fromEdbInfo, secondEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_LJZTBPJ: sourName = "累计值同比拼接" if fromEdbInfo.Frequency != "月度" { br.Msg = "待拼接指标只能筛选月度指标" br.ErrMsg = "待拼接指标只能筛选月度指标" return } if len(req.EdbInfoIdArr) != 1 { br.Msg = "请传入同比值指标" br.ErrMsg = "请传入同比值指标" return } secondEdbInfoReq := req.EdbInfoIdArr[0] tbzEdbInfo, tmpErr := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId) if tmpErr != nil { br.Msg = "获取同比值指标信息失败" br.ErrMsg = "获取同比值指标信息失败:Err:" + tmpErr.Error() return } if tbzEdbInfo.Source != utils.DATA_SOURCE_CALCULATE_TBZ { br.Msg = "指标必须是传入同比值指标类型" br.ErrMsg = "指标必须是传入同比值指标类型" return } if tbzEdbInfo.Frequency != "月度" { br.Msg = "同比值指标只能筛选月度指标" br.ErrMsg = "同比值指标只能筛选月度指标" return } if fromEdbInfo.EdbInfoId == tbzEdbInfo.EdbInfoId { br.Msg = "两个指标不允许为同一个" br.ErrMsg = "两个指标不允许为同一个" return } edbInfo, err = models.AddCalculateLjztbpj(&req, fromEdbInfo, tbzEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_CJJX: sourName = "超季节性" edbInfo, err = models.AddCalculateCjjx(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName, formulaInt) case utils.DATA_SOURCE_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, err, errMsg = models.AddCalculateNhcc(&req, fromEdbInfo, secondEdbInfo, edbCode, uniqueCode, nhccDate, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_JP: if !models.CheckFrequency(fromEdbInfo.Frequency, req.Frequency) { br.Msg = "频度异常,不允许低频降频到高频" return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_JP edbInfo, err = models.AddCalculateJp(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_NH: sourName = utils.DATA_SOURCE_NAME_CALCULATE_NH edbInfo, err = models.AddCalculateNh(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_KSZS: //关联的指标信息 if len(req.EdbInfoIdArr) < 2 { br.Msg = "指标数量不能小于2个,请重新选择" br.ErrMsg = "指标数量不能小于2个,请重新选择" br.IsSendEmail = false return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_KSZS edbInfo, err = models.AddCalculateKszs(&req, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_CORRELATION: //关联的指标信息 if len(req.EdbInfoIdArr) < 2 { br.Msg = "指标数量不能小于2个,请重新选择" br.ErrMsg = "指标数量不能小于2个,请重新选择" br.IsSendEmail = false return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION edbInfo, err, errMsg = models.AddCalculateCorrelation(&req, edbCode, uniqueCode, sysUserId, sysUserName) case utils.DATA_SOURCE_CALCULATE_RJZ: if req.Frequency == "日度" { br.Msg = "日度指标无需进行日均值计算" return } if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != fromEdbInfo.Unit { br.Msg = "单位只允许为和原指标频度保持一致,禁止选择其他单位" return } sourName = "日均值" edbInfo, err = models.AddCalculateRjz(&req, fromEdbInfo, edbCode, uniqueCode, sysUserId, sysUserName) default: // 获取通用的数据源处理服务 baseEdbInfoModel = models.GetBaseEdbInfoModel(req.Source) // 没有找到的话,那么就直接返回报错吧 if baseEdbInfoModel == nil { br.Msg = "无效计算方式" br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source) return } sourName = baseEdbInfoModel.GetSourceName() edbInfo, err, errMsg = baseEdbInfoModel.Add(addParam) } if err != nil { br.Msg = "生成" + sourName + "失败" if errMsg != `` { br.Msg = errMsg } br.ErrMsg = "生成" + sourName + "失败 Err:" + err.Error() return } if edbInfo == nil { br.Msg = "生成" + sourName + "失败" br.ErrMsg = "生成" + sourName + "失败,指标ID错误:" + strconv.Itoa(edbInfoId) return } edbInfoId = edbInfo.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 } } } } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } newEdbInfo := new(models.EdbInfoEditRecord) newEdbInfo.EdbName = req.EdbName newEdbInfo.Frequency = req.Frequency newEdbInfo.Unit = req.Unit newEdbInfo.OperateUserId = req.AdminId newEdbInfo.OperateUserRealName = req.AdminName err = services.AddEditEdbInfoRcord(edbInfo, newEdbInfo) if err != nil { br.Msg = "保存失败" br.ErrMsg = "保存失败,Err:" + err.Error() return } // 判断是否需要禁用 go services.DisableEdbInfoNoUpdate(edbInfo) resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: edbInfo.UniqueCode, } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // BatchEdit // @Title 累计值转月-同比值-同差等计算新增 // @Description 累计值转月-同比值-同差等计算新增接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /batch/edit [post] func (this *CalculateController) BatchEdit() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.EdbInfoCalculateBatchEditReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } 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 req.EdbInfoId <= 0 { br.Msg = "请选择指标" return } // 根据指标名称和指标ID校验库中是否还存在其他同名指标 existEdbName, err := logic.CheckExistByEdbNameAndEdbInfoId(0, req.EdbInfoId, req.EdbName, this.Lang) if err != nil { br.Msg = "判断指标名称是否存在失败" br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error() return } if existEdbName { br.Msg = "指标名称已存在,请重新填写" br.ErrMsg = "指标名称已存在,请重新填写" br.IsSendEmail = false return } 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 } // 记录原始指标信息 oldEdbName := edbInfo.EdbName oldFrequency := edbInfo.Frequency oldUnit := edbInfo.Unit // 基础指标id fromEdbInfoId := req.FromEdbInfoId if req.Source <= 0 { req.Source = edbInfo.Source } var formulaInt int var nhccDate models.NhccDate // 拟合残差的日期 // 初期的参数校验 switch req.Source { case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SOURCE_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_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_CALCULATE_ZJPJ: //直接拼接指标 //校验时间格式 _, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local) if err != nil { br.Msg = "拼接日期有误,请重新输入" return } case utils.DATA_SOURCE_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_JP: if req.Formula != "期末值" && req.Formula != "平均值" { br.Msg = "数据取值类型错误:" + req.Formula return } 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 } } var fromEdbInfo *models.EdbInfo if fromEdbInfoId > 0 { // 获取基础指标信息 fromEdbInfo, err = models.GetEdbInfoById(fromEdbInfoId) if err != nil { if err.Error() == utils.ErrNoRow() { br.Msg = "指标已被删除,请刷新页面" br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error() return } br.Msg = "获取指标信息失败" br.ErrMsg = "获取指标信息失败:Err:" + err.Error() return } } //dataUpdateTime := time.Now().Format(utils.FormatDateTime) // 额外赋值 switch this.Lang { case utils.EnLangVersion: req.EdbNameEn = req.EdbName req.UnitEn = req.Unit req.EdbName = edbInfo.EdbName req.Unit = edbInfo.Unit default: req.EdbNameEn = edbInfo.EdbNameEn req.UnitEn = edbInfo.UnitEn } var sourName, errMsg string var edbInfoId int var baseEdbInfoModel models.BaseEdbInfoInterface editParams := models.EditCalculateBatchParams{ Req: &req, EdbInfo: edbInfo, FromEdbInfo: fromEdbInfo, } switch req.Source { case utils.DATA_SOURCE_CALCULATE_LJZZY: sourName = "累计值转月值" if fromEdbInfo.Frequency != "月度" { br.Msg = "请选择月度指标" return } err = models.EditCalculateLjzzy(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_TBZ: sourName = "同比值" err = models.EditCalculateTbz(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_TCZ: fmt.Println("start edit", time.Now()) sourName = "同差值" err = models.EditCalculateTcz(edbInfo, &req, fromEdbInfo) fmt.Println("end edit", time.Now()) case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS: sourName = "N数值移动平均计算" err = models.EditCalculateNszydpjjs(edbInfo, &req, fromEdbInfo, formulaInt, edbInfo.CalculateFormula) case utils.DATA_SOURCE_CALCULATE_HBZ: checkCount, tmpErr := models.GetLteZeroEdbDataCount(fromEdbInfo.Source, fromEdbInfo.SubSource, req.FromEdbInfoId) if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() { br.Msg = "判断环比值是否可计算失败" br.ErrMsg = "判断环比值是否可计算失败,Err:" + tmpErr.Error() return } if checkCount > 0 { br.Msg = "原始数据中存在0或负数,该指标不能进行环比运算" br.ErrMsg = "原始数据中出现0和负值时,提示该指标不能进行环比运算" return } sourName = "环比值" err = models.EditCalculateHbz(edbInfo, &req, fromEdbInfo, formulaInt, edbInfo.CalculateFormula) case utils.DATA_SOURCE_CALCULATE_HCZ: sourName = "环差值" err = models.EditCalculateHcz(edbInfo, &req, fromEdbInfo, formulaInt, edbInfo.CalculateFormula) case utils.DATA_SOURCE_CALCULATE_BP: sourName = utils.DATA_SOURCE_NAME_CALCULATE_BP err = models.EditCalculateBp(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_TIME_SHIFT: sourName = "时间移位" err = models.EditCalculateTimeShift(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_ZJPJ: sourName = "直接拼接" if len(req.EdbInfoIdArr) != 1 { br.Msg = "请传入拼接日期之后的指标" br.ErrMsg = "请传入拼接日期之后的指标" return } secondEdbInfoReq := req.EdbInfoIdArr[0] 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 } err = models.EditCalculateZjpj(&req, edbInfo, fromEdbInfo, secondEdbInfo) case utils.DATA_SOURCE_CALCULATE_LJZTBPJ: //累计值同比拼接 sourName = "累计值同比拼接" if fromEdbInfo.Frequency != "月度" { br.Msg = "待拼接指标只能筛选月度指标" br.ErrMsg = "待拼接指标只能筛选月度指标" return } if len(req.EdbInfoIdArr) != 1 { br.Msg = "请传入同比值指标" br.ErrMsg = "请传入同比值指标" return } secondEdbInfoReq := req.EdbInfoIdArr[0] tbzEdbInfo, tmpErr := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId) if tmpErr != nil { br.Msg = "获取同比值指标信息失败" br.ErrMsg = "获取同比值指标信息失败:Err:" + tmpErr.Error() return } if tbzEdbInfo.Source != utils.DATA_SOURCE_CALCULATE_TBZ { br.Msg = "指标必须是传入同比值指标类型" br.ErrMsg = "指标必须是传入同比值指标类型" return } if tbzEdbInfo.Frequency != "月度" { br.Msg = "同比值指标只能筛选月度指标" br.ErrMsg = "同比值指标只能筛选月度指标" return } if fromEdbInfo.EdbInfoId == tbzEdbInfo.EdbInfoId { br.Msg = "两个指标不允许为同一个" br.ErrMsg = "两个指标不允许为同一个" return } err = models.EditCalculateLjztbpj(&req, edbInfo, fromEdbInfo, tbzEdbInfo) case utils.DATA_SOURCE_CALCULATE_CJJX: sourName = "超季节性" err = models.EditCalculateCjjx(&req, edbInfo, fromEdbInfo, formulaInt) case utils.DATA_SOURCE_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 } err, errMsg = models.EditCalculateNhcc(&req, edbInfo, fromEdbInfo, secondEdbInfo, nhccDate) case utils.DATA_SOURCE_CALCULATE_JP: if !models.CheckFrequency(fromEdbInfo.Frequency, req.Frequency) { br.Msg = "频度异常,不允许低频降频到高频" return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_JP err = models.EditCalculateJp(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_NH: sourName = utils.DATA_SOURCE_NAME_CALCULATE_NH err = models.EditCalculateNh(edbInfo, &req, fromEdbInfo) case utils.DATA_SOURCE_CALCULATE_KSZS: //关联的指标信息 if len(req.EdbInfoIdArr) < 2 { br.Msg = "指标数量不能小于2个,请重新选择" br.ErrMsg = "指标数量不能小于2个,请重新选择" br.IsSendEmail = false return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_KSZS err = models.EditCalculateKszs(edbInfo, &req) case utils.DATA_SOURCE_CALCULATE_CORRELATION: //关联的指标信息 if len(req.EdbInfoIdArr) < 2 { br.Msg = "指标数量不能小于2个,请重新选择" br.ErrMsg = "指标数量不能小于2个,请重新选择" br.IsSendEmail = false return } sourName = utils.DATA_SOURCE_NAME_CALCULATE_CORRELATION err, errMsg = models.EditCalculateCorrelation(edbInfo, &req) case utils.DATA_SOURCE_CALCULATE_RJZ: if req.Frequency == "日度" { br.Msg = "日度指标无需进行日均值计算" return } if req.Frequency != fromEdbInfo.Frequency { br.Msg = "当前频度和原指标频度不一致" return } if req.Unit != fromEdbInfo.Unit { br.Msg = "单位只允许为和原指标频度保持一致,禁止选择其他单位" return } sourName = "日均值" err = models.EditCalculateRjz(edbInfo, &req, fromEdbInfo) default: // 获取通用的数据源处理服务 baseEdbInfoModel = models.GetBaseEdbInfoModel(req.Source) // 没有找到的话,那么就直接返回报错吧 if baseEdbInfoModel == nil { br.Msg = "无效计算方式" br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source) return } sourName = baseEdbInfoModel.GetSourceName() err, errMsg = baseEdbInfoModel.Edit(editParams) } 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 + "失败,指标ID错误:" + strconv.Itoa(edbInfoId) return } edbInfoId = edbInfo.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 } } } } // 更新指标最大最小值 //err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfoTmp(edbInfo, dataUpdateTime) err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } // 记录指标的操作记录 oldEdbInfo := new(models.EdbInfo) oldEdbInfo.EdbInfoId = edbInfo.EdbInfoId oldEdbInfo.EdbName = oldEdbName oldEdbInfo.Frequency = oldFrequency oldEdbInfo.Unit = oldUnit newEdbInfoRecord := new(models.EdbInfoEditRecord) newEdbInfoRecord.EdbName = req.EdbName newEdbInfoRecord.Frequency = req.Frequency newEdbInfoRecord.Unit = req.Unit newEdbInfoRecord.OperateUserId = req.AdminId newEdbInfoRecord.OperateUserRealName = req.AdminName err = services.AddEditEdbInfoRcord(oldEdbInfo, newEdbInfoRecord) if err != nil { br.Msg = "保存失败" br.ErrMsg = "记录指标操作记录失败,Err:" + err.Error() } // 重置计算指标中的引用关系 go services.ResetEdbRelation(edbInfoId) resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: edbInfo.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 *CalculateController) 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 = "系统处理中,请稍后重试" 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 subSource := edbInfo.SubSource var baseEdbInfoModel models.BaseEdbInfoInterface refreshParams := models.RefreshParams{ EdbInfo: edbInfo, StartDate: "", // 更新所有 EndDate: "", // 更新所有数据 } switch source { case utils.DATA_SOURCE_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) edbInfoTag := make(map[string]int) for _, v := range calculateMap { edbInfoTag[v.FromTag] = v.FromEdbInfoId formulaStr += v.FromTag + "," edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag) edbInfo, _ := models.GetEdbInfoById(v.FromEdbInfoId) edbInfoList = append(edbInfoList, edbInfo) } err = models.RefreshAllCalculate(edbInfoList, edbInfoTag, edbInfo.EdbInfoId, source, subSource, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, endDate, edbInfoIdBytes, edbInfo.EmptyType, edbInfo.MaxEmptyType, edbInfo.Extra) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshCalculate Err:" + err.Error() break } case utils.DATA_SOURCE_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 } //startDate = edbInfo.StartDate //endDate = time.Now().Format(utils.FormatDate) endDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 err = models.RefreshAllCalculateLjzzy(edbInfoId, source, subSource, fromEdbInfo, calculateLjzzy.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateLjzzy Err:" + err.Error() break } case utils.DATA_SOURCE_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 } //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateTbz(edbInfoId, source, subSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateTbz Err:" + err.Error() break } case utils.DATA_SOURCE_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 endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateTcz(edbInfoId, source, subSource, fromEdbInfo, calculateTcz.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshCalculateTcz Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS: //N数值移动平均计算 calculateNszydpjjs, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateNszydpjjsDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateNszydpjjs.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula) //startDate = edbInfo.StartDate startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 err = models.RefreshAllCalculateNszydpjjs(edbInfoId, edbInfo.Source, edbInfo.SubSource, formulaInt, fromEdbInfo, calculateNszydpjjs.EdbCode, startDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshCalculateNszydpjjs Err:" + err.Error() break } case utils.DATA_SOURCE_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) err = models.RefreshAllCalculateHbz(edbInfoId, source, subSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateHbz Err:" + err.Error() break } case utils.DATA_SOURCE_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) err = models.RefreshAllCalculateHcz(edbInfoId, source, subSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateHcz Err:" + err.Error() break } case utils.DATA_SOURCE_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 } //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateBp(edbInfoId, source, subSource, fromEdbInfo, calculateTbz.EdbCode, startDate, endDate, edbInfo.EmptyType) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateBp Err:" + err.Error() break } case utils.DATA_SOURCE_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) err = models.RefreshAllCalculateTimeShift(edbInfoId, source, 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_CALCULATE_ZJPJ: //刷新直接拼接 err = models.RefreshAllCalculateZjpj(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateZjpj Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_LJZTBPJ: //刷新累计值同比拼接 err = models.RefreshAllCalculateLjztbpj(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateLjztbpj Err:" + err.Error() break } case utils.DATA_SOURCE_PYTHON: //python代码运算 edbPythonCode, err := models.GetEdbPythonCodeById(edbInfo.EdbInfoId) if err != nil { errMsg = "获取python代码失败 Err:" + err.Error() break } edbData, err, errMsg := services.ExecPythonCode(edbInfo.EdbCode, edbPythonCode.PythonCode) if err != nil { br.Msg = "获取数据失败" br.ErrMsg = "python代码获取数据失败,err:" + err.Error() if errMsg != "" { br.Msg = errMsg } return } err = models.RefreshAllPythonEdb(edbInfo, edbData) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllPythonEdb Err:" + err.Error() break } case utils.DATA_SOURCE_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 = `` //只要填写日期,就会出现问题,还是把日期给去掉吧 err = models.RefreshAllCalculateCjjx(edbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, calculateCjjx.EdbCode, startDate, "", edbInfo.Calendar, formulaInt) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateCjjx Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_NHCC: //nhcc err = models.RefreshAllCalculateNhcc(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateNhcc Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_ADJUST: calculateMapping, err := models.GetEdbInfoCalculateMappingDetail(edbInfo.EdbInfoId) if err != nil { br.Msg = "获取来源指标异常!" br.ErrMsg = "获取来源指标异常,Err:" + err.Error() return } fromEdbInfo, err := models.GetEdbInfoById(calculateMapping.FromEdbInfoId) if err != nil { br.Msg = "来源指标不存在!" br.ErrMsg = "来源指标不存在" return } err = models.RefreshAllAdjustEdb(edbInfo, fromEdbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllAdjustEdb Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_JP: //刷新降频 calculateMapping, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateMapping.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateJp(edbInfoId, source, subSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.Frequency, edbInfo.CalculateFormula) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateJp Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_NH: //刷新年化 calculateMapping, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateTbzDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateMapping.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateNh(edbInfoId, source, subSource, fromEdbInfo, edbInfo.EdbCode) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateNh Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_KSZS: //刷新扩散指数 //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateKszs(edbInfo) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateKszs Err:" + err.Error() break } case utils.DATA_SOURCE_STOCK_PLANT: //存量装置 //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) req.StartDate = `` // 开始日期也给过滤吧,万一研究员补充了之前的数据呢,还是过滤掉吧 err = models.RefreshEdbDataFromStockPlant(req.EdbInfoId, req.EdbCode, req.StartDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshEdbDataFromStockPlant Err:" + err.Error() break } case utils.DATA_SOURCE_CALCULATE_CORRELATION: err, errMsg = models.RefreshAllCalculateCorrelation(edbInfo) case utils.DATA_SOURCE_CALCULATE_RJZ: //刷新日均值 calculateRjz, err := models.GetEdbInfoCalculateMappingDetail(edbInfoId) if err != nil { errMsg = "GetEdbInfoCalculateMappingDetail Err:" + err.Error() break } fromEdbInfo, err := models.GetEdbInfoById(calculateRjz.FromEdbInfoId) if err != nil { errMsg = "GetEdbInfoById Err:" + err.Error() break } //startDate = edbInfo.StartDate endDate = time.Now().Format(utils.FormatDate) err = models.RefreshAllCalculateRjz(edbInfoId, source, fromEdbInfo, calculateRjz.EdbCode, startDate, endDate) if err != nil && err.Error() != utils.ErrNoRow() { errMsg = "RefreshAllCalculateRjz Err:" + err.Error() break } default: // 获取通用的数据源处理服务 baseEdbInfoModel = models.GetBaseEdbInfoModel(source) // 没有找到的话,那么就直接返回报错吧 if baseEdbInfoModel == nil { br.Msg = "来源异常,请联系相关开发!" br.ErrMsg = "来源异常,请联系相关开发" return } err, errMsg = baseEdbInfoModel.Refresh(refreshParams) } if errMsg != `` { br.Msg = "刷新指标失败!" br.ErrMsg = "刷新指标失败,err:" + errMsg return } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } // 更新ES go logic.UpdateEs(edbInfoId) br.Ret = 200 br.Success = true br.Msg = "获取成功" } // SaveAdjust // @Title 保存数据调整指标接口 // @Description 保存数据调整指标接口 // @Success 200 {object} models.SaveAdjustEdbReq // @router /adjust/save [post] func (this *CalculateController) SaveAdjust() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.SaveAdjustEdbReq 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 } if len(req.DataList) == 0 { br.Msg = "请填写数据" return } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("edb_info:adjust:add:", utils.DATA_SOURCE_CALCULATE_ADJUST, ":", 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) }() } //获取指标数据 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 } edbInfo, err, errMsg := models.SaveAdjustEdb(req) if err != nil { br.Msg = errMsg br.Msg = "添加指标失败,Err:" + err.Error() 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.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } resp := models.AddEdbInfoResp{ EdbInfoId: edbInfo.EdbInfoId, UniqueCode: edbInfo.UniqueCode, } // 判断是否需要禁用 go services.DisableEdbInfoNoUpdate(edbInfo) // 重置计算指标中的引用关系 go services.ResetEdbRelation(edbInfo.EdbInfoId) br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // CalculateComputeCorrelation // @Title 拟合残差计算相关性 // @Description 拟合残差计算相关性接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /compute_correlation [post] func (this *CalculateController) 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 // 基础指标id 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 } // 因变量指标 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 } aVal, bVal, rVal, err, errMsg := models.CalculateComputeCorrelation(&req, fromEdbInfo, secondEdbInfo, nhccDate) if err != nil { br.Msg = "计算失败" if errMsg != `` { br.Msg = errMsg } br.ErrMsg = "计算失败,ERR:" + err.Error() return } connStr := `` if bVal >= 0 { connStr = `+` } valStr := fmt.Sprintf("y = %sx %s %s R²=%f", utils.SubFloatToString(aVal, 4), connStr, utils.SubFloatToString(bVal, 4), rVal) br.Ret = 200 br.Success = true br.Msg = "计算成功" br.Data = valStr br.IsAddLog = true } // ResetCustomAnalysisData // @Title 自定义表格数据重置 // @Description 自定义表格数据重置 // @Param request body models.ResetCustomAnalysisData true "type json string" // @Success Ret=200 返回指标id // @router /custom_analysis/reset [post] func (this *CalculateController) ResetCustomAnalysisData() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.ResetCustomAnalysisData err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() br.IsSendEmail = false return } if req.EdbInfoId <= 0 { br.Msg = "请选择指标" br.ErrMsg = br.Msg br.IsSendEmail = false return } if len(req.DateList) <= 0 { br.Msg = "请传入日期序列" br.ErrMsg = br.Msg br.IsSendEmail = false return } if len(req.DataList) <= 0 { br.Msg = "请传入数据序列" br.ErrMsg = br.Msg br.IsSendEmail = false return } 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 } baseEdbInfoModel := models.CustomAnalysis{} err, errMsg := baseEdbInfoModel.ResetData(edbInfo, req.DateList, req.DataList) if err != nil { br.Msg = "更新数据失败" if errMsg != `` { br.Msg = errMsg } br.ErrMsg = "更新数据失败 Err:" + err.Error() return } if edbInfo == nil { br.Msg = "更新数据失败" br.ErrMsg = "更新数据失败,指标ID错误:" return } // 更新指标最大最小值 err, errMsg = models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo) 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 } // Calculate // @Title 基础数据计算 // @Description 拟合残差计算相关性接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /base [post] func (this *CalculateController) Calculate() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() var req models.BaseCalculateBySearchData err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } dateDataMap := make(map[time.Time]float64) var errMsg string dataList, err := models.EdbInfoSearchDataToData(req.DataList) if err != nil { br.Msg = "计算失败,数据异常!" br.ErrMsg = "计算失败,数据异常,Err:" + err.Error() return } baseCalculate := models.BaseCalculate{ DataList: dataList, Frequency: req.Frequency, Formula: req.Formula, Calendar: req.Calendar, MoveType: req.MoveType, MoveFrequency: req.MoveFrequency, FromFrequency: req.FromFrequency, Source: req.Source, } //1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值 switch baseCalculate.Source { case 1: dateDataMap, err, errMsg = baseCalculate.Ljzzy() case 2: dateDataMap, err, errMsg = baseCalculate.Ljzzj() case 3: dateDataMap, err, errMsg = baseCalculate.Tbz() case 4: dateDataMap, err, errMsg = baseCalculate.Tcz() case 5: dateDataMap, err, errMsg = baseCalculate.Nszydpjjs() case 6: dateDataMap, err, errMsg = baseCalculate.Hbz() case 7: dateDataMap, err, errMsg = baseCalculate.Hcz() case 8: dateDataMap, err, errMsg = baseCalculate.UpFrequency() case 9: dateDataMap, err, errMsg = baseCalculate.DownFrequency() case 10: dateDataMap, err, errMsg = baseCalculate.TimeShift() case 11: dateDataMap, err, errMsg = baseCalculate.Cjjx() case 12: dateDataMap, err, errMsg = baseCalculate.Annualized() case 13: dateDataMap, err, errMsg = baseCalculate.Ljz() case 14: dateDataMap, err, errMsg = baseCalculate.LjzNczj() case 15: dateDataMap, err, errMsg = baseCalculate.ExponentialSmoothing() case 16: dateDataMap, err, errMsg = baseCalculate.Rjz() default: errMsg = "错误的计算类型" err = errors.New(errMsg + ":" + strconv.Itoa(baseCalculate.Source)) } if err != nil { br.Msg = "计算失败" if errMsg != `` { br.Msg = errMsg } br.ErrMsg = err.Error() return } dateStrDataMap, dateList := models.GetDateDataAndDateList(dateDataMap) br.Ret = 200 br.Success = true br.Msg = "计算成功" br.Data = models.BaseCalculateResp{ DataMap: dateStrDataMap, DateList: dateList, } br.IsAddLog = true } // BatchSaveMulti // @Title 批量计算 累计值转月-同比值-同差等计算新增 // @Description 批量计算 累计值转月-同比值-同差等计算新增接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /batch/save/multi [post] func (this *CalculateController) BatchSaveMulti() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() var req models.CalculateBatchSaveReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } resp := models.BatchEdbInfoCalculateBatchSaveResp{ Fail: make([]models.BatchEdbInfoCalculateBatchSaveFailResp, 0), Success: make([]models.BatchEdbInfoCalculateBatchSaveSuccessResp, 0), } redisKeyList := make([]string, 0) //需要清理的缓存key列表 defer func() { for _, redisKey := range redisKeyList { utils.Rc.Delete(redisKey) } }() var wg sync.WaitGroup // 校验参数 for _, item := range req.EdbList { calculateId := item.CalculateId //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("edb_info:calculate:batch:save:", req.AdminId, ":", req.Source, ":", calculateId) isExist := utils.Rc.IsExist(redisKey) if isExist { resp.Fail = append(resp.Fail, models.BatchEdbInfoCalculateBatchSaveFailResp{ CalculateId: calculateId, Msg: "指标正在处理,请勿重复提交", }) continue } else { //设置3分钟缓存 utils.Rc.SetNX(redisKey, 1, time.Second*300) redisKeyList = append(redisKeyList, redisKey) } wg.Add(1) reqItem := models.EdbInfoCalculateBatchSaveReq{ AdminId: req.AdminId, AdminName: req.AdminName, EdbInfoId: item.EdbInfoId, EdbName: item.EdbName, Frequency: item.Frequency, Unit: item.Unit, ClassifyId: item.ClassifyId, Formula: req.Formula, //N数值移动平均计算、环比值、环差值 FromEdbInfoId: item.FromEdbInfoId, CalculateFormula: req.CalculateFormula, Source: req.Source, MoveType: req.MoveType, MoveFrequency: req.MoveFrequency, EdbInfoIdArr: req.EdbInfoIdArr, Calendar: req.Calendar, EmptyType: req.EmptyType, MaxEmptyType: req.MaxEmptyType, Extra: req.Extra, } var edbInfo *models.EdbInfo uniqueCode := "" errMsg := "" go func() { defer func() { // todo 批量报错处理 if err != nil { // 整理报错的指标 utils.FileLog.Info(fmt.Sprintf("批量指标计算,保存失败 Err:%v, ErrMsg:%s", err, errMsg)) resp.Fail = append(resp.Fail, models.BatchEdbInfoCalculateBatchSaveFailResp{ CalculateId: calculateId, Msg: err.Error(), ErrMsg: errMsg, }) } else { // 整理成功的指标 //todo 整理执行成功指标信息 resp.Success = append(resp.Success, models.BatchEdbInfoCalculateBatchSaveSuccessResp{ ClassifyId: reqItem.ClassifyId, CalculateId: calculateId, EdbInfoId: edbInfo.EdbInfoId, UniqueCode: uniqueCode, }) } wg.Done() }() edbInfo, uniqueCode, err, errMsg = services.EdbCalculateBatchSave(reqItem, this.Lang) return }() } wg.Wait() br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // BatchEditMulti // @Title 批量计算 累计值转月-同比值-同差等计算编辑 // @Description 批量计算 累计值转月-同比值-同差等计算编辑接口 // @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string" // @Success Ret=200 返回指标id // @router /batch/edit/multi [post] func (this *CalculateController) BatchEditMulti() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() var req models.CalculateBatchSaveReq err := json.Unmarshal(this.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } resp := models.BatchEdbInfoCalculateBatchSaveResp{ Fail: make([]models.BatchEdbInfoCalculateBatchSaveFailResp, 0), Success: make([]models.BatchEdbInfoCalculateBatchSaveSuccessResp, 0), } redisKeyList := make([]string, 0) //需要清理的缓存key列表 defer func() { for _, redisKey := range redisKeyList { utils.Rc.Delete(redisKey) } }() var wg sync.WaitGroup // 校验参数 for _, item := range req.EdbList { calculateId := item.CalculateId if item.EdbInfoId <= 0 { resp.Fail = append(resp.Fail, models.BatchEdbInfoCalculateBatchSaveFailResp{ CalculateId: calculateId, Msg: "请选择要编辑的指标", }) continue } //加入缓存机制,避免创建同一个名称的指标 start redisKey := fmt.Sprint("edb_info:calculate:batch:edit:", req.AdminId, ":", req.Source, ":", item.EdbInfoId) isExist := utils.Rc.IsExist(redisKey) if isExist { resp.Fail = append(resp.Fail, models.BatchEdbInfoCalculateBatchSaveFailResp{ CalculateId: calculateId, Msg: "指标正在处理,请勿重复提交", }) continue } else { //设置3分钟缓存 utils.Rc.SetNX(redisKey, 1, time.Second*300) redisKeyList = append(redisKeyList, redisKey) } wg.Add(1) reqItem := models.EdbInfoCalculateBatchEditReq{ EdbInfoId: item.EdbInfoId, EdbName: item.EdbName, Frequency: item.Frequency, Unit: item.Unit, ClassifyId: item.ClassifyId, AdminId: req.AdminId, AdminName: req.AdminName, Formula: req.Formula, //N数值移动平均计算、环比值、环差值 FromEdbInfoId: item.FromEdbInfoId, CalculateFormula: req.CalculateFormula, Source: req.Source, MoveType: req.MoveType, MoveFrequency: req.MoveFrequency, EdbInfoIdArr: req.EdbInfoIdArr, Calendar: req.Calendar, EmptyType: req.EmptyType, MaxEmptyType: req.MaxEmptyType, Extra: req.Extra, } var errMsg string var edbInfo *models.EdbInfo uniqueCode := "" go func() { defer func() { // todo 批量报错处理 if err != nil { // 整理报错的指标 utils.FileLog.Info(fmt.Sprintf("批量指标计算,保存失败 Err:%v, ErrMsg:%s", err, errMsg)) resp.Fail = append(resp.Fail, models.BatchEdbInfoCalculateBatchSaveFailResp{ CalculateId: calculateId, Msg: err.Error(), ErrMsg: errMsg, }) } else { // 整理成功的指标 //todo 整理执行成功指标信息 resp.Success = append(resp.Success, models.BatchEdbInfoCalculateBatchSaveSuccessResp{ ClassifyId: reqItem.ClassifyId, CalculateId: calculateId, EdbInfoId: edbInfo.EdbInfoId, UniqueCode: uniqueCode, }) } wg.Done() }() edbInfo, uniqueCode, err, errMsg = services.EdbCalculateBatchEdit(reqItem) return }() } wg.Wait() if err != nil { br.Msg = "批量指标计算,保存失败" br.ErrMsg = "批量指标计算,保存失败,Err:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "保存成功" br.Data = resp br.IsAddLog = true } // StepCalculate // @Title 多步骤计算 // @Description 多步骤计算 // @Param request body models.StepCalculateBySearchData true "type json string" // @Success Ret=200 返回指标id // @router /base/step_calculate [post] func (this *CalculateController) StepCalculate() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() var req models.StepCalculateBySearchData if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil { br.Msg = "参数解析异常" br.ErrMsg = fmt.Sprintf("参数解析失败, Err: %v", e) return } //sort.Slice(req.Calculates, func(i, j int) bool { // return req.Calculates[i].Sort < req.Calculates[j].Sort //}) // //var errMsg string //originData, e := models.EdbInfoSearchDataToData(req.DataList) //if e != nil { // br.Msg = "基础数据异常" // br.ErrMsg = fmt.Sprintf("计算失败, 基础数据异常, Err: %v", e) // return //} // //calculateData := originData //dateDataMap := make(map[time.Time]float64) //for _, v := range req.Calculates { // baseCalculate := models.BaseCalculate{ // DataList: calculateData, // Frequency: v.Frequency, // Formula: v.Formula, // Calendar: v.Calendar, // MoveType: v.MoveType, // MoveFrequency: v.MoveFrequency, // FromFrequency: v.FromFrequency, // Source: v.Source, // } // // // 计算方式 // switch baseCalculate.Source { // case utils.EdbBaseCalculateLjzzy: // dateDataMap, e, errMsg = baseCalculate.Ljzzy() // case utils.EdbBaseCalculateLjzzj: // dateDataMap, e, errMsg = baseCalculate.Ljzzj() // case utils.EdbBaseCalculateTbz: // dateDataMap, e, errMsg = baseCalculate.Tbz() // case utils.EdbBaseCalculateTcz: // dateDataMap, e, errMsg = baseCalculate.Tcz() // case utils.EdbBaseCalculateNszydpjjs: // dateDataMap, e, errMsg = baseCalculate.Nszydpjjs() // case utils.EdbBaseCalculateHbz: // dateDataMap, e, errMsg = baseCalculate.Hbz() // case utils.EdbBaseCalculateHcz: // dateDataMap, e, errMsg = baseCalculate.Hcz() // case utils.EdbBaseCalculateUpFrequency: // dateDataMap, e, errMsg = baseCalculate.UpFrequency() // case utils.EdbBaseCalculateDownFrequency: // dateDataMap, e, errMsg = baseCalculate.DownFrequency() // case utils.EdbBaseCalculateTimeShift: // dateDataMap, e, errMsg = baseCalculate.TimeShift() // case utils.EdbBaseCalculateCjjx: // dateDataMap, e, errMsg = baseCalculate.Cjjx() // case utils.EdbBaseCalculateAnnualized: // dateDataMap, e, errMsg = baseCalculate.Annualized() // case utils.EdbBaseCalculateLjz: // dateDataMap, e, errMsg = baseCalculate.Ljz() // case utils.EdbBaseCalculateLjzNczj: // dateDataMap, e, errMsg = baseCalculate.LjzNczj() // case utils.EdbBaseCalculateExponentialSmoothing: // dateDataMap, e, errMsg = baseCalculate.ExponentialSmoothing() // case utils.EdbBaseCalculateRjz: // dateDataMap, e, errMsg = baseCalculate.Rjz() // default: // errMsg = "计算方式无效" // e = fmt.Errorf("%s:%d", errMsg, baseCalculate.Source) // } // if e != nil { // br.Msg = "计算失败" // if errMsg != "" { // br.Msg = errMsg // } // br.ErrMsg = e.Error() // return // } // // calculateData = models.TransDateData2EdbData(dateDataMap) //} resultData, dates, errMsg, e := services.StepCalculate(req.DataList, req.Calculates) if e != nil { br.Msg = "计算失败" if errMsg != "" { br.Msg = errMsg } br.ErrMsg = fmt.Sprintf("分步骤计算失败, Err: %v", e) return } br.Ret = 200 br.Success = true br.Msg = "计算成功" br.Data = models.BaseCalculateResp{ DataMap: resultData, DateList: dates, } br.IsAddLog = true }