dashboard.go 14 KB

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