浏览代码

fix:新增计算指标的刷新方法

Roc 3 年之前
父节点
当前提交
ba8283c1ed

+ 315 - 1
models/edb_data_calculate_bp.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -10,7 +11,7 @@ import (
 	"time"
 )
 
-//变频
+// AddCalculateBp 变频
 func AddCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
@@ -154,3 +155,316 @@ func AddCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edb
 	}
 	return
 }
+
+// EditCalculateBp 修改变频数据
+func EditCalculateBp(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("EditCalculateBp,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_bp WHERE edb_info_id = ? `
+		//_, err = o.Raw(sql, edbInfoId).Exec()
+		//if err != nil {
+		//	return
+		//}
+
+		//calculateItem := new(EdbInfoCalculateHbz)
+		//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 {
+			err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
+			return
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_calculate_bp 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_BP
+			calculateMappingItem.SourceName = "变频"
+			_, err = o.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+		fmt.Println("edbInfoIdStr:" + edbInfoIdStr)
+		//计算数据
+		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
+		}
+		addSql := ` INSERT INTO edb_data_calculate_bp(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		var isAdd bool
+		existMap := make(map[string]string)
+		dataLen := len(dataList)
+		for i := 0; i < dataLen; i++ {
+			//当期
+			currentItem := dataList[i]
+			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+			var day int
+			var preItem *EdbInfoSearchData
+			var preDate time.Time
+			if i == 0 {
+				day = int(time.Now().Sub(currentDate).Hours() / float64(24))
+				preDate = time.Now()
+			} else {
+				j := i + 1
+				if j < dataLen {
+					preItem = dataList[j]
+					preDate, _ = time.Parse(utils.FormatDate, preItem.DataTime)
+					day = int(currentDate.Sub(preDate).Hours() / float64(24))
+				}
+			}
+			for k := 0; k <= day; k++ {
+				needDay := preDate.AddDate(0, 0, -k)
+				needDayStr := needDay.Format(utils.FormatDate)
+				existKey := edbCode + needDayStr
+				if _, ok := existMap[existKey]; !ok {
+					timestamp := needDay.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					valStr := decimal.NewFromFloat(currentItem.Value).String()
+					addSql += GetAddSql(edbInfoIdStr, edbCode, needDayStr, timestampStr, valStr)
+				}
+				existMap[existKey] = needDayStr
+			}
+			existKey := edbCode + currentItem.DataTime
+			if _, ok := existMap[existKey]; !ok {
+				currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+				timestamp := currentDate.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				valStr := decimal.NewFromFloat(currentItem.Value).String()
+				addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, valStr)
+			}
+			existMap[existKey] = currentItem.DataTime
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateBp 刷新所有变频数据
+func RefreshAllCalculateBp(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("RefreshAllCalculateBp,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_calculate_bp(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+
+	existMap := make(map[string]string)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+		currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+		var day int
+		var preItem *EdbInfoSearchData
+		var preDate time.Time
+		if i == 0 {
+			day = int(time.Now().Sub(currentDate).Hours() / float64(24))
+			preDate = time.Now()
+		} else {
+			j := i + 1
+			if j < dataLen {
+				preItem = dataList[j]
+				preDate, _ = time.Parse(utils.FormatDate, preItem.DataTime)
+				day = int(currentDate.Sub(preDate).Hours() / float64(24))
+			}
+		}
+		for k := 0; k <= day; k++ {
+			needDay := preDate.AddDate(0, 0, -k)
+			needDayStr := needDay.Format(utils.FormatDate)
+			existKey := edbCode + needDayStr
+			if _, ok := existMap[existKey]; !ok {
+				timestamp := needDay.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				valStr := decimal.NewFromFloat(currentItem.Value).String()
+				if existVal, ok := existDataMap[needDayStr]; !ok {
+					addSql += GetAddSql(edbInfoIdStr, edbCode, needDayStr, timestampStr, valStr)
+				} else {
+					if existVal != valStr {
+						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+						sql = fmt.Sprintf(sql, dataTableName)
+						_, err = o.Raw(sql, valStr, edbInfoId, needDay).Exec()
+						if err != nil {
+							return err
+						}
+					}
+				}
+			}
+			existMap[existKey] = needDayStr
+		}
+		existKey := edbCode + currentItem.DataTime
+		if _, ok := existMap[existKey]; !ok {
+			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+			timestamp := currentDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+			valStr := decimal.NewFromFloat(currentItem.Value).String()
+			if existVal, ok := existDataMap[currentItem.DataTime]; !ok {
+				addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, valStr)
+			} else {
+				if existVal != valStr {
+					sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+					sql = fmt.Sprintf(sql, dataTableName)
+					_, err = o.Raw(sql, valStr, edbInfoId, currentItem.DataTime).Exec()
+					if err != nil {
+						return err
+					}
+				}
+			}
+		}
+		existMap[existKey] = currentItem.DataTime
+	}
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}

+ 245 - 4
models/edb_data_calculate_hbz.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -10,7 +11,7 @@ import (
 	"time"
 )
 
-//环比值
+// AddCalculateHbz 新增环比值指标
 func AddCalculateHbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (edbInfoId int, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
@@ -132,13 +133,253 @@ func AddCalculateHbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	return
 }
 
-//环比值,current:当期,pre:上期 公式: (当期-上期)/上期
+// EditCalculateHbz 环比值
+func EditCalculateHbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string, formulaInt int, calculateFormula 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("EditCalculateHbz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+ 			  calculate_formula=?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.Formula, 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 || strconv.Itoa(formulaInt) != calculateFormula {
+		//删除,计算指标关联的,基础指标的关联关系
+		if count <= 0 {
+			sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+			_, err = o.Raw(sql, edbInfoId).Exec()
+			if err != nil {
+				return
+			}
+			//关联关系
+			{
+				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_HBZ
+				calculateMappingItem.SourceName = "环比值"
+				_, err = o.Insert(calculateMappingItem)
+				if err != nil {
+					return
+				}
+			}
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_calculate_hbz WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+		//计算数据
+		var condition string
+		var pars []interface{}
+		condition += " AND edb_info_id=? "
+		pars = append(pars, req.FromEdbInfoId)
+		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+		if err != nil {
+			return edbInfoId, err
+		}
+		addSql := ` INSERT INTO edb_data_calculate_hbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		var isAdd bool
+		existMap := make(map[string]string)
+		dataLen := len(dataList)
+		for i := 0; i < dataLen; i++ {
+			j := i + formulaInt
+			if j < dataLen {
+				//当期
+				currentItem := dataList[i]
+				preItem := dataList[j]
+				if currentItem != nil && preItem != nil {
+					existKey := edbCode + currentItem.DataTime
+					if _, ok := existMap[existKey]; !ok {
+						currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+						timestamp := currentDate.UnixNano() / 1e6
+						timestampStr := fmt.Sprintf("%d", timestamp)
+						val := HbzDiv(currentItem.Value, preItem.Value)
+						if val != "" {
+							addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
+							isAdd = true
+						}
+					}
+					existMap[existKey] = currentItem.DataTime
+				}
+			}
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateHbz 刷新所有环比值数据
+func RefreshAllCalculateHbz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string, formulaInt int) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EditCalculateHbz,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
+	}
+	addSql := ` INSERT INTO edb_data_calculate_hbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+	existMap := make(map[string]string)
+	dataLen := len(dataList)
+	fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+			if currentItem != nil && preItem != nil {
+				existKey := edbCode + currentItem.DataTime
+
+				if _, ok := existMap[existKey]; !ok {
+					currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					val := HbzDiv(currentItem.Value, preItem.Value)
+					if val != "" {
+						if existVal, findOk := existDataMap[currentItem.DataTime]; !findOk {
+							addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
+							isAdd = true
+						} else {
+							if existVal != 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, currentItem.DataTime).Exec()
+								if err != nil {
+									return err
+								}
+							}
+						}
+					}
+				}
+				existMap[existKey] = currentItem.DataTime
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
+// HbzDiv 环比值计算,current:当期,pre:上期 公式: (当期-上期)/上期
 func HbzDiv(current, pre float64) string {
 	if pre == 0 {
 		return ""
 	}
-	currentVal := decimal.NewFromFloat(float64(current))
-	preVal := decimal.NewFromFloat(float64(pre))
+	currentVal := decimal.NewFromFloat(current)
+	preVal := decimal.NewFromFloat(pre)
 	val, _ := currentVal.Sub(preVal).Div(preVal).Float64()
 	valStr := utils.SubFloatToString(val, 4)
 	return valStr

+ 252 - 1
models/edb_data_calculate_hcz.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -10,7 +11,7 @@ import (
 	"time"
 )
 
-//环差值
+// AddCalculateHcz 新增环差值指标
 func AddCalculateHcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (edbInfoId int, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
@@ -138,6 +139,256 @@ func AddCalculateHcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	return
 }
 
+// EditCalculateHcz 修改环差值指标
+func EditCalculateHcz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string, formulaInt int, calculateFormula 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("EditCalculateHcz,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+ 			  calculate_formula=?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.Formula, 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 || strconv.Itoa(formulaInt) != calculateFormula {
+		//删除,计算指标关联的,基础指标的关联关系
+		if count <= 0 {
+			sql = ` DELETE FROM edb_info_calculate_mapping 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_HCZ
+				calculateMappingItem.SourceName = "环差值"
+				_, err = o.Insert(calculateMappingItem)
+				if err != nil {
+					return
+				}
+			}
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_calculate_hcz WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+		fmt.Println("edbInfoIdStr:" + edbInfoIdStr)
+		//计算数据
+		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_calculate_hcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		var isAdd bool
+		existMap := make(map[string]string)
+		dataLen := len(dataList)
+		fmt.Println("dataLen:", dataLen)
+		for i := 0; i < dataLen; i++ {
+			j := i + formulaInt
+			if j < dataLen {
+				//当期
+				currentItem := dataList[i]
+				preItem := dataList[j]
+				if currentItem != nil && preItem != nil {
+					existKey := edbCode + currentItem.DataTime
+					if _, ok := existMap[existKey]; !ok {
+						currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+						timestamp := currentDate.UnixNano() / 1e6
+						timestampStr := fmt.Sprintf("%d", timestamp)
+						val := HczDiv(currentItem.Value, preItem.Value)
+						if val != "" {
+							addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
+							isAdd = true
+						}
+					}
+					existMap[existKey] = currentItem.DataTime
+				}
+			}
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateHcz 刷新所有环差值数据
+func RefreshAllCalculateHcz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string, formulaInt int) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateHcz,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_calculate_hcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+	existMap := make(map[string]string)
+	dataLen := len(dataList)
+	fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+			if currentItem != nil && preItem != nil {
+				existKey := edbCode + currentItem.DataTime
+				if _, ok := existMap[existKey]; !ok {
+					currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+					timestamp := currentDate.UnixNano() / 1e6
+					timestampStr := fmt.Sprintf("%d", timestamp)
+					val := HczDiv(currentItem.Value, preItem.Value)
+					if val != "" {
+						if existVal, findOk := existDataMap[currentItem.DataTime]; !findOk {
+							addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
+							isAdd = true
+						} else {
+							if existVal != 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, currentItem.DataTime).Exec()
+								if err != nil {
+									return err
+								}
+							}
+						}
+					}
+				}
+				existMap[existKey] = currentItem.DataTime
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
 // HczDiv 环差值计算,current:当期,pre:上期 公式:当期-上期
 func HczDiv(current, pre float64) string {
 	if pre == 0 {

+ 380 - 1
models/edb_data_calculate_ljzzy.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -17,9 +18,9 @@ func AddCalculateLjzzy(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo,
 	if err != nil {
 		return
 	}
-
 	defer func() {
 		if err != nil {
+			fmt.Println("AddCalculateLjzzy,Err:" + err.Error())
 			_ = to.Rollback()
 		} else {
 			_ = to.Commit()
@@ -197,3 +198,381 @@ func AddCalculateLjzzy(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo,
 	}
 	return
 }
+
+// EditCalculateLjzzy 编辑累计值转月数据
+func EditCalculateLjzzy(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("EditCalculateLjzzy,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_ljzzy WHERE edb_info_id = ? `
+		//_, err = o.Raw(sql, edbInfoId).Exec()
+		//if err != nil {
+		//	return
+		//}
+
+		//calculateItem := new(EdbInfoCalculateLjzzy)
+		//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_calculate_ljzzy 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_LJZZY
+			calculateMappingItem.SourceName = "累计值转月"
+			_, err = o.Insert(calculateMappingItem)
+			if err != nil {
+				return
+			}
+		}
+
+		//计算数据
+		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, 1)
+		if err != nil {
+			return edbInfoId, err
+		}
+
+		yearMap := make(map[int]map[int]*EdbInfoSearchData)
+		dataLen := len(dataList)
+		for i := 0; i < dataLen; i++ {
+			item := dataList[i]
+			//日其中获取年
+			itemDate, err := time.Parse(utils.FormatDate, item.DataTime)
+			if err != nil {
+				return edbInfoId, err
+			}
+			year := itemDate.Year()
+			month := int(itemDate.Month())
+			if monthMap, yok := yearMap[year]; yok {
+				monthMap[month] = item
+				yearMap[year] = monthMap
+			} else {
+				monthMap = make(map[int]*EdbInfoSearchData)
+				monthMap[month] = item
+				yearMap[year] = monthMap
+			}
+		}
+
+		addSql := ` INSERT INTO edb_data_calculate_ljzzy(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		nowStr := time.Now().Format(utils.FormatDateTime)
+		var isAdd bool
+
+		for yk, yv := range yearMap {
+			_, oneMonthOk := yv[1]
+			_, twoMonthOk := yv[2]
+			if !oneMonthOk && !twoMonthOk {
+				continue
+			}
+			for i := 1; i <= 12; i++ {
+				fmt.Println(yk, i, yv[i])
+				dataCurrentItem := yv[i]
+				var date string
+				var val float64
+				if i == 1 || i == 2 {
+					if _, mok := yv[1]; mok { //1月有值
+						if i == 1 {
+							date = dataCurrentItem.DataTime
+							val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+						}
+						if i == 2 {
+							dataOneItem := yv[1]
+							date = dataCurrentItem.DataTime
+							twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
+							oneMonth := decimal.NewFromFloat(dataOneItem.Value)
+							val, _ = twoMonth.Sub(oneMonth).Float64()
+						}
+					} else { //1月无值
+						dataTwoItem := yv[2]
+						if i == 1 {
+							date = strconv.Itoa(yk) + "-01-31"
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+						}
+						if i == 2 {
+							date = dataCurrentItem.DataTime
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+						}
+					}
+				} else {
+					dataPreItem := yv[i-1]
+					if dataCurrentItem != nil && dataPreItem != nil {
+						date = dataCurrentItem.DataTime
+						//val = dataCurrentItem.Value - dataPreItem.Value
+						a := decimal.NewFromFloat(dataCurrentItem.Value)
+						b := decimal.NewFromFloat(dataPreItem.Value)
+						val, _ = a.Sub(b).Float64()
+					}
+				}
+				if date != "" {
+					dataTime, _ := time.Parse(utils.FormatDate, date)
+					timestamp := dataTime.UnixNano() / 1e6
+					timeStr := fmt.Sprintf("%d", timestamp)
+
+					addSql += "("
+					addSql += strconv.Itoa(edbInfoId) + "," + "'" + edbCode + "'" + "," + "'" + date + "'" + "," + utils.SubFloatToString(val, 4) + "," + "'" + nowStr + "'" +
+						"," + "'" + nowStr + "'" + "," + "1"
+					addSql += "," + "'" + timeStr + "'"
+					addSql += "),"
+					isAdd = true
+				}
+			}
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateLjzzy 刷新全部累计值转月数据
+func RefreshAllCalculateLjzzy(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("RefreshAllCalculateLjzzy,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, 1)
+	if err != nil {
+		return err
+	}
+
+	yearMap := make(map[int]map[int]*EdbInfoSearchData)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		item := dataList[i]
+		//日其中获取年
+		itemDate, err := time.Parse(utils.FormatDate, item.DataTime)
+		if err != nil {
+			return err
+		}
+		year := itemDate.Year()
+		month := int(itemDate.Month())
+		if monthMap, yok := yearMap[year]; yok {
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		} else {
+			monthMap = make(map[int]*EdbInfoSearchData)
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		}
+	}
+
+	addSql := ` INSERT INTO edb_data_calculate_ljzzy(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+	//获取指标所有数据
+	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
+	}
+	dataMap := make(map[string]string)
+	for _, v := range existDataList {
+		dataMap[v.DataTime] = v.Value
+	}
+	existDataMap := make(map[string]string)
+	for yk, yv := range yearMap {
+		_, oneMonthOk := yv[1]
+		_, twoMonthOk := yv[2]
+		if !oneMonthOk && !twoMonthOk {
+			continue
+		}
+		for i := 1; i <= 12; i++ {
+			fmt.Println(yk, i, yv[i])
+			dataCurrentItem := yv[i]
+			var date string
+			var val float64
+			if i == 1 || i == 2 {
+				if _, mok := yv[1]; mok { //1月有值
+					if i == 1 {
+						date = dataCurrentItem.DataTime
+						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+					}
+					if i == 2 {
+						dataOneItem := yv[1]
+						date = dataCurrentItem.DataTime
+						twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
+						oneMonth := decimal.NewFromFloat(dataOneItem.Value)
+						val, _ = twoMonth.Sub(oneMonth).Float64()
+					}
+				} else { //1月无值
+					dataTwoItem := yv[2]
+					if i == 1 {
+						date = strconv.Itoa(yk) + "-01-31"
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+					if i == 2 {
+						date = dataCurrentItem.DataTime
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+				}
+			} else {
+				dataPreItem := yv[i-1]
+				if dataCurrentItem != nil && dataPreItem != nil {
+					date = dataCurrentItem.DataTime
+					//val =  dataCurrentItem.Value - dataPreItem.Value
+					a := decimal.NewFromFloat(dataCurrentItem.Value)
+					b := decimal.NewFromFloat(dataPreItem.Value)
+					val, _ = a.Sub(b).Float64()
+				}
+			}
+			if date != "" {
+				saveValue := utils.SubFloatToString(val, 4)
+				//判断数据是否存在
+				if existVal, ok := dataMap[date]; !ok {
+					dataTime, _ := time.Parse(utils.FormatDate, date)
+					timestamp := dataTime.UnixNano() / 1e6
+					timeStr := fmt.Sprintf("%d", timestamp)
+					if _, existOk := existDataMap[date]; !existOk {
+						addSql += GetAddSql(edbInfoIdStr, edbCode, date, timeStr, saveValue)
+						isAdd = true
+					}
+					existDataMap[date] = date
+				} else {
+					if existVal != saveValue {
+						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+						sql = fmt.Sprintf(sql, dataTableName)
+						_, err = o.Raw(sql, saveValue, edbInfoId, date).Exec()
+						if err != nil {
+							return err
+						}
+					}
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			fmt.Println("RefreshAllCalculateLjzzy add Err", err.Error())
+			return
+		}
+	}
+	return
+}

+ 292 - 1
models/edb_data_calculate_nszydbpjjs.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -10,12 +11,13 @@ import (
 	"time"
 )
 
-//N数值移动平均计算
+// AddCalculateNszydpjjs N数值移动平均计算
 func AddCalculateNszydpjjs(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (edbInfoId int, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	defer func() {
 		if err != nil {
+			fmt.Println("AddCalculateNszydpjjs,Err:" + err.Error())
 			_ = to.Rollback()
 		} else {
 			_ = to.Commit()
@@ -154,3 +156,292 @@ func AddCalculateNszydpjjs(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbIn
 	}
 	return
 }
+
+// EditCalculateNszydpjjs 修改N数值移动平均计算
+func EditCalculateNszydpjjs(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string, formulaInt int, oldCalculateFormula string) (edbInfoId int, err error) {
+	edbInfoId = req.EdbInfoId
+
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateNszydpjjs,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+              edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+			  calculate_formula=?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.Formula, 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.Error() != utils.ErrNoRow() {
+		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
+		return
+	}
+	if count <= 0 || oldCalculateFormula != req.Formula {
+		//删除,计算指标关联的,基础指标的关联关系
+		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_calculate_nszydpjjs 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_NSZYDPJJS
+			calculateMappingItem.SourceName = "N数值移动平均计算"
+			_, 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)
+		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_calculate_nszydpjjs(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		var isAdd bool
+
+		arrLen := len(dateArr)
+		for ak, av := range dateArr {
+			//处理第一个值
+			var valArr []float64
+			if findItem, ok := dataMap[av]; ok {
+				valArr = append(valArr, findItem.Value)
+			} else {
+				continue
+			}
+			if ak+1 != arrLen {
+				//处理除第一个值之外的N-1个值
+				for i := 1; i < formulaInt; i++ {
+					arrIndex := ak + i
+					if arrIndex >= arrLen {
+						break
+					}
+					arrVal := dateArr[arrIndex]
+					if findItem, ok := dataMap[arrVal]; ok {
+						valArr = append(valArr, findItem.Value)
+					} else {
+						continue
+					}
+				}
+			}
+			valArrLen := len(valArr)
+			totalVal := decimal.NewFromFloat(0.00)
+			for _, v := range valArr {
+				newDecimal := decimal.NewFromFloat(v)
+				totalVal = totalVal.Add(newDecimal)
+			}
+			af := totalVal
+			bf := decimal.NewFromFloat(float64(valArrLen))
+			val, _ := af.Div(bf).Float64()
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return edbInfoId, err
+			}
+
+			timestamp := currentDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+
+			valStr := utils.SubFloatToString(val, 4)
+			addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, valStr)
+			isAdd = true
+		}
+
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateNszydpjjs 刷新全部N数值移动平均计算
+func RefreshAllCalculateNszydpjjs(edbInfoId, source, formulaInt int, fromEdbInfo *EdbInfo, edbCode, startDate string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshCalculateNszydpjjs Err:" + err.Error())
+			utils.FileLog.Info("RefreshCalculateNszydpjjs Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	fmt.Println(edbInfoIdStr)
+	//计算数据
+	var condition string
+	var pars []interface{}
+	condition += " AND edb_info_id=? "
+	pars = append(pars, edbInfoId)
+
+	existDataList, err := GetEdbDataListAll(condition, pars, source, 0)
+	if err != nil {
+		fmt.Println("existDataList GetEdbDataListAll Err:" + err.Error())
+		return err
+	}
+
+	existDataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v
+	}
+
+	//计算来源数据
+	var fromCondition string
+	var fromPars []interface{}
+	fromCondition += " AND edb_info_id=? "
+	fromPars = append(fromPars, fromEdbInfo.EdbInfoId)
+	fromCondition += " AND data_time>=? "
+	fromPars = append(fromPars, startDate)
+
+	fmt.Println("fromPars:", fromPars)
+	fromDataList, err := GetEdbDataListAll(fromCondition, fromPars, fromEdbInfo.Source, 0)
+	if err != nil {
+		fmt.Println("from GetEdbDataListAll Err:" + err.Error())
+		return err
+	}
+
+	var fromDateArr []string
+	fromDataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range fromDataList {
+		fromDateArr = append(fromDateArr, v.DataTime)
+		fromDataMap[v.DataTime] = v
+	}
+
+	addSql := ` INSERT INTO edb_data_calculate_nszydpjjs(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+	dataTableName := GetEdbDataTableName(source)
+	arrLen := len(fromDateArr)
+	existAddDataMap := make(map[string]string)
+	for ak, av := range fromDateArr {
+		//处理第一个值
+		var valArr []float64
+		if findItem, ok := fromDataMap[av]; ok {
+			valArr = append(valArr, findItem.Value)
+		} else {
+			continue
+		}
+		if ak+1 != arrLen {
+			//处理除第一个值之外的N-1个值
+			for i := 1; i < formulaInt; i++ {
+				arrIndex := ak + i
+				if arrIndex >= arrLen {
+					break
+				}
+				arrVal := fromDateArr[arrIndex]
+				if findItem, ok := fromDataMap[arrVal]; ok {
+					valArr = append(valArr, findItem.Value)
+				} else {
+					continue
+				}
+			}
+		}
+		valArrLen := len(valArr)
+		//var totalVal float64
+		totalVal := decimal.NewFromFloat(0.00)
+		for _, v := range valArr {
+			newDecimal := decimal.NewFromFloat(v)
+			totalVal = totalVal.Add(newDecimal)
+		}
+		af := totalVal //decimal.NewFromFloat(totalVal)
+		bf := decimal.NewFromFloat(float64(valArrLen))
+		val, _ := af.Div(bf).Float64()
+		valStr := utils.SubFloatToString(val, 4)
+
+		if existVal, existOk := existDataMap[av]; !existOk {
+			currentDate, err := time.Parse(utils.FormatDate, av)
+			if err != nil {
+				return err
+			}
+			timestamp := currentDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+			if _, existOk := existAddDataMap[av]; !existOk {
+				addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, valStr)
+				isAdd = true
+			}
+			existAddDataMap[av] = av
+		} else {
+			saveValue := utils.SubFloatToString(existVal.Value, 30)
+			if saveValue != valStr {
+				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
+				}
+			}
+		}
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		utils.FileLog.Info("addSql:" + addSql)
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}

+ 504 - 3
models/edb_data_calculate_tbz.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -12,7 +13,6 @@ import (
 
 // AddCalculateTbz 同比值
 func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
-	fmt.Println("AddCalculateTbz")
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	if err != nil {
@@ -20,6 +20,7 @@ func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	}
 	defer func() {
 		if err != nil {
+			fmt.Println("AddCalculateTbz,Err:" + err.Error())
 			_ = to.Rollback()
 		} else {
 			_ = to.Commit()
@@ -225,11 +226,511 @@ func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	return
 }
 
+// EditCalculateTbz 同比值
+func EditCalculateTbz(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_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_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,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
+}
+
+// RefreshAllCalculateTbz 刷新所有同比值数据
+func RefreshAllCalculateTbz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		fmt.Println("RefreshAllCalculateTbz,Err:" + err.Error())
+		if err != nil {
+			_ = 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_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,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 {
+					if existVal != 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 {
+								if existVal != 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 {
+									if existVal != 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 {
+							if existVal != 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 {
+								if existVal != 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 {
+									if existVal != 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
+}
+
 func TbzDiv(a, b float64) string {
 	var valStr string
 	if b != 0 {
-		af := decimal.NewFromFloat(float64(a))
-		bf := decimal.NewFromFloat(float64(b))
+		af := decimal.NewFromFloat(a)
+		bf := decimal.NewFromFloat(b)
 		val, _ := af.Div(bf).Float64()
 		val = val - 1
 		valStr = utils.SubFloatToString(val, 4)

+ 496 - 0
models/edb_data_calculate_tcz.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -19,6 +20,7 @@ func AddCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	}
 	defer func() {
 		if err != nil {
+			fmt.Println("AddCalculateTcz,Err:" + err.Error())
 			_ = to.Rollback()
 		} else {
 			_ = to.Commit()
@@ -228,6 +230,500 @@ func AddCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	return
 }
 
+// EditCalculateTcz 同差值
+func EditCalculateTcz(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_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_calculate_tcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,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
+}
+
+// RefreshAllCalculateTcz 刷新全部同差值数据
+func RefreshAllCalculateTcz(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_calculate_tcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,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 {
+					if existVal != 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 {
+								if existVal != 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 {
+									if existVal != 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 {
+							if existVal != 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 {
+								if existVal != 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 {
+									if existVal != 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
+}
+
 // TczSub 计算同差值
 func TczSub(a, b float64) string {
 	af := decimal.NewFromFloat(a)

+ 279 - 1
models/edb_data_calculate_time_shift.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
@@ -10,7 +11,7 @@ import (
 	"time"
 )
 
-//时间移位
+// AddCalculateTimeShift 时间移位
 func AddCalculateTimeShift(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
@@ -147,3 +148,280 @@ func AddCalculateTimeShift(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbIn
 	}
 	return
 }
+
+// EditCalculateTimeShift 修改时间移位
+func EditCalculateTimeShift(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string, oldEdbInfo *EdbInfo) (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("EditCalculateTimeShift,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source=?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+			  move_type=?,
+			  move_frequency=?,
+			  calculate_formula=?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+	_, err = o.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.MoveType, req.MoveFrequency, req.Formula, 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 || req.MoveType != oldEdbInfo.MoveType || req.MoveFrequency != oldEdbInfo.MoveFrequency || req.Formula != oldEdbInfo.CalculateFormula {
+		if count <= 0 {
+			//删除,计算指标关联的,基础指标的关联关系
+			sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+			_, err = o.Raw(sql, edbInfoId).Exec()
+			if err != nil {
+				err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
+				return
+			}
+			//关联关系
+			{
+				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_TIME_SHIFT
+				calculateMappingItem.SourceName = "时间移位"
+				_, err = o.Insert(calculateMappingItem)
+				if err != nil {
+					return
+				}
+			}
+		}
+		//清空原有数据
+		sql = ` DELETE FROM edb_data_calculate_time_shift WHERE edb_info_id = ? `
+		_, err = o.Raw(sql, edbInfoId).Exec()
+		if err != nil {
+			return edbInfoId, err
+		}
+
+		edbInfoIdStr := strconv.Itoa(edbInfoId)
+
+		var shiftDay int
+		formulaInt, _ := strconv.Atoi(req.Formula)
+		switch req.MoveFrequency {
+		case "天":
+			shiftDay = formulaInt
+		case "周":
+			shiftDay = formulaInt * 7
+		case "月":
+			shiftDay = formulaInt * 30
+		case "季":
+			shiftDay = formulaInt * 90
+		case "年":
+			shiftDay = formulaInt * 365
+		default:
+			shiftDay = formulaInt
+		}
+
+		//计算数据
+		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
+		}
+		addSql := ` INSERT INTO edb_data_calculate_time_shift(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+		var isAdd bool
+		existMap := make(map[string]string)
+		dataLen := len(dataList)
+		if req.MoveType == 2 {
+			shiftDay = -shiftDay
+		}
+		for i := 0; i < dataLen; i++ {
+			//当期
+			currentItem := dataList[i]
+			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+			newDate := currentDate.AddDate(0, 0, shiftDay)
+			existKey := edbCode + newDate.Format(utils.FormatDate)
+			if _, ok := existMap[existKey]; !ok {
+				timestamp := newDate.UnixNano() / 1e6
+				timestampStr := fmt.Sprintf("%d", timestamp)
+				valStr := decimal.NewFromFloat(currentItem.Value).String()
+				addSql += GetAddSql(edbInfoIdStr, edbCode, newDate.Format(utils.FormatDate), timestampStr, valStr)
+				isAdd = true
+			}
+			existMap[existKey] = currentItem.DataTime
+		}
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = o.Raw(addSql).Exec()
+			if err != nil {
+				return edbInfoId, err
+			}
+		}
+	}
+	return
+}
+
+// RefreshAllCalculateTimeShift 刷新所有时间移位数据
+func RefreshAllCalculateTimeShift(edbInfoId, source, formulaInt, moveType int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate, moveFrequency string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateTimeShift,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)
+	}
+
+	var shiftDay int
+	switch moveFrequency {
+	case "天":
+		shiftDay = formulaInt
+	case "周":
+		shiftDay = formulaInt * 7
+	case "月":
+		shiftDay = formulaInt * 30
+	case "季":
+		shiftDay = formulaInt * 90
+	case "年":
+		shiftDay = formulaInt * 365
+	default:
+		shiftDay = formulaInt
+	}
+
+	if moveType == 2 {
+		shiftDay = -shiftDay
+	}
+
+	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_calculate_time_shift(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
+	var isAdd bool
+
+	existMap := make(map[string]string)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+		existKey := edbCode + currentItem.DataTime
+		if _, ok := existMap[existKey]; !ok {
+			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
+			newDate := currentDate.AddDate(0, 0, shiftDay)
+
+			timestamp := newDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+			valStr := decimal.NewFromFloat(currentItem.Value).String()
+			if existVal, ok := existDataMap[newDate.Format(utils.FormatDate)]; !ok {
+				isAdd = true
+				addSql += GetAddSql(edbInfoIdStr, edbCode, newDate.Format(utils.FormatDate), timestampStr, valStr)
+			} else {
+				if existVal != valStr {
+					sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+					sql = fmt.Sprintf(sql, dataTableName)
+					_, err = o.Raw(sql, valStr, edbInfoId, newDate.Format(utils.FormatDate)).Exec()
+					if err != nil {
+						return err
+					}
+				}
+			}
+		}
+		existMap[existKey] = currentItem.DataTime
+	}
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			return err
+		}
+	}
+	return
+}

+ 14 - 2
models/edb_info.go

@@ -86,8 +86,8 @@ func GetEdbInfoById(edbInfoId int) (item *EdbInfo, err error) {
 
 // EdbInfoSearchData
 type EdbInfoSearchData struct {
-	EdbDataId int    `description:"数据ID"`
-	DataTime  string `description:"数据日期"`
+	EdbDataId int     `description:"数据ID"`
+	DataTime  string  `description:"数据日期"`
 	Value     float64 `description:"数据"`
 }
 
@@ -195,3 +195,15 @@ func GetEdbInfoCalculateListByCondition(condition string, pars []interface{}) (i
 	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
+
+// GetEdbInfoCalculateCountByCondition 获取关联指标数量
+func GetEdbInfoCalculateCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+
+	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_mapping WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}