predict_edb_data_calculate_nh.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package models
  2. import (
  3. "errors"
  4. "eta/eta_index_lib/utils"
  5. "fmt"
  6. "github.com/beego/beego/v2/client/orm"
  7. "github.com/shopspring/decimal"
  8. "strconv"
  9. "strings"
  10. "time"
  11. )
  12. // SavePredictCalculateNh 预测年化值
  13. func SavePredictCalculateNh(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) {
  14. o := orm.NewOrm()
  15. to, err := o.Begin()
  16. if err != nil {
  17. return
  18. }
  19. defer func() {
  20. if err != nil {
  21. fmt.Println("SavePredictCalculateNh,Err:" + err.Error())
  22. _ = to.Rollback()
  23. } else {
  24. _ = to.Commit()
  25. }
  26. }()
  27. fmt.Println("reqEdbInfoId:", reqEdbInfoId)
  28. if reqEdbInfoId <= 0 {
  29. edbInfo = &EdbInfo{
  30. //EdbInfoId: 0,
  31. EdbInfoType: 1,
  32. SourceName: utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_NH,
  33. Source: utils.DATA_SOURCE_PREDICT_CALCULATE_NH,
  34. EdbCode: edbCode,
  35. EdbName: edbName,
  36. EdbNameSource: edbName,
  37. Frequency: frequency,
  38. Unit: unit,
  39. //StartDate: "",
  40. //EndDate: "",
  41. ClassifyId: classifyId,
  42. SysUserId: sysUserId,
  43. SysUserRealName: sysUserRealName,
  44. UniqueCode: uniqueCode,
  45. CreateTime: time.Now(),
  46. ModifyTime: time.Now(),
  47. MinValue: 0,
  48. MaxValue: 0,
  49. CalculateFormula: formula,
  50. EdbType: 2,
  51. Sort: GetAddEdbMaxSortByClassifyId(classifyId, utils.PREDICT_EDB_INFO_TYPE),
  52. MoveType: 0,
  53. MoveFrequency: "",
  54. NoUpdate: 0,
  55. ServerUrl: "",
  56. EdbNameEn: edbName,
  57. UnitEn: unit,
  58. LatestDate: "",
  59. LatestValue: 0,
  60. ChartImage: "",
  61. }
  62. newEdbInfoId, tmpErr := to.Insert(edbInfo)
  63. if tmpErr != nil {
  64. err = tmpErr
  65. return
  66. }
  67. edbInfo.EdbInfoId = int(newEdbInfoId)
  68. // 添加关联关系
  69. {
  70. calculateMappingItem := &EdbInfoCalculateMapping{
  71. EdbInfoCalculateMappingId: 0,
  72. EdbInfoId: edbInfo.EdbInfoId,
  73. Source: edbInfo.Source,
  74. SourceName: edbInfo.SourceName,
  75. EdbCode: edbCode,
  76. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  77. FromEdbCode: fromEdbInfo.EdbCode,
  78. FromEdbName: fromEdbInfo.EdbName,
  79. FromSource: fromEdbInfo.Source,
  80. FromSourceName: fromEdbInfo.SourceName,
  81. FromTag: "",
  82. Sort: 1,
  83. CreateTime: time.Now(),
  84. ModifyTime: time.Now(),
  85. }
  86. _, err = to.Insert(calculateMappingItem)
  87. if err != nil {
  88. return
  89. }
  90. }
  91. } else {
  92. edbInfo, err = GetEdbInfoById(reqEdbInfoId)
  93. if err != nil {
  94. if err.Error() == utils.ErrNoRow() {
  95. errMsg = `获取指标信息失败`
  96. }
  97. return
  98. }
  99. if edbInfo.EdbInfoType != 1 {
  100. errMsg = `该指标不是预测指标`
  101. err = errors.New(errMsg)
  102. return
  103. }
  104. latestDateStr = edbInfo.LatestDate
  105. latestValue = edbInfo.LatestValue
  106. //修改指标信息
  107. switch lang {
  108. case utils.EnLangVersion:
  109. edbInfo.EdbNameEn = edbName
  110. edbInfo.UnitEn = unit
  111. default:
  112. edbInfo.EdbName = edbName
  113. edbInfo.Unit = unit
  114. edbInfo.EdbNameSource = edbName
  115. }
  116. edbInfo.Frequency = frequency
  117. edbInfo.ClassifyId = classifyId
  118. edbInfo.CalculateFormula = formula
  119. edbInfo.ModifyTime = time.Now()
  120. _, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EdbNameEn", "UnitEn")
  121. if err != nil {
  122. return
  123. }
  124. //判断计算指标是否被更换
  125. var existCondition string
  126. var existPars []interface{}
  127. existCondition += " AND edb_info_id=? AND from_edb_info_id=? "
  128. existPars = append(existPars, edbInfo.EdbInfoId, fromEdbInfo.EdbInfoId)
  129. count, tmpErr := GetEdbInfoCalculateCountByCondition(existCondition, existPars)
  130. if tmpErr != nil {
  131. err = errors.New("判断指标是否改变失败,Err:" + tmpErr.Error())
  132. return
  133. }
  134. if count > 0 { // 指标未被替换,无需重新计算
  135. return
  136. }
  137. //删除,计算指标关联的,基础指标的关联关系
  138. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
  139. _, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
  140. if err != nil {
  141. err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
  142. return
  143. }
  144. //清空原有已经入库的数据
  145. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  146. sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
  147. _, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
  148. if err != nil {
  149. return
  150. }
  151. //关联关系
  152. {
  153. calculateMappingItem := &EdbInfoCalculateMapping{
  154. EdbInfoCalculateMappingId: 0,
  155. EdbInfoId: edbInfo.EdbInfoId,
  156. Source: edbInfo.Source,
  157. SourceName: edbInfo.SourceName,
  158. EdbCode: edbCode,
  159. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  160. FromEdbCode: fromEdbInfo.EdbCode,
  161. FromEdbName: fromEdbInfo.EdbName,
  162. FromSource: fromEdbInfo.Source,
  163. FromSourceName: fromEdbInfo.SourceName,
  164. FromTag: "",
  165. Sort: 1,
  166. CreateTime: time.Now(),
  167. ModifyTime: time.Now(),
  168. }
  169. _, err = to.Insert(calculateMappingItem)
  170. if err != nil {
  171. return
  172. }
  173. }
  174. }
  175. // 计算数据
  176. latestDateStr, latestValue, err = refreshAllPredictCalculateNh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbCode)
  177. return
  178. }
  179. // RefreshAllPredictCalculateNh 刷新全部预测年化值数据
  180. func RefreshAllPredictCalculateNh(edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode, edbFrequency, formula string) (latestDateStr string, latestValue float64, err error) {
  181. o := orm.NewOrm()
  182. to, err := o.Begin()
  183. if err != nil {
  184. return
  185. }
  186. defer func() {
  187. if err != nil {
  188. fmt.Println("RefreshAllCalculateNh,Err:" + err.Error())
  189. _ = to.Rollback()
  190. } else {
  191. _ = to.Commit()
  192. }
  193. }()
  194. // 计算数据
  195. latestDateStr, latestValue, err = refreshAllPredictCalculateNh(to, edbInfoId, source, subSource, fromEdbInfo, edbCode)
  196. return
  197. }
  198. // refreshAllPredictCalculateNh 刷新预测年化数据
  199. func refreshAllPredictCalculateNh(to orm.TxOrmer, edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode string) (latestDateStr string, latestValue float64, err error) {
  200. edbInfoIdStr := strconv.Itoa(edbInfoId)
  201. tableName := GetEdbDataTableName(utils.DATA_SOURCE_PREDICT_CALCULATE_NH, subSource)
  202. //获取年化指标所有数据
  203. existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source, subSource)
  204. if err != nil {
  205. return
  206. }
  207. //计算指标的map
  208. existDataMap := make(map[string]*EdbData, 0)
  209. removeDateMap := make(map[string]string)
  210. for _, v := range existDataList {
  211. existDataMap[v.DataTime] = v
  212. removeDateMap[v.DataTime] = ``
  213. }
  214. //获取源指标数据
  215. fmt.Println("EdbInfoId:", fromEdbInfo.EdbInfoId)
  216. fromDataList, err := GetPredictEdbDataListAll(fromEdbInfo, 1)
  217. if err != nil {
  218. return
  219. }
  220. // 插值法数据处理
  221. handleDataMap := make(map[string]float64)
  222. _, err = HandleDataByLinearRegression(fromDataList, handleDataMap)
  223. if err != nil {
  224. return
  225. }
  226. var dateArr []string
  227. dataMap := make(map[string]*EdbInfoSearchData)
  228. fromDataMap := make(map[string]float64)
  229. //来源指指标数据
  230. for _, v := range fromDataList {
  231. dateArr = append(dateArr, v.DataTime)
  232. dataMap[v.DataTime] = v
  233. fromDataMap[v.DataTime] = v.Value
  234. }
  235. lenFromDataList := len(fromDataList)
  236. // 如果来源指标没有数据,那么就直接返回得了
  237. if lenFromDataList <= 0 {
  238. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? `, tableName)
  239. _, err = to.Raw(sql, edbInfoId).Exec()
  240. if err != nil {
  241. err = fmt.Errorf("删除年化指标数据失败,Err:" + err.Error())
  242. return
  243. }
  244. return
  245. }
  246. fmt.Println("source:", source)
  247. // 真实数据的最后日期
  248. latestDateStr = fromEdbInfo.LatestDate
  249. // 每年的最后一天的数据值
  250. yearLastValMap := make(map[int]float64)
  251. startDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[0].DataTime, time.Local)
  252. endDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[lenFromDataList-1].DataTime, time.Local)
  253. for i := startDataTime.Year(); i <= endDataTime.Year(); i++ {
  254. tmpDateStr := fmt.Sprintf("%d-12-31", i)
  255. if tmpVal, ok := handleDataMap[tmpDateStr]; ok {
  256. yearLastValMap[i] = tmpVal
  257. }
  258. }
  259. addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  260. var isAdd bool
  261. //来源指指标数据
  262. for _, v := range fromDataList {
  263. currDateStr := v.DataTime
  264. currDate, _ := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
  265. perValMap := make(map[time.Time]float64)
  266. //前3年当日的数据
  267. for i := 1; i <= 3; i++ {
  268. tmpDateTime := currDate.AddDate(-i, 0, 0)
  269. if tmpVal, ok := handleDataMap[tmpDateTime.Format(utils.FormatDate)]; ok {
  270. perValMap[tmpDateTime] = tmpVal
  271. }
  272. }
  273. lenPerValMap := len(perValMap)
  274. // 如果数据少于2年,那么就不参与计算,结束当前循环,进入下一个循环
  275. if lenPerValMap < 2 {
  276. continue
  277. }
  278. // N年 当前值占全年比重 的值列表
  279. divValList := make([]decimal.Decimal, 0)
  280. for tmpDateTime, tmpVal := range perValMap {
  281. yearLastVal, ok2 := yearLastValMap[tmpDateTime.Year()]
  282. // 如果当年最后一天没有数据
  283. if !ok2 {
  284. continue
  285. }
  286. // 当前值占全年比重
  287. divVal := decimal.NewFromFloat(tmpVal).Div(decimal.NewFromFloat(yearLastVal))
  288. divValList = append(divValList, divVal)
  289. }
  290. lenDivValList := len(divValList)
  291. // 如果 N年 当前值占全年比重 的值 小于 2个,那么就不参与计算,结束当前循环,进入下一个循环
  292. if lenDivValList < 2 {
  293. continue
  294. }
  295. divValSum := decimal.NewFromFloat(0)
  296. for _, divVal := range divValList {
  297. divValSum = divValSum.Add(divVal)
  298. }
  299. // 当前计算出来的结果
  300. currVal, _ := decimal.NewFromFloat(v.Value).Div(divValSum.Div(decimal.NewFromInt(int64(lenDivValList)))).Round(4).Float64()
  301. // 给实际日期数据的值赋值
  302. if fromEdbInfo.LatestDate == currDateStr {
  303. latestValue = currVal
  304. }
  305. // 判断年化指标是否存在数据
  306. if existData, ok := existDataMap[currDateStr]; ok {
  307. // 处理年化数据的值
  308. existValStr := existData.Value
  309. existValDeci, tmpErr := decimal.NewFromString(existValStr)
  310. if tmpErr != nil {
  311. err = tmpErr
  312. return
  313. }
  314. existVal, _ := existValDeci.Round(4).Float64()
  315. // 判断年化数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
  316. if existVal != currVal {
  317. err = ModifyEdbDataById(source, subSource, existData.EdbDataId, fmt.Sprint(currVal))
  318. if err != nil {
  319. return
  320. }
  321. }
  322. } else {
  323. // 直接入库
  324. timestamp := currDate.UnixNano() / 1e6
  325. timestampStr := fmt.Sprintf("%d", timestamp)
  326. addSql += GetAddSql(edbInfoIdStr, edbCode, currDateStr, timestampStr, fmt.Sprint(currVal))
  327. isAdd = true
  328. }
  329. delete(removeDateMap, currDateStr)
  330. }
  331. if isAdd {
  332. addSql = strings.TrimRight(addSql, ",")
  333. _, err = to.Raw(addSql).Exec()
  334. }
  335. // 移除不存在的日期数据
  336. if len(removeDateMap) > 0 {
  337. removeDateList := make([]string, 0) //需要移除的日期
  338. for k := range removeDateMap {
  339. removeDateList = append(removeDateList, k)
  340. }
  341. removeDateStr := strings.Join(removeDateList, `","`)
  342. removeDateStr = `"` + removeDateStr + `"`
  343. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
  344. _, err = to.Raw(sql, edbInfoId).Exec()
  345. if err != nil {
  346. err = fmt.Errorf("删除年化指标数据失败,Err:" + err.Error())
  347. return
  348. }
  349. }
  350. return
  351. }