dashboard.go 14 KB

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