edb_data.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. package services
  2. import (
  3. "eta/eta_forum_hub/models"
  4. "eta/eta_forum_hub/models/mgodb"
  5. "eta/eta_forum_hub/utils"
  6. "fmt"
  7. "github.com/shopspring/decimal"
  8. "strconv"
  9. "time"
  10. )
  11. func BatchAddOrUpdateEdbData(req []*models.AddEdbDataReq) (err error) {
  12. for _, reqData := range req {
  13. if reqData.EdbType == 1 {
  14. err = AddOrUpdateEdbData(reqData.EdbCode, reqData.DataList)
  15. if err != nil {
  16. return
  17. }
  18. } else {
  19. err = AddOrUpdateEdbDataCalculate(reqData.EdbCode, reqData.DataList)
  20. if err != nil {
  21. return
  22. }
  23. }
  24. }
  25. return
  26. }
  27. func AddOrUpdateEdbData(edbCode string, dataList []*models.EdbDataBase) (err error) {
  28. addList := make([]interface{}, 0)
  29. existList, err := mgodb.GetEdbDataBaseByEdbCode(edbCode)
  30. if err != nil {
  31. err = fmt.Errorf("查询指标数据出错 error, %v", err)
  32. return
  33. }
  34. existMap := make(map[string]*mgodb.EdbDataBase, len(existList))
  35. deleteMap := make(map[string]struct{}, len(existList))
  36. for _, exist := range existList {
  37. tmp := exist.DataTime.Format(utils.FormatDate)
  38. existMap[tmp] = exist
  39. deleteMap[tmp] = struct{}{}
  40. }
  41. for _, v := range dataList {
  42. dataTime, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  43. if e != nil {
  44. err = fmt.Errorf("时间格式化出错 error, %v", e)
  45. return
  46. }
  47. val, e := strconv.ParseFloat(v.Value, 64)
  48. if e != nil {
  49. err = fmt.Errorf("指标数据格式化出错 error, %v", e)
  50. return
  51. }
  52. if oldObj, ok := existMap[v.DataTime]; !ok {
  53. tmp := &mgodb.EdbDataBase{
  54. EdbInfoId: 0,
  55. EdbCode: v.EdbCode,
  56. DataTime: dataTime,
  57. Value: val,
  58. Status: v.Status,
  59. CreateTime: time.Now(),
  60. ModifyTime: time.Now(),
  61. DataTimestamp: v.DataTimestamp,
  62. }
  63. addList = append(addList, tmp)
  64. if len(addList) >= 500 {
  65. err = mgodb.InsertEdbDataBatch(addList)
  66. if err != nil {
  67. err = fmt.Errorf("批量新增指标数据失败 error, %v", e)
  68. return
  69. }
  70. addList = make([]interface{}, 0)
  71. }
  72. } else {
  73. delete(deleteMap, v.DataTime)
  74. if val != oldObj.Value {
  75. err = mgodb.ModifyValueEdbDataValue(oldObj.EdbDataId, val)
  76. if err != nil {
  77. err = fmt.Errorf("更新指标数据出错 error, %v", err)
  78. return
  79. }
  80. }
  81. }
  82. }
  83. //遍历deletemap,找出需要删除的日期
  84. {
  85. removeDateList := make([]time.Time, 0)
  86. for dateTime := range deleteMap {
  87. dateT, e := time.ParseInLocation(utils.FormatDate, dateTime, time.Local)
  88. if e != nil {
  89. err = fmt.Errorf("日期格式错误 error, %v", e)
  90. return
  91. }
  92. removeDateList = append(removeDateList, dateT)
  93. }
  94. removeNum := len(removeDateList)
  95. if removeNum > 0 {
  96. err = mgodb.DeleteEdbInfoDataByEdbInfoIdAndDate(edbCode, removeDateList)
  97. if err != nil {
  98. err = fmt.Errorf("删除多余日期失败,error, %v", err)
  99. return
  100. }
  101. }
  102. }
  103. if len(addList) > 0 {
  104. err = mgodb.InsertEdbDataBatch(addList)
  105. }
  106. return
  107. }
  108. func AddOrUpdateEdbDataCalculate(edbCode string, dataList []*models.EdbDataBase) (err error) {
  109. addList := make([]interface{}, 0)
  110. existList, err := mgodb.GetEdbDataCalculateByEdbCode(edbCode)
  111. if err != nil {
  112. err = fmt.Errorf("查询指标数据出错 error, %v", err)
  113. return
  114. }
  115. existMap := make(map[string]*mgodb.EdbDataBase, len(existList))
  116. deleteMap := make(map[string]struct{}, len(existList))
  117. for _, exist := range existList {
  118. tmp := exist.DataTime.Format(utils.FormatDate)
  119. existMap[tmp] = exist
  120. deleteMap[tmp] = struct{}{}
  121. }
  122. for _, v := range dataList {
  123. dataTime, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  124. if e != nil {
  125. err = fmt.Errorf("时间格式化出错 error, %v", e)
  126. return
  127. }
  128. val, e := strconv.ParseFloat(v.Value, 64)
  129. if e != nil {
  130. err = fmt.Errorf("指标数据格式化出错 error, %v", e)
  131. return
  132. }
  133. if oldObj, ok := existMap[v.DataTime]; !ok {
  134. tmp := &mgodb.EdbDataBase{
  135. EdbInfoId: 0,
  136. EdbCode: v.EdbCode,
  137. DataTime: dataTime,
  138. Value: val,
  139. Status: v.Status,
  140. CreateTime: time.Now(),
  141. ModifyTime: time.Now(),
  142. DataTimestamp: v.DataTimestamp,
  143. }
  144. addList = append(addList, tmp)
  145. if len(addList) >= 500 {
  146. err = mgodb.InsertEdbCalculateDataBatch(addList)
  147. if err != nil {
  148. err = fmt.Errorf("批量新增指标数据失败 error, %v", e)
  149. return
  150. }
  151. addList = make([]interface{}, 0)
  152. }
  153. } else {
  154. delete(deleteMap, v.DataTime)
  155. if val != oldObj.Value {
  156. err = mgodb.ModifyValueEdbCalculateDataValue(oldObj.EdbDataId, val)
  157. if err != nil {
  158. err = fmt.Errorf("更新指标数据出错 error, %v", err)
  159. return
  160. }
  161. }
  162. }
  163. }
  164. //遍历deleteMap,找出需要删除的日期
  165. {
  166. removeDateList := make([]time.Time, 0)
  167. for dateTime := range deleteMap {
  168. dateT, e := time.ParseInLocation(utils.FormatDate, dateTime, time.Local)
  169. if e != nil {
  170. err = fmt.Errorf("日期格式错误 error, %v", e)
  171. return
  172. }
  173. removeDateList = append(removeDateList, dateT)
  174. }
  175. removeNum := len(removeDateList)
  176. if removeNum > 0 {
  177. err = mgodb.DeleteEdbCalculateDataByEdbInfoIdAndDate(edbCode, removeDateList)
  178. if err != nil {
  179. err = fmt.Errorf("删除多余日期失败,error, %v", err)
  180. return
  181. }
  182. }
  183. }
  184. if len(addList) > 0 {
  185. err = mgodb.InsertEdbCalculateDataBatch(addList)
  186. }
  187. return
  188. }
  189. // GetEdbDataList 获取指标的数据(日期正序返回)
  190. func GetEdbDataList(endInfoId, edbType int, startDate, endDate string) (list []*models.EdbDataList, err error) {
  191. dataList := make([]*mgodb.EdbDataBase, 0)
  192. var startDateT, endDateT time.Time
  193. if startDate != "" {
  194. startDateT, err = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  195. if err != nil {
  196. err = fmt.Errorf("日期格式错误 error, %v", err)
  197. return
  198. }
  199. }
  200. if endDate != "" {
  201. endDateT, err = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  202. if err != nil {
  203. err = fmt.Errorf("日期格式错误 error, %v", err)
  204. return
  205. }
  206. }
  207. if edbType == 1 {
  208. dataList, err = mgodb.GetEdbDataList(endInfoId, startDateT, endDateT)
  209. if err != nil {
  210. err = fmt.Errorf("查询指标数据出错 error, %v", err)
  211. return
  212. }
  213. } else {
  214. dataList, err = mgodb.GetEdbCalculateDataList(endInfoId, startDateT, endDateT)
  215. if err != nil {
  216. err = fmt.Errorf("查询指标数据出错 error, %v", err)
  217. return
  218. }
  219. }
  220. list = make([]*models.EdbDataList, 0)
  221. for _, v := range dataList {
  222. // 字符串转成浮点数
  223. list = append(list, &models.EdbDataList{
  224. EdbInfoId: v.EdbInfoId,
  225. DataTime: v.DataTime.Format(utils.FormatDate),
  226. DataTimestamp: v.DataTimestamp,
  227. Value: v.Value,
  228. },
  229. )
  230. }
  231. return
  232. }
  233. // TbzDiv 同比值计算
  234. func TbzDiv(a, b float64) float64 {
  235. var valFloat float64
  236. if b != 0 {
  237. af := decimal.NewFromFloat(a)
  238. bf := decimal.NewFromFloat(b)
  239. val, _ := af.Div(bf).Float64()
  240. val = val - 1
  241. valFloat, _ = decimal.NewFromFloat(val).RoundCeil(4).Float64()
  242. } else {
  243. valFloat = 0
  244. }
  245. return valFloat
  246. }
  247. // GetEdbDataTbzForSeason 获取指标的同比值数据
  248. func GetEdbDataTbzForSeason(frequency string, tmpDataList []*models.EdbDataList, startDateTime time.Time) (dataList []*models.EdbDataList, minValue, maxValue float64, err error) {
  249. dataList = make([]*models.EdbDataList, 0)
  250. // 数据处理
  251. var dateArr []string
  252. dataMap := make(map[string]*models.EdbDataList)
  253. for _, v := range tmpDataList {
  254. dateArr = append(dateArr, v.DataTime)
  255. dataMap[v.DataTime] = v
  256. }
  257. for _, av := range dateArr {
  258. currentItem, ok := dataMap[av]
  259. // 如果找不到当前日期的数据,那么终止当前循环,进入下一循环
  260. if !ok {
  261. continue
  262. }
  263. tmpItem := *currentItem
  264. var isOk bool //是否计算出来结果
  265. //当前日期
  266. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
  267. if tmpErr != nil {
  268. err = tmpErr
  269. return
  270. }
  271. // 如果存在开始日期,同时,当前日期早于开始日期,那么终止当前循环,进入下一循环
  272. if !startDateTime.IsZero() && currentDate.Before(startDateTime) {
  273. continue
  274. }
  275. //上一年的日期
  276. preDate := currentDate.AddDate(-1, 0, 0)
  277. preDateStr := preDate.Format(utils.FormatDate)
  278. if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
  279. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  280. isOk = true
  281. } else {
  282. if frequency == "月度" { //向上和向下,各找一个月
  283. for i := 0; i <= 35; i++ {
  284. nextDateDay := preDate.AddDate(0, 0, i)
  285. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  286. if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  287. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  288. isOk = true
  289. break
  290. } else {
  291. preDateDay := preDate.AddDate(0, 0, -i)
  292. preDateDayStr := preDateDay.Format(utils.FormatDate)
  293. if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  294. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  295. isOk = true
  296. break
  297. }
  298. }
  299. }
  300. } else if frequency == "季度" || frequency == "年度" {
  301. if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
  302. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  303. isOk = true
  304. break
  305. }
  306. } else {
  307. nextDateDay := preDate.AddDate(0, 0, 1)
  308. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  309. preDateDay := preDate.AddDate(0, 0, -1)
  310. preDateDayStr := preDateDay.Format(utils.FormatDate)
  311. for i := 0; i < 35; i++ {
  312. if i >= 1 {
  313. nextDateDay = nextDateDay.AddDate(0, 0, i)
  314. nextDateDayStr = nextDateDay.Format(utils.FormatDate)
  315. }
  316. if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  317. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  318. isOk = true
  319. break
  320. } else {
  321. if i >= 1 {
  322. preDateDay = preDate.AddDate(0, 0, -i)
  323. preDateDayStr = nextDateDay.Format(utils.FormatDate)
  324. }
  325. if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  326. tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
  327. isOk = true
  328. break
  329. }
  330. }
  331. }
  332. }
  333. }
  334. if isOk {
  335. if tmpItem.Value > maxValue {
  336. maxValue = tmpItem.Value
  337. }
  338. if tmpItem.Value < minValue {
  339. minValue = tmpItem.Value
  340. }
  341. dataList = append(dataList, &tmpItem)
  342. }
  343. }
  344. return
  345. }