Browse Source

fix:更改表名

Roc 2 years ago
parent
commit
57b2949e07

+ 663 - 0
controllers/base_from_predict_calculate.go

@@ -460,6 +460,669 @@ func editPredictCalculate(br *models.BaseResponse, req models.EdbInfoCalculateSa
 	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
+	}
+
+	if req.FromEdbInfoId <= 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	var formulaInt int
+	if req.Source == utils.DATA_SOURCE_CALCULATE_NSZYDPJJS ||
+		req.Source == utils.DATA_SOURCE_CALCULATE_HBZ ||
+		req.Source == utils.DATA_SOURCE_CALCULATE_HCZ ||
+		req.Source == utils.DATA_SOURCE_CALCULATE_TIME_SHIFT {
+		if req.Formula == "" {
+			br.Msg = "请填写N值"
+			return
+		}
+		formulaInt, _ = strconv.Atoi(req.Formula)
+		if formulaInt <= 0 {
+			br.Msg = "N值输入错误,请重新输入"
+			return
+		}
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_ZJPJ {
+		//直接拼接指标
+
+		//校验时间格式
+		_, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local)
+		if err != nil {
+			br.Msg = "拼接日期有误,请重新输入"
+			return
+		}
+	}
+
+	// 获取指标详情
+	edbInfo, err := models.GetEdbInfoById(req.EdbInfoId)
+	if err != nil {
+		br.Msg = "指标不存在!"
+		br.ErrMsg = "指标不存在"
+		return
+	}
+
+	//加入缓存机制,避免创建同一个名称的指标 start
+	redisKey := fmt.Sprint("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
+
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_name=? "
+	pars = append(pars, 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
+	}
+
+	fromEdbInfo, err := models.GetEdbInfoById(req.FromEdbInfoId)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
+		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 edbInfoId int
+	if req.Source == utils.DATA_SOURCE_CALCULATE_LJZZY {
+		sourName = "累计值转月值"
+		if fromEdbInfo.Frequency != "月度" {
+			br.Msg = "请选择月度指标"
+			return
+		}
+		edbInfoId, err = models.AddCalculateLjzzy(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_TBZ {
+		sourName = "同比值"
+		edbInfoId, err = models.AddCalculateTbz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_TCZ {
+		sourName = "同差值"
+		edbInfoId, err = models.AddCalculateTcz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_NSZYDPJJS {
+		sourName = "N数值移动平均计算"
+		edbInfoId, err = models.AddCalculateNszydpjjs(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_HBZ { //环比值
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id =? "
+		pars = append(pars, req.FromEdbInfoId)
+		condition += " AND value <=0 "
+		checkCount, err := models.GetEdbDataCount(condition, pars, fromEdbInfo.Source)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "判断环比值是否可计算失败"
+			br.ErrMsg = "判断环比值是否可计算失败,Err:" + err.Error()
+			return
+		}
+		if checkCount > 0 {
+			br.Msg = "原始数据中存在0或负数,该指标不能进行环比运算"
+			br.ErrMsg = "原始数据中出现0和负值时,提示该指标不能进行环比运算"
+			return
+		}
+		sourName = "环比值"
+		edbInfoId, err = models.AddCalculateHbz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_HCZ {
+		sourName = "环差值"
+		edbInfoId, err = models.AddCalculateHcz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName, formulaInt)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_BP {
+		if fromEdbInfo.Frequency == "日度" {
+			br.Msg = "日度指标,无法进行变频操作"
+			br.ErrMsg = "日度指标,无法进行变频操作:edbcode:" + fromEdbInfo.EdbCode
+			return
+		}
+		sourName = "变频"
+		edbInfoId, err = models.AddCalculateBp(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_TIME_SHIFT { //时间移位
+		sourName = "时间移位"
+		edbInfoId, err = models.AddCalculateTimeShift(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_CALCULATE_ZJPJ { //直接拼接
+		sourName = "直接拼接"
+
+		if len(req.EdbInfoIdArr) != 1 {
+			br.Msg = "请传入拼接日期之后的指标"
+			br.ErrMsg = "请传入拼接日期之后的指标"
+			return
+		}
+
+		secondEdbInfoReq := req.EdbInfoIdArr[0]
+		secondEdbInfo, err := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId)
+		if err != nil {
+			br.Msg = "获取拼接日期之后的指标信息失败"
+			br.ErrMsg = "获取拼接日期之后的指标信息失败:Err:" + err.Error()
+			return
+		}
+
+		if fromEdbInfo.EdbInfoId == secondEdbInfo.EdbInfoId {
+			br.Msg = "两个指标不允许为同一个"
+			br.ErrMsg = "两个指标不允许为同一个"
+			return
+		}
+		edbInfoId, err = models.AddCalculateZjpj(&req, fromEdbInfo, secondEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == 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, err := models.GetEdbInfoById(secondEdbInfoReq.EdbInfoId)
+		if err != nil {
+			br.Msg = "获取同比值指标信息失败"
+			br.ErrMsg = "获取同比值指标信息失败:Err:" + err.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
+		}
+		edbInfoId, err = models.AddCalculateLjztbpj(&req, fromEdbInfo, tbzEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else {
+		br.Msg = "无效计算方式"
+		br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source)
+		return
+	}
+
+	if err != nil {
+		br.Msg = "生成" + sourName + "失败"
+		br.Msg = "生成" + sourName + "失败 Err:" + err.Error()
+		return
+	}
+	if edbInfoId <= 0 {
+		br.Msg = "生成" + sourName + "失败"
+		br.ErrMsg = "生成" + sourName + "失败,指标ID错误:" + strconv.Itoa(edbInfoId)
+		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:  edbInfoId,
+		UniqueCode: uniqueCode,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+func AddCalculateBatchSave(br *models.BaseResponse, req models.EdbInfoCalculateBatchSaveReq) {
+	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 req.FromEdbInfoId <= 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	// 获取指标详情
+	edbInfo, err := models.GetEdbInfoById(req.EdbInfoId)
+	if err != nil {
+		br.Msg = "指标不存在!"
+		br.ErrMsg = "指标不存在"
+		return
+	}
+
+	//加入缓存机制,避免创建同一个名称的指标 start
+	redisKey := fmt.Sprint("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
+
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_name=? "
+	pars = append(pars, 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
+	}
+
+	fromEdbInfo, err := models.GetEdbInfoById(req.FromEdbInfoId)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
+		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 edbInfoId int
+	if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_TBZ {
+		sourName = "预测同比"
+		edbInfoId, err = models.AddPredictCalculateTbz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else if req.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_TCZ {
+		sourName = "预测同差"
+		edbInfoId, err = models.AddPredictCalculateTcz(&req, fromEdbInfo, edbCode, uniqueCode, adminId, adminName)
+	} else {
+		br.Msg = "无效计算方式"
+		br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(req.Source)
+		return
+	}
+
+	if err != nil {
+		br.Msg = "生成" + sourName + "失败"
+		br.Msg = "生成" + sourName + "失败 Err:" + err.Error()
+		return
+	}
+	if edbInfoId <= 0 {
+		br.Msg = "生成" + sourName + "失败"
+		br.ErrMsg = "生成" + sourName + "失败,指标ID错误:" + strconv.Itoa(edbInfoId)
+		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:  edbInfoId,
+		UniqueCode: uniqueCode,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// 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)
+//	}
+//	formulaMap := services.CheckFormula(req.CalculateFormula)
+//	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)
+//		}
+//	}
+//
+//	// 指标入库
+//	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,
+//	}
+//	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, int(edbInfoId), 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
+//}
+
 // Refresh
 // @Title 刷新计算指标接口
 // @Description 刷新计算指标接口

+ 1 - 1
models/base_predict_from_calculate.go

@@ -135,7 +135,7 @@ func AddPredictCalculateData(edbInfoIdList []*EdbInfo, edbInfoId int, edbCode, f
 		item.DataMap = dataMap
 	}
 	formulaMap := services.CheckFormula(formulaStr)
-	addSql := ` INSERT INTO edb_predict_data_calculate (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	addSql := ` INSERT INTO edb_data_predict_calculate (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
 	nowStr := time.Now().Format(utils.FormatDateTime)
 	var isAdd bool
 

+ 5 - 1
models/edb_data_table.go

@@ -64,7 +64,11 @@ func GetEdbDataTableName(source int) (tableName string) {
 	case utils.DATA_SOURCE_GOOGLE_TRAVEL:
 		tableName = "edb_data_google_travel"
 	case utils.DATA_SOURCE_PREDICT_CALCULATE:
-		tableName = "edb_predict_data_calculate"
+		tableName = "edb_data_predict_calculate"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_TBZ:
+		tableName = "edb_data_predict_calculate_tbz"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_TCZ:
+		tableName = "edb_data_predict_calculate_tcz"
 	default:
 		tableName = ""
 	}

+ 740 - 0
models/predict_edb_data_calculate_tbz.go

@@ -0,0 +1,740 @@
+package models
+
+import (
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// AddPredictCalculateTbz 同比值
+func AddPredictCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateTbz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	if req.EdbInfoId <= 0 {
+		edbInfo := new(EdbInfo)
+		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_TBZ
+		edbInfo.SourceName = "同比值"
+		edbInfo.EdbCode = edbCode
+		edbInfo.EdbName = req.EdbName
+		edbInfo.EdbNameSource = req.EdbName
+		edbInfo.Frequency = req.Frequency
+		edbInfo.Unit = req.Unit
+		edbInfo.ClassifyId = req.ClassifyId
+		edbInfo.SysUserId = sysUserId
+		edbInfo.SysUserRealName = sysUserRealName
+		edbInfo.CreateTime = time.Now()
+		edbInfo.ModifyTime = time.Now()
+		edbInfo.UniqueCode = uniqueCode
+		edbInfo.CalculateFormula = req.Formula
+		edbInfo.EdbType = 2
+		newEdbInfoId, tmpErr := to.Insert(edbInfo)
+		if tmpErr != nil {
+			return edbInfoId, tmpErr
+		}
+		edbInfoId = int(newEdbInfoId)
+
+		//关联关系
+		{
+			calculateMappingItem := new(EdbInfoCalculateMapping)
+			calculateMappingItem.CreateTime = time.Now()
+			calculateMappingItem.ModifyTime = time.Now()
+			calculateMappingItem.Sort = 1
+			calculateMappingItem.EdbCode = edbCode
+			calculateMappingItem.EdbInfoId = edbInfoId
+			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+			calculateMappingItem.FromSource = fromEdbInfo.Source
+			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+			calculateMappingItem.FromTag = ""
+			calculateMappingItem.Source = edbInfo.Source
+			calculateMappingItem.SourceName = edbInfo.SourceName
+			_, err = to.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+
+	} else {
+		edbInfoId = req.EdbInfoId
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TBZ)
+		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
+		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
+		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+	//计算数据
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_info_id=? "
+	if req.EdbInfoId <= 0 {
+		pars = append(pars, req.FromEdbInfoId)
+	} else {
+		pars = append(pars, fromEdbInfo.EdbInfoId)
+	}
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	if err != nil {
+		return edbInfoId, err
+	}
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	addSql := ` INSERT INTO edb_data_predict_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	existMap := make(map[string]string)
+	for _, av := range dateArr {
+		//fmt.Println(ak, av)
+		currentItem := dataMap[av]
+		if currentItem != nil {
+			//当前日期
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return edbInfoId, err
+			}
+			//上一年的日期
+			preDate := currentDate.AddDate(-1, 0, 0)
+			preDateStr := preDate.Format(utils.FormatDate)
+			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+				//dataTime, _ := time.Parse(utils.FormatDate, date)
+				if _, ok := existMap[edbCode+av]; !ok {
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					val := TbzDiv(currentItem.Value, findItem.Value)
+					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+					isAdd = true
+					utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
+				}
+				existMap[edbCode+av] = av
+			} else {
+				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+					nextDateDay := preDate
+					preDateDay := preDate
+					for i := 0; i <= 35; i++ {
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							if _, ok := existMap[edbCode+av]; !ok {
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existMap[edbCode+av] = av
+							break
+						} else {
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								if _, ok := existMap[edbCode+av]; !ok {
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TbzDiv(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existMap[edbCode+av] = av
+								break
+							}
+						}
+						nextDateDay = nextDateDay.AddDate(0, 0, 1)
+						preDateDay = preDateDay.AddDate(0, 0, -1)
+					}
+				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+						if _, ok := existMap[edbCode+av]; !ok {
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TbzDiv(currentItem.Value, findItem.Value)
+
+							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+							isAdd = true
+						}
+						existMap[edbCode+av] = av
+						break
+					}
+				} else {
+					nextDateDay := preDate
+					preDateDay := preDate
+
+					for i := 0; i < 35; i++ {
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							if _, ok := existMap[edbCode+av]; !ok {
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existMap[edbCode+av] = av
+							break
+						} else {
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								if _, ok := existMap[edbCode+av]; !ok {
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TbzDiv(currentItem.Value, findItem.Value)
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existMap[edbCode+av] = av
+								break
+							} else {
+								//fmt.Println("pre not find:", preDateStr, "i:", i)
+							}
+						}
+						nextDateDay = nextDateDay.AddDate(0, 0, 1)
+						preDateDay = preDateDay.AddDate(0, 0, -1)
+					}
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = to.Raw(addSql).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+	}
+	return
+}
+
+// EditPredictCalculateTbz 同比值
+func EditPredictCalculateTbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string) (edbInfoId int, err error) {
+	edbInfoId = req.EdbInfoId
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EditCalculateTbz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	var existCondition string
+	var existPars []interface{}
+	existCondition += " AND edb_info_id=? "
+	existPars = append(existPars, edbInfoId)
+
+	existCondition += " AND from_edb_info_id=? "
+	existPars = append(existPars, req.FromEdbInfoId)
+
+	//判断计算指标是否被更换
+	count, err := GetEdbInfoCalculateCountByCondition(existCondition, existPars)
+	if err != nil {
+		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
+		return
+	}
+	if count <= 0 {
+		//删除指标关联计算指标
+		//sql := ` DELETE FROM edb_info_calculate_tbz WHERE edb_info_id = ? `
+		//_, err = o.Raw(sql, edbInfoId).Exec()
+		//if err != nil {
+		//	return
+		//}
+		//
+		//calculateItem := new(EdbInfoCalculateTbz)
+		//calculateItem.CreateTime = time.Now()
+		//calculateItem.ModifyTime = time.Now()
+		//calculateItem.Sort = 1
+		//calculateItem.EdbCode = edbCode
+		//calculateItem.EdbInfoId = edbInfoId
+		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
+		//calculateItem.FromEdbName = fromEdbInfo.EdbName
+		//calculateItem.FromSource = fromEdbInfo.Source
+		//calculateItem.FromSourceName = fromEdbInfo.SourceName
+		//
+		//_, err = o.Insert(calculateItem)
+		//if err != nil {
+		//	return
+		//}
+
+		//删除,计算指标关联的,基础指标的关联关系
+		sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_predict_calculate_tbz WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+		//关联关系
+		{
+			calculateMappingItem := new(EdbInfoCalculateMapping)
+			calculateMappingItem.CreateTime = time.Now()
+			calculateMappingItem.ModifyTime = time.Now()
+			calculateMappingItem.Sort = 1
+			calculateMappingItem.EdbCode = edbCode
+			calculateMappingItem.EdbInfoId = edbInfoId
+			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+			calculateMappingItem.FromSource = fromEdbInfo.Source
+			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+			calculateMappingItem.FromTag = ""
+			calculateMappingItem.Source = utils.DATA_SOURCE_CALCULATE_TBZ
+			calculateMappingItem.SourceName = "同比值"
+			_, err = o.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+		//计算数据
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id=? "
+		pars = append(pars, req.FromEdbInfoId)
+		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
+		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+		if err != nil {
+			return edbInfoId, err
+		}
+		var dateArr []string
+		dataMap := make(map[string]*EdbInfoSearchData)
+		for _, v := range dataList {
+			dateArr = append(dateArr, v.DataTime)
+			dataMap[v.DataTime] = v
+		}
+
+		addSql := ` INSERT INTO edb_data_predict_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+		var isAdd bool
+		for _, av := range dateArr {
+			currentItem := dataMap[av]
+			if currentItem != nil {
+				//当前日期
+				currentDate, err := time.Parse(utils.FormatDate, av)
+				if err != nil {
+					return edbInfoId, err
+				}
+				//上一年的日期
+				preDate := currentDate.AddDate(-1, 0, 0)
+				preDateStr := preDate.Format(utils.FormatDate)
+				if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+					//dataTime, _ := time.Parse(utils.FormatDate, date)
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					val := TbzDiv(currentItem.Value, findItem.Value)
+					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+					isAdd = true
+					utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
+					continue
+				} else {
+					if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+						nextDateDay := preDate.AddDate(0, 1, 0)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+						preDateDay := preDate.AddDate(0, -1, 0)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+						for i := 0; i <= 6; i++ {
+							if i >= 1 {
+								nextDateDay = nextDateDay.AddDate(0, 0, i)
+								nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+							}
+							if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+								break
+							} else {
+								if i >= 1 {
+									preDateDay = preDate.AddDate(0, 0, -i)
+									preDateDayStr = nextDateDay.Format(utils.FormatDate)
+								}
+								if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TbzDiv(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+									break
+								}
+							}
+						}
+					} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+						if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TbzDiv(currentItem.Value, findItem.Value)
+
+							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+							isAdd = true
+							break
+						}
+					} else {
+						nextDateDay := preDate.AddDate(0, 0, 1)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+						preDateDay := preDate.AddDate(0, 0, -1)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+						for i := 0; i < 35; i++ {
+							if i >= 1 {
+								nextDateDay = nextDateDay.AddDate(0, 0, i)
+								nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+							}
+							if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+								break
+							} else {
+								if i >= 1 {
+									preDateDay = preDate.AddDate(0, 0, -i)
+									preDateDayStr = nextDateDay.Format(utils.FormatDate)
+								}
+								if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TbzDiv(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+									break
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllPredictCalculateTbz 刷新所有同比值数据
+func RefreshAllPredictCalculateTbz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateTbz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	//计算数据
+
+	//计算数据
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_info_id=? "
+	pars = append(pars, fromEdbInfo.EdbInfoId)
+
+	if startDate != "" {
+		condition += " AND data_time>=? "
+		pars = append(pars, startDate)
+	}
+	//if endDate != "" {
+	//	condition += " AND data_time<=? "
+	//	pars = append(pars, endDate)
+	//}
+
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	if err != nil {
+		return err
+	}
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+	fmt.Println("source:", source)
+	//获取指标所有数据
+	existDataList := make([]*EdbData, 0)
+	dataTableName := GetEdbDataTableName(source)
+	fmt.Println("dataTableName:", dataTableName)
+	sql := `SELECT * FROM %s WHERE edb_info_id=? `
+	sql = fmt.Sprintf(sql, dataTableName)
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&existDataList)
+	if err != nil {
+		return err
+	}
+	existDataMap := make(map[string]string)
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v.Value
+	}
+	fmt.Println("existDataMap:", existDataMap)
+	addSql := ` INSERT INTO edb_data_predict_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	existAddDataMap := make(map[string]string)
+	for _, av := range dateArr {
+		currentItem := dataMap[av]
+		if currentItem != nil {
+			//当前日期
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return err
+			}
+			//上一年的日期
+			preDate := currentDate.AddDate(-1, 0, 0)
+			preDateStr := preDate.Format(utils.FormatDate)
+			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+				//dataTime, _ := time.Parse(utils.FormatDate, date)
+				timestamp := currentDate.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				val := TbzDiv(currentItem.Value, findItem.Value)
+
+				if existVal, ok := existDataMap[av]; !ok {
+					if _, existOk := existAddDataMap[av]; !existOk {
+						addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+						isAdd = true
+					}
+					existAddDataMap[av] = av
+				} else {
+					existValDecimal, err := decimal.NewFromString(existVal)
+					existStr := existValDecimal.String()
+					if existStr != val {
+						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+						sql = fmt.Sprintf(sql, dataTableName)
+						_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+						if err != nil {
+							return err
+						}
+					}
+				}
+				continue
+			} else {
+				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+					for i := 0; i <= 35; i++ {
+						nextDateDay := preDate.AddDate(0, 0, i)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TbzDiv(currentItem.Value, findItem.Value)
+
+							if existVal, ok := existDataMap[av]; !ok {
+								if _, existOk := existAddDataMap[av]; !existOk {
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existAddDataMap[av] = av
+							} else {
+								existValDecimal, err := decimal.NewFromString(existVal)
+								existStr := existValDecimal.String()
+								if existStr != val {
+									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+									sql = fmt.Sprintf(sql, dataTableName)
+									_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+									if err != nil {
+										return err
+									}
+								}
+							}
+							break
+						} else {
+							preDateDay := preDate.AddDate(0, 0, -i)
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+
+								if existVal, ok := existDataMap[av]; !ok {
+									if _, existOk := existAddDataMap[av]; !existOk {
+										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+										isAdd = true
+									}
+									existAddDataMap[av] = av
+								} else {
+									existValDecimal, err := decimal.NewFromString(existVal)
+									existStr := existValDecimal.String()
+									if existStr != val {
+										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+										sql = fmt.Sprintf(sql, dataTableName)
+										_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+										if err != nil {
+											return err
+										}
+									}
+								}
+								break
+							}
+						}
+					}
+				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+						timestamp := currentDate.UnixNano() / 1e6
+						timestampStr := fmt.Sprintf("%d", timestamp)
+						val := TbzDiv(currentItem.Value, findItem.Value)
+
+						if existVal, ok := existDataMap[av]; !ok {
+							if _, existOk := existAddDataMap[av]; !existOk {
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existAddDataMap[av] = av
+						} else {
+							existValDecimal, err := decimal.NewFromString(existVal)
+							existStr := existValDecimal.String()
+							if existStr != val {
+								sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+								sql = fmt.Sprintf(sql, dataTableName)
+								_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+								if err != nil {
+									return err
+								}
+							}
+						}
+						break
+					}
+				} else {
+					nextDateDay := preDate.AddDate(0, 0, 1)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+					preDateDay := preDate.AddDate(0, 0, -1)
+					preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+					for i := 0; i < 35; i++ {
+						if i >= 1 {
+							nextDateDay = nextDateDay.AddDate(0, 0, i)
+							nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+						}
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TbzDiv(currentItem.Value, findItem.Value)
+
+							if existVal, ok := existDataMap[av]; !ok {
+								if _, existOk := existAddDataMap[av]; !existOk {
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existAddDataMap[av] = av
+							} else {
+								existValDecimal, err := decimal.NewFromString(existVal)
+								existStr := existValDecimal.String()
+								if existStr != val {
+									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+									sql = fmt.Sprintf(sql, dataTableName)
+									_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+									if err != nil {
+										return err
+									}
+								}
+							}
+							break
+						} else {
+							if i >= 1 {
+								preDateDay = preDate.AddDate(0, 0, -i)
+								preDateDayStr = nextDateDay.Format(utils.FormatDate)
+							}
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TbzDiv(currentItem.Value, findItem.Value)
+
+								if existVal, ok := existDataMap[av]; !ok {
+									if _, existOk := existAddDataMap[av]; !existOk {
+										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+										isAdd = true
+									}
+									existAddDataMap[av] = av
+								} else {
+									existValDecimal, err := decimal.NewFromString(existVal)
+									existStr := existValDecimal.String()
+									if existStr != val {
+										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+										sql = fmt.Sprintf(sql, dataTableName)
+										_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+										if err != nil {
+											return err
+										}
+									}
+								}
+								break
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}

+ 737 - 0
models/predict_edb_data_calculate_tcz.go

@@ -0,0 +1,737 @@
+package models
+
+import (
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// AddPredictCalculateTcz 同差值
+func AddPredictCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateTcz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	fmt.Println("req.EdbInfoId:", req.EdbInfoId)
+	if req.EdbInfoId <= 0 {
+		edbInfo := new(EdbInfo)
+		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_TCZ
+		edbInfo.SourceName = "同差值"
+		edbInfo.EdbCode = edbCode
+		edbInfo.EdbName = req.EdbName
+		edbInfo.EdbNameSource = req.EdbName
+		edbInfo.Frequency = req.Frequency
+		edbInfo.Unit = req.Unit
+		edbInfo.ClassifyId = req.ClassifyId
+		edbInfo.SysUserId = sysUserId
+		edbInfo.SysUserRealName = sysUserRealName
+		edbInfo.CreateTime = time.Now()
+		edbInfo.ModifyTime = time.Now()
+		edbInfo.UniqueCode = uniqueCode
+		edbInfo.CalculateFormula = req.Formula
+		edbInfo.EdbType = 2
+		newEdbInfoId, tmpErr := to.Insert(edbInfo)
+		if tmpErr != nil {
+			return edbInfoId, tmpErr
+		}
+		edbInfoId = int(newEdbInfoId)
+
+		//关联关系
+		{
+			calculateMappingItem := new(EdbInfoCalculateMapping)
+			calculateMappingItem.CreateTime = time.Now()
+			calculateMappingItem.ModifyTime = time.Now()
+			calculateMappingItem.Sort = 1
+			calculateMappingItem.EdbCode = edbCode
+			calculateMappingItem.EdbInfoId = edbInfoId
+			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+			calculateMappingItem.FromSource = fromEdbInfo.Source
+			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+			calculateMappingItem.FromTag = ""
+			calculateMappingItem.Source = edbInfo.Source
+			calculateMappingItem.SourceName = edbInfo.SourceName
+			_, err = to.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+	} else {
+		edbInfoId = req.EdbInfoId
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TCZ)
+		fmt.Println("dataTableName:", dataTableName)
+		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
+		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
+		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+	}
+
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+	//计算数据
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_info_id=? "
+	if req.EdbInfoId <= 0 {
+		pars = append(pars, req.FromEdbInfoId)
+	} else {
+		pars = append(pars, fromEdbInfo.EdbInfoId)
+	}
+
+	fmt.Println("EdbInfoId:", req.FromEdbInfoId)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	if err != nil {
+		return edbInfoId, err
+	}
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+	fmt.Println("Frequency:", fromEdbInfo.Frequency)
+	addSql := ` INSERT INTO edb_data_predict_calculate_tcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	existMap := make(map[string]string)
+	for _, av := range dateArr {
+		//fmt.Println("dateArr:", ak, av)
+		currentItem := dataMap[av]
+		if currentItem != nil {
+			//当前日期
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return edbInfoId, err
+			}
+			//上一年的日期
+			preDate := currentDate.AddDate(-1, 0, 0)
+			preDateStr := preDate.Format(utils.FormatDate)
+			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+				//dataTime, _ := time.Parse(utils.FormatDate, date)
+				if _, ok := existMap[edbCode+av]; !ok {
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+
+					val := TczSub(currentItem.Value, findItem.Value)
+					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+					isAdd = true
+				}
+				existMap[edbCode+av] = av
+			} else {
+				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+					nextDateDay := preDate
+					preDateDay := preDate
+					for i := 0; i <= 35; i++ {
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //下一年同期->下一个月找到
+							if _, ok := existMap[edbCode+av]; !ok {
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existMap[edbCode+av] = av
+							break
+						} else {
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								if _, ok := existMap[edbCode+av]; !ok {
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TczSub(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existMap[edbCode+av] = av
+								break
+							}
+						}
+						nextDateDay = nextDateDay.AddDate(0, 0, 1)
+						preDateDay = preDateDay.AddDate(0, 0, -1)
+					}
+				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+						if _, ok := existMap[edbCode+av]; !ok {
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TczSub(currentItem.Value, findItem.Value)
+							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+							isAdd = true
+						}
+						existMap[edbCode+av] = av
+						break
+					}
+				} else {
+					nextDateDay := preDate
+					preDateDay := preDate
+					for i := 0; i < 35; i++ {
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							if _, ok := existMap[edbCode+av]; !ok {
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existMap[edbCode+av] = av
+							break
+						} else {
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								if _, ok := existMap[edbCode+av]; !ok {
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TczSub(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existMap[edbCode+av] = av
+								break
+							} else {
+
+							}
+						}
+						nextDateDay = nextDateDay.AddDate(0, 0, 1)
+						preDateDay = preDateDay.AddDate(0, 0, -1)
+					}
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = to.Raw(addSql).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+	}
+	return
+}
+
+// EditPredictCalculateTcz 同差值
+func EditPredictCalculateTcz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string) (edbInfoId int, err error) {
+	edbInfoId = req.EdbInfoId
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EditCalculateTcz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	var existCondition string
+	var existPars []interface{}
+	existCondition += " AND edb_info_id=? "
+	existPars = append(existPars, edbInfoId)
+
+	existCondition += " AND from_edb_info_id=? "
+	existPars = append(existPars, req.FromEdbInfoId)
+
+	//判断计算指标是否被更换
+	count, err := GetEdbInfoCalculateCountByCondition(existCondition, existPars)
+	if err != nil {
+		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
+		return
+	}
+	if count <= 0 {
+		//删除指标关联计算指标
+		//sql := ` DELETE FROM edb_info_calculate_tcz WHERE edb_info_id = ? `
+		//_, err = o.Raw(sql, edbInfoId).Exec()
+		//if err != nil {
+		//	return
+		//}
+		//
+		//calculateItem := new(EdbInfoCalculateTcz)
+		//calculateItem.CreateTime = time.Now()
+		//calculateItem.ModifyTime = time.Now()
+		//calculateItem.Sort = 1
+		//calculateItem.EdbCode = edbCode
+		//calculateItem.EdbInfoId = edbInfoId
+		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
+		//calculateItem.FromEdbName = fromEdbInfo.EdbName
+		//calculateItem.FromSource = fromEdbInfo.Source
+		//calculateItem.FromSourceName = fromEdbInfo.SourceName
+		//
+		//_, err = o.Insert(calculateItem)
+		//if err != nil {
+		//	return
+		//}
+
+		//删除,计算指标关联的,基础指标的关联关系
+		sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return
+		}
+
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_predict_calculate_tcz WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+
+		//关联关系
+		{
+			calculateMappingItem := new(EdbInfoCalculateMapping)
+			calculateMappingItem.CreateTime = time.Now()
+			calculateMappingItem.ModifyTime = time.Now()
+			calculateMappingItem.Sort = 1
+			calculateMappingItem.EdbCode = edbCode
+			calculateMappingItem.EdbInfoId = edbInfoId
+			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+			calculateMappingItem.FromSource = fromEdbInfo.Source
+			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+			calculateMappingItem.FromTag = ""
+			calculateMappingItem.Source = utils.DATA_SOURCE_CALCULATE_TCZ
+			calculateMappingItem.SourceName = "同差值"
+			_, err = o.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+		//计算数据
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id=? "
+		pars = append(pars, req.FromEdbInfoId)
+		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
+		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+		if err != nil {
+			return edbInfoId, err
+		}
+		var dateArr []string
+		dataMap := make(map[string]*EdbInfoSearchData)
+		for _, v := range dataList {
+			dateArr = append(dateArr, v.DataTime)
+			dataMap[v.DataTime] = v
+		}
+
+		addSql := ` INSERT INTO edb_data_predict_calculate_tcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+		var isAdd bool
+		for ak, av := range dateArr {
+			fmt.Println(ak, av)
+			currentItem := dataMap[av]
+			if currentItem != nil {
+				//当前日期
+				currentDate, err := time.Parse(utils.FormatDate, av)
+				if err != nil {
+					return edbInfoId, err
+				}
+				//上一年的日期
+				preDate := currentDate.AddDate(-1, 0, 0)
+				preDateStr := preDate.Format(utils.FormatDate)
+				if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+					//dataTime, _ := time.Parse(utils.FormatDate, date)
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+
+					val := TczSub(currentItem.Value, findItem.Value)
+					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+					isAdd = true
+					utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
+					continue
+				} else {
+					if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+						nextDateDay := preDate.AddDate(0, 1, 0)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+						preDateDay := preDate.AddDate(0, -1, 0)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+						for i := 0; i <= 6; i++ {
+							if i >= 1 {
+								nextDateDay = nextDateDay.AddDate(0, 0, i)
+								nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+							}
+							if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+								break
+							} else {
+								if i >= 1 {
+									preDateDay = preDate.AddDate(0, 0, -i)
+									preDateDayStr = nextDateDay.Format(utils.FormatDate)
+								}
+								if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TczSub(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+									break
+								}
+							}
+						}
+					} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+						if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TczSub(currentItem.Value, findItem.Value)
+
+							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+							isAdd = true
+							break
+						}
+					} else {
+						nextDateDay := preDate.AddDate(0, 0, 1)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+						preDateDay := preDate.AddDate(0, 0, -1)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+						for i := 0; i < 35; i++ {
+							if i >= 1 {
+								nextDateDay = nextDateDay.AddDate(0, 0, i)
+								nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+							}
+							if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+								break
+							} else {
+								if i >= 1 {
+									preDateDay = preDate.AddDate(0, 0, -i)
+									preDateDayStr = nextDateDay.Format(utils.FormatDate)
+								}
+								if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+									timestamp := currentDate.UnixNano() / 1e6
+									timestampStr := fmt.Sprintf("%d", timestamp)
+									val := TczSub(currentItem.Value, findItem.Value)
+
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+									break
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllPredictCalculateTcz 刷新全部同差值数据
+func RefreshAllPredictCalculateTcz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateTcz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	//计算数据
+
+	//计算数据
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_info_id=? "
+	pars = append(pars, fromEdbInfo.EdbInfoId)
+
+	if startDate != "" {
+		condition += " AND data_time>=? "
+		pars = append(pars, startDate)
+	}
+	//if endDate != "" {
+	//	condition += " AND data_time<=? "
+	//	pars = append(pars, endDate)
+	//}
+
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	if err != nil {
+		return err
+	}
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+	//获取指标所有数据
+	existDataList := make([]*EdbData, 0)
+	dataTableName := GetEdbDataTableName(source)
+	sql := `SELECT * FROM %s WHERE edb_info_id=? `
+	sql = fmt.Sprintf(sql, dataTableName)
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&existDataList)
+	if err != nil {
+		return err
+	}
+	existDataMap := make(map[string]string)
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v.Value
+	}
+
+	addSql := ` INSERT INTO edb_data_predict_calculate_tcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	existAddDataMap := make(map[string]string)
+	for _, av := range dateArr {
+		currentItem := dataMap[av]
+		if currentItem != nil {
+			//当前日期
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return err
+			}
+			//上一年的日期
+			preDate := currentDate.AddDate(-1, 0, 0)
+			preDateStr := preDate.Format(utils.FormatDate)
+			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+				//dataTime, _ := time.Parse(utils.FormatDate, date)
+				timestamp := currentDate.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				val := TczSub(currentItem.Value, findItem.Value)
+
+				if existVal, ok := existDataMap[av]; !ok {
+					if _, existOk := existAddDataMap[av]; !existOk {
+						addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+						isAdd = true
+					}
+					existAddDataMap[av] = av
+				} else {
+					existValDecimal, err := decimal.NewFromString(existVal)
+					existStr := existValDecimal.String()
+					if existStr != val {
+						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+						sql = fmt.Sprintf(sql, dataTableName)
+						_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+						if err != nil {
+							return err
+						}
+					}
+				}
+				utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
+				continue
+			} else {
+				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
+					for i := 0; i <= 35; i++ {
+						nextDateDay := preDate.AddDate(0, 0, 1)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TczSub(currentItem.Value, findItem.Value)
+
+							if existVal, ok := existDataMap[av]; !ok {
+								if _, existOk := existAddDataMap[av]; !existOk {
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existAddDataMap[av] = av
+							} else {
+								existValDecimal, err := decimal.NewFromString(existVal)
+								existStr := existValDecimal.String()
+								if existStr != val {
+									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+									sql = fmt.Sprintf(sql, dataTableName)
+									_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+									if err != nil {
+										return err
+									}
+								}
+							}
+							break
+						} else {
+							preDateDay := preDate.AddDate(0, 0, -1)
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								if existVal, ok := existDataMap[av]; !ok {
+									if _, existOk := existAddDataMap[av]; !existOk {
+										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+										isAdd = true
+									}
+									existAddDataMap[av] = av
+								} else {
+									existValDecimal, err := decimal.NewFromString(existVal)
+									existStr := existValDecimal.String()
+									if existStr != val {
+										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+										sql = fmt.Sprintf(sql, dataTableName)
+										_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+										if err != nil {
+											return err
+										}
+									}
+								}
+								break
+							}
+						}
+					}
+				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
+					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+						timestamp := currentDate.UnixNano() / 1e6
+						timestampStr := fmt.Sprintf("%d", timestamp)
+						val := TczSub(currentItem.Value, findItem.Value)
+
+						if existVal, ok := existDataMap[av]; !ok {
+							if _, existOk := existAddDataMap[av]; !existOk {
+								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+								isAdd = true
+							}
+							existAddDataMap[av] = av
+						} else {
+							existValDecimal, err := decimal.NewFromString(existVal)
+							existStr := existValDecimal.String()
+							if existStr != val {
+								sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+								sql = fmt.Sprintf(sql, dataTableName)
+								_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+								if err != nil {
+									return err
+								}
+							}
+						}
+						break
+					}
+				} else {
+					for i := 0; i < 35; i++ {
+						nextDateDay := preDate.AddDate(0, 0, 1)
+						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+							timestamp := currentDate.UnixNano() / 1e6
+							timestampStr := fmt.Sprintf("%d", timestamp)
+							val := TczSub(currentItem.Value, findItem.Value)
+
+							if existVal, ok := existDataMap[av]; !ok {
+								if _, existOk := existAddDataMap[av]; !existOk {
+									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+									isAdd = true
+								}
+								existAddDataMap[av] = av
+							} else {
+								existValDecimal, err := decimal.NewFromString(existVal)
+								existStr := existValDecimal.String()
+								if existStr != val {
+									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+									sql = fmt.Sprintf(sql, dataTableName)
+									_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+									if err != nil {
+										return err
+									}
+								}
+							}
+							break
+						} else {
+							preDateDay := preDate.AddDate(0, 0, -1)
+							preDateDayStr := preDateDay.Format(utils.FormatDate)
+							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+								timestamp := currentDate.UnixNano() / 1e6
+								timestampStr := fmt.Sprintf("%d", timestamp)
+								val := TczSub(currentItem.Value, findItem.Value)
+
+								if existVal, ok := existDataMap[av]; !ok {
+									if _, existOk := existAddDataMap[av]; !existOk {
+										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
+										isAdd = true
+									}
+									existAddDataMap[av] = av
+								} else {
+									existValDecimal, err := decimal.NewFromString(existVal)
+									existStr := existValDecimal.String()
+									if existStr != val {
+										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+										sql = fmt.Sprintf(sql, dataTableName)
+										_, err = o.Raw(sql, val, edbInfoId, av).Exec()
+										if err != nil {
+											return err
+										}
+									}
+								}
+								break
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}

+ 33 - 31
utils/constants.go

@@ -28,37 +28,39 @@ const (
 
 //数据来源渠道
 const (
-	DATA_SOURCE_THS                  = iota + 1 //同花顺
-	DATA_SOURCE_WIND                            //wind
-	DATA_SOURCE_PB                              //彭博
-	DATA_SOURCE_CALCULATE                       //指标运算
-	DATA_SOURCE_CALCULATE_LJZZY                 //累计值转月
-	DATA_SOURCE_CALCULATE_TBZ                   //同比值
-	DATA_SOURCE_CALCULATE_TCZ                   //同差值
-	DATA_SOURCE_CALCULATE_NSZYDPJJS             //N数值移动平均计算
-	DATA_SOURCE_MANUAL                          //手工指标
-	DATA_SOURCE_LZ                              //隆众
-	DATA_SOURCE_YS                              //有色
-	DATA_SOURCE_CALCULATE_HBZ                   //环比值->12
-	DATA_SOURCE_CALCULATE_HCZ                   //环差值->13
-	DATA_SOURCE_CALCULATE_BP                    //变频->14
-	DATA_SOURCE_GL                              //钢联->15
-	DATA_SOURCE_ZZ                              //郑商所->16
-	DATA_SOURCE_DL                              //大商所->17
-	DATA_SOURCE_SH                              //上期所->18
-	DATA_SOURCE_CFFEX                           //中金所->19
-	DATA_SOURCE_SHFE                            //上期能源->20
-	DATA_SOURCE_GIE                             //欧洲天然气->21
-	DATA_SOURCE_CALCULATE_TIME_SHIFT            //时间移位->22
-	DATA_SOURCE_CALCULATE_ZJPJ                  //直接拼接->23
-	DATA_SOURCE_CALCULATE_LJZTBPJ               //累计值同比拼接->24
-	DATA_SOURCE_LT                              //路透->25
-	DATA_SOURCE_COAL                            //煤炭网->26
-	DATA_SOURCE_PYTHON                          //python代码->27
-	DATA_SOURCE_PB_FINANCE                      //彭博财务数据->28
-	DATA_SOURCE_GOOGLE_TRAVEL                   //谷歌出行数据->29
-	DATA_SOURCE_PREDICT                         //普通预测指标->30
-	DATA_SOURCE_PREDICT_CALCULATE               //预测指标运算->31
+	DATA_SOURCE_THS                   = iota + 1 //同花顺
+	DATA_SOURCE_WIND                             //wind
+	DATA_SOURCE_PB                               //彭博
+	DATA_SOURCE_CALCULATE                        //指标运算
+	DATA_SOURCE_CALCULATE_LJZZY                  //累计值转月
+	DATA_SOURCE_CALCULATE_TBZ                    //同比值
+	DATA_SOURCE_CALCULATE_TCZ                    //同差值
+	DATA_SOURCE_CALCULATE_NSZYDPJJS              //N数值移动平均计算
+	DATA_SOURCE_MANUAL                           //手工指标
+	DATA_SOURCE_LZ                               //隆众
+	DATA_SOURCE_YS                               //有色
+	DATA_SOURCE_CALCULATE_HBZ                    //环比值->12
+	DATA_SOURCE_CALCULATE_HCZ                    //环差值->13
+	DATA_SOURCE_CALCULATE_BP                     //变频->14
+	DATA_SOURCE_GL                               //钢联->15
+	DATA_SOURCE_ZZ                               //郑商所->16
+	DATA_SOURCE_DL                               //大商所->17
+	DATA_SOURCE_SH                               //上期所->18
+	DATA_SOURCE_CFFEX                            //中金所->19
+	DATA_SOURCE_SHFE                             //上期能源->20
+	DATA_SOURCE_GIE                              //欧洲天然气->21
+	DATA_SOURCE_CALCULATE_TIME_SHIFT             //时间移位->22
+	DATA_SOURCE_CALCULATE_ZJPJ                   //直接拼接->23
+	DATA_SOURCE_CALCULATE_LJZTBPJ                //累计值同比拼接->24
+	DATA_SOURCE_LT                               //路透->25
+	DATA_SOURCE_COAL                             //煤炭网->26
+	DATA_SOURCE_PYTHON                           //python代码->27
+	DATA_SOURCE_PB_FINANCE                       //彭博财务数据->28
+	DATA_SOURCE_GOOGLE_TRAVEL                    //谷歌出行数据->29
+	DATA_SOURCE_PREDICT                          //普通预测指标->30
+	DATA_SOURCE_PREDICT_CALCULATE                //预测指标运算->31
+	DATA_SOURCE_PREDICT_CALCULATE_TBZ            //同比值->32
+	DATA_SOURCE_PREDICT_CALCULATE_TCZ            //同差值->33
 )
 
 //基础数据初始化日期