edb_data_calculate_qjjs.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  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, err := time.ParseInLocation(utils.FormatDate, currentDate, time.Local)
  322. if err != nil {
  323. err = fmt.Errorf("获取当前时间失败:%s", err.Error())
  324. return
  325. }
  326. switch req.DateRangeType {
  327. case 0:
  328. // 智能划分得到一个开始日期,和结束日期
  329. var startDateTime time.Time
  330. if req.AutoDateConf.IsAutoStartDate == 0 { //固定设置
  331. startDate := req.AutoDateConf.StartDate
  332. if startDate == "" {
  333. startDate = "2020-01-01"
  334. }
  335. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  336. } else {
  337. startConf := req.AutoDateConf.StartDateConf
  338. startDate := ""
  339. if startConf.BaseDateType == 0 { //
  340. startDate = currentDate
  341. } else if startConf.BaseDateType == 1 {
  342. startDate = time.Now().Format(utils.FormatDate)
  343. }
  344. if startConf.MoveForward > 0 {
  345. startDate = GetEdbDateByMoveForward(startDate, startConf.MoveForward, dataList)
  346. }
  347. if len(startConf.DateChange) > 0 {
  348. startDate, err = HandleEdbDateChange(startDate, startConf.DateChange)
  349. if err != nil {
  350. err = fmt.Errorf("智能划分开始日期处理失败:%s", err.Error())
  351. return
  352. }
  353. }
  354. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  355. }
  356. var calStartTime, calEndTime time.Time
  357. if currentDateTime.Before(startDateTime) {
  358. calStartTime = currentDateTime
  359. calEndTime = startDateTime
  360. } else {
  361. calStartTime = startDateTime
  362. calEndTime = currentDateTime
  363. }
  364. // 根据日期,获取数据
  365. for _, vv := range dataList {
  366. dataTimeT, _ := time.ParseInLocation(utils.FormatDate, vv.DataTime, time.Local)
  367. if dataTimeT.After(calStartTime) && dataTimeT.Before(calEndTime) ||
  368. dataTimeT.Equal(calStartTime) ||
  369. dataTimeT.Equal(calEndTime) {
  370. newDataList = append(newDataList, vv)
  371. }
  372. }
  373. }
  374. return
  375. }
  376. // HandleDataByCalculateType 根据计算公式处理数据
  377. func HandleRangeAnalysisDataByCalculateType(originList []*ChartRangeAnalysisDateDataItem, originDataList []*EdbInfoSearchData, req RangeAnalysisCalculateFormula) (newList []*EdbInfoSearchData, err error) {
  378. if len(originList) == 0 {
  379. return
  380. }
  381. calculateType := req.CalculateType
  382. switch calculateType {
  383. case 0: //均值
  384. var sum float64
  385. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  386. for _, item := range originList {
  387. for _, v := range item.DataList {
  388. sum = 0
  389. //计算的数据返回需要重新确定
  390. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  391. if e != nil {
  392. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  393. return
  394. }
  395. for _, vv := range calDataList {
  396. sum += vv.Value
  397. }
  398. val := sum / float64(len(calDataList))
  399. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  400. newList = append(newList, &EdbInfoSearchData{
  401. DataTime: v.DataTime,
  402. Value: val,
  403. DataTimestamp: v.DataTimestamp,
  404. })
  405. }
  406. }
  407. } else {
  408. for _, item := range originList {
  409. sum = 0
  410. for k, v := range item.DataList {
  411. sum += v.Value
  412. val := sum / float64(k+1)
  413. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  414. newList = append(newList, &EdbInfoSearchData{
  415. DataTime: v.DataTime,
  416. Value: val,
  417. DataTimestamp: v.DataTimestamp,
  418. })
  419. }
  420. }
  421. }
  422. case 1: //累计值
  423. var sum float64
  424. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  425. for _, item := range originList {
  426. sum = 0
  427. for _, v := range item.DataList {
  428. sum = 0
  429. //计算的数据返回需要重新确定
  430. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  431. if e != nil {
  432. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  433. return
  434. }
  435. for _, vv := range calDataList {
  436. sum += vv.Value
  437. }
  438. val := sum
  439. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  440. newList = append(newList, &EdbInfoSearchData{
  441. DataTime: v.DataTime,
  442. Value: val,
  443. DataTimestamp: v.DataTimestamp,
  444. })
  445. }
  446. }
  447. } else {
  448. for _, item := range originList {
  449. sum = 0
  450. for _, v := range item.DataList {
  451. sum += v.Value
  452. val := sum
  453. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  454. newList = append(newList, &EdbInfoSearchData{
  455. DataTime: v.DataTime,
  456. Value: val,
  457. DataTimestamp: v.DataTimestamp,
  458. })
  459. }
  460. }
  461. }
  462. case 2: //涨幅
  463. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  464. for _, item := range originList {
  465. for _, v := range item.DataList {
  466. var baseVal float64
  467. //计算的数据返回需要重新确定
  468. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  469. if e != nil {
  470. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  471. return
  472. }
  473. if len(calDataList) == 0 {
  474. continue
  475. }
  476. baseVal = calDataList[0].Value
  477. baseDate := calDataList[0].DataTime
  478. if baseVal == 0 {
  479. continue
  480. }
  481. if v.DataTime == baseDate {
  482. continue
  483. }
  484. val := (v.Value - baseVal) / baseVal
  485. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  486. newList = append(newList, &EdbInfoSearchData{
  487. DataTime: v.DataTime,
  488. Value: val,
  489. DataTimestamp: v.DataTimestamp,
  490. })
  491. }
  492. }
  493. } else {
  494. for _, item := range originList {
  495. if len(item.DataList) == 0 {
  496. break
  497. }
  498. baseVal := item.DataList[0].Value
  499. baseDate := item.DataList[0].DataTime
  500. if baseVal == 0 {
  501. break
  502. }
  503. for _, v := range item.DataList {
  504. if v.DataTime == baseDate {
  505. continue
  506. }
  507. val := (v.Value - baseVal) / baseVal
  508. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  509. newList = append(newList, &EdbInfoSearchData{
  510. DataTime: v.DataTime,
  511. Value: val,
  512. DataTimestamp: v.DataTimestamp,
  513. })
  514. }
  515. }
  516. }
  517. case 3: //复合增长率
  518. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  519. for _, item := range originList {
  520. for _, v := range item.DataList {
  521. var baseVal float64
  522. var baseDate string
  523. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  524. if e != nil {
  525. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  526. return
  527. }
  528. if len(calDataList) == 0 {
  529. continue
  530. }
  531. baseVal = calDataList[0].Value
  532. baseDate = calDataList[0].DataTime
  533. if v.DataTime == baseDate {
  534. continue
  535. }
  536. if baseVal == 0 {
  537. continue
  538. }
  539. baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
  540. if e != nil {
  541. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  542. return
  543. }
  544. tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  545. if e != nil {
  546. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  547. return
  548. }
  549. // 计算两个日期相差的天数
  550. diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
  551. val := v.Value / baseVal
  552. val = math.Pow(val, 1/diff) - 1
  553. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  554. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  555. }
  556. }
  557. } else {
  558. for _, item := range originList {
  559. if len(item.DataList) == 0 {
  560. break
  561. }
  562. baseVal := item.DataList[0].Value
  563. baseDate := item.DataList[0].DataTime
  564. if baseVal == 0 {
  565. break
  566. }
  567. for _, v := range item.DataList {
  568. if v.DataTime == baseDate {
  569. continue
  570. }
  571. baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
  572. if e != nil {
  573. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  574. return
  575. }
  576. tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  577. if e != nil {
  578. err = fmt.Errorf("time.ParseInLocation err: %v", e)
  579. return
  580. }
  581. // 计算两个日期相差的天数
  582. diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
  583. val := v.Value / baseVal
  584. val = math.Pow(val, 1/diff) - 1
  585. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  586. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  587. }
  588. }
  589. }
  590. case 4: //最大值
  591. var maxVal float64
  592. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  593. for _, item := range originList {
  594. for _, v := range item.DataList {
  595. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  596. if e != nil {
  597. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  598. return
  599. }
  600. for kk, vv := range calDataList {
  601. if kk == 0 {
  602. maxVal = vv.Value
  603. }
  604. if vv.Value > maxVal {
  605. maxVal = vv.Value
  606. }
  607. }
  608. val := maxVal
  609. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  610. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  611. }
  612. }
  613. } else {
  614. for _, item := range originList {
  615. for k, v := range item.DataList {
  616. if k == 0 {
  617. maxVal = v.Value
  618. }
  619. if v.Value > maxVal {
  620. maxVal = v.Value
  621. }
  622. val := maxVal
  623. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  624. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  625. }
  626. }
  627. }
  628. case 5: //最小值
  629. var minVal float64
  630. if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
  631. for _, item := range originList {
  632. for _, v := range item.DataList {
  633. calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
  634. if e != nil {
  635. err = fmt.Errorf("获取区间数据失败:%s", e.Error())
  636. return
  637. }
  638. for kk, vv := range calDataList {
  639. if kk == 0 {
  640. minVal = vv.Value
  641. }
  642. if vv.Value < minVal {
  643. minVal = vv.Value
  644. }
  645. }
  646. val := minVal
  647. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  648. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  649. }
  650. }
  651. } else {
  652. for _, item := range originList {
  653. for k, v := range item.DataList {
  654. if k == 0 {
  655. minVal = v.Value
  656. }
  657. if v.Value < minVal {
  658. minVal = v.Value
  659. }
  660. val := minVal
  661. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  662. newList = append(newList, &EdbInfoSearchData{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
  663. }
  664. }
  665. }
  666. }
  667. return
  668. }
  669. // GetRangeAnalysisChartDataByEdbInfo 区间计算
  670. func GetRangeAnalysisChartDataByEdbInfo(fromEdbInfo *EdbInfo, calculateFormula RangeAnalysisCalculateFormula) (newDataList []*EdbInfoSearchData, err error) {
  671. // 指标的开始日期和结束日期
  672. edbStartDateTime, err := time.ParseInLocation(utils.FormatDate, fromEdbInfo.StartDate, time.Local)
  673. if err != nil {
  674. err = fmt.Errorf("指标开始日期解析失败:%s", err.Error())
  675. return
  676. }
  677. edbEndDateTime, err := time.ParseInLocation(utils.FormatDate, fromEdbInfo.EndDate, time.Local)
  678. if err != nil {
  679. err = fmt.Errorf("指标结束日期解析失败:%s", err.Error())
  680. return
  681. }
  682. edbEndDate := edbEndDateTime.Format(utils.FormatDate)
  683. // 获取时间基准指标在时间区间内的值
  684. dataList := make([]*EdbInfoSearchData, 0)
  685. switch fromEdbInfo.EdbInfoType {
  686. case 0:
  687. //获取来源指标的数据
  688. dataList, err = GetEdbDataListAll(fromEdbInfo.Source, fromEdbInfo.SubSource,
  689. FindEdbDataListAllCond{
  690. EdbInfoId: fromEdbInfo.EdbInfoId,
  691. }, 1)
  692. case 1:
  693. dataList, err = GetPredictEdbDataListAllByStartDate(fromEdbInfo, 1, "")
  694. default:
  695. err = errors.New(fmt.Sprint("获取失败,指标base类型异常", fromEdbInfo.EdbInfoType))
  696. return
  697. }
  698. if err != nil {
  699. err = fmt.Errorf("获取时间基准指标在时间区间内的值失败,Err:" + err.Error())
  700. return
  701. }
  702. dateList := make([]*ChartRangeAnalysisDateDataItem, 0)
  703. switch calculateFormula.DateRangeType {
  704. case 0:
  705. // 智能划分得到一个开始日期,和结束日期
  706. var startDateTime, endDateTime time.Time
  707. startDateTime = edbStartDateTime
  708. if calculateFormula.AutoDateConf.IsAutoStartDate == 0 { //固定设置
  709. startDate := calculateFormula.AutoDateConf.StartDate
  710. if startDate == "" {
  711. startDate = "2020-01-01"
  712. }
  713. startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  714. }
  715. if calculateFormula.AutoDateConf.IsAutoEndDate == 0 { //固定设置
  716. endDate := calculateFormula.AutoDateConf.EndDate
  717. if endDate == "" {
  718. err = fmt.Errorf("智能划分截止日期处理失败:请输入截止日期")
  719. return
  720. }
  721. // todo 如果截止日期比指标日期还要大,则用指标的最新日期
  722. endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  723. } else {
  724. endConf := calculateFormula.AutoDateConf.EndDateConf
  725. endDate := edbEndDate
  726. if endConf.MoveForward > 0 {
  727. endDate = GetEdbDateByMoveForward(endDate, endConf.MoveForward, dataList)
  728. }
  729. if len(endConf.DateChange) > 0 {
  730. endDate, err = HandleEdbDateChange(endDate, endConf.DateChange)
  731. if err != nil {
  732. err = fmt.Errorf("智能划分结束日期处理失败:%s", err.Error())
  733. return
  734. }
  735. }
  736. endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  737. }
  738. dateList = append(dateList, &ChartRangeAnalysisDateDataItem{
  739. StartDate: startDateTime,
  740. EndDate: endDateTime})
  741. case 1:
  742. // 手工划分得到多个开始日期和结束日期(已排序)
  743. for _, v := range calculateFormula.ManualDateConf {
  744. startDateT, _ := time.ParseInLocation(utils.FormatDate, v.StartDate, time.Local)
  745. endDateT, _ := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  746. tmp := &ChartRangeAnalysisDateDataItem{
  747. StartDate: startDateT,
  748. EndDate: endDateT,
  749. }
  750. dateList = append(dateList, tmp)
  751. }
  752. case 2:
  753. // 跨年划分得到多个开始日期和结束日期
  754. startYear := edbStartDateTime.Year()
  755. endYear := edbEndDateTime.Year()
  756. startDay := calculateFormula.YearDateConf.StartDay
  757. endDay := calculateFormula.YearDateConf.EndDay
  758. for year := startYear; year <= endYear; year++ {
  759. startDate := fmt.Sprintf("%d-%s", year, startDay)
  760. endDate := fmt.Sprintf("%d-%s", year+1, endDay)
  761. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  762. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  763. if startDateTime.Before(edbStartDateTime) {
  764. break
  765. }
  766. tmp := &ChartRangeAnalysisDateDataItem{
  767. StartDate: startDateTime,
  768. EndDate: endDateTime,
  769. }
  770. dateList = append(dateList, tmp)
  771. }
  772. }
  773. // 根据日期,获取数据
  774. for _, v := range dateList {
  775. for _, vv := range dataList {
  776. dataTimeT, _ := time.ParseInLocation(utils.FormatDate, vv.DataTime, time.Local)
  777. if dataTimeT.After(v.StartDate) && dataTimeT.Before(v.EndDate) ||
  778. dataTimeT.Equal(v.StartDate) ||
  779. dataTimeT.Equal(v.EndDate) {
  780. v.DataList = append(v.DataList, vv)
  781. }
  782. }
  783. }
  784. // 根据时间区间类型来获取数据的计算窗口,然后再拼接成整段数据
  785. newDataList, err = HandleRangeAnalysisDataByCalculateType(dateList, dataList, calculateFormula)
  786. if err != nil {
  787. return
  788. }
  789. if calculateFormula.UnNormalDataDealType > 0 {
  790. switch calculateFormula.UnNormalDataDealType { //0:不处理,1:剔除,2替换
  791. case 1:
  792. dealDataList := make([]*EdbInfoSearchData, 0)
  793. for _, v := range newDataList {
  794. if !utils.CompareFloatByOpStrings(calculateFormula.UnNormalDataConf.Formula, v.Value, calculateFormula.UnNormalDataConf.Value) {
  795. dealDataList = append(dealDataList, v)
  796. }
  797. }
  798. case 2:
  799. for i, v := range newDataList {
  800. if utils.CompareFloatByOpStrings(calculateFormula.UnNormalDataConf.Formula, v.Value, calculateFormula.UnNormalDataConf.Value) {
  801. newDataList[i].Value = calculateFormula.UnNormalDataConf.ReplaceValue
  802. }
  803. }
  804. }
  805. }
  806. if calculateFormula.DataConvertType > 0 {
  807. // 数据转换类型 0不转, 1乘 2除 3对数
  808. switch calculateFormula.DataConvertType {
  809. case 1:
  810. for i, v := range newDataList {
  811. val := v.Value * calculateFormula.DataConvertConf.Value
  812. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  813. newDataList[i].Value = val
  814. }
  815. case 2:
  816. for i, v := range newDataList {
  817. val := v.Value / calculateFormula.DataConvertConf.Value
  818. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  819. newDataList[i].Value = val
  820. }
  821. case 3:
  822. for i, v := range newDataList {
  823. if v.Value <= 0 {
  824. err = errors.New("数据中含有负数或0,无法对数运算")
  825. return
  826. }
  827. val := math.Log(v.Value) / math.Log(calculateFormula.DataConvertConf.Value)
  828. val, _ = decimal.NewFromFloat(val).Round(4).Float64()
  829. newDataList[i].Value = val
  830. }
  831. }
  832. }
  833. return
  834. }
  835. func GetEdbDateByMoveForward(startDate string, moveForward int, edbDataList []*EdbInfoSearchData) (date string) {
  836. // 根据日期进行排序
  837. index := 0
  838. length := len(edbDataList)
  839. for i := length - 1; i >= 0; i-- {
  840. item := edbDataList[i]
  841. if item.DataTime == startDate {
  842. index += 1
  843. continue
  844. }
  845. if index >= moveForward {
  846. date = item.DataTime
  847. break
  848. }
  849. if index > 0 {
  850. index += 1
  851. date = item.DataTime
  852. }
  853. }
  854. return
  855. }
  856. // HandleEdbDateChange 处理日期变换
  857. func HandleEdbDateChange(date string, dateChange []*EdbDataDateChangeConf) (newDate string, err error) {
  858. newDate = date
  859. if newDate != "" {
  860. if len(dateChange) > 0 {
  861. var dateTime time.Time
  862. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  863. if err != nil {
  864. err = fmt.Errorf("日期解析失败: %s", err.Error())
  865. return
  866. }
  867. for _, v := range dateChange {
  868. if v.ChangeType == 1 {
  869. dateTime = dateTime.AddDate(v.Year, v.Month, v.Day)
  870. newDate = dateTime.Format(utils.FormatDate)
  871. } else if v.ChangeType == 2 {
  872. newDate, err, _ = utils.HandleSystemAppointDateT(dateTime, v.FrequencyDay, v.Frequency)
  873. if err != nil {
  874. return
  875. }
  876. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  877. if err != nil {
  878. err = fmt.Errorf("日期解析失败: %s", err.Error())
  879. return
  880. }
  881. }
  882. }
  883. }
  884. }
  885. return
  886. }
  887. // GetSource 获取来源编码id
  888. func (obj CalculateRangeAnalysis) GetSource() int {
  889. return utils.DATA_SOURCE_CALCULATE_RANGEANLYSIS
  890. }
  891. // GetSourceName 获取来源名称
  892. func (obj CalculateRangeAnalysis) GetSourceName() string {
  893. return utils.DATA_SOURCE_NAME_CALCULATE_RANGEANLYSIS
  894. }
  895. // GetEdbType 获取指标类型
  896. func (obj CalculateRangeAnalysis) GetEdbType() int {
  897. return utils.CALCULATE_EDB_TYPE
  898. }