dashboard.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package backend
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "kpt-pasture/model"
  7. "kpt-pasture/util"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "gorm.io/gorm"
  13. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  14. "go.uber.org/zap"
  15. "gitee.com/xuyiping_admin/pkg/xerr"
  16. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  17. )
  18. func (s *StoreEntry) Bar(ctx context.Context) (*pasturePb.BarCowStructResponse, error) {
  19. barCowStructList := make([]*model.BarCowStruct, 0)
  20. var count int32 = 0
  21. if err := s.DB.Model(new(model.Cow)).
  22. Select("COUNT(*) AS number ,cow_type").
  23. Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
  24. Group("cow_type").
  25. Find(&barCowStructList).Error; err != nil {
  26. return nil, xerr.WithStack(err)
  27. }
  28. cowTypeMap := s.CowTypeMap()
  29. for _, v := range barCowStructList {
  30. count += v.Number
  31. }
  32. return &pasturePb.BarCowStructResponse{
  33. Code: http.StatusOK,
  34. Msg: "ok",
  35. Data: &pasturePb.BarCowStructData{
  36. List: model.BarCowStructSlice(barCowStructList).ToPB(cowTypeMap, count),
  37. Total: 38563,
  38. },
  39. }, nil
  40. }
  41. func (s *StoreEntry) NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckRingResponse, error) {
  42. userModel, err := s.GetUserModel(ctx)
  43. if err != nil {
  44. return nil, xerr.WithStack(err)
  45. }
  46. estrusWarningCowList := make([]*model.NeckRingEstrus, 0)
  47. estrusWarningLevelItems := map[int32]int32{
  48. int32(pasturePb.EstrusLevel_Low): 0,
  49. int32(pasturePb.EstrusLevel_Middle): 0,
  50. int32(pasturePb.EstrusLevel_High): 0,
  51. }
  52. if err = s.DB.Model(new(model.EventEstrus)).
  53. Where("pasture_id = ?", userModel.AppPasture.Id).
  54. Where("is_show = ?", pasturePb.IsShow_Ok).
  55. Group("cow_id").Find(&estrusWarningCowList).Error; err != nil {
  56. zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
  57. }
  58. for _, v := range estrusWarningCowList {
  59. estrusWarningLevelItems[int32(v.Level)] += estrusWarningLevelItems[int32(v.Level)]
  60. }
  61. healthWarningNumber := int64(0)
  62. if err = s.DB.Model(new(model.NeckRingHealthWarning)).
  63. Where("pasture_id = ?", userModel.AppPasture.Id).
  64. Where("is_show = ?", pasturePb.IsShow_Ok).
  65. Group("cow_id").
  66. Count(&healthWarningNumber).Error; err != nil {
  67. zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
  68. }
  69. return &pasturePb.IndexNeckRingResponse{
  70. Code: http.StatusOK,
  71. Msg: "ok",
  72. Data: &pasturePb.NeckRingData{
  73. EstrusWarningNumber: int32(len(estrusWarningCowList)),
  74. HealthWarningNumber: int32(healthWarningNumber),
  75. AbortionWarningNumber: 0,
  76. StressWarningNumber: 0,
  77. EstrusWarningLevelItems: estrusWarningLevelItems,
  78. },
  79. }, nil
  80. }
  81. func (s *StoreEntry) FocusIndicatorsList(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error) {
  82. userModel, err := s.GetUserModel(ctx)
  83. if err != nil {
  84. return nil, xerr.WithStack(err)
  85. }
  86. userFocusIndicators := userModel.SystemUser.IndicatorsKinds
  87. if len(userFocusIndicators) <= 0 {
  88. userFocusIndicators = model.DefaultFocusIndicators
  89. }
  90. userFocusIndicatorsList := strings.Split(userFocusIndicators, ",")
  91. indicatorsDataList := make([]*model.IndicatorsData, 0)
  92. pref := s.DB.Model(new(model.IndicatorsData)).
  93. Where("pasture_id = ?", userModel.AppPasture.Id).
  94. Where("kind in (?)", userFocusIndicatorsList)
  95. /*if dimension == "Year" {
  96. pref.Where("date = ?", time.Now().Format(model.LayoutMonth))
  97. }*/
  98. nowTime := time.Now()
  99. if dimension == "Month" {
  100. pref.Where("date = ?", nowTime.Format(model.LayoutMonth))
  101. }
  102. if err = pref.Find(&indicatorsDataList).Error; err != nil {
  103. zaplog.Error("FocusIndicators", zap.Any("err", err))
  104. }
  105. indicatorsDetailsMap, err := s.GetIndicatorsDetailsMap(ctx)
  106. if err != nil {
  107. return nil, xerr.WithStack(err)
  108. }
  109. focusIndicatorsList := make([]*pasturePb.FocusIndicators, 0)
  110. for _, v := range indicatorsDataList {
  111. indicatorsDetails, ok := indicatorsDetailsMap[v.Kind]
  112. if !ok {
  113. continue
  114. }
  115. onYear, onMonth := "", ""
  116. if dimension == "Year" {
  117. return nil, xerr.Custom("暂不支持该维度")
  118. }
  119. if dimension == "Month" {
  120. lastMonth := nowTime.AddDate(0, -1, 0).Format(model.LayoutMonth)
  121. oldIndicators, _ := s.GetIndicatorsDataByDate(userModel.AppPasture.Id, v.Kind, lastMonth)
  122. if oldIndicators != nil {
  123. if oldIndicators.Value != "" && oldIndicators.Value != "0" {
  124. oldValue, _ := strconv.ParseFloat(oldIndicators.Value, 64)
  125. currValue, _ := strconv.ParseFloat(v.Value, 64)
  126. onMonthValue := (oldValue - currValue) / oldValue * 100
  127. omv := util.RoundToTwoDecimals(onMonthValue)
  128. onMonth = strconv.FormatFloat(omv, 'f', 2, 64) + "%"
  129. }
  130. }
  131. }
  132. focusIndicatorsList = append(focusIndicatorsList, &pasturePb.FocusIndicators{
  133. Kind: indicatorsDetails.Kind,
  134. Name: indicatorsDetails.Name,
  135. Value: v.Value,
  136. Describe: indicatorsDetails.Zh,
  137. UnitName: indicatorsDetails.Unit,
  138. OnMonth: onMonth,
  139. OnYear: onYear,
  140. })
  141. }
  142. indicatorsDetailsList, _ := s.FindIndicatorsDetailsList(ctx)
  143. return &pasturePb.IndexFocusIndicatorsResponse{
  144. Code: http.StatusOK,
  145. Msg: "ok",
  146. Data: &pasturePb.FocusData{
  147. FocusIndicators: focusIndicatorsList,
  148. IndicatorsSet: model.IndicatorsDetailsSlice(indicatorsDetailsList).ToPB(userFocusIndicatorsList),
  149. },
  150. }, err
  151. }
  152. func (s *StoreEntry) FocusIndicatorsSet(ctx context.Context, req *pasturePb.IndexFocusIndicatorsSetRequest) error {
  153. userModel, err := s.GetUserModel(ctx)
  154. if err != nil {
  155. return xerr.WithStack(err)
  156. }
  157. if len(req.IndicatorsKind) <= 0 {
  158. return nil
  159. }
  160. userFocusIndicators := strings.Join(req.IndicatorsKind, ",")
  161. if err = s.DB.Model(new(model.SystemUser)).
  162. Where("id = ?", userModel.SystemUser.Id).
  163. Update("indicators_kinds", userFocusIndicators).Error; err != nil {
  164. return xerr.WithStack(err)
  165. }
  166. return nil
  167. }
  168. func (s *StoreEntry) DataWarningSet(ctx context.Context, req *pasturePb.IndexDataWarningSetRequest) error {
  169. userModel, err := s.GetUserModel(ctx)
  170. if err != nil {
  171. return xerr.WithStack(err)
  172. }
  173. if len(req.WarningDataSet) <= 0 {
  174. return nil
  175. }
  176. currentUserDataWarningList, err := s.FindDataWarning(ctx, userModel.SystemUser.Id)
  177. fmt.Println(currentUserDataWarningList)
  178. if errors.Is(err, gorm.ErrRecordNotFound) {
  179. // 如果不存在则新增
  180. defaultDataWarningMap, err := s.defaultDataWarningMap(ctx)
  181. if err != nil {
  182. return xerr.WithStack(err)
  183. }
  184. dataWarningList := model.NewDataWarningList(userModel.SystemUser.Id, req.WarningDataSet, defaultDataWarningMap)
  185. fmt.Println(dataWarningList)
  186. } else {
  187. return xerr.WithStack(err)
  188. }
  189. return nil
  190. }
  191. func (s *StoreEntry) DataWarningList(ctx context.Context) (*pasturePb.IndexDataWarningResponse, error) {
  192. userModel, err := s.GetUserModel(ctx)
  193. if err != nil {
  194. return nil, xerr.WithStack(err)
  195. }
  196. defaultUserDataWarningList, err := s.FindDataWarning(ctx, model.DefaultUserId)
  197. if err != nil {
  198. return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
  199. }
  200. var isExist bool // 判断是否存在自己的设置的数据
  201. currentUserDataWarningList, err := s.FindDataWarning(ctx, userModel.SystemUser.Id)
  202. if errors.Is(err, gorm.ErrRecordNotFound) {
  203. // 如果用户没有配置自己的预警数据,则使用默认数据
  204. isExist = true
  205. currentUserDataWarningList = defaultUserDataWarningList
  206. } else {
  207. return nil, xerr.WithStack(err)
  208. }
  209. newTime := time.Now().Unix()
  210. needUpdateWarningIds := make([]int64, 0)
  211. warningMap := make(map[int64]*model.DataWarning)
  212. for _, warningData := range currentUserDataWarningList {
  213. warningMap[warningData.Id] = warningData
  214. // 如果预警数据更新时间大于预警条件更新时间,并且更新时间距离当前时间小于2小时,则跳过
  215. if warningData.DataUpdateAt > warningData.ConditionUpdateAt && newTime-warningData.DataUpdateAt < int64(2*time.Hour) {
  216. continue
  217. }
  218. needUpdateWarningIds = append(needUpdateWarningIds, warningData.Id)
  219. }
  220. // 需要重新计算更新的warningId
  221. if len(needUpdateWarningIds) > 0 {
  222. s.UpdateWarningData(ctx, needUpdateWarningIds)
  223. }
  224. if isExist {
  225. currentUserDataWarningList, _ = s.FindDataWarning(ctx, model.DefaultUserId)
  226. } else {
  227. currentUserDataWarningList, _ = s.FindDataWarning(ctx, userModel.SystemUser.Id)
  228. }
  229. dataSet := make([]*pasturePb.WarningDataSet, 0)
  230. dataShow := make([]*pasturePb.WarningDataShow, 0)
  231. for _, warningData := range currentUserDataWarningList {
  232. dataUpdateTimeFormat := ""
  233. if warningData.DataUpdateAt > 0 {
  234. dataUpdateTimeFormat = time.Unix(warningData.DataUpdateAt, 0).Format(model.LayoutTime)
  235. }
  236. dataShow = append(dataShow, &pasturePb.WarningDataShow{
  237. Name: warningData.Name,
  238. Number: warningData.DataValue,
  239. Describe: warningData.Description,
  240. DataUpdateTimeFormat: dataUpdateTimeFormat,
  241. })
  242. }
  243. defaultDataWarningItems, err := s.FindDataWarningItems(ctx, model.DefaultUserId)
  244. fmt.Println(defaultDataWarningItems)
  245. return &pasturePb.IndexDataWarningResponse{
  246. Code: http.StatusOK,
  247. Msg: "ok",
  248. Data: &pasturePb.DataWarning{
  249. DataSet: dataSet,
  250. DataShow: dataShow,
  251. },
  252. }, nil
  253. }
  254. func (s *StoreEntry) FindDataWarning(ctx context.Context, userId int64) ([]*model.DataWarning, error) {
  255. defaultUserDataWarningList := make([]*model.DataWarning, 0)
  256. if err := s.DB.Model(new(model.DataWarning)).
  257. Where("user_id = ?", userId).
  258. Find(&defaultUserDataWarningList).Error; err != nil {
  259. return nil, xerr.WithStack(err)
  260. }
  261. return defaultUserDataWarningList, nil
  262. }
  263. func (s *StoreEntry) FindDataWarningItems(ctx context.Context, userId int64) ([]*model.DataWarningItems, error) {
  264. defaultUserDataWarningItemsList := make([]*model.DataWarningItems, 0)
  265. if err := s.DB.Model(new(model.DataWarningItems)).
  266. Where("user_id = ?", userId).
  267. Find(&defaultUserDataWarningItemsList).Error; err != nil {
  268. return nil, xerr.WithStack(err)
  269. }
  270. return defaultUserDataWarningItemsList, nil
  271. }
  272. func (s *StoreEntry) defaultDataWarningMap(ctx context.Context) (map[string]*model.DataWarning, error) {
  273. defaultDataWarning, err := s.FindDataWarning(ctx, model.DefaultUserId)
  274. if err != nil {
  275. return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
  276. }
  277. defaultDataWarningMap := make(map[string]*model.DataWarning)
  278. for _, v := range defaultDataWarning {
  279. defaultDataWarningMap[v.Kind] = v
  280. }
  281. return defaultDataWarningMap, nil
  282. }
  283. // UpdateWarningData 更新计算数据
  284. func (s *StoreEntry) UpdateWarningData(ctx context.Context, needUpdateWarningIds []int64) {
  285. if len(needUpdateWarningIds) <= 0 {
  286. return
  287. }
  288. for _, warningId := range needUpdateWarningIds {
  289. query, params, err := s.BuildQuery(warningId)
  290. if err != nil {
  291. zaplog.Error("UpdateWarningData", zap.Any("BuildQuery", err), zap.Any("warningId", warningId))
  292. }
  293. if len(query) == 0 || len(params) == 0 {
  294. continue
  295. }
  296. var count int64
  297. if err = s.DB.Model(new(model.Cow)).Where(query, params...).Count(&count).Error; err != nil {
  298. zaplog.Error("UpdateWarningData", zap.Any("err", err), zap.Any("query", query), zap.Any("params", params))
  299. }
  300. if err = s.DB.Model(new(model.DataWarning)).
  301. Where("id = ?", warningId).
  302. Updates(map[string]interface{}{
  303. "data_value": count,
  304. "data_update_at": time.Now().Unix(),
  305. }).Error; err != nil {
  306. zaplog.Error("UpdateWarningData", zap.Any("update", err))
  307. }
  308. }
  309. }