predict_edb_data_calculate_jp.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. package models
  2. import (
  3. "errors"
  4. "eta_gn/eta_index_lib/global"
  5. "eta_gn/eta_index_lib/utils"
  6. "fmt"
  7. "gorm.io/gorm"
  8. "github.com/shopspring/decimal"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. // SavePredictCalculateJp 预测降频值
  14. func SavePredictCalculateJp(reqEdbInfoId, classifyId int, edbName, frequency, unit, formula string, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName, lang string) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error, errMsg string) {
  15. to := global.DEFAULT_DmSQL.Begin()
  16. defer func() {
  17. if err != nil {
  18. to.Rollback()
  19. } else {
  20. to.Commit()
  21. }
  22. }()
  23. fmt.Println("reqEdbInfoId:", reqEdbInfoId)
  24. if reqEdbInfoId <= 0 {
  25. edbInfo = &EdbInfo{
  26. //EdbInfoId: 0,
  27. EdbInfoType: 1,
  28. SourceName: utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_JP,
  29. Source: utils.DATA_SOURCE_PREDICT_CALCULATE_JP,
  30. EdbCode: edbCode,
  31. EdbName: edbName,
  32. EdbNameSource: edbName,
  33. Frequency: frequency,
  34. Unit: unit,
  35. //StartDate: "",
  36. //EndDate: "",
  37. ClassifyId: classifyId,
  38. SysUserId: sysUserId,
  39. SysUserRealName: sysUserRealName,
  40. UniqueCode: uniqueCode,
  41. CreateTime: time.Now(),
  42. ModifyTime: time.Now(),
  43. MinValue: 0,
  44. MaxValue: 0,
  45. CalculateFormula: formula,
  46. EdbType: 2,
  47. Sort: GetAddEdbMaxSortByClassifyId(classifyId, utils.PREDICT_EDB_INFO_TYPE),
  48. MoveType: 0,
  49. MoveFrequency: "",
  50. NoUpdate: 0,
  51. ServerUrl: "",
  52. EdbNameEn: edbName,
  53. UnitEn: unit,
  54. LatestDate: "",
  55. LatestValue: 0,
  56. ChartImage: "",
  57. }
  58. tmpErr := to.Create(edbInfo).Error
  59. if tmpErr != nil {
  60. err = tmpErr
  61. return
  62. }
  63. // 添加关联关系
  64. {
  65. calculateMappingItem := &EdbInfoCalculateMapping{
  66. EdbInfoCalculateMappingId: 0,
  67. EdbInfoId: edbInfo.EdbInfoId,
  68. Source: edbInfo.Source,
  69. SourceName: edbInfo.SourceName,
  70. EdbCode: edbCode,
  71. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  72. FromEdbCode: fromEdbInfo.EdbCode,
  73. FromEdbName: fromEdbInfo.EdbName,
  74. FromSource: fromEdbInfo.Source,
  75. FromSourceName: fromEdbInfo.SourceName,
  76. FromTag: "",
  77. Sort: 1,
  78. CreateTime: time.Now(),
  79. ModifyTime: time.Now(),
  80. }
  81. err = to.Create(calculateMappingItem).Error
  82. if err != nil {
  83. return
  84. }
  85. }
  86. } else {
  87. edbInfo, err = GetEdbInfoById(reqEdbInfoId)
  88. if err != nil {
  89. if err.Error() == utils.ErrNoRow() {
  90. errMsg = `获取指标信息失败`
  91. }
  92. return
  93. }
  94. if edbInfo.EdbInfoType != 1 {
  95. errMsg = `该指标不是预测指标`
  96. err = errors.New(errMsg)
  97. return
  98. }
  99. latestDateStr = edbInfo.LatestDate
  100. latestValue = edbInfo.LatestValue
  101. oldCalculateFormula := edbInfo.CalculateFormula
  102. //修改指标信息
  103. switch lang {
  104. case utils.EnLangVersion:
  105. edbInfo.EdbNameEn = edbName
  106. edbInfo.UnitEn = unit
  107. default:
  108. edbInfo.EdbName = edbName
  109. edbInfo.Unit = unit
  110. edbInfo.EdbNameSource = edbName
  111. }
  112. edbInfo.Frequency = frequency
  113. edbInfo.ClassifyId = classifyId
  114. edbInfo.CalculateFormula = formula
  115. edbInfo.ModifyTime = time.Now()
  116. err = to.Model(edbInfo).Select([]string{"EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EdbNameEn", "UnitEn"}).Updates(edbInfo).Error
  117. if err != nil {
  118. return
  119. }
  120. //判断计算指标是否被更换
  121. var existCondition string
  122. var existPars []interface{}
  123. existCondition += " AND edb_info_id=? AND from_edb_info_id=? "
  124. existPars = append(existPars, edbInfo.EdbInfoId, fromEdbInfo.EdbInfoId)
  125. count, tmpErr := GetEdbInfoCalculateCountByCondition(existCondition, existPars)
  126. if tmpErr != nil {
  127. err = errors.New("判断指标是否改变失败,Err:" + tmpErr.Error())
  128. return
  129. }
  130. if count > 0 && formula == oldCalculateFormula { // 指标未被替换,无需重新计算
  131. return
  132. }
  133. //删除,计算指标关联的,基础指标的关联关系
  134. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
  135. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  136. if err != nil {
  137. err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
  138. return
  139. }
  140. //清空原有已经入库的数据
  141. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  142. sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
  143. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  144. if err != nil {
  145. return
  146. }
  147. //关联关系
  148. {
  149. calculateMappingItem := &EdbInfoCalculateMapping{
  150. EdbInfoCalculateMappingId: 0,
  151. EdbInfoId: edbInfo.EdbInfoId,
  152. Source: edbInfo.Source,
  153. SourceName: edbInfo.SourceName,
  154. EdbCode: edbCode,
  155. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  156. FromEdbCode: fromEdbInfo.EdbCode,
  157. FromEdbName: fromEdbInfo.EdbName,
  158. FromSource: fromEdbInfo.Source,
  159. FromSourceName: fromEdbInfo.SourceName,
  160. FromTag: "",
  161. Sort: 1,
  162. CreateTime: time.Now(),
  163. ModifyTime: time.Now(),
  164. }
  165. err = to.Create(calculateMappingItem).Error
  166. if err != nil {
  167. return
  168. }
  169. }
  170. }
  171. // 计算数据
  172. latestDateStr, latestValue, err = refreshAllPredictCalculateJp(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbCode, edbInfo.Frequency, formula)
  173. return
  174. }
  175. // RefreshAllPredictCalculateJp 刷新全部预测降频值数据
  176. func RefreshAllPredictCalculateJp(edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode, edbFrequency, formula string) (latestDateStr string, latestValue float64, err error) {
  177. to := global.DEFAULT_DmSQL.Begin()
  178. defer func() {
  179. if err != nil {
  180. to.Rollback()
  181. } else {
  182. to.Commit()
  183. }
  184. }()
  185. // 计算数据
  186. latestDateStr, latestValue, err = refreshAllPredictCalculateJp(to, edbInfoId, source, subSource, fromEdbInfo, edbCode, edbFrequency, formula)
  187. return
  188. }
  189. // refreshAllPredictCalculateJp 刷新预测降频数据
  190. func refreshAllPredictCalculateJp(to *gorm.DB, edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode, edbFrequency, formula string) (latestDateStr string, latestValue float64, err error) {
  191. edbInfoIdStr := strconv.Itoa(edbInfoId)
  192. //获取源指标数据
  193. fmt.Println("EdbInfoId:", fromEdbInfo.EdbInfoId)
  194. dataList, err := GetPredictEdbDataListAll(fromEdbInfo, 1)
  195. if err != nil {
  196. return
  197. }
  198. var dateArr []string
  199. dataMap := make(map[string]*EdbInfoSearchData)
  200. fromDataMap := make(map[string]float64)
  201. //来源指指标数据
  202. for _, v := range dataList {
  203. dateArr = append(dateArr, v.DataTime)
  204. dataMap[v.DataTime] = v
  205. fromDataMap[v.DataTime] = v.Value
  206. }
  207. fmt.Println("source:", source)
  208. //获取降频指标所有数据
  209. existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source, subSource)
  210. if err != nil {
  211. return
  212. }
  213. //计算指标的map
  214. existDataMap := make(map[string]*EdbData)
  215. // 已经入库的日期map
  216. existDelDateMap := make(map[string]string)
  217. for _, v := range existDataList {
  218. existDataMap[v.DataTime] = v
  219. existDelDateMap[v.DataTime] = v.DataTime
  220. }
  221. latestDateStr = fromEdbInfo.LatestDate
  222. tableName := GetEdbDataTableName(utils.DATA_SOURCE_PREDICT_CALCULATE_JP, subSource)
  223. addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  224. var isAdd bool
  225. //existMap := make(map[string]string)
  226. dataLen := len(dataList)
  227. if dataLen <= 0 {
  228. return
  229. }
  230. startDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  231. endDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[dataLen-1].DataTime, time.Local)
  232. nextEndDate := utils.GetFrequencyEndDay(startDataTime, edbFrequency) // 下一个节点的日期
  233. weekDayDataList := make([]float64, 0)
  234. for currStartDataTime := startDataTime; !currStartDataTime.After(endDataTime); currStartDataTime = currStartDataTime.AddDate(0, 0, 1) {
  235. // 将当前数据加入到 weekDayDataList
  236. if tmpData, ok := dataMap[currStartDataTime.Format(utils.FormatDate)]; ok {
  237. tmpValue := decimal.NewFromFloat(tmpData.Value)
  238. tmpValueFloat, _ := tmpValue.Round(4).Float64()
  239. weekDayDataList = append(weekDayDataList, tmpValueFloat)
  240. }
  241. // 日期处理过滤
  242. switch edbFrequency {
  243. case "周度":
  244. if currStartDataTime.Weekday() != 0 {
  245. //不是周日,代表需要进入下一个循环获取数据并计算
  246. continue
  247. } else {
  248. //记录下一个结束节点的日期
  249. nextEndDate = currStartDataTime.AddDate(0, 0, 7)
  250. }
  251. case "旬度":
  252. nextDay := currStartDataTime.AddDate(0, 0, 1)
  253. if nextDay.Day() != 1 && nextDay.Day() != 11 && nextDay.Day() != 21 {
  254. //不是每月10、20、最后一天,代表需要进入下一个循环获取数据并计算
  255. continue
  256. } else {
  257. //记录下一个结束节点的日期
  258. if nextDay.Day() == 1 || nextDay.Day() == 11 {
  259. //月初或者月末的时候,加10天就好了
  260. nextEndDate = nextDay.AddDate(0, 0, 9)
  261. } else {
  262. tmpNextMonth := nextDay.AddDate(0, 1, 0)
  263. nextEndDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
  264. }
  265. }
  266. case "月度":
  267. nextDay := currStartDataTime.AddDate(0, 0, 1)
  268. if nextDay.Day() != 1 {
  269. //不是每月最后一天,代表需要进入下一个循环获取数据并计算
  270. continue
  271. } else {
  272. //记录下一个结束节点的日期
  273. nextEndDate = nextDay.AddDate(0, 1, -1)
  274. }
  275. case "季度":
  276. nextDay := currStartDataTime.AddDate(0, 0, 1)
  277. if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
  278. //记录下一个结束节点的日期
  279. nextEndDate = nextDay.AddDate(0, 3, -1)
  280. } else {
  281. //不是3,6,9,12 月份的最后一天,代表需要进入下一个循环获取数据并计算
  282. continue
  283. }
  284. case "年度":
  285. if currStartDataTime.Month() == 12 && currStartDataTime.Day() == 31 {
  286. //记录下一个结束节点的日期
  287. nextEndDate = currStartDataTime.AddDate(1, 0, 0)
  288. } else {
  289. //不是每年的12-31日,代表需要进入下一个循环获取数据并计算
  290. continue
  291. }
  292. default:
  293. err = errors.New("错误的频度:" + edbFrequency)
  294. return
  295. }
  296. // 本期的数据值
  297. lenWeekDayDataList := len(weekDayDataList)
  298. if lenWeekDayDataList <= 0 {
  299. continue
  300. }
  301. // 当前时间段内的数据计算,得出实际值
  302. var currVal float64
  303. if formula == "期末值" { // 期末值,取区间最后一个日期的数据值
  304. currVal = weekDayDataList[lenWeekDayDataList-1]
  305. } else {
  306. // 平均值 取区间平均值
  307. sumValDeci := decimal.NewFromFloat(0)
  308. for _, v := range weekDayDataList {
  309. tmpValDeci := decimal.NewFromFloat(v)
  310. sumValDeci = sumValDeci.Add(tmpValDeci)
  311. }
  312. lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
  313. currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
  314. }
  315. // 给实际日期数据的值赋值
  316. if fromEdbInfo.LatestDate == currStartDataTime.Format(utils.FormatDate) {
  317. latestValue = currVal
  318. }
  319. currStartDataTimeStr := currStartDataTime.Format(utils.FormatDate)
  320. // 判断降频指标是否存在数据
  321. if existData, ok := existDataMap[currStartDataTimeStr]; ok {
  322. // 处理降频数据的值
  323. existValStr := existData.Value
  324. existValDeci, tmpErr := decimal.NewFromString(existValStr)
  325. if tmpErr != nil {
  326. err = tmpErr
  327. return
  328. }
  329. existVal, _ := existValDeci.Round(4).Float64()
  330. // 判断降频数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
  331. if existVal != currVal {
  332. err = ModifyEdbDataById(source, subSource, existData.EdbDataId, fmt.Sprint(currVal))
  333. if err != nil {
  334. return
  335. }
  336. }
  337. // 移除待删除的日期
  338. delete(existDelDateMap, currStartDataTimeStr)
  339. } else {
  340. // 直接入库
  341. timestamp := currStartDataTime.UnixNano() / 1e6
  342. timestampStr := fmt.Sprintf("%d", timestamp)
  343. addSql += GetAddSql(edbInfoIdStr, edbCode, currStartDataTime.Format(utils.FormatDate), timestampStr, fmt.Sprint(currVal))
  344. isAdd = true
  345. // 移除待删除的日期
  346. delete(existDelDateMap, currStartDataTimeStr)
  347. }
  348. // 一轮结束后,数据清空
  349. weekDayDataList = make([]float64, 0)
  350. }
  351. // 最后已有的日期处理完成后,需要对剩余不在时间段内的数据做处理
  352. lenWeekDayDataList := len(weekDayDataList)
  353. if lenWeekDayDataList > 0 {
  354. // 当前时间段内的数据计算,得出实际值
  355. var currVal float64
  356. if formula == "期末值" {
  357. currVal = weekDayDataList[lenWeekDayDataList-1]
  358. } else {
  359. // 平均值
  360. sumValDeci := decimal.NewFromFloat(0)
  361. for _, v := range weekDayDataList {
  362. tmpValDeci := decimal.NewFromFloat(v)
  363. sumValDeci = sumValDeci.Add(tmpValDeci)
  364. }
  365. lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
  366. currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
  367. }
  368. nextEndDateStr := nextEndDate.Format(utils.FormatDate)
  369. // 判断降频指标是否存在数据
  370. if existData, ok := existDataMap[nextEndDateStr]; ok {
  371. // 处理降频数据的值
  372. existValStr := existData.Value
  373. existValDeci, tmpErr := decimal.NewFromString(existValStr)
  374. if tmpErr != nil {
  375. err = tmpErr
  376. return
  377. }
  378. existVal, _ := existValDeci.Round(4).Float64()
  379. // 判断降频数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
  380. if existVal != currVal {
  381. err = ModifyEdbDataById(source, subSource, existData.EdbDataId, fmt.Sprint(currVal))
  382. if err != nil {
  383. return
  384. }
  385. }
  386. // 移除待删除的日期
  387. delete(existDelDateMap, nextEndDateStr)
  388. } else {
  389. // 直接入库
  390. timestamp := nextEndDate.UnixNano() / 1e6
  391. timestampStr := fmt.Sprintf("%d", timestamp)
  392. addSql += GetAddSql(edbInfoIdStr, edbCode, nextEndDate.Format(utils.FormatDate), timestampStr, fmt.Sprint(currVal))
  393. isAdd = true
  394. // 移除待删除的日期
  395. delete(existDelDateMap, nextEndDateStr)
  396. }
  397. }
  398. if isAdd {
  399. addSql = strings.TrimRight(addSql, ",")
  400. err = to.Exec(addSql).Error
  401. }
  402. // 移除不存在的日期数据
  403. if len(existDelDateMap) > 0 {
  404. removeDateList := make([]string, 0) //需要移除的日期
  405. for k := range existDelDateMap {
  406. removeDateList = append(removeDateList, k)
  407. }
  408. removeDateStr := strings.Join(removeDateList, `','`)
  409. removeDateStr = `'` + removeDateStr + `'`
  410. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
  411. err = to.Exec(sql, edbInfoId).Error
  412. if err != nil {
  413. err = fmt.Errorf("删除年化指标数据失败,Err:" + err.Error())
  414. return
  415. }
  416. }
  417. return
  418. }