base_predict_from_calculate.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package models
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/beego/beego/v2/client/orm"
  6. "github.com/shopspring/decimal"
  7. "github.com/yidane/formula"
  8. "hongze/hongze_edb_lib/services"
  9. "hongze/hongze_edb_lib/utils"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. // PredictEdbInfoCalculateSaveReq 预测计算(运算)指标请求参数
  15. type PredictEdbInfoCalculateSaveReq struct {
  16. AdminId int `description:"添加人id"`
  17. AdminName string `description:"添加人名称"`
  18. EdbName string `description:"指标名称"`
  19. Frequency string `description:"频率"`
  20. Unit string `description:"单位"`
  21. ClassifyId int `description:"分类id"`
  22. CalculateFormula string `description:"计算公式"`
  23. EdbInfoIdArr []struct {
  24. EdbInfoId int `description:"指标id"`
  25. FromTag string `description:"指标对应标签"`
  26. }
  27. }
  28. // PredictCalculateItems 预测计算(运算)指标信息
  29. type PredictCalculateItems struct {
  30. EdbInfoId int
  31. DataMap map[string]float64
  32. }
  33. // AddPredictCalculate 新增预测计算(运算)指标的数据
  34. func AddPredictCalculate(edbInfoIdArr []*EdbInfo, edbInfoId int, edbCode, formulaStr string, edbInfoIdBytes []string) (err error) {
  35. o := orm.NewOrm()
  36. defer func() {
  37. if err != nil {
  38. utils.FileLog.Info(fmt.Sprintf("Calculate Err:%s" + err.Error()))
  39. }
  40. }()
  41. saveDataMap := make(map[string]map[int]float64)
  42. for _, v := range edbInfoIdArr {
  43. dataList, err := GetPredictEdbDataListAll(v, 1)
  44. if err != nil {
  45. return err
  46. }
  47. dataMap := make(map[string]float64)
  48. for _, dv := range dataList {
  49. if val, ok := saveDataMap[dv.DataTime]; ok {
  50. if _, ok := val[v.EdbInfoId]; !ok {
  51. val[v.EdbInfoId] = dv.Value
  52. }
  53. } else {
  54. temp := make(map[int]float64)
  55. temp[v.EdbInfoId] = dv.Value
  56. saveDataMap[dv.DataTime] = temp
  57. }
  58. }
  59. item := new(PredictCalculateItems)
  60. item.EdbInfoId = v.EdbInfoId
  61. item.DataMap = dataMap
  62. }
  63. formulaMap := services.CheckFormula(formulaStr)
  64. addSql := ` INSERT INTO edb_predict_data_calculate (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  65. nowStr := time.Now().Format(utils.FormatDateTime)
  66. var isAdd bool
  67. for sk, sv := range saveDataMap {
  68. formulaStr = strings.ToUpper(formulaStr)
  69. formulaFormStr := ReplaceFormula(edbInfoIdArr, sv, formulaMap, formulaStr, edbInfoIdBytes)
  70. if formulaStr == "" {
  71. return
  72. }
  73. if formulaFormStr != "" {
  74. expression := formula.NewExpression(formulaFormStr)
  75. calResult, err := expression.Evaluate()
  76. if err != nil {
  77. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  78. fmt.Println(err)
  79. return err
  80. }
  81. calVal, err := calResult.Float64()
  82. if err != nil {
  83. err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  84. fmt.Println(err)
  85. return err
  86. }
  87. //需要存入的数据
  88. {
  89. dataTime, _ := time.Parse(utils.FormatDate, sk)
  90. timestamp := dataTime.UnixNano() / 1e6
  91. timeStr := fmt.Sprintf("%d", timestamp)
  92. addSql += "("
  93. addSql += strconv.Itoa(edbInfoId) + "," + "'" + edbCode + "'" + "," + "'" + sk + "'" + "," + utils.SubFloatToString(calVal, 4) + "," + "'" + nowStr + "'" +
  94. "," + "'" + nowStr + "'" + "," + "'" + timeStr + "'"
  95. addSql += "),"
  96. isAdd = true
  97. }
  98. } else {
  99. fmt.Println("formulaFormStr is empty")
  100. }
  101. }
  102. if isAdd {
  103. addSql = strings.TrimRight(addSql, ",")
  104. _, err = o.Raw(addSql).Exec()
  105. if err != nil {
  106. fmt.Println("AddPredictCalculate Err:" + err.Error())
  107. //errMsg = " tx.Exec Err :" + err.Error()
  108. return
  109. }
  110. }
  111. return
  112. }
  113. // RefreshAllPredictCalculate 刷新预测计算指标的全部数据
  114. func RefreshAllPredictCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
  115. o := orm.NewOrm()
  116. to, err := o.Begin()
  117. if err != nil {
  118. return
  119. }
  120. defer func() {
  121. if err != nil {
  122. fmt.Println("RefreshAllCalculate,Err:" + err.Error())
  123. _ = to.Rollback()
  124. } else {
  125. _ = to.Commit()
  126. }
  127. }()
  128. fmt.Println(startDate, endDate)
  129. saveDataMap := make(map[string]map[int]float64)
  130. for _, v := range edbInfoIdArr {
  131. var condition string
  132. var pars []interface{}
  133. condition += " AND edb_info_id=? "
  134. pars = append(pars, v.EdbInfoId)
  135. if startDate != "" {
  136. condition += " AND data_time>=? "
  137. pars = append(pars, startDate)
  138. }
  139. //if endDate != "" {
  140. // condition += " AND data_time<=? "
  141. // pars = append(pars, endDate)
  142. //}
  143. //fmt.Println("v.Source:", v.Source)
  144. dataList, err := GetEdbDataListAll(condition, pars, v.Source, 1)
  145. if err != nil {
  146. return err
  147. }
  148. dataMap := make(map[string]float64)
  149. for _, dv := range dataList {
  150. if val, ok := saveDataMap[dv.DataTime]; ok {
  151. if _, ok := val[v.EdbInfoId]; !ok {
  152. val[v.EdbInfoId] = dv.Value
  153. }
  154. } else {
  155. temp := make(map[int]float64)
  156. temp[v.EdbInfoId] = dv.Value
  157. saveDataMap[dv.DataTime] = temp
  158. }
  159. }
  160. item := new(CalculateItems)
  161. item.EdbInfoId = v.EdbInfoId
  162. item.DataMap = dataMap
  163. }
  164. formulaMap := services.CheckFormula(formulaStr)
  165. addSql := ` INSERT INTO edb_data_calculate(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
  166. var isAdd bool
  167. //获取指标所有数据
  168. dataList := make([]*EdbData, 0)
  169. dataTableName := GetEdbDataTableName(source)
  170. sql := `SELECT * FROM %s WHERE edb_info_id=? `
  171. sql = fmt.Sprintf(sql, dataTableName)
  172. _, err = o.Raw(sql, edbInfoId).QueryRows(&dataList)
  173. if err != nil {
  174. return err
  175. }
  176. dataMap := make(map[string]string)
  177. for _, v := range dataList {
  178. dataMap[v.DataTime] = v.Value
  179. }
  180. edbInfoIdStr := strconv.Itoa(edbInfoId)
  181. existDataMap := make(map[string]string)
  182. removeDateList := make([]string, 0) //需要移除的日期
  183. for sk, sv := range saveDataMap {
  184. //fmt.Println(sk, sv)
  185. formulaStr = strings.ToUpper(formulaStr)
  186. formulaFormStr := ReplaceFormula(edbInfoIdArr, sv, formulaMap, formulaStr, edbInfoIdBytes)
  187. if formulaFormStr != "" {
  188. utils.FileLog.Info(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
  189. expression := formula.NewExpression(formulaFormStr)
  190. calResult, err := expression.Evaluate()
  191. if err != nil {
  192. // 分母为0的报错
  193. if strings.Contains(err.Error(), "divide by zero") {
  194. removeDateList = append(removeDateList, sk)
  195. continue
  196. }
  197. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  198. fmt.Println(err)
  199. return err
  200. }
  201. calVal, err := calResult.Float64()
  202. if err != nil {
  203. err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  204. fmt.Println(err)
  205. return err
  206. }
  207. saveValue := decimal.NewFromFloat(calVal).RoundCeil(4).String() //utils.SubFloatToString(calVal, 4)
  208. if existVal, ok := dataMap[sk]; !ok {
  209. dataTime, _ := time.Parse(utils.FormatDate, sk)
  210. timestamp := dataTime.UnixNano() / 1e6
  211. timeStr := fmt.Sprintf("%d", timestamp)
  212. if _, existOk := existDataMap[sk]; !existOk {
  213. addSql += GetAddSql(edbInfoIdStr, edbCode, sk, timeStr, saveValue)
  214. isAdd = true
  215. }
  216. existDataMap[sk] = sk
  217. } else {
  218. existValDecimal, err := decimal.NewFromString(existVal)
  219. existStr := existValDecimal.String()
  220. if existStr != saveValue {
  221. sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
  222. sql = fmt.Sprintf(sql, dataTableName)
  223. _, err = o.Raw(sql, saveValue, edbInfoId, sk).Exec()
  224. if err != nil {
  225. return err
  226. }
  227. }
  228. }
  229. } else {
  230. //计算公式异常,那么就移除该指标
  231. removeDateList = append(removeDateList, sk)
  232. continue
  233. }
  234. }
  235. if isAdd {
  236. addSql = strings.TrimRight(addSql, ",")
  237. _, err = o.Raw(addSql).Exec()
  238. if err != nil {
  239. fmt.Println("RefreshAllCalculate add Err", err.Error())
  240. return
  241. }
  242. }
  243. if len(removeDateList) > 0 {
  244. removeDateStr := strings.Join(removeDateList, `","`)
  245. removeDateStr = `"` + removeDateStr + `"`
  246. //如果拼接指标变更了,那么需要删除所有的指标数据
  247. tableName := GetEdbDataTableName(source)
  248. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
  249. _, err = o.Raw(sql, edbInfoId).Exec()
  250. if err != nil {
  251. err = fmt.Errorf("删除计算失败的计算指标数据失败,Err:" + err.Error())
  252. return
  253. }
  254. }
  255. return
  256. }