predict_edb_data_calculate_tbz.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. package models
  2. import (
  3. "errors"
  4. "eta_gn/eta_index_lib/global"
  5. "eta_gn/eta_index_lib/utils"
  6. "fmt"
  7. "github.com/shopspring/decimal"
  8. "gorm.io/gorm"
  9. "reflect"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. // PredictTb 预测同比值
  15. type PredictTb struct {
  16. }
  17. // Add 添加
  18. func (obj PredictTb) Add(params BatchSaveCalculateBatchParams) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error, errMsg string) {
  19. req := params.Req
  20. fromEdbInfo := params.FromEdbInfo
  21. edbCode := params.EdbCode
  22. to := global.DEFAULT_DmSQL.Begin()
  23. defer func() {
  24. if err != nil {
  25. to.Rollback()
  26. } else {
  27. to.Commit()
  28. }
  29. }()
  30. edbInfo = &EdbInfo{
  31. //EdbInfoId: 0,
  32. SourceName: obj.GetSourceName(),
  33. Source: obj.GetSource(),
  34. EdbCode: edbCode,
  35. EdbName: req.EdbName,
  36. EdbNameSource: req.EdbName,
  37. Frequency: req.Frequency,
  38. Unit: req.Unit,
  39. StartDate: "",
  40. EndDate: "",
  41. ClassifyId: req.ClassifyId,
  42. SysUserId: params.SysUserId,
  43. SysUserRealName: params.SysUserRealName,
  44. UniqueCode: params.UniqueCode,
  45. CreateTime: time.Now(),
  46. ModifyTime: time.Now(),
  47. MinValue: 0,
  48. MaxValue: 0,
  49. CalculateFormula: req.Formula,
  50. EdbType: 2,
  51. Sort: GetAddEdbMaxSortByClassifyId(req.ClassifyId, utils.PREDICT_EDB_INFO_TYPE),
  52. MoveType: 0,
  53. MoveFrequency: "",
  54. NoUpdate: 0,
  55. ServerUrl: "",
  56. EdbInfoType: 1,
  57. EdbNameEn: req.EdbName,
  58. UnitEn: req.Unit,
  59. LatestDate: "",
  60. LatestValue: 0,
  61. ChartImage: "",
  62. Calendar: "",
  63. }
  64. tmpErr := to.Create(edbInfo).Error
  65. if tmpErr != nil {
  66. err = tmpErr
  67. return
  68. }
  69. //关联关系
  70. {
  71. calculateMappingItem := new(EdbInfoCalculateMapping)
  72. calculateMappingItem.CreateTime = time.Now()
  73. calculateMappingItem.ModifyTime = time.Now()
  74. calculateMappingItem.Sort = 1
  75. calculateMappingItem.EdbCode = edbCode
  76. calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
  77. calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
  78. calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
  79. calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
  80. calculateMappingItem.FromSource = fromEdbInfo.Source
  81. calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
  82. calculateMappingItem.FromTag = ""
  83. calculateMappingItem.Source = edbInfo.Source
  84. calculateMappingItem.SourceName = edbInfo.SourceName
  85. err = to.Create(calculateMappingItem).Error
  86. if err != nil {
  87. return
  88. }
  89. }
  90. //计算数据
  91. latestDateStr, latestValue, err = obj.refresh(to, edbInfo, fromEdbInfo, edbInfo.EdbCode, "")
  92. return
  93. }
  94. // Edit 编辑
  95. func (obj PredictTb) Edit(params BatchSaveCalculateBatchParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
  96. req := params.Req
  97. edbInfo := params.EdbInfo
  98. fromEdbInfo := params.FromEdbInfo
  99. latestDateStr = edbInfo.LatestDate
  100. latestValue = edbInfo.LatestValue
  101. if fromEdbInfo.Frequency != req.Frequency {
  102. errMsg = "生成指标频度与原指标频度不同"
  103. err = errors.New(errMsg)
  104. return
  105. }
  106. if edbInfo.EdbInfoType != 1 {
  107. errMsg = `该指标不是预测指标`
  108. err = errors.New(errMsg)
  109. return
  110. }
  111. latestDateStr = edbInfo.LatestDate
  112. latestValue = edbInfo.LatestValue
  113. to := global.DEFAULT_DmSQL.Begin()
  114. defer func() {
  115. if err != nil {
  116. to.Rollback()
  117. } else {
  118. to.Commit()
  119. }
  120. }()
  121. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  122. //修改指标信息
  123. switch params.Lang {
  124. case utils.EnLangVersion:
  125. edbInfo.EdbNameEn = req.EdbName
  126. edbInfo.UnitEn = req.Unit
  127. default:
  128. edbInfo.EdbName = req.EdbName
  129. edbInfo.Unit = req.Unit
  130. edbInfo.EdbNameSource = req.EdbName
  131. }
  132. edbInfo.Frequency = req.Frequency
  133. edbInfo.ClassifyId = req.ClassifyId
  134. edbInfo.ModifyTime = time.Now()
  135. err = to.Model(edbInfo).Select([]string{"EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "ModifyTime", "EdbNameEn", "UnitEn"}).Updates(edbInfo).Error
  136. if err != nil {
  137. return
  138. }
  139. //判断计算指标是否被更换
  140. var existCondition string
  141. var existPars []interface{}
  142. existCondition += " AND edb_info_id=? AND from_edb_info_id=? "
  143. existPars = append(existPars, edbInfo.EdbInfoId, fromEdbInfo.EdbInfoId)
  144. var count int
  145. count, err = GetEdbInfoCalculateCountByCondition(existCondition, existPars)
  146. if err != nil {
  147. err = errors.New("判断指标是否改变失败,Err:" + err.Error())
  148. return
  149. }
  150. if count > 0 { // 指标未被替换,无需重新计算
  151. return
  152. }
  153. //删除,计算指标关联的,基础指标的关联关系
  154. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
  155. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  156. if err != nil {
  157. return
  158. }
  159. // 删除该指标所有的同比数据
  160. sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
  161. err = to.Exec(sql, edbInfo.EdbInfoId).Error
  162. if err != nil {
  163. return
  164. }
  165. //关联关系
  166. {
  167. calculateMappingItem := &EdbInfoCalculateMapping{
  168. EdbInfoCalculateMappingId: 0,
  169. EdbInfoId: edbInfo.EdbInfoId,
  170. Source: obj.GetSource(),
  171. SourceName: obj.GetSourceName(),
  172. EdbCode: edbInfo.EdbCode,
  173. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  174. FromEdbCode: fromEdbInfo.EdbCode,
  175. FromEdbName: fromEdbInfo.EdbName,
  176. FromSource: fromEdbInfo.Source,
  177. FromSourceName: fromEdbInfo.SourceName,
  178. FromTag: "",
  179. Sort: 1,
  180. CreateTime: time.Now(),
  181. ModifyTime: time.Now(),
  182. }
  183. err = to.Create(calculateMappingItem).Error
  184. if err != nil {
  185. return
  186. }
  187. }
  188. //计算数据
  189. latestDateStr, latestValue, err = obj.refresh(to, edbInfo, fromEdbInfo, edbInfo.EdbCode, "")
  190. return
  191. }
  192. // Refresh 刷新
  193. func (obj PredictTb) Refresh(params RefreshParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
  194. calculateMapping, err := GetEdbInfoCalculateMappingDetail(params.EdbInfo.EdbInfoId)
  195. if err != nil {
  196. return
  197. }
  198. fromEdbInfo, err := GetEdbInfoById(calculateMapping.FromEdbInfoId)
  199. if err != nil {
  200. errMsg = "GetEdbInfoById Err:" + err.Error()
  201. return
  202. }
  203. to := global.DEFAULT_DmSQL.Begin()
  204. defer func() {
  205. if err != nil {
  206. to.Rollback()
  207. } else {
  208. to.Commit()
  209. }
  210. }()
  211. // 计算数据
  212. latestDateStr, latestValue, err = obj.refresh(to, params.EdbInfo, fromEdbInfo, params.EdbInfo.EdbCode, params.StartDate)
  213. return
  214. }
  215. // GetSource 获取来源编码id
  216. func (obj PredictTb) GetSource() int {
  217. return utils.DATA_SOURCE_PREDICT_CALCULATE_TBZ
  218. }
  219. // GetSourceName 获取来源名称
  220. func (obj PredictTb) GetSourceName() string {
  221. return utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_TBZ
  222. }
  223. func (obj PredictTb) refresh(to *gorm.DB, edbInfo, fromEdbInfo *EdbInfo, edbCode, startDate string) (latestDateStr string, latestValue float64, err error) {
  224. edbInfoId := edbInfo.EdbInfoId
  225. dataTableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  226. edbInfoIdStr := strconv.Itoa(edbInfoId)
  227. // 获取关联指标数据
  228. dataList, err := GetPredictEdbDataListAllByStartDate(fromEdbInfo, 0, "")
  229. if err != nil {
  230. return
  231. }
  232. // 来源指标数据参与计算
  233. calculateDataList, err := EdbInfoSearchDataToEdbInfoData(dataList)
  234. if err != nil {
  235. return
  236. }
  237. baseCalculate := BaseCalculate{
  238. DataList: calculateDataList,
  239. Frequency: fromEdbInfo.Frequency,
  240. Source: 3,
  241. }
  242. dateDataMap, err, _ := baseCalculate.Tbz()
  243. if err != nil {
  244. return
  245. }
  246. // 真实数据的最后日期
  247. latestDateStr = fromEdbInfo.LatestDate
  248. //获取指标所有数据
  249. existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, edbInfo.Source, edbInfo.SubSource)
  250. if err != nil {
  251. return
  252. }
  253. existDataMap := make(map[string]string)
  254. removeDataTimeMap := make(map[string]int) //需要移除的日期数据
  255. for _, v := range existDataList {
  256. existDataMap[v.DataTime] = v.Value
  257. removeDataTimeMap[v.DataTime] = 1
  258. }
  259. //fmt.Println("existDataMap:", existDataMap)
  260. addSql := ` INSERT INTO edb_data_predict_calculate_tbz (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  261. var isAdd bool
  262. existAddDataMap := make(map[string]string)
  263. for currentDate, valFloat := range dateDataMap {
  264. currentDateStr := currentDate.Format(utils.FormatDate)
  265. timestamp := currentDate.UnixNano() / 1e6
  266. timestampStr := fmt.Sprintf("%d", timestamp)
  267. val := decimal.NewFromFloat(valFloat).String()
  268. //校验待删除日期数据里面是否存在该元素,如果存在的话,那么移除该日期
  269. delete(removeDataTimeMap, currentDateStr)
  270. if existVal, ok := existDataMap[currentDateStr]; !ok {
  271. if _, existOk := existAddDataMap[currentDateStr]; !existOk {
  272. addSql += GetAddSql(edbInfoIdStr, edbCode, currentDateStr, timestampStr, val)
  273. isAdd = true
  274. }
  275. existAddDataMap[currentDateStr] = currentDateStr
  276. } else {
  277. existValDecimal, tmpErr := decimal.NewFromString(existVal)
  278. if tmpErr != nil {
  279. err = tmpErr
  280. return
  281. }
  282. existStr := existValDecimal.String()
  283. if existStr != val {
  284. sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
  285. sql = fmt.Sprintf(sql, dataTableName)
  286. err = to.Exec(sql, val, edbInfoId, currentDateStr).Error
  287. if err != nil {
  288. return
  289. }
  290. }
  291. }
  292. // 实际数据的值
  293. if fromEdbInfo.LatestDate == currentDateStr {
  294. latestValueDecimal, tmpErr := decimal.NewFromString(val)
  295. if tmpErr != nil {
  296. return
  297. }
  298. latestValue, _ = latestValueDecimal.Truncate(4).Float64() //保留4位小数
  299. }
  300. }
  301. //删除已经不存在的指标数据(由于该指标当日的数据删除了)
  302. {
  303. removeDateList := make([]string, 0)
  304. for dateTime := range removeDataTimeMap {
  305. removeDateList = append(removeDateList, dateTime)
  306. }
  307. removeNum := len(removeDateList)
  308. if removeNum > 0 {
  309. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (`+utils.GetOrmInReplace(removeNum)+`) `, dataTableName)
  310. err = to.Exec(sql, edbInfo.EdbInfoId, removeDateList).Error
  311. if err != nil {
  312. fmt.Println(reflect.TypeOf(obj).Name(), " add data ;delete Err", err.Error())
  313. err = fmt.Errorf("删除不存在的指标数据失败,Err:" + err.Error())
  314. return
  315. }
  316. }
  317. }
  318. // 批量插入
  319. if isAdd {
  320. addSql = strings.TrimRight(addSql, ",")
  321. err = to.Exec(addSql).Error
  322. if err != nil {
  323. return
  324. }
  325. }
  326. //确定实际数据的最终值
  327. {
  328. finalLast, tmpErr := GetFinalLastByTo(to, edbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo.LatestDate)
  329. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  330. return
  331. }
  332. if tmpErr == nil {
  333. latestDateStr = finalLast.DataTime
  334. latestValue = finalLast.Value
  335. }
  336. }
  337. return
  338. }