package backend import ( "context" "errors" "fmt" "kpt-pasture/model" "kpt-pasture/util" "net/http" "strconv" "strings" "time" "gorm.io/gorm" "gitee.com/xuyiping_admin/pkg/xerr" pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow" ) func (s *StoreEntry) Detail(ctx context.Context, req *pasturePb.SearchEventRequest) (*pasturePb.CowInfoResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } cowInfo := &model.Cow{} pref := s.DB.Model(new(model.Cow)). Where("pasture_id = ?", userModel.AppPasture.Id) if req.CowId != "" { cowId, _ := strconv.Atoi(req.CowId) pref.Where("id = ?", cowId) } if req.NeckRingNumber != "" { pref.Where("neck_ring_number = ?", req.NeckRingNumber) } if req.EarNumber != "" { pref.Where("ear_number = ?", req.EarNumber) } if err = pref.Order("id desc"). First(cowInfo).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, xerr.Custom("该牛只未找到") } else { return nil, xerr.WithStack(err) } } penMap := s.PenMap(ctx, userModel.AppPasture.Id) cowTypeMap := s.CowTypeMap() breedStatusMap := s.CowBreedStatusMap() cowKindMap := s.CowKindMap() cowSourceMap := s.CowSourceMap() admissionStatusMap := s.AdmissionStatusMap() healthStatusMap := s.HealthStatusMap() return &pasturePb.CowInfoResponse{ Code: http.StatusOK, Msg: "ok", Data: model.CowSlice([]*model.Cow{cowInfo}).ToPB(penMap, cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap, admissionStatusMap, healthStatusMap)[0], }, nil } func (s *StoreEntry) List(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchCowListResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } cowList := make([]*model.Cow, 0) var count int64 = 0 pref := s.DB.Model(new(model.Cow)). Where("pasture_id = ?", userModel.AppPasture.Id) if len(req.CowId) > 0 { cowIds := strings.Split(req.CowId, ",") pref.Where("id IN ?", cowIds) } if req.Id > 0 { pref.Where("id = ?", req.Id) } if req.PenId > 0 { pref.Where("pen_id = ?", req.PenId) } if req.CowType > 0 { pref.Where("cow_type = ?", req.CowType) } if req.BreedStatus > 0 { pref.Where("breed_status = ?", req.BreedStatus) } if req.CowKind > 0 { pref.Where("cow_kind = ?", req.CowKind) } if req.Sex > 0 { pref.Where("sex = ?", req.Sex) } if req.Lact > 0 { pref.Where("lact = ?", req.Lact) } if req.CowSource > 0 { pref.Where("source_id = ?", req.CowSource) } if req.EarNumber != "" { pref.Where("ear_number = ?", req.EarNumber) } if err = pref.Order("id desc"). Count(&count). Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&cowList).Error; err != nil { return nil, xerr.WithStack(err) } penMap := s.PenMap(ctx, userModel.AppPasture.Id) cowTypeMap := s.CowTypeMap() breedStatusMap := s.CowBreedStatusMap() cowKindMap := s.CowKindMap() cowSourceMap := s.CowSourceMap() admissionStatusMap := s.AdmissionStatusMap() healthStatusMap := s.HealthStatusMap() return &pasturePb.SearchCowListResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchCowData{ List: model.CowSlice(cowList).ToPB( penMap, cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap, admissionStatusMap, healthStatusMap, ), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) EventList(ctx context.Context, req *pasturePb.SearchCowEventListRequest, pagination *pasturePb.PaginationModel) (*pasturePb.CowEventListResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } eventCowLogList := make([]*model.EventCowLog, 0) eventCowLog := &model.EventCowLog{CowId: int64(req.CowId)} pref := s.DB.Table(eventCowLog.TableName()). Where("cow_id = ?", req.CowId).Where("pasture_id = ?", userModel.AppPasture.Id) if req.Lact >= 0 { pref.Where("lact = ?", req.Lact) } if req.EventCategoryKind > 0 { pref.Where("event_type = ?", req.EventCategoryKind) } if err = pref.Order("id desc"). Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&eventCowLogList).Error; err != nil { return nil, xerr.WithStack(err) } eventCategoryMap := s.EventCategoryMap() return &pasturePb.CowEventListResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.CowEventData{ List: model.EventCowLogSlice(eventCowLogList).ToPB(eventCategoryMap), Total: int32(len(eventCowLogList)), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*model.CowBehaviorCurveResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } cowInfo, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId)) if err != nil { return nil, xerr.Customf("错误的牛只信息: %d", req.CowId) } nowTime := time.Now() nowDayZero := util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2)) endDataTime := nowTime.Format(model.LayoutDate2) startDataTime := nowTime.AddDate(0, 0, -30).Format(model.LayoutDate2) // 行为曲线数据 neckActiveHabitList := make([]*model.NeckActiveHabit, 0) if err = s.DB.Table(new(model.NeckActiveHabit).TableName()). Where("neck_ring_number = ?", cowInfo.NeckRingNumber). Where("pasture_id = ?", userModel.AppPasture.Id). Where("heat_date BETWEEN ? AND ?", startDataTime, endDataTime). Order("heat_date, frameid"). Find(&neckActiveHabitList).Error; err != nil { return nil, xerr.WithStack(err) } // 牛只事件列表 eventLogList := make([]*model.EventCowLog, 0) eventLog := &model.EventCowLog{CowId: cowInfo.Id} if err = s.DB.Table(eventLog.TableName()). Where("cow_id = ?", cowInfo.Id). Where("pasture_id = ?", userModel.AppPasture.Id). Where("event_at BETWEEN ? AND ?", nowDayZero-(30*86400), nowDayZero+86400). Order("event_at"). Find(&eventLogList).Error; err != nil { return nil, xerr.WithStack(err) } data := model.NeckActiveHabitSlice(neckActiveHabitList).ToPB(req.CurveName, startDataTime, endDataTime) data.EventMap = s.EventTypeMap() for _, v := range eventLogList { eventAt := time.Unix(v.EventAt, 0) if data.EventList[v.EventTypeName] == nil { data.EventList[v.EventTypeName] = make([]string, 0) } data.EventList[v.EventTypeName] = append(data.EventList[v.EventTypeName], fmt.Sprintf("%s 09", eventAt.Format(model.LayoutDate2))) } // 发情数据 estrusList := make([]*model.NeckRingEstrus, 0) if err = s.DB.Table(new(model.NeckRingEstrus).TableName()). Where("cow_id = ?", cowInfo.Id). Where("pasture_id = ?", userModel.AppPasture.Id). Where("estrus_start_date >= ?", startDataTime). Where("estrus_start_date <= ?", endDataTime). Order("estrus_start_date"). Find(&estrusList).Error; err != nil { return nil, xerr.WithStack(err) } for _, v := range estrusList { if data.EstrusList[v.Level] == nil { data.EstrusList[v.Level] = make([]string, 0) } if len(v.EstrusStartDate) > 0 { // 格式化为到小时的字符串 parsedTime, _ := time.Parse(model.LayoutTime, v.EstrusStartDate) hourStr := parsedTime.Format(model.LayoutHour) data.EstrusList[v.Level] = append(data.EstrusList[v.Level], hourStr) } } return &model.CowBehaviorCurveResponse{ Code: http.StatusOK, Msg: "ok", Data: data, }, nil } func (s *StoreEntry) CowGrowthCurve(ctx context.Context, req *pasturePb.CowGrowthCurveRequest) (*pasturePb.CowGrowthCurveResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } cowInfo, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId)) if err != nil { return nil, xerr.Customf("错误的牛只信息: %d", req.CowId) } weightList := make([]*model.EventWeight, 0) if err = s.DB.Table(new(model.EventWeight).TableName()). Where("cow_id = ?", cowInfo.Id). Where("pasture_id = ?", userModel.AppPasture.Id). Order("weight_at"). Find(&weightList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.CowGrowthCurveResponse{ Code: http.StatusOK, Msg: "ok", Data: model.EventWeightSlice(weightList).ToPB(), }, nil }