dashboard.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. package backend
  2. import (
  3. "context"
  4. "kpt-pasture/model"
  5. "kpt-pasture/util"
  6. "net/http"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "gorm.io/gorm"
  11. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  12. "gitee.com/xuyiping_admin/pkg/xerr"
  13. "go.uber.org/zap"
  14. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  15. )
  16. func (s *StoreEntry) NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckRingResponse, error) {
  17. userModel, err := s.GetUserModel(ctx)
  18. if err != nil {
  19. return nil, xerr.WithStack(err)
  20. }
  21. estrusWarningCowList := make([]*model.NeckRingEstrus, 0)
  22. estrusWarningLevelItems := map[int32]int32{
  23. int32(pasturePb.EstrusLevel_Low): 0,
  24. int32(pasturePb.EstrusLevel_Middle): 0,
  25. int32(pasturePb.EstrusLevel_High): 0,
  26. }
  27. if err = s.DB.Model(new(model.EventEstrus)).
  28. Where("pasture_id = ?", userModel.AppPasture.Id).
  29. Where("is_show = ?", pasturePb.IsShow_Ok).
  30. Group("cow_id").Find(&estrusWarningCowList).Error; err != nil {
  31. zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
  32. }
  33. for _, v := range estrusWarningCowList {
  34. estrusWarningLevelItems[int32(v.Level)] += estrusWarningLevelItems[int32(v.Level)]
  35. }
  36. healthWarningNumber := int64(0)
  37. if err = s.DB.Model(new(model.NeckRingHealthWarning)).
  38. Where("pasture_id = ?", userModel.AppPasture.Id).
  39. Where("is_show = ?", pasturePb.IsShow_Ok).
  40. Group("cow_id").
  41. Count(&healthWarningNumber).Error; err != nil {
  42. zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
  43. }
  44. return &pasturePb.IndexNeckRingResponse{
  45. Code: http.StatusOK,
  46. Msg: "ok",
  47. Data: &pasturePb.NeckRingData{
  48. EstrusWarningNumber: int32(len(estrusWarningCowList)),
  49. HealthWarningNumber: int32(healthWarningNumber),
  50. AbortionWarningNumber: 0,
  51. StressWarningNumber: 0,
  52. EstrusWarningLevelItems: estrusWarningLevelItems,
  53. },
  54. }, nil
  55. }
  56. func (s *StoreEntry) FocusIndicatorsList(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error) {
  57. userModel, err := s.GetUserModel(ctx)
  58. if err != nil {
  59. return nil, xerr.WithStack(err)
  60. }
  61. userFocusIndicators := userModel.SystemUser.IndicatorsKinds
  62. if len(userFocusIndicators) <= 0 {
  63. userFocusIndicators = model.DefaultFocusIndicators
  64. }
  65. userFocusIndicatorsList := strings.Split(userFocusIndicators, ",")
  66. indicatorsDataList := make([]*model.IndicatorsData, 0)
  67. pref := s.DB.Model(new(model.IndicatorsData)).
  68. Where("pasture_id = ?", userModel.AppPasture.Id).
  69. Where("kind in (?)", userFocusIndicatorsList)
  70. /*if dimension == "Year" {
  71. pref.Where("date = ?", time.Now().Format(model.LayoutMonth))
  72. }*/
  73. nowTime := time.Now()
  74. if dimension == "Month" {
  75. pref.Where("date = ?", nowTime.Format(model.LayoutMonth))
  76. }
  77. if err = pref.Find(&indicatorsDataList).Error; err != nil {
  78. zaplog.Error("FocusIndicators", zap.Any("err", err))
  79. }
  80. indicatorsDetailsMap, _, err := s.GetIndicatorsDetailsMap(ctx)
  81. if err != nil {
  82. return nil, xerr.WithStack(err)
  83. }
  84. focusIndicatorsList := make([]*pasturePb.FocusIndicators, 0)
  85. for _, v := range indicatorsDataList {
  86. indicatorsDetails, ok := indicatorsDetailsMap[v.Kind]
  87. if !ok {
  88. continue
  89. }
  90. onYear, onMonth := "", ""
  91. if dimension == "Year" {
  92. return nil, xerr.Custom("暂不支持该维度")
  93. }
  94. if dimension == "Month" {
  95. lastMonth := nowTime.AddDate(0, -1, 0).Format(model.LayoutMonth)
  96. oldIndicators, _ := s.GetIndicatorsDataByDate(userModel.AppPasture.Id, v.Kind, lastMonth)
  97. if oldIndicators != nil {
  98. if oldIndicators.Value != "" && oldIndicators.Value != "0" {
  99. oldValue, _ := strconv.ParseFloat(oldIndicators.Value, 64)
  100. currValue, _ := strconv.ParseFloat(v.Value, 64)
  101. onMonthValue := (oldValue - currValue) / oldValue * 100
  102. omv := util.RoundToTwoDecimals(onMonthValue)
  103. onMonth = strconv.FormatFloat(omv, 'f', 2, 64) + "%"
  104. }
  105. }
  106. }
  107. focusIndicatorsList = append(focusIndicatorsList, &pasturePb.FocusIndicators{
  108. Kind: indicatorsDetails.Kind,
  109. Name: indicatorsDetails.Name,
  110. Value: v.Value,
  111. Describe: indicatorsDetails.Zh,
  112. UnitName: indicatorsDetails.Unit,
  113. OnMonth: onMonth,
  114. OnYear: onYear,
  115. })
  116. }
  117. indicatorsDetailsList, _ := s.FindIndicatorsDetailsList(ctx)
  118. return &pasturePb.IndexFocusIndicatorsResponse{
  119. Code: http.StatusOK,
  120. Msg: "ok",
  121. Data: &pasturePb.FocusData{
  122. FocusIndicators: focusIndicatorsList,
  123. IndicatorsSet: model.IndicatorsDetailsSlice(indicatorsDetailsList).ToPB(userFocusIndicatorsList),
  124. },
  125. }, err
  126. }
  127. func (s *StoreEntry) FocusIndicatorsSet(ctx context.Context, req *pasturePb.IndexFocusIndicatorsSetRequest) error {
  128. userModel, err := s.GetUserModel(ctx)
  129. if err != nil {
  130. return xerr.WithStack(err)
  131. }
  132. if len(req.IndicatorsKind) <= 0 {
  133. return nil
  134. }
  135. userFocusIndicators := strings.Join(req.IndicatorsKind, ",")
  136. if err = s.DB.Model(new(model.SystemUser)).
  137. Where("id = ?", userModel.SystemUser.Id).
  138. Update("indicators_kinds", userFocusIndicators).Error; err != nil {
  139. return xerr.WithStack(err)
  140. }
  141. return nil
  142. }
  143. func (s *StoreEntry) DataWarningSet(ctx context.Context, req *pasturePb.IndexDataWarningSetRequest) error {
  144. userModel, err := s.GetUserModel(ctx)
  145. if err != nil {
  146. return xerr.WithStack(err)
  147. }
  148. if len(req.WarningDataSet) <= 0 {
  149. return nil
  150. }
  151. defaultDataWarning, _ := s.FindDataWarning(ctx, model.DefaultUserId)
  152. if len(defaultDataWarning) <= 0 {
  153. return xerr.Custom("默认预警数据不存在,请联系管理员!")
  154. }
  155. userDataWarningList, err := s.FindDataWarning(ctx, userModel.SystemUser.Id)
  156. if err != nil {
  157. return xerr.WithStack(err)
  158. }
  159. if len(userDataWarningList) <= 0 { // 新增
  160. return s.addUserDataWarning(ctx, userModel.SystemUser.Id, defaultDataWarning, req.WarningDataSet)
  161. }
  162. return s.updateUserDataWarning(ctx, userModel.SystemUser.Id, userDataWarningList, req.WarningDataSet)
  163. }
  164. func (s *StoreEntry) DataWarningList(ctx context.Context) (*pasturePb.IndexDataWarningResponse, error) {
  165. userModel, err := s.GetUserModel(ctx)
  166. if err != nil {
  167. return nil, xerr.WithStack(err)
  168. }
  169. defaultDataWarning, _ := s.FindDataWarning(ctx, model.DefaultUserId)
  170. if len(defaultDataWarning) <= 0 {
  171. return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
  172. }
  173. var isExist bool // 判断是否存在自己的设置的数据
  174. userDataWarning, _ := s.FindDataWarning(ctx, userModel.SystemUser.Id)
  175. if len(userDataWarning) == 0 {
  176. // 如果用户没有配置自己的预警数据,则使用默认数据
  177. isExist = true
  178. userDataWarning = defaultDataWarning
  179. }
  180. newTime := time.Now().Unix()
  181. needUpdateWarningIds := make([]int64, 0)
  182. for _, warningData := range userDataWarning {
  183. // 如果预警数据更新时间大于预警条件更新时间,并且更新时间距离当前时间小于2小时,则跳过
  184. if warningData.DataUpdateAt > warningData.ConditionUpdateAt && newTime-warningData.DataUpdateAt < int64(2*time.Hour) {
  185. continue
  186. }
  187. needUpdateWarningIds = append(needUpdateWarningIds, warningData.Id)
  188. }
  189. // 需要重新计算更新的warningId
  190. if len(needUpdateWarningIds) > 0 {
  191. s.UpdateWarningData(ctx, needUpdateWarningIds)
  192. }
  193. userDataWarningItems := make([]*model.DataWarningItems, 0)
  194. // 计算过后重新获取数据
  195. if isExist {
  196. userDataWarning, _ = s.FindDataWarning(ctx, model.DefaultUserId)
  197. userDataWarningItems, _ = s.FindDataWarningItems(ctx, model.DefaultUserId)
  198. } else {
  199. userDataWarning, _ = s.FindDataWarning(ctx, userModel.SystemUser.Id)
  200. userDataWarningItems, _ = s.FindDataWarningItems(ctx, userModel.SystemUser.Id)
  201. }
  202. return &pasturePb.IndexDataWarningResponse{
  203. Code: http.StatusOK,
  204. Msg: "ok",
  205. Data: &pasturePb.DataWarning{
  206. DataSet: model.DataWarningItemsSlice(userDataWarningItems).ToPB(userDataWarning),
  207. DataShow: model.DataWarningSlice(userDataWarning).ToPB(),
  208. },
  209. }, nil
  210. }
  211. // 新增用户预警数据
  212. func (s *StoreEntry) addUserDataWarning(ctx context.Context, userId int64, defaultDataWarning []*model.DataWarning, warningDataSet []*pasturePb.WarningDataSet) error {
  213. // 将默认预警数据按 Kind 映射
  214. defaultDataWarningMap := make(map[string]*model.DataWarning)
  215. for _, v := range defaultDataWarning {
  216. defaultDataWarningMap[v.Kind] = v
  217. }
  218. // 在事务中执行新增操作
  219. return s.DB.Transaction(func(tx *gorm.DB) error {
  220. addedKinds := make(map[string]bool) // 记录已添加的 Kind
  221. for _, set := range warningDataSet {
  222. dataWarning := model.NewDataWarning(userId, set.Kind, pasturePb.IsShow_Ok, defaultDataWarningMap[set.Kind])
  223. // 如果该 Kind 已添加,跳过
  224. if !addedKinds[set.Kind] {
  225. // 创建新的预警数据
  226. if err := tx.Create(dataWarning).Error; err != nil {
  227. return xerr.WithStack(err)
  228. }
  229. } else {
  230. oldDataWarning := &model.DataWarning{}
  231. if err := tx.Model(new(model.DataWarning)).
  232. Where("user_id = ?", userId).
  233. Where("kind = ?", set.Kind).
  234. First(oldDataWarning).Error; err != nil {
  235. return xerr.WithStack(err)
  236. }
  237. dataWarning.Id = oldDataWarning.Id
  238. }
  239. // 创建预警项数据
  240. if err := tx.Create(model.NewDataWarningItems(userId, dataWarning, set)).Error; err != nil {
  241. return xerr.WithStack(err)
  242. }
  243. addedKinds[set.Kind] = true
  244. }
  245. return nil
  246. })
  247. }
  248. // 更新用户预警数据
  249. func (s *StoreEntry) updateUserDataWarning(ctx context.Context, userId int64, userDataWarningList []*model.DataWarning, warningDataSet []*pasturePb.WarningDataSet) error {
  250. // 将请求数据按 WarningId 和 Id 映射
  251. warningIsShowMap := make(map[int32]pasturePb.IsShow_Kind)
  252. warningItemDataMap := make(map[int32]*pasturePb.WarningDataSet)
  253. for _, set := range warningDataSet {
  254. warningIsShowMap[set.WarningId] = set.IsShow
  255. warningItemDataMap[set.Id] = set
  256. }
  257. // 获取用户预警项数据
  258. userDataWarningItems, err := s.FindDataWarningItems(ctx, userId)
  259. if err != nil {
  260. return xerr.WithStack(err)
  261. }
  262. if len(userDataWarningItems) == 0 {
  263. return xerr.Custom("预警数据有误,请联系管理员!")
  264. }
  265. // 在事务中执行更新操作
  266. return s.DB.Transaction(func(tx *gorm.DB) error {
  267. // 更新预警数据的 IsShow 字段
  268. for _, warning := range userDataWarningList {
  269. if isShow, ok := warningIsShowMap[int32(warning.Id)]; ok {
  270. if err = tx.Model(&model.DataWarning{}).
  271. Where("id = ?", warning.Id).
  272. Update("is_show", isShow).Error; err != nil {
  273. return xerr.WithStack(err)
  274. }
  275. }
  276. }
  277. // 更新预警项数据的 IsShow 和 Value 字段
  278. for _, item := range userDataWarningItems {
  279. if set, ok := warningItemDataMap[int32(item.Id)]; ok {
  280. if err = tx.Model(&model.DataWarningItems{}).
  281. Where("id = ?", item.Id).
  282. Updates(map[string]interface{}{
  283. "is_show": set.IsShow,
  284. "value": set.Value,
  285. }).Error; err != nil {
  286. return xerr.WithStack(err)
  287. }
  288. }
  289. }
  290. return nil
  291. })
  292. }
  293. func (s *StoreEntry) FindDataWarning(ctx context.Context, userId int64) ([]*model.DataWarning, error) {
  294. dataWarningList := make([]*model.DataWarning, 0)
  295. if err := s.DB.Model(new(model.DataWarning)).
  296. Where("user_id = ?", userId).
  297. Find(&dataWarningList).Error; err != nil {
  298. return nil, xerr.WithStack(err)
  299. }
  300. return dataWarningList, nil
  301. }
  302. func (s *StoreEntry) FindDataWarningItems(ctx context.Context, userId int64) ([]*model.DataWarningItems, error) {
  303. dataWarningItemsList := make([]*model.DataWarningItems, 0)
  304. if err := s.DB.Model(new(model.DataWarningItems)).
  305. Where("user_id = ?", userId).
  306. Find(&dataWarningItemsList).Error; err != nil {
  307. return nil, xerr.WithStack(err)
  308. }
  309. return dataWarningItemsList, nil
  310. }
  311. func (s *StoreEntry) FindDataWarningMap(ctx context.Context, userId int64) (map[int64]*model.DataWarning, error) {
  312. dataWarning, err := s.FindDataWarning(ctx, userId)
  313. if err != nil {
  314. return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
  315. }
  316. dataWarningMap := make(map[int64]*model.DataWarning)
  317. for _, v := range dataWarning {
  318. dataWarningMap[v.Id] = v
  319. }
  320. return dataWarningMap, nil
  321. }
  322. func (s *StoreEntry) FindDataWarningItemsMap(ctx context.Context, userId int64) (map[int64]*model.DataWarningItems, error) {
  323. dataWarningItemsList := make([]*model.DataWarningItems, 0)
  324. if err := s.DB.Model(new(model.DataWarningItems)).
  325. Where("user_id = ?", userId).
  326. Find(&dataWarningItemsList).Error; err != nil {
  327. return nil, xerr.WithStack(err)
  328. }
  329. dataWarningItemsMap := make(map[int64]*model.DataWarningItems)
  330. for _, v := range dataWarningItemsList {
  331. dataWarningItemsMap[v.Id] = v
  332. }
  333. return dataWarningItemsMap, nil
  334. }
  335. // UpdateWarningData 更新计算数据
  336. func (s *StoreEntry) UpdateWarningData(ctx context.Context, needUpdateWarningIds []int64) {
  337. if len(needUpdateWarningIds) <= 0 {
  338. return
  339. }
  340. for _, warningId := range needUpdateWarningIds {
  341. query, params, err := s.BuildQuery(warningId)
  342. if err != nil {
  343. zaplog.Error("UpdateWarningData", zap.Any("BuildQuery", err), zap.Any("warningId", warningId))
  344. }
  345. if len(query) == 0 || len(params) == 0 {
  346. continue
  347. }
  348. var count int64
  349. if err = s.DB.Model(new(model.Cow)).Where(query, params...).Count(&count).Error; err != nil {
  350. zaplog.Error("UpdateWarningData", zap.Any("err", err), zap.Any("query", query), zap.Any("params", params))
  351. }
  352. if err = s.DB.Model(new(model.DataWarning)).
  353. Where("id = ?", warningId).
  354. Updates(map[string]interface{}{
  355. "data_value": count,
  356. "data_update_at": time.Now().Unix(),
  357. }).Error; err != nil {
  358. zaplog.Error("UpdateWarningData", zap.Any("update", err))
  359. }
  360. }
  361. }