Prechádzať zdrojové kódy

Merge branch 'chart/12.1' into debug

# Conflicts:
#	models/base_from_calculate.go
Roc 2 rokov pred
rodič
commit
ece5f71398

+ 1 - 1
controllers/base_from_calculate.go

@@ -1409,7 +1409,7 @@ func (this *CalculateController) Refresh() {
 		}
 		formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
 		startDate = `` //只要填写日期,就会出现问题,还是把日期给去掉吧
-		err = models.RefreshAllCalculateCjjx(edbInfoId, edbInfo.Source, fromEdbInfo, calculateCjjx.EdbCode, startDate, "", formulaInt)
+		err = models.RefreshAllCalculateCjjx(edbInfoId, edbInfo.Source, fromEdbInfo, calculateCjjx.EdbCode, startDate, "", edbInfo.Calendar, formulaInt)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			errMsg = "RefreshAllCalculateCjjx Err:" + err.Error()
 			break

+ 1 - 0
go.mod

@@ -8,6 +8,7 @@ require (
 	github.com/beego/beego/v2 v2.0.2
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-sql-driver/mysql v1.6.0
+	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
 	github.com/olivere/elastic/v7 v7.0.32
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/shopspring/decimal v1.3.1

+ 2 - 0
go.sum

@@ -330,6 +330,8 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19 h1:LhWT2dBuNkYexwRSsPpYh67e0ikmH1ebBDaVkGHoMts=
+github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19/go.mod h1:LjhyrWzOLJ9l1azMoNr9iCvfNrHEREqvJHzSLQcD0/o=
 github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=

+ 2 - 0
models/base_from_calculate.go

@@ -595,6 +595,7 @@ type EdbInfoCalculateBatchSaveReq struct {
 	}
 	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
 	MoveFrequency string `description:"移动频度:天/周/月/季/年"`
+	Calendar      string `description:"公历/农历"`
 }
 
 // EdbInfoCalculateBatchEditReq 编辑计算指标的请求参数
@@ -617,6 +618,7 @@ type EdbInfoCalculateBatchEditReq struct {
 	}
 	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
 	MoveFrequency string `description:"移动频度:天/周/月/季/年"`
+	Calendar string `description:"公历/农历" orm:"default(公历)"`
 }
 
 // DeleteCalculateData 删除计算数据

+ 1 - 1
models/base_predict_from_calculate.go

@@ -347,7 +347,7 @@ func refreshAllPredictCalculate(to orm.TxOrmer, edbInfoIdList []*EdbInfo, edbInf
 		formulaStr = strings.ToUpper(formulaStr)
 		formulaFormStr := ReplaceFormula(edbInfoIdList, sv, formulaMap, formulaStr, edbInfoIdBytes)
 		if formulaFormStr != "" {
-			utils.FileLog.Info(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
+			//utils.FileLog.Info(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
 			expression := formula.NewExpression(formulaFormStr)
 			calResult, tmpErr := expression.Evaluate()
 			if tmpErr != nil {

+ 101 - 13
models/edb_data_calculate_cjjx.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"github.com/nosixtools/solarlunar"
 	"github.com/shopspring/decimal"
 	"hongze/hongze_edb_lib/utils"
 	"strconv"
@@ -43,6 +44,7 @@ func AddCalculateCjjx(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, e
 		edbInfo.ModifyTime = time.Now()
 		edbInfo.UniqueCode = uniqueCode
 		edbInfo.CalculateFormula = req.Formula
+		edbInfo.Calendar = req.Calendar
 		edbInfo.EdbType = 2
 		newEdbInfoId, tmpErr := to.Insert(edbInfo)
 		if tmpErr != nil {
@@ -88,7 +90,7 @@ func AddCalculateCjjx(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, e
 	}
 
 	//计算数据
-	err = refreshAllCalculateCjjx(to, edbInfo.EdbInfoId, edbInfo.Source, fromEdbInfo, edbInfo.EdbCode, "", "", formulaInt)
+	err = refreshAllCalculateCjjx(to, edbInfo.EdbInfoId, edbInfo.Source, fromEdbInfo, edbInfo.EdbCode, "", "", edbInfo.Calendar, formulaInt)
 
 	return
 }
@@ -122,8 +124,9 @@ func EditCalculateCjjx(req *EdbInfoCalculateBatchEditReq, edbInfo, fromEdbInfo *
 	edbInfo.Unit = req.Unit
 	edbInfo.ClassifyId = req.ClassifyId
 	edbInfo.CalculateFormula = req.Formula
+	edbInfo.Calendar = req.Calendar
 	edbInfo.ModifyTime = time.Now()
-	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime")
+	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "Calendar", "ModifyTime")
 	if err != nil {
 		return
 	}
@@ -187,13 +190,13 @@ func EditCalculateCjjx(req *EdbInfoCalculateBatchEditReq, edbInfo, fromEdbInfo *
 	}
 
 	//计算数据
-	err = refreshAllCalculateCjjx(to, edbInfo.EdbInfoId, edbInfo.Source, fromEdbInfo, edbInfo.EdbCode, "", "", formulaInt)
+	err = refreshAllCalculateCjjx(to, edbInfo.EdbInfoId, edbInfo.Source, fromEdbInfo, edbInfo.EdbCode, "", "", edbInfo.Calendar, formulaInt)
 
 	return
 }
 
 // RefreshAllCalculateCjjx 刷新全部超季节性数据
-func RefreshAllCalculateCjjx(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string, formulaInt int) (err error) {
+func RefreshAllCalculateCjjx(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate, calendar string, formulaInt int) (err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	if err != nil {
@@ -209,13 +212,13 @@ func RefreshAllCalculateCjjx(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCod
 	}()
 
 	// 重新计算
-	err = refreshAllCalculateCjjx(to, edbInfoId, source, fromEdbInfo, edbCode, startDate, endDate, formulaInt)
+	err = refreshAllCalculateCjjx(to, edbInfoId, source, fromEdbInfo, edbCode, startDate, endDate, calendar, formulaInt)
 
 	return
 }
 
 // refreshAllCalculateCjjx 刷新全部超季节性数据
-func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string, formulaInt int) (err error) {
+func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate, calendar string, formulaInt int) (err error) {
 	if err != nil {
 		return
 	}
@@ -257,8 +260,10 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 		return err
 	}
 	existDataMap := make(map[string]string)
+	removeDataTimeMap := make(map[string]int) //需要移除的日期数据
 	for _, v := range existDataList {
 		existDataMap[edbCode+v.DataTime] = v.Value
+		removeDataTimeMap[v.DataTime] = 1
 	}
 
 	addSql := ` INSERT INTO edb_data_calculate_cjjx(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
@@ -269,6 +274,12 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 		isCompatibility = true
 	}
 
+	// 每个年份的日期数据需要平移的天数
+	moveDayMap := make(map[int]int, 0) // 每个年份的春节公历
+	var lastDataDay time.Time
+	if len(dataList) > 0 {
+		lastDataDay, _ = time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+	}
 	for _, av := range dateArr {
 		currentItem := dataMap[av]
 		if currentItem != nil {
@@ -280,15 +291,31 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 				return
 			}
 			pastValueList = append(pastValueList, currentItem.Value)
+
 			for i := 1; i < formulaInt; i++ {
-				//前几年的日期
-				preDate := currentDate.AddDate(-i, 0, 0)
-				preDateStr := preDate.Format(utils.FormatDate)
-				if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+				//前几年当天公历的日期
+				hisoryPreDate := currentDate.AddDate(-i, 0, 0)
+				moveDay := 0
+				if calendar == "农历" {
+					if tmpMoveDay, ok := moveDayMap[hisoryPreDate.Year()]; !ok {
+						moveDay, err = getMoveDay(lastDataDay, hisoryPreDate)
+						if err != nil {
+							return
+						}
+					} else {
+						moveDay = tmpMoveDay
+					}
+
+					// 移动天数到对应农历 的 公历 日期
+					hisoryPreDate = hisoryPreDate.AddDate(0, 0, moveDay)
+				}
+
+				hisoryPreDateStr := hisoryPreDate.Format(utils.FormatDate)
+				if findItem, ok := dataMap[hisoryPreDateStr]; ok { //上一年同期找到
 					pastValueList = append(pastValueList, findItem.Value)
 				} else if isCompatibility { // 如果需要兼容上下35天
-					nextDateDay := preDate
-					preDateDay := preDate
+					nextDateDay := hisoryPreDate
+					preDateDay := hisoryPreDate
 					for i := 0; i < 35; i++ {
 						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
 						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
@@ -305,9 +332,17 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 						preDateDay = preDateDay.AddDate(0, 0, -1)
 					}
 				}
+				if av == "2022-11-28" {
+					fmt.Println(moveDay)
+				}
+			}
+			if av == "2022-11-28" {
+				fmt.Println(pastValueList)
 			}
 
 			if len(pastValueList) == formulaInt {
+				delete(removeDataTimeMap, av) //将待删除的日期给移除
+
 				val := CjjxSub(currentItem.Value, pastValueList)
 
 				if existVal, ok := existDataMap[edbCode+av]; !ok {
@@ -331,6 +366,26 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 			existDataMap[edbCode+av] = av
 		}
 	}
+
+	//删除已经不存在的超季节性指标数据(由于该指标当日的数据删除了)
+	{
+		removeDateList := make([]string, 0)
+		for dateTime := range removeDataTimeMap {
+			removeDateList = append(removeDateList, dateTime)
+		}
+		removeNum := len(removeDateList)
+		if removeNum > 0 {
+			//如果拼接指标变更了,那么需要删除所有的指标数据
+			tableName := GetEdbDataTableName(source)
+			sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (`+utils.GetOrmInReplace(removeNum)+`) `, tableName)
+			_, err = to.Raw(sql, edbInfoId, removeDateList).Exec()
+			if err != nil {
+				err = fmt.Errorf("删除不存在的超季节性指标数据失败,Err:" + err.Error())
+				return
+			}
+		}
+	}
+
 	if isAdd {
 		addSql = strings.TrimRight(addSql, ",")
 		_, err = to.Raw(addSql).Exec()
@@ -341,6 +396,39 @@ func refreshAllCalculateCjjx(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo
 	return
 }
 
+// getMoveDay 获取两个日期的平移天数
+func getMoveDay(lastDataDay, currentDataDay time.Time) (moveDay int, err error) {
+	if lastDataDay.Month() >= 11 { //最新数据的日期如果大于等于11月份,那么用的是下一年的春节
+		lastDataDay = lastDataDay.AddDate(1, 0, 0)
+	}
+
+	currentYear := lastDataDay.Year()
+	currentYearCjnl := fmt.Sprintf("%d-01-01", currentYear)            //当年的春节农历
+	currentYearCjgl := solarlunar.LunarToSolar(currentYearCjnl, false) //当年的春节公历
+	currentYearCjglTime, tmpErr := time.ParseInLocation(utils.FormatDate, currentYearCjgl, time.Local)
+	if tmpErr != nil {
+		err = errors.New("当前春节公历日期转换失败:" + tmpErr.Error())
+		return
+	}
+
+	//指定年的春节农历
+	tmpYearCjnl := fmt.Sprintf("%d-01-01", currentDataDay.Year())
+	//指定年的春节公历
+	tmpYearCjgl := solarlunar.LunarToSolar(tmpYearCjnl, false)
+
+	tmpYearCjglTime, tmpErr := time.ParseInLocation(utils.FormatDate, tmpYearCjgl, time.Local)
+	if tmpErr != nil {
+		err = errors.New(fmt.Sprintf("%d公历日期转换失败:%s", currentDataDay.Year(), tmpErr.Error()))
+		return
+	}
+
+	// 将两个日期同步到同一年,然后计算两个日期相差的天数
+	tmpCurrentYearCjglTime := currentYearCjglTime.AddDate(currentDataDay.Year()-currentYear, 0, 0)
+	moveDay = utils.GetTimeSubDay(tmpYearCjglTime, tmpCurrentYearCjglTime)
+
+	return
+}
+
 // CjjxSub 计算超季节性值
 // 计算公式=现值-过去n年(包括今年)均值,n为取数个数,需大于等于1;
 //举例:A指标  2022-10-13值100,2021-10-13值120,2020-10-13值110,设置n=3,则“超季节性”指标计算值为100-(100+120+110)/3=-10。
@@ -352,7 +440,7 @@ func CjjxSub(currValue float64, pastValue []float64) (value string) {
 	numDecimal := decimal.NewFromInt(int64(num))
 
 	af := decimal.NewFromFloat(currValue)
-	fmt.Println(af)
+	//fmt.Println(af)
 
 	bf := decimal.NewFromFloat(pastValue[0])
 

+ 1 - 1
models/edb_data_calculate_tcz.go

@@ -283,7 +283,7 @@ func refreshAllCalculateTcz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 						}
 					}
 				}
-				utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
+				//utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
 				continue
 			} else {
 				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月

+ 1 - 0
models/edb_info.go

@@ -43,6 +43,7 @@ type EdbInfo struct {
 	LatestDate  string  `description:"数据最新日期"`
 	LatestValue float64 `description:"数据最新值"`
 	ChartImage  string  `description:"图表图片"`
+	Calendar    string  `description:"公历/农历"`
 }
 
 // AddEdbInfo 添加指标