|
@@ -9,10 +9,18 @@ import (
|
|
"github.com/nosixtools/solarlunar"
|
|
"github.com/nosixtools/solarlunar"
|
|
"github.com/shopspring/decimal"
|
|
"github.com/shopspring/decimal"
|
|
"math"
|
|
"math"
|
|
|
|
+ "strconv"
|
|
"strings"
|
|
"strings"
|
|
"time"
|
|
"time"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+var (
|
|
|
|
+ yoyMap = map[int]string{
|
|
|
|
+ 17: "同比",
|
|
|
|
+ 18: "同差",
|
|
|
|
+ }
|
|
|
|
+)
|
|
|
|
+
|
|
type RuleParams struct {
|
|
type RuleParams struct {
|
|
EdbInfoId int
|
|
EdbInfoId int
|
|
DayList []time.Time
|
|
DayList []time.Time
|
|
@@ -1536,6 +1544,157 @@ type AnnualValueInversionConf struct {
|
|
YearList []int `description:"指定年份列表"`
|
|
YearList []int `description:"指定年份列表"`
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func getReplaceValue(replaceValueMap map[string]float64, days, dayStep int, currentDate time.Time) (replaceValue decimal.Decimal, success bool) {
|
|
|
|
+ nextDateDay := currentDate
|
|
|
|
+ for i := 0; i <= days; i++ {
|
|
|
|
+ replaceDateDayStr := nextDateDay.Format(utils.FormatDate)
|
|
|
|
+ if preValue, ok := replaceValueMap[replaceDateDayStr]; ok { //上一年同期->下一个月找到
|
|
|
|
+ replaceValue = decimal.NewFromFloat(preValue)
|
|
|
|
+ success = true
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ nextDateDay = nextDateDay.AddDate(0, 0, dayStep)
|
|
|
|
+ }
|
|
|
|
+ return decimal.NewFromInt(0), false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetChartPredictEdbInfoDataListByRuleDynamicYOYComparisonOrDifference 动态同比
|
|
|
|
+// 2、指标选择范围为预测指标。
|
|
|
|
+// 3、动态同比计算方法:预测值=去年同期值*(1+同比指标预测值)
|
|
|
|
+// 4、上述“去年同期”如果没有严格对应的日期,则前后查找最近35天的值。
|
|
|
|
+// 5、选择的同比指标日期需要与预测指标未来日期对应上,对应不上的不生成预测值。
|
|
|
|
+func GetChartPredictEdbInfoDataListByRuleDynamicYOYComparisonOrDifference(ruleType, edbInfoId int, configValue string, dayList []time.Time, realPredictEdbInfoData []*data_manage.EdbDataList, existMap map[string]float64) (newPredictEdbInfoData []*data_manage.EdbDataList, minValue, maxValue float64, err error) {
|
|
|
|
+ var yoyType string
|
|
|
|
+ if _, ok := yoyMap[ruleType]; !ok {
|
|
|
|
+ err = errors.New("计算规则不存在")
|
|
|
|
+ return
|
|
|
|
+ } else {
|
|
|
|
+ yoyType = yoyMap[ruleType]
|
|
|
|
+ }
|
|
|
|
+ //预测指标的去年同期数据
|
|
|
|
+ baseDynamicDataList := make(map[string]decimal.Decimal, len(dayList))
|
|
|
|
+ DynamicCalculateDataList := make(map[string]decimal.Decimal, len(dayList))
|
|
|
|
+ index := len(realPredictEdbInfoData)
|
|
|
|
+ if index <= 0 {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ dynamicYOYComparisonIndexId, err := strconv.Atoi(configValue)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ newPredictEdbInfoData = make([]*data_manage.EdbDataList, 0, len(dayList))
|
|
|
|
+ // 获取同比预测指标的预测数据
|
|
|
|
+ dynamicYOYComparisonIndex, err := data_manage.GetEdbInfoById(dynamicYOYComparisonIndexId)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if dynamicYOYComparisonIndex.EdbInfoType != 1 {
|
|
|
|
+ err = errors.New("选择的指标不是预测指标")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ startDate, endDate := dayList[0].Format(utils.FormatDate), dayList[len(dayList)-1].Format(utils.FormatDate)
|
|
|
|
+ //获取动态同比指标对应预测日期的预测数据
|
|
|
|
+ dynamicYOYComparisonIndexDataList, err := data_manage.GetEdbDataList(dynamicYOYComparisonIndex.Source, dynamicYOYComparisonIndex.SubSource, dynamicYOYComparisonIndex.EdbInfoId, startDate, endDate)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if len(dynamicYOYComparisonIndexDataList) <= 0 {
|
|
|
|
+ err = errors.New(fmt.Sprintf("选择%s指标没有预测数据", yoyType))
|
|
|
|
+ return
|
|
|
|
+ } else {
|
|
|
|
+ for _, v := range dynamicYOYComparisonIndexDataList {
|
|
|
|
+ DynamicCalculateDataList[v.DataTime] = decimal.NewFromFloat(v.Value)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //检查是不存在同期数据
|
|
|
|
+ for _, date := range dayList {
|
|
|
|
+ dayStr := date.Format(utils.FormatDate)
|
|
|
|
+ if _, ok := DynamicCalculateDataList[dayStr]; !ok {
|
|
|
|
+ err = errors.New(fmt.Sprintf("选择%s指标没有同期预测数据,日期:[%s]", yoyType, dayStr))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //获取上一期的同期数据
|
|
|
|
+ for _, date := range dayList {
|
|
|
|
+ preDate := date.AddDate(-1, 0, 0)
|
|
|
|
+ preDateStr := preDate.Format(utils.FormatDate)
|
|
|
|
+ if preValue, ok := existMap[preDateStr]; ok { //上一年同期找到
|
|
|
|
+ baseDynamicDataList[preDateStr] = decimal.NewFromFloat(preValue)
|
|
|
|
+ } else {
|
|
|
|
+ if baseDynamicDataList[preDateStr], ok = getReplaceValue(existMap, 0, -1, preDate); !ok {
|
|
|
|
+ err = errors.New(fmt.Sprintf("指标没有历史同期数据,Date:[%s]", preDateStr))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //获取后面的预测数据
|
|
|
|
+
|
|
|
|
+ for k, currentDate := range dayList {
|
|
|
|
+ var calculateValue decimal.Decimal
|
|
|
|
+ var dateStr = currentDate.Format(utils.FormatDate)
|
|
|
|
+ switch ruleType {
|
|
|
|
+ case 17:
|
|
|
|
+ calculateValue = baseDynamicDataList[dateStr].Mul(DynamicCalculateDataList[dateStr].Add(decimal.NewFromInt(1)))
|
|
|
|
+ case 18:
|
|
|
|
+ calculateValue = baseDynamicDataList[dateStr].Add(DynamicCalculateDataList[dateStr])
|
|
|
|
+ default:
|
|
|
|
+ err = errors.New("计算规则不存在")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tmpData := &data_manage.EdbDataList{
|
|
|
|
+ EdbDataId: edbInfoId + 100000 + index + k,
|
|
|
|
+ EdbInfoId: edbInfoId,
|
|
|
|
+ DataTime: currentDate.Format(utils.FormatDate),
|
|
|
|
+ DataTimestamp: currentDate.UnixNano() / 1e6,
|
|
|
|
+ }
|
|
|
|
+ //currentItem := existMap[av]
|
|
|
|
+ var val = calculateValue.InexactFloat64()
|
|
|
|
+ tmpData.Value = val
|
|
|
|
+ newPredictEdbInfoData = append(newPredictEdbInfoData, tmpData)
|
|
|
|
+ existMap[tmpData.DataTime] = val
|
|
|
|
+ if k == 0 {
|
|
|
|
+ minValue = val
|
|
|
|
+ maxValue = val
|
|
|
|
+ } else {
|
|
|
|
+ // 最大最小值
|
|
|
|
+ if val < minValue {
|
|
|
|
+ minValue = val
|
|
|
|
+ }
|
|
|
|
+ if val > maxValue {
|
|
|
|
+ maxValue = val
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// getYearListBySeasonConf 根据配置获取年份列表
|
|
|
|
+func getYearListBySeasonConf(configValue string) (yearList []int, seasonConf SeasonConf, err error) {
|
|
|
|
+ tmpErr := json.Unmarshal([]byte(configValue), &seasonConf)
|
|
|
|
+ if tmpErr != nil {
|
|
|
|
+ err = errors.New("年份配置信息异常:" + tmpErr.Error())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ //选择方式,1:连续N年;2:指定年份
|
|
|
|
+ if seasonConf.YearType == 1 {
|
|
|
|
+ if seasonConf.NValue < 1 {
|
|
|
|
+ err = errors.New("连续N年不允许小于1")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ currYear := time.Now().Year()
|
|
|
|
+ for i := 0; i < seasonConf.NValue; i++ {
|
|
|
|
+ yearList = append(yearList, currYear-i-1)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ yearList = seasonConf.YearList
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
// GetChartPredictEdbInfoDataListByRuleAnnualValueInversion 根据 年度值倒推 规则获取预测数据
|
|
// GetChartPredictEdbInfoDataListByRuleAnnualValueInversion 根据 年度值倒推 规则获取预测数据
|
|
// 预测指标-年度值倒推
|
|
// 预测指标-年度值倒推
|
|
// 1、年度值倒推,选择同比法,支持选择多个年份(当前只可选择一个年份)。选择多个年份时,计算多个年份的余额平均,和同期平均。
|
|
// 1、年度值倒推,选择同比法,支持选择多个年份(当前只可选择一个年份)。选择多个年份时,计算多个年份的余额平均,和同期平均。
|
|
@@ -1896,28 +2055,3 @@ func GetChartPredictEdbInfoDataListByRuleAnnualValueInversion(edbInfoId int, con
|
|
|
|
|
|
return
|
|
return
|
|
}
|
|
}
|
|
-
|
|
|
|
-// getYearListBySeasonConf 根据配置获取年份列表
|
|
|
|
-func getYearListBySeasonConf(configValue string) (yearList []int, seasonConf SeasonConf, err error) {
|
|
|
|
- tmpErr := json.Unmarshal([]byte(configValue), &seasonConf)
|
|
|
|
- if tmpErr != nil {
|
|
|
|
- err = errors.New("年份配置信息异常:" + tmpErr.Error())
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- //选择方式,1:连续N年;2:指定年份
|
|
|
|
- if seasonConf.YearType == 1 {
|
|
|
|
- if seasonConf.NValue < 1 {
|
|
|
|
- err = errors.New("连续N年不允许小于1")
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- currYear := time.Now().Year()
|
|
|
|
- for i := 0; i < seasonConf.NValue; i++ {
|
|
|
|
- yearList = append(yearList, currYear-i-1)
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- yearList = seasonConf.YearList
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return
|
|
|
|
-}
|
|
|