edb_data_calculate_qjjs.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. package models
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta_gn/eta_index_lib/global"
  6. "eta_gn/eta_index_lib/utils"
  7. "fmt"
  8. "github.com/shopspring/decimal"
  9. "gorm.io/gorm"
  10. "math"
  11. "strconv"
  12. "strings"
  13. "time"
  14. )
  15. type CalculateRangeAnalysis struct {
  16. }
  17. type RangeAnalysisCalculateFormula struct {
  18. DateRangeType int `description:"区间划分类型 0:智能划分,1:手工划分,2:跨年划分"`
  19. AutoDateConf ChartRangeAnalysisAutoDateConf `description:"智能划分时间区间配置"`
  20. ManualDateConf []ChartRangeAnalysisManualDateConf `description:"手工划分时间区间配置"`
  21. YearDateConf ChartRangeAnalysisYearDateConf `description:"跨年划分时间区间配置"`
  22. CalculateType int `description:"计算类型 0: 区间均值,1: 区间累计值,2:区间涨幅,3:区间年化增长率,4:区间最大值,5:区间最小值"`
  23. UnNormalDataDealType int `description:"异常值处理配置 0:不处理,1:剔除,2替换"`
  24. UnNormalDataConf ChartRangeAnalysisDeleteDataConf
  25. DataConvertType int `description:"数据转换类型 0不转, 1乘 2除 3对数"`
  26. DataConvertConf ChartRangeAnalysisDataConvertConf `description:"数据转换详情"`
  27. }
  28. type ChartRangeAnalysisAutoDateConf struct { //智能划分
  29. IsAutoStartDate int `description:"起始日期是否是动态设置:0固定,1动态"`
  30. StartDate string `description:"起始日期"` //固定模式下,截止日期为指标的最新日期
  31. EndDate string `description:"固定模式下的截止日期"`
  32. IsAutoEndDate int `description:"截止日期是否是动态设置:0固定,1动态"`
  33. StartDateConf ChartRangeAnalysisAutoDateChangeConf `description:"动态起始日期配置"`
  34. EndDateConf ChartRangeAnalysisAutoDateChangeConf `description:"动态截止日期配置"`
  35. }
  36. type ChartRangeAnalysisAutoDateChangeConf struct {
  37. BaseDateType int `description:"基准日期类型:0指标日期,1系统日期,2固定日期"`
  38. MoveForward int `description:"前移的期数"`
  39. DateChange []*EdbDataDateChangeConf
  40. }
  41. type EdbDataDateChangeConf struct {
  42. Year int
  43. Month int
  44. Day int
  45. Frequency string `description:"频度变换"`
  46. FrequencyDay string `description:"频度的固定日期"`
  47. ChangeType int `description:"日期变换类型1日期位移,2指定频率"`
  48. }
  49. type ChartRangeAnalysisManualDateConf struct { //手工划分
  50. StartDate string `description:"开始日期"`
  51. EndDate string `description:"结束日期"`
  52. }
  53. type ChartRangeAnalysisYearDateConf struct {
  54. StartDay string `description:"开始日"`
  55. EndDay string `description:"结束日"`
  56. }
  57. type ChartRangeAnalysisDeleteDataConf struct {
  58. Formula string
  59. Value float64
  60. ReplaceValue float64 `description:"替换的值"`
  61. }
  62. type ChartRangeAnalysisDataConvertConf struct {
  63. Value float64 `description:"数据转换值"`
  64. Unit string `description:"数据转换单位"`
  65. EnUnit string `description:"数据转换单位"`
  66. }
  67. type ChartRangeAnalysisDateDataItem struct {
  68. StartDate time.Time
  69. EndDate time.Time
  70. DataList []*EdbInfoSearchData
  71. }
  72. func (obj CalculateRangeAnalysis) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, err error, errMsg string) {
  73. req := params.Req
  74. edbCode := params.EdbCode
  75. uniqueCode := params.UniqueCode
  76. sysUserId := params.SysUserId
  77. sysUserRealName := params.SysUserRealName
  78. to := global.DEFAULT_DmSQL.Begin()
  79. defer func() {
  80. if err != nil {
  81. to.Rollback()
  82. } else {
  83. to.Commit()
  84. }
  85. }()
  86. if req.EdbInfoId > 0 {
  87. err = errors.New("无法新增")
  88. return
  89. }
  90. edbInfo = new(EdbInfo)
  91. edbInfo.Source = obj.GetSource()
  92. edbInfo.SourceName = obj.GetSourceName()
  93. edbInfo.EdbCode = edbCode
  94. edbInfo.EdbName = req.EdbName
  95. edbInfo.EdbNameSource = req.EdbName
  96. edbInfo.Frequency = req.Frequency
  97. edbInfo.Unit = req.Unit
  98. edbInfo.ClassifyId = req.ClassifyId
  99. edbInfo.SysUserId = sysUserId
  100. edbInfo.SysUserRealName = sysUserRealName
  101. edbInfo.CreateTime = time.Now()
  102. edbInfo.ModifyTime = time.Now()
  103. edbInfo.UniqueCode = uniqueCode
  104. edbInfo.CalculateFormula = req.CalculateFormula
  105. edbInfo.EdbNameEn = req.EdbName
  106. edbInfo.UnitEn = req.Unit
  107. edbInfo.EdbType = obj.GetEdbType()
  108. tmpErr := to.Create(edbInfo).Error
  109. if tmpErr != nil {
  110. err = tmpErr
  111. return
  112. }
  113. //关联关系
  114. fromEdbInfo, e := GetEdbInfoById(req.FromEdbInfoId)
  115. if e != nil {
  116. err = fmt.Errorf("获取来源指标失败,Err:%s", e.Error())
  117. return
  118. }
  119. calculateMappingItem := new(EdbInfoCalculateMapping)
  120. calculateMappingItem.CreateTime = time.Now()
  121. calculateMappingItem.ModifyTime = time.Now()
  122. calculateMappingItem.Sort = 1
  123. calculateMappingItem.EdbCode = edbCode
  124. calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
  125. calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
  126. calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
  127. calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
  128. calculateMappingItem.FromSource = fromEdbInfo.Source
  129. calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
  130. calculateMappingItem.FromTag = ""
  131. calculateMappingItem.Source = edbInfo.Source
  132. calculateMappingItem.SourceName = edbInfo.SourceName
  133. calculateMappingItem.FromSubSource = edbInfo.SubSource
  134. err = to.Create(calculateMappingItem).Error
  135. if err != nil {
  136. return
  137. }
  138. //计算数据
  139. err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
  140. return
  141. }
  142. func (obj CalculateRangeAnalysis) Edit(params EditCalculateBatchParams) (err error, errMsg string) {
  143. edbInfo := params.EdbInfo
  144. req := params.Req
  145. to := global.DEFAULT_DmSQL.Begin()
  146. defer func() {
  147. if err != nil {
  148. to.Rollback()
  149. } else {
  150. to.Commit()
  151. }
  152. }()
  153. //修改指标信息
  154. edbInfo.EdbName = req.EdbName
  155. edbInfo.EdbNameSource = req.EdbName
  156. edbInfo.Frequency = req.Frequency
  157. edbInfo.Unit = req.Unit
  158. edbInfo.ClassifyId = req.ClassifyId
  159. edbInfo.CalculateFormula = req.CalculateFormula
  160. edbInfo.EdbNameEn = req.EdbNameEn
  161. edbInfo.UnitEn = req.UnitEn
  162. edbInfo.ModifyTime = time.Now()
  163. err = to.Model(edbInfo).Select([]string{"EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EdbNameEn", "UnitEn"}).Updates(edbInfo).Error
  164. if err != nil {
  165. return
  166. }
  167. //删除,计算指标关联的,基础指标的关联关系
  168. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
  169. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  170. if err != nil {
  171. err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
  172. return
  173. }
  174. //清空原有数据
  175. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  176. sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
  177. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  178. if err != nil {
  179. return
  180. }
  181. fromEdbInfo, e := GetEdbInfoById(req.FromEdbInfoId)
  182. if e != nil {
  183. err = fmt.Errorf("获取来源指标失败,Err:%s", e.Error())
  184. return
  185. }
  186. calculateMappingItem := new(EdbInfoCalculateMapping)
  187. calculateMappingItem.CreateTime = time.Now()
  188. calculateMappingItem.ModifyTime = time.Now()
  189. calculateMappingItem.Sort = 1
  190. calculateMappingItem.EdbCode = edbInfo.EdbCode
  191. calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
  192. calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
  193. calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
  194. calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
  195. calculateMappingItem.FromSource = fromEdbInfo.Source
  196. calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
  197. calculateMappingItem.FromTag = ""
  198. calculateMappingItem.Source = edbInfo.Source
  199. calculateMappingItem.SourceName = edbInfo.SourceName
  200. calculateMappingItem.FromSubSource = edbInfo.SubSource
  201. err = to.Create(calculateMappingItem).Error
  202. if err != nil {
  203. return
  204. }
  205. //计算数据
  206. err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
  207. return
  208. }
  209. func (obj CalculateRangeAnalysis) Refresh(params RefreshParams) (err error, errMsg string) {
  210. edbInfo := params.EdbInfo
  211. edbInfoCalculateDetailList, err := GetEdbInfoCalculateDetailList(edbInfo.EdbInfoId)
  212. if err != nil {
  213. return
  214. }
  215. var fromEdbInfo *EdbInfo
  216. for _, v := range edbInfoCalculateDetailList {
  217. fromEdbInfo, _ = GetEdbInfoById(v.FromEdbInfoId)
  218. break
  219. }
  220. if fromEdbInfo == nil {
  221. errMsg = "指标异常"
  222. err = errors.New(errMsg)
  223. return
  224. }
  225. to := global.DEFAULT_DmSQL.Begin()
  226. defer func() {
  227. if err != nil {
  228. to.Rollback()
  229. } else {
  230. to.Commit()
  231. }
  232. }()
  233. // 计算数据
  234. err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
  235. return
  236. }
  237. func (obj CalculateRangeAnalysis) refresh(to *gorm.DB, edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode, calculateFormula string) (err error, errMsg string) {
  238. edbInfoIdStr := strconv.Itoa(edbInfoId)
  239. tableName := GetEdbDataTableName(obj.GetSource(), utils.DATA_SUB_SOURCE_EDB)
  240. //获取扩散指数指标所有数据
  241. existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source, subSource)
  242. if err != nil {
  243. return
  244. }
  245. //计算指标的map
  246. existDataMap := make(map[string]*EdbData, 0)
  247. removeDateMap := make(map[string]string)
  248. for _, v := range existDataList {
  249. existDataMap[v.DataTime] = v
  250. removeDateMap[v.DataTime] = ``
  251. }
  252. var rangeAnalysisConf RangeAnalysisCalculateFormula
  253. //fmt.Println("calculateFormula:", calculateFormula)
  254. err = json.Unmarshal([]byte(calculateFormula), &rangeAnalysisConf)
  255. if err != nil {
  256. err = fmt.Errorf("解析区间计算公式失败 %s", err.Error())
  257. return
  258. }
  259. rangeAnalysisChartData, err := GetRangeAnalysisChartDataByEdbInfo(fromEdbInfo, rangeAnalysisConf)
  260. if err != nil {
  261. err = fmt.Errorf("获取区间计算数据失败 %s", err.Error())
  262. return
  263. }
  264. addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  265. var isAdd bool
  266. for _, item := range rangeAnalysisChartData {
  267. currDateStr := item.DataTime
  268. currVal := item.Value
  269. // 判断扩散指数指标是否存在数据
  270. if existData, ok := existDataMap[currDateStr]; ok {
  271. // 处理扩散指数数据的值
  272. existValStr := existData.Value
  273. existValDeci, tmpErr := decimal.NewFromString(existValStr)
  274. if tmpErr != nil {
  275. err = tmpErr
  276. return
  277. }
  278. existVal, _ := existValDeci.Round(4).Float64()
  279. // 判断扩散指数数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
  280. if existVal != currVal {
  281. err = ModifyEdbDataById(source, subSource, existData.EdbDataId, fmt.Sprint(currVal))
  282. if err != nil {
  283. return
  284. }
  285. }
  286. } else {
  287. // 直接入库
  288. timestamp := item.DataTimestamp
  289. timestampStr := fmt.Sprintf("%d", timestamp)
  290. addSql += GetAddSql(edbInfoIdStr, edbCode, currDateStr, timestampStr, fmt.Sprint(currVal))
  291. isAdd = true
  292. }
  293. delete(removeDateMap, currDateStr)
  294. }
  295. // 数据入库
  296. {
  297. if isAdd {
  298. addSql = strings.TrimRight(addSql, ",")
  299. err = to.Exec(addSql).Error
  300. }
  301. // 移除不存在的日期数据
  302. if len(removeDateMap) > 0 {
  303. removeDateList := make([]string, 0) //需要移除的日期
  304. for k := range removeDateMap {
  305. removeDateList = append(removeDateList, k)
  306. }
  307. removeDateStr := strings.Join(removeDateList, `","`)
  308. removeDateStr = `"` + removeDateStr + `"`
  309. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
  310. err = to.Exec(sql, edbInfoId).Error
  311. if err != nil {
  312. err = fmt.Errorf("删除扩散指数指标数据失败,Err:" + err.Error())
  313. return
  314. }
  315. }
  316. }
  317. return
  318. }
  319. // GetAutoCalculateDateDataList 获取当前时间相关的区间作为计算依据
  320. func GetAutoCalculateDateDataList(currentDate string, dataList []*EdbInfoSearchData, req RangeAnalysisCalculateFormula) (newDataList []*EdbInfoSearchData, err error) {
  321. currentDateTime, _ := time.ParseInLocation(utils.FormatDate, currentDate, time.Local)
  322. switch req.DateRangeType {
  323. case 0:
  324. // 智能划分得到一个开始日期,和结束日期
  325. var startDateTime time.Time
  326. if req.AutoDateConf.IsAutoStartDate == 0 { //固定设置
  327. startDate := req.AutoDateConf.StartDate
  328. if startDate == "" {
  329. startDate = "2020-01-01"
  330. }
  331. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  332. } else {
  333. startConf := req.AutoDateConf.StartDateConf
  334. startDate := ""
  335. if startConf.BaseDateType == 0 { //
  336. startDate = currentDate
  337. } else if startConf.BaseDateType == 1 {
  338. startDate = time.Now().Format(utils.FormatDate)
  339. }
  340. if startConf.MoveForward > 0 {
  341. startDate = GetEdbDateByMoveForward(startDate, startConf.MoveForward, dataList)
  342. }
  343. if len(startConf.DateChange) > 0 {
  344. startDate, err = HandleEdbDateChange(startDate, startConf.DateChange)
  345. if err != nil {
  346. err = fmt.Errorf("智能划分开始日期处理失败:%s", err.Error())
  347. return
  348. }
  349. }
  350. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  351. }
  352. var calStartTime, calEndTime time.Time
  353. if currentDateTime.Before(startDateTime) {
  354. calStartTime = currentDateTime
  355. calEndTime = startDateTime
  356. } else {
  357. calStartTime = startDateTime
  358. calEndTime = currentDateTime
  359. }
  360. // 根据日期,获取数据
  361. for _, vv := range dataList {
  362. dataTimeT, _ := time.ParseInLocation(utils.FormatDate, vv.DataTime, time.Local)
  363. if dataTimeT.After(calStartTime) && dataTimeT.Before(calEndTime) ||
  364. dataTimeT.Equal(calStartTime) ||
  365. dataTimeT.Equal(calEndTime) {
  366. newDataList = append(newDataList, vv)
  367. }
  368. }
  369. }
  370. return
  371. }
  372. // HandleDataByCalculateType 根据计算公式处理数据
  373. func HandleRangeAnalysisDataByCalculateType(originList []*ChartRangeAnalysisDateDataItem, originDataList []*EdbInfoSearchData, req RangeAnalysisCalculateFormula) (newList []*EdbInfoSearchData, err error) {
  374. if len(originList) == 0 {
  375. return
  376. }
  377. calculateType := req.CalculateType
  378. switch calculateType {
  379. case 0: //均值
  380. var sum float64
  381. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  382. for _, item := range originList {
  383. for _, v := range item.DataList {
  384. sum = 0
  385. //计算的数据返回需要重新确定
  386. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  387. if e != nil {
  388. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  389. return
  390. }
  391. for _, vv := range calDataList {
  392. sum += vv.Value
  393. }
  394. val := sum / float64(len(calDataList))
  395. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  396. newList = append(newList, &EdbInfoSearchData{
  397. DataTime: v.DataTime,
  398. Value: val,
  399. DataTimestamp: v.DataTimestamp,
  400. })
  401. }
  402. }
  403. } else {
  404. for _, item := range originList {
  405. sum = 0
  406. for k, v := range item.DataList {
  407. sum += v.Value
  408. val := sum / float64(k+1)
  409. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  410. newList = append(newList, &EdbInfoSearchData{
  411. DataTime: v.DataTime,
  412. Value: val,
  413. DataTimestamp: v.DataTimestamp,
  414. })
  415. }
  416. }
  417. }
  418. case 1: //累计值
  419. var sum float64
  420. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  421. for _, item := range originList {
  422. sum = 0
  423. for _, v := range item.DataList {
  424. sum = 0
  425. //计算的数据返回需要重新确定
  426. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  427. if e != nil {
  428. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  429. return
  430. }
  431. for _, vv := range calDataList {
  432. sum += vv.Value
  433. }
  434. val := sum
  435. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  436. newList = append(newList, &EdbInfoSearchData{
  437. DataTime: v.DataTime,
  438. Value: val,
  439. DataTimestamp: v.DataTimestamp,
  440. })
  441. }
  442. }
  443. } else {
  444. for _, item := range originList {
  445. sum = 0
  446. for _, v := range item.DataList {
  447. sum += v.Value
  448. val := sum
  449. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  450. newList = append(newList, &EdbInfoSearchData{
  451. DataTime: v.DataTime,
  452. Value: val,
  453. DataTimestamp: v.DataTimestamp,
  454. })
  455. }
  456. }
  457. }
  458. case 2: //涨幅
  459. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  460. for _, item := range originList {
  461. for _, v := range item.DataList {
  462. var baseVal float64
  463. //计算的数据返回需要重新确定
  464. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  465. if e != nil {
  466. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  467. return
  468. }
  469. if len(calDataList) == 0 {
  470. continue
  471. }
  472. baseVal = calDataList[0].Value
  473. baseDate := calDataList[0].DataTime
  474. if baseVal == 0 {
  475. continue
  476. }
  477. if v.DataTime == baseDate {
  478. continue
  479. }
  480. val := (v.Value - baseVal) / baseVal
  481. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  482. newList = append(newList, &EdbInfoSearchData{
  483. DataTime: v.DataTime,
  484. Value: val,
  485. DataTimestamp: v.DataTimestamp,
  486. })
  487. }
  488. }
  489. } else {
  490. for _, item := range originList {
  491. if len(item.DataList) == 0 {
  492. break
  493. }
  494. baseVal := item.DataList[0].Value
  495. baseDate := item.DataList[0].DataTime
  496. if baseVal == 0 {
  497. break
  498. }
  499. for _, v := range item.DataList {
  500. if v.DataTime == baseDate {
  501. continue
  502. }
  503. val := (v.Value - baseVal) / baseVal
  504. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  505. newList = append(newList, &EdbInfoSearchData{
  506. DataTime: v.DataTime,
  507. Value: val,
  508. DataTimestamp: v.DataTimestamp,
  509. })
  510. }
  511. }
  512. }
  513. case 3: //复合增长率
  514. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  515. for _, item := range originList {
  516. for _, v := range item.DataList {
  517. var baseVal float64
  518. var baseDate string
  519. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  520. if e != nil {
  521. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  522. return
  523. }
  524. if len(calDataList) == 0 {
  525. continue
  526. }
  527. baseVal = calDataList[0].Value
  528. baseDate = calDataList[0].DataTime
  529. if v.DataTime == baseDate {
  530. continue
  531. }
  532. if baseVal == 0 {
  533. continue
  534. }
  535. baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
  536. if e != nil {
  537. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  538. return
  539. }
  540. tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  541. if e != nil {
  542. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  543. return
  544. }
  545. // 计算两个日期相差的天数
  546. diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
  547. val := v.Value / baseVal
  548. val = math.Pow(val, 1/diff) - 1
  549. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  550. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  551. }
  552. }
  553. } else {
  554. for _, item := range originList {
  555. if len(item.DataList) == 0 {
  556. break
  557. }
  558. baseVal := item.DataList[0].Value
  559. baseDate := item.DataList[0].DataTime
  560. if baseVal == 0 {
  561. break
  562. }
  563. for _, v := range item.DataList {
  564. if v.DataTime == baseDate {
  565. continue
  566. }
  567. baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
  568. if e != nil {
  569. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  570. return
  571. }
  572. tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  573. if e != nil {
  574. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  575. return
  576. }
  577. // 计算两个日期相差的天数
  578. diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
  579. val := v.Value / baseVal
  580. val = math.Pow(val, 1/diff) - 1
  581. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  582. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  583. }
  584. }
  585. }
  586. case 4: //最大值
  587. var maxVal float64
  588. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  589. for _, item := range originList {
  590. for _, v := range item.DataList {
  591. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  592. if e != nil {
  593. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  594. return
  595. }
  596. for kk, vv := range calDataList {
  597. if kk == 0 {
  598. maxVal = vv.Value
  599. }
  600. if vv.Value > maxVal {
  601. maxVal = vv.Value
  602. }
  603. }
  604. val := maxVal
  605. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  606. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  607. }
  608. }
  609. } else {
  610. for _, item := range originList {
  611. for k, v := range item.DataList {
  612. if k == 0 {
  613. maxVal = v.Value
  614. }
  615. if v.Value > maxVal {
  616. maxVal = v.Value
  617. }
  618. val := maxVal
  619. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  620. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  621. }
  622. }
  623. }
  624. case 5: //最小值
  625. var minVal float64
  626. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  627. for _, item := range originList {
  628. for _, v := range item.DataList {
  629. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  630. if e != nil {
  631. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  632. return
  633. }
  634. for kk, vv := range calDataList {
  635. if kk == 0 {
  636. minVal = vv.Value
  637. }
  638. if vv.Value < minVal {
  639. minVal = vv.Value
  640. }
  641. }
  642. val := minVal
  643. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  644. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  645. }
  646. }
  647. } else {
  648. for _, item := range originList {
  649. for k, v := range item.DataList {
  650. if k == 0 {
  651. minVal = v.Value
  652. }
  653. if v.Value < minVal {
  654. minVal = v.Value
  655. }
  656. val := minVal
  657. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  658. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  659. }
  660. }
  661. }
  662. }
  663. return
  664. }
  665. // GetRangeAnalysisChartDataByEdbInfo 区间计算
  666. func GetRangeAnalysisChartDataByEdbInfo(fromEdbInfo *EdbInfo, calculateFormula RangeAnalysisCalculateFormula) (newDataList []*EdbInfoSearchData, err error) {
  667. // 指标的开始日期和结束日期
  668. edbStartDateTime, _ := time.ParseInLocation(utils.FormatDate, fromEdbInfo.StartDate, time.Local)
  669. edbEndDateTime, _ := time.ParseInLocation(utils.FormatDate, fromEdbInfo.EndDate, time.Local)
  670. edbEndDate := edbEndDateTime.Format(utils.FormatDate)
  671. // 获取时间基准指标在时间区间内的值
  672. dataList := make([]*EdbInfoSearchData, 0)
  673. switch fromEdbInfo.EdbInfoType {
  674. case 0:
  675. //获取来源指标的数据
  676. dataList, err = GetEdbDataListAll(fromEdbInfo.Source, fromEdbInfo.SubSource,
  677. FindEdbDataListAllCond{
  678. EdbInfoId: fromEdbInfo.EdbInfoId,
  679. }, 1)
  680. case 1:
  681. dataList, err = GetPredictEdbDataListAllByStartDate(fromEdbInfo, 1, "")
  682. default:
  683. err = errors.New(fmt.Sprint("获取失败,指标base类型异常", fromEdbInfo.EdbInfoType))
  684. return
  685. }
  686. if err != nil {
  687. err = fmt.Errorf("获取时间基准指标在时间区间内的值失败,Err:" + err.Error())
  688. return
  689. }
  690. dateList := make([]*ChartRangeAnalysisDateDataItem, 0)
  691. switch calculateFormula.DateRangeType {
  692. case 0:
  693. // 智能划分得到一个开始日期,和结束日期
  694. var startDateTime, endDateTime time.Time
  695. startDateTime = edbStartDateTime
  696. if calculateFormula.AutoDateConf.IsAutoStartDate == 0 { //固定设置
  697. startDate := calculateFormula.AutoDateConf.StartDate
  698. if startDate == "" {
  699. startDate = "2020-01-01"
  700. }
  701. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  702. }
  703. if calculateFormula.AutoDateConf.IsAutoEndDate == 0 { //固定设置
  704. endDate := calculateFormula.AutoDateConf.EndDate
  705. if endDate == "" {
  706. err = fmt.Errorf("智能划分截止日期处理失败:请输入截止日期")
  707. return
  708. }
  709. // todo 如果截止日期比指标日期还要大,则用指标的最新日期
  710. endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  711. } else {
  712. endConf := calculateFormula.AutoDateConf.EndDateConf
  713. endDate := edbEndDate
  714. if endConf.MoveForward > 0 {
  715. endDate = GetEdbDateByMoveForward(endDate, endConf.MoveForward, dataList)
  716. }
  717. if len(endConf.DateChange) > 0 {
  718. endDate, err = HandleEdbDateChange(endDate, endConf.DateChange)
  719. if err != nil {
  720. err = fmt.Errorf("智能划分结束日期处理失败:%s", err.Error())
  721. return
  722. }
  723. }
  724. endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  725. }
  726. dateList = append(dateList, &ChartRangeAnalysisDateDataItem{
  727. StartDate: startDateTime,
  728. EndDate: endDateTime})
  729. case 1:
  730. // 手工划分得到多个开始日期和结束日期(已排序)
  731. for _, v := range calculateFormula.ManualDateConf {
  732. startDateT, _ := time.ParseInLocation(utils.FormatDate, v.StartDate, time.Local)
  733. endDateT, _ := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  734. tmp := &ChartRangeAnalysisDateDataItem{
  735. StartDate: startDateT,
  736. EndDate: endDateT,
  737. }
  738. dateList = append(dateList, tmp)
  739. }
  740. case 2:
  741. // 跨年划分得到多个开始日期和结束日期
  742. startYear := edbStartDateTime.Year()
  743. endYear := edbEndDateTime.Year()
  744. startDay := calculateFormula.YearDateConf.StartDay
  745. endDay := calculateFormula.YearDateConf.EndDay
  746. for year := startYear; year <= endYear; year++ {
  747. startDate := fmt.Sprintf("%d-%s", year, startDay)
  748. endDate := fmt.Sprintf("%d-%s", year+1, endDay)
  749. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  750. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  751. if startDateTime.Before(edbStartDateTime) {
  752. break
  753. }
  754. tmp := &ChartRangeAnalysisDateDataItem{
  755. StartDate: startDateTime,
  756. EndDate: endDateTime,
  757. }
  758. dateList = append(dateList, tmp)
  759. }
  760. }
  761. // 根据日期,获取数据
  762. for _, v := range dateList {
  763. for _, vv := range dataList {
  764. dataTimeT, _ := time.ParseInLocation(utils.FormatDate, vv.DataTime, time.Local)
  765. if dataTimeT.After(v.StartDate) && dataTimeT.Before(v.EndDate) ||
  766. dataTimeT.Equal(v.StartDate) ||
  767. dataTimeT.Equal(v.EndDate) {
  768. v.DataList = append(v.DataList, vv)
  769. }
  770. }
  771. }
  772. // 根据时间区间类型来获取数据的计算窗口,然后再拼接成整段数据
  773. newDataList, err = HandleRangeAnalysisDataByCalculateType(dateList, dataList, calculateFormula)
  774. if err != nil {
  775. return
  776. }
  777. if calculateFormula.UnNormalDataDealType > 0 {
  778. switch calculateFormula.UnNormalDataDealType { //0:不处理,1:剔除,2替换
  779. case 1:
  780. dealDataList := make([]*EdbInfoSearchData, 0)
  781. for _, v := range newDataList {
  782. if !utils.CompareFloatByOpStrings(calculateFormula.UnNormalDataConf.Formula, v.Value, calculateFormula.UnNormalDataConf.Value) {
  783. dealDataList = append(dealDataList, v)
  784. }
  785. }
  786. case 2:
  787. for i, v := range newDataList {
  788. if utils.CompareFloatByOpStrings(calculateFormula.UnNormalDataConf.Formula, v.Value, calculateFormula.UnNormalDataConf.Value) {
  789. newDataList[i].Value = calculateFormula.UnNormalDataConf.ReplaceValue
  790. }
  791. }
  792. }
  793. }
  794. if calculateFormula.DataConvertType > 0 {
  795. // 数据转换类型 0不转, 1乘 2除 3对数
  796. switch calculateFormula.DataConvertType {
  797. case 1:
  798. for i, v := range newDataList {
  799. val := v.Value * calculateFormula.DataConvertConf.Value
  800. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  801. newDataList[i].Value = val
  802. }
  803. case 2:
  804. for i, v := range newDataList {
  805. val := v.Value / calculateFormula.DataConvertConf.Value
  806. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  807. newDataList[i].Value = val
  808. }
  809. case 3:
  810. for i, v := range newDataList {
  811. if v.Value <= 0 {
  812. err = errors.New("数据中含有负数或0,无法对数运算")
  813. return
  814. }
  815. val := math.Log(v.Value) / math.Log(calculateFormula.DataConvertConf.Value)
  816. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  817. newDataList[i].Value = val
  818. }
  819. }
  820. }
  821. return
  822. }
  823. func GetEdbDateByMoveForward(startDate string, moveForward int, edbDataList []*EdbInfoSearchData) (date string) {
  824. // 根据日期进行排序
  825. index := 0
  826. length := len(edbDataList)
  827. for i := length - 1; i >= 0; i-- {
  828. item := edbDataList[i]
  829. if item.DataTime == startDate {
  830. index += 1
  831. continue
  832. }
  833. if index >= moveForward {
  834. date = item.DataTime
  835. break
  836. }
  837. if index > 0 {
  838. index += 1
  839. date = item.DataTime
  840. }
  841. }
  842. return
  843. }
  844. // HandleEdbDateChange 处理日期变换
  845. func HandleEdbDateChange(date string, dateChange []*EdbDataDateChangeConf) (newDate string, err error) {
  846. newDate = date
  847. if newDate != "" {
  848. if len(dateChange) > 0 {
  849. var dateTime time.Time
  850. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  851. if err != nil {
  852. err = fmt.Errorf("日期解析失败: %s", err.Error())
  853. return
  854. }
  855. for _, v := range dateChange {
  856. if v.ChangeType == 1 {
  857. dateTime = dateTime.AddDate(v.Year, v.Month, v.Day)
  858. newDate = dateTime.Format(utils.FormatDate)
  859. } else if v.ChangeType == 2 {
  860. newDate, err, _ = utils.HandleSystemAppointDateT(dateTime, v.FrequencyDay, v.Frequency)
  861. if err != nil {
  862. return
  863. }
  864. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  865. if err != nil {
  866. err = fmt.Errorf("日期解析失败: %s", err.Error())
  867. return
  868. }
  869. }
  870. }
  871. }
  872. }
  873. return
  874. }
  875. // GetSource 获取来源编码id
  876. func (obj CalculateRangeAnalysis) GetSource() int {
  877. return utils.DATA_SOURCE_CALCULATE_RANGEANLYSIS
  878. }
  879. // GetSourceName 获取来源名称
  880. func (obj CalculateRangeAnalysis) GetSourceName() string {
  881. return utils.DATA_SOURCE_NAME_CALCULATE_RANGEANLYSIS
  882. }
  883. // GetEdbType 获取指标类型
  884. func (obj CalculateRangeAnalysis) GetEdbType() int {
  885. return utils.CALCULATE_EDB_TYPE
  886. }