Yi 4 дней назад
Родитель
Сommit
709938ed67
6 измененных файлов с 184 добавлено и 61 удалено
  1. 1 1
      go.mod
  2. 8 0
      go.sum
  3. 140 44
      model/cow.go
  4. 25 2
      module/backend/cow.go
  5. 8 0
      module/backend/enum_map.go
  6. 2 14
      module/crontab/milk_daily.go

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250412093307-d7a38b54919d
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250414061726-cf591d3e4e66
 	gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3

+ 8 - 0
go.sum

@@ -38,6 +38,12 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250412093307-d7a38b54919d h1:WhYvj5DAdpH4lDALEDOB29JnRwuc3Zk1nP+5K3bddZE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250412093307-d7a38b54919d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414040639-40b4f13de9bf h1:yiMpIbAvXY/pf7CdWBXWwZbhrqYI1c70naYEF6sjK78=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414040639-40b4f13de9bf/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414060036-6d016734b75e h1:4G5Qytt6KNPTrMP/BZ5YCpCQrOBBUrOHbr4mgO5qDHw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414060036-6d016734b75e/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414061726-cf591d3e4e66 h1:9MiP71UwVhQsKBdSY2M0re1kaLHQh+3Om4vXzMpTj44=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250414061726-cf591d3e4e66/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b h1:w05MxH7yqveRlaRbxHhbif5YjPrJFodRPfOjYhXn7Zk=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -173,6 +179,7 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
@@ -611,6 +618,7 @@ go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM=
 go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI=
 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=

+ 140 - 44
model/cow.go

@@ -46,9 +46,12 @@ type Cow struct {
 	BirthAt               int64                          `json:"birthAt"`               // 出生时间
 	AdmissionAt           int64                          `json:"admissionAt"`           // 入场时间
 	DepartureAt           int64                          `json:"departureAt"`           // 离场时间
+	DeparturePrice        float32                        `json:"departurePrice"`        // 离场价格
+	DepartureAvgWeight    int32                          `json:"departureAvgWeight"`    // 离场平均体重
 	FirstMatingAt         int64                          `json:"firstMatingAt"`         // 首次配种时间
 	MatingTimes           int32                          `json:"matingTimes"`           // 配种次数
 	AbortionTimes         int32                          `json:"abortionTimes"`         // 流产次数
+	PregnancyCheckName    string                         `json:"pregnancyCheckName"`    // 孕检名称
 	WeeklyActive          int32                          `json:"weeklyActive"`          // 每周活跃度
 	LastEstrusAt          int64                          `json:"lastEstrusAt"`          // 最后一次发情时间
 	LastCalvingAt         int64                          `json:"lastCalvingAt"`         // 最后一次产犊时间
@@ -215,6 +218,18 @@ func (c *Cow) UnForbiddenMatingUpdate() {
 	c.BreedStatus = pasturePb.BreedStatus_UnBreed
 }
 
+// GetAvgDailyWeight 牛只平均日增重
+func (c *Cow) GetAvgDailyWeight() float32 {
+	if c.AdmissionAge <= 0 {
+		c.AdmissionAge = c.GetAdmissionAge()
+	}
+
+	if c.AdmissionAge <= 0 {
+		return 0
+	}
+	return float32(c.CurrentWeight-c.AdmissionWeight) / 1000 / float32(c.AdmissionAge)
+}
+
 type CowSlice []*Cow
 
 func (c CowSlice) ToPB(
@@ -224,6 +239,8 @@ func (c CowSlice) ToPB(
 	cowSourceMap map[pasturePb.CowSource_Kind]string,
 	admissionStatusMap map[pasturePb.AdmissionStatus_Kind]string,
 	healthStatusMap map[pasturePb.HealthStatus_Kind]string,
+	purposeMap map[pasturePb.Purpose_Kind]string,
+	pregnancyAge int32,
 ) []*pasturePb.CowDetails {
 	res := make([]*pasturePb.CowDetails, len(c))
 	for i, v := range c {
@@ -288,44 +305,111 @@ func (c CowSlice) ToPB(
 			lastSecondWeightAtFormat = time.Unix(v.LastSecondWeightAt, 0).Format(LayoutDate2)
 		}
 
+		departureAtFormat := ""
+		if v.DepartureAt > 0 {
+			departureAtFormat = time.Unix(v.DepartureAt, 0).Format(LayoutDate2)
+		}
+
+		lastForbiddenMatingAtFormat := ""
+		if v.LastForbiddenMatingAt > 0 {
+			lastForbiddenMatingAtFormat = time.Unix(v.LastForbiddenMatingAt, 0).Format(LayoutDate2)
+		}
+
+		lastEstrusAtFormat := ""
+		if v.LastEstrusAt > 0 {
+			lastEstrusAtFormat = time.Unix(v.LastEstrusAt, 0).Format(LayoutDate2)
+		}
+
+		cowTypeName := ""
+		if cn, ok := cowTypeMap[v.CowType]; ok {
+			cowTypeName = cn
+		}
+
+		breedStatusName := ""
+		if bs, ok := breedStatusMap[v.BreedStatus]; ok {
+			breedStatusName = bs
+		}
+
+		cowKindName := ""
+		if ck, ok := cowKindMap[v.CowKind]; ok {
+			cowKindName = ck
+		}
+
+		sourceName := ""
+		if sn, ok := cowSourceMap[v.SourceKind]; ok {
+			sourceName = sn
+		}
+
+		admissionStatusName := ""
+		if as, ok := admissionStatusMap[v.AdmissionStatus]; ok {
+			admissionStatusName = as
+		}
+
+		healthStatusName := ""
+		if hs, ok := healthStatusMap[v.HealthStatus]; ok {
+			healthStatusName = hs
+		}
+
+		pregnancyDate := ""
+		if pregnancyAgeAt := v.GetDaysPregnancy(pregnancyAge); pregnancyAgeAt > 0 {
+			pregnancyDate = time.Unix(int64(pregnancyAge), 0).Local().Format(LayoutDate2)
+		}
+
+		purposeName := ""
+		if pn, ok := purposeMap[v.PurposeKind]; ok {
+			purposeName = pn
+		}
+
 		res[i] = &pasturePb.CowDetails{
-			CowId:                     int32(v.Id),
-			Sex:                       sex,
-			NeckRingNumber:            v.NeckRingNumber,
-			PenName:                   v.PenName,
-			Lact:                      v.Lact,
-			CowTypeName:               cowTypeMap[v.CowType],
-			CowType:                   v.CowType,
-			BreedStatusName:           breedStatusMap[v.BreedStatus],
-			BreedStatus:               v.BreedStatus,
-			CowKindName:               cowKindMap[v.CowKind],
-			EarNumber:                 v.EarNumber,
-			BirthWeight:               float32(v.BirthWeight) / 1000,
-			CurrentWeight:             float32(v.CurrentWeight) / 1000,
-			CurrentHeight:             int32(v.CurrentHeight),
-			DayAge:                    v.DayAge,
-			AdmissionAge:              v.AdmissionAge,
-			SourceName:                cowSourceMap[v.SourceKind],
-			MotherNumber:              v.MotherNumber,
-			FatherNumber:              v.FatherNumber,
-			AdmissionStatusName:       admissionStatusMap[v.AdmissionStatus],
-			HealthStatusName:          healthStatusMap[v.HealthStatus],
-			IsPregnantName:            isPregnantName,
-			AdmissionAtFormat:         admissionAtFormat,
-			BirthAtFormat:             birthAtFormat,
-			WeaningAtFormat:           weaningAtFormat,
-			CalvingAge:                v.GetCalvingAge(),
-			AbortionAge:               v.AbortionAge,
-			MatingTimes:               v.MatingTimes,
-			FirstMatingAtFormat:       firstMatingAtFormat,
-			LastMatingAtFormat:        lastMatingAtFormat,
-			LastBullNumber:            v.LastBullNumber,
-			LastPregnantCheckAtFormat: lastPregnantCheckAtFormat,
-			LastWeightAtFormat:        lastWeightAtFormat,
-			LastCalvingAtFormat:       lastCalvingAtFormat,
-			LastAbortionAtFormat:      lastAbortionAtFormat,
-			LastSecondWeight:          float32(v.LastSecondWeight) / 1000,
-			LastSecondWeightAtFormat:  lastSecondWeightAtFormat,
+			CowId:                       int32(v.Id),
+			Sex:                         sex,
+			NeckRingNumber:              v.NeckRingNumber,
+			PenName:                     v.PenName,
+			Lact:                        v.Lact,
+			CowTypeName:                 cowTypeName,
+			CowType:                     v.CowType,
+			BreedStatusName:             breedStatusName,
+			BreedStatus:                 v.BreedStatus,
+			CowKindName:                 cowKindName,
+			EarNumber:                   v.EarNumber,
+			BirthWeight:                 float32(v.BirthWeight) / 1000,
+			CurrentWeight:               float32(v.CurrentWeight) / 1000,
+			CurrentHeight:               int32(v.CurrentHeight),
+			DayAge:                      v.DayAge,
+			AdmissionAge:                v.AdmissionAge,
+			SourceName:                  sourceName,
+			MotherNumber:                v.MotherNumber,
+			FatherNumber:                v.FatherNumber,
+			AdmissionStatusName:         admissionStatusName,
+			HealthStatusName:            healthStatusName,
+			IsPregnantName:              isPregnantName,
+			AdmissionAtFormat:           admissionAtFormat,
+			BirthAtFormat:               birthAtFormat,
+			WeaningAtFormat:             weaningAtFormat,
+			CalvingAge:                  v.GetCalvingAge(),
+			AbortionAge:                 v.AbortionAge,
+			MatingTimes:                 v.MatingTimes,
+			AbortionTimes:               v.AbortionTimes,
+			FirstMatingAtFormat:         firstMatingAtFormat,
+			LastMatingAtFormat:          lastMatingAtFormat,
+			LastBullNumber:              v.LastBullNumber,
+			LastPregnantCheckAtFormat:   lastPregnantCheckAtFormat,
+			LastWeightAtFormat:          lastWeightAtFormat,
+			LastCalvingAtFormat:         lastCalvingAtFormat,
+			LastAbortionAtFormat:        lastAbortionAtFormat,
+			LastSecondWeight:            float32(v.LastSecondWeight) / 1000,
+			LastSecondWeightAtFormat:    lastSecondWeightAtFormat,
+			DepartureAtFormat:           departureAtFormat,
+			DeparturePrice:              v.DeparturePrice,
+			DepartureWeight:             float32(v.DepartureAvgWeight / 1000),
+			LastForbiddenMatingAtFormat: lastForbiddenMatingAtFormat,
+			LastEstrusAtFormat:          lastEstrusAtFormat,
+			PregnancyDate:               pregnancyDate,
+			PregnancyCheckTimes:         v.PregnancyCheckName,
+			AvgDailyWeight:              float32(v.GetAverageDailyWeight()),
+			EleEarNumber:                v.EleEarNumber,
+			AdmissionPrice:              float32(v.AdmissionWeight / 1000),
+			PurposeName:                 purposeName,
 		}
 	}
 	return res
@@ -494,6 +578,16 @@ func (c *Cow) GetDaysPregnant() int32 {
 	return 0
 }
 
+// GetDaysPregnancy 牛只预产日期
+func (c *Cow) GetDaysPregnancy(pregnancyAgeValue int32) int32 {
+	if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
+		c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
+		c.IsPregnant == pasturePb.IsShow_Ok {
+		return int32(math.Floor(float64(c.LastMatingAt + int64(pregnancyAgeValue)*86400)))
+	}
+	return 0
+}
+
 // GetLactationDays 泌乳天数
 func (c *Cow) GetLactationDays() int32 {
 	if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
@@ -510,18 +604,20 @@ func (c *Cow) GetAdmissionAge() int32 {
 	return 0
 }
 
-// GetAverageDailyWeight 平均日增重 (最后一次称重 -  第一次称重 ) ÷ 在群天数
+// GetAverageDailyWeight 平均日增重 (最后一次称重 -  入场体重 ) ÷ 在群天数
 func (c *Cow) GetAverageDailyWeight() float64 {
-	if c.CurrentWeight <= 0 || c.AdmissionAge <= 0 {
+	if c.AdmissionAge <= 0 {
+		c.AdmissionAge = c.GetAdmissionAge()
+	}
+
+	if c.AdmissionAge <= 0 {
 		return 0
 	}
-	firstWeight := c.BirthWeight
-	if c.SourceKind == pasturePb.CowSource_Buy {
-		firstWeight = c.AdmissionWeight
 
+	if c.CurrentWeight-c.AdmissionWeight <= 0 {
+		return 0
 	}
-	res := math.Round(1.0 * float64(c.CurrentWeight-firstWeight) / float64(c.AdmissionAge))
-	return res / 1000
+	return float64(c.CurrentWeight-c.AdmissionWeight) / 1000 / float64(c.AdmissionAge)
 }
 
 // GetPreviousStageDailyWeight 上一个阶段日增重

+ 25 - 2
module/backend/cow.go

@@ -47,11 +47,25 @@ func (s *StoreEntry) Detail(ctx context.Context, req *pasturePb.SearchEventReque
 	cowSourceMap := s.CowSourceMap()
 	admissionStatusMap := s.AdmissionStatusMap()
 	healthStatusMap := s.HealthStatusMap()
+	purposeMap := s.PurposeMap()
+	systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
+	if err != nil {
+		return nil, xerr.Custom("请在基础参数配置妊娠天数")
+	}
+
+	cowDetails := model.CowSlice([]*model.Cow{cowInfo}).ToPB(
+		cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap,
+		admissionStatusMap, healthStatusMap, purposeMap, systemBasic.MinValue,
+	)
+	if len(cowDetails) != 1 {
+		return nil, xerr.Custom("该牛只未找到")
+	}
 
+	data := cowDetails[0]
 	return &pasturePb.CowInfoResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: model.CowSlice([]*model.Cow{cowInfo}).ToPB(cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap, admissionStatusMap, healthStatusMap)[0],
+		Data: data,
 	}, nil
 }
 
@@ -61,6 +75,11 @@ func (s *StoreEntry) List(ctx context.Context, req *pasturePb.SearchEventRequest
 		return nil, xerr.WithStack(err)
 	}
 
+	systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
+	if err != nil {
+		return nil, xerr.Custom("请在基础参数配置妊娠天数")
+	}
+
 	cowList := make([]*model.Cow, 0)
 	var count int64 = 0
 	pref := s.DB.Model(new(model.Cow)).
@@ -121,11 +140,15 @@ func (s *StoreEntry) List(ctx context.Context, req *pasturePb.SearchEventRequest
 	cowSourceMap := s.CowSourceMap()
 	admissionStatusMap := s.AdmissionStatusMap()
 	healthStatusMap := s.HealthStatusMap()
+	purposeMap := s.PurposeMap()
 	return &pasturePb.SearchCowListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchCowData{
-			List:     model.CowSlice(cowList).ToPB(cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap, admissionStatusMap, healthStatusMap),
+			List: model.CowSlice(cowList).ToPB(
+				cowTypeMap, breedStatusMap, cowKindMap, cowSourceMap,
+				admissionStatusMap, healthStatusMap, purposeMap, systemBasic.MinValue,
+			),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,

+ 8 - 0
module/backend/enum_map.go

@@ -171,6 +171,14 @@ func (s *StoreEntry) HealthStatusMap() map[pasturePb.HealthStatus_Kind]string {
 	return res
 }
 
+func (s *StoreEntry) PurposeMap() map[pasturePb.Purpose_Kind]string {
+	res := make(map[pasturePb.Purpose_Kind]string)
+	for _, v := range s.CowPurposeList("") {
+		res[pasturePb.Purpose_Kind(v.Value)] = v.Label
+	}
+	return res
+}
+
 func (s *StoreEntry) DiseaseTypeMap() map[int32]string {
 	res := make(map[int32]string)
 	for _, v := range s.diseaseTypeEnumList("") {

+ 2 - 14
module/crontab/milk_daily.go

@@ -1,10 +1,5 @@
 package crontab
 
-import (
-	"kpt-pasture/model"
-	"time"
-)
-
 func (e *Entry) InsertMilkDaily() error {
 	pastureList := e.FindPastureList()
 	if pastureList == nil || len(pastureList) == 0 {
@@ -19,13 +14,6 @@ func (e *Entry) InsertMilkDaily() error {
 }
 
 func (e *Entry) ProcessMilkDaily(pastureId int64) {
-	nowTime := time.Now()
-	newMilkDaily := &model.MilkDaily{}
-	if err := e.DB.Model(new(model.MilkDaily)).
-		Where("pasture_id = ? AND DATE_FORMAT(created_at,'%Y-%m-%d') = ?", pastureId, nowTime.Format("2006-01-02")).
-		First(newMilkDaily).Error; err != nil {
-		newMilkDaily.PastureId = pastureId
-		newMilkDaily.CreatedAt = nowTime.Unix()
-		newMilkDaily.UpdatedAt = nowTime.Unix()
-	}
+	//nowTime := time.Now()
+
 }