Yi 4 өдөр өмнө
parent
commit
7b66c55cce

+ 3 - 1
config/app.develop.yaml

@@ -53,6 +53,7 @@ cron:
   neck_ring_health_warning: "*/50 * * * * ?"   # 脖环预警(每50分钟执行一次
   neck_ring_health_warning: "*/50 * * * * ?"   # 脖环预警(每50分钟执行一次
   update_pen_behavior: "0 45 * * * ?"  # 更新栏舍行行为数据
   update_pen_behavior: "0 45 * * * ?"  # 更新栏舍行行为数据
   update_pen_behavior_daily: "0 05 2 * * ?"  # 更新栏舍饲养监测数据
   update_pen_behavior_daily: "0 05 2 * * ?"  # 更新栏舍饲养监测数据
+  update_milk_original: "0 */30 * * * ?"     # 更新奶厅原始数据(每30分钟执行一次
 
 
 mqtt:
 mqtt:
   broker: "kptyun.com:1983"
   broker: "kptyun.com:1983"
@@ -75,7 +76,8 @@ milk_hall:
     - "/file2"
     - "/file2"
   back_path: "http://your-api-endpoint"
   back_path: "http://your-api-endpoint"
   url_path: "/api/v1/milk/hall/original"
   url_path: "/api/v1/milk/hall/original"
-  brand: "afimilk"
+  brand: "gea"
+  milk_hall_number: "三期"
   farm_id: "c7357ce63cc7dddf6aa75c5baa37c507"
   farm_id: "c7357ce63cc7dddf6aa75c5baa37c507"
 
 
 
 

+ 8 - 6
config/app.go

@@ -69,6 +69,7 @@ type CronSetting struct {
 	NeckRingHealthWarning   string `yaml:"neck_ring_health_warning"`   //  脖环健康预警
 	NeckRingHealthWarning   string `yaml:"neck_ring_health_warning"`   //  脖环健康预警
 	UpdatePenBehavior       string `yaml:"update_pen_behavior"`        //  栏舍行为数据
 	UpdatePenBehavior       string `yaml:"update_pen_behavior"`        //  栏舍行为数据
 	UpdatePenBehaviorDaily  string `yaml:"update_pen_behavior_daily"`  //  栏舍饲养监测
 	UpdatePenBehaviorDaily  string `yaml:"update_pen_behavior_daily"`  //  栏舍饲养监测
+	UpdateMilkOriginal      string `yaml:"update_milk_original"`       //  奶厅原始数据更新
 }
 }
 
 
 type JwtTokenKeyConfig struct {
 type JwtTokenKeyConfig struct {
@@ -185,12 +186,13 @@ type MqttSetting struct {
 }
 }
 
 
 type MilkHallSetting struct {
 type MilkHallSetting struct {
-	BasePath string   `yaml:"base_path"`
-	FilePath []string `yaml:"file_path"`
-	BackPath string   `json:"back_path"`
-	UrlPath  string   `yaml:"url_path"`
-	Brand    string   `yaml:"brand"`
-	FarmId   string   `yaml:"farm_id"`
+	BasePath       string   `yaml:"base_path"`
+	FilePath       []string `yaml:"file_path"`
+	BackPath       string   `json:"back_path"`
+	UrlPath        string   `yaml:"url_path"`
+	Brand          string   `yaml:"brand"`
+	FarmId         string   `yaml:"farm_id"`
+	MilkHallNumber string   `yaml:"milk_hall_number"`
 }
 }
 
 
 func (a *AppConfig) Name() string {
 func (a *AppConfig) Name() string {

+ 2 - 0
dep/di_crontab.go

@@ -128,6 +128,8 @@ func EntryCrontab(dependency CrontabDependency) *cron.Crontab {
 		panic(err)
 		panic(err)
 	}
 	}
 
 
+	err = newCrontab.Bind("UpdateMilkOriginal", cs.UpdateMilkOriginal, dependency.CrontabHub.UpdateMilkOriginal)
+
 	/*err = newCrontab.Bind("GenerateWorkOrder", cs.GenerateWorkOrder, dependency.CrontabHub.GenerateAsynqWorkOrder)
 	/*err = newCrontab.Bind("GenerateWorkOrder", cs.GenerateWorkOrder, dependency.CrontabHub.GenerateAsynqWorkOrder)
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)

+ 1 - 1
go.mod

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

+ 10 - 0
go.sum

@@ -100,6 +100,16 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250331022421-15889f6c46c3 h1:4bIc13fi
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331022421-15889f6c46c3/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331022421-15889f6c46c3/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331025336-cc1744596fab h1:Y4tbyz3hLuoyLjixwDK3JMIIWGfLH94UxUuaFXZxEtI=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331025336-cc1744596fab h1:Y4tbyz3hLuoyLjixwDK3JMIIWGfLH94UxUuaFXZxEtI=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331025336-cc1744596fab/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250331025336-cc1744596fab/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250331103026-c284e7da7be0 h1:NEiteoQE+x7Rzs0sjip9LOqJDhgqc3YnsTREo/dcnVo=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250331103026-c284e7da7be0/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401012917-fe0b01a85574 h1:acpexjsGZYca4Bug25z/UMcbEgeotZbg5dkqrEASUus=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401012917-fe0b01a85574/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401013759-480302d9deb1 h1:KTIt5nZAQGhcs6BQCjRbcNsPipFf0iF96IzubNnuaMo=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401013759-480302d9deb1/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401071526-0bfd7f4af6d3 h1:DlhNaXi3Sp1PIT8Lb5m8/BL89MV4z2eyaYnZANWU6OU=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401071526-0bfd7f4af6d3/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401072057-a324cc76215b h1:kdALC/8+x5bYGQxBBSAq9FvsneuwfMSu0x6evwzJoP4=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250401072057-a324cc76215b/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 h1:w05MxH7yqveRlaRbxHhbif5YjPrJFodRPfOjYhXn7Zk=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 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=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 1 - 1
http/handler/event/event_health.go

@@ -231,7 +231,7 @@ func ImmunizationBatch(c *gin.Context) {
 	if err := valid.ValidateStruct(&req,
 	if err := valid.ValidateStruct(&req,
 		valid.Field(&req.PlanId, valid.Required),
 		valid.Field(&req.PlanId, valid.Required),
 		valid.Field(&req.OperationId, valid.Required),
 		valid.Field(&req.OperationId, valid.Required),
-		valid.Field(&req.CowIds, valid.Required),
+		valid.Field(&req.EarNumbers, valid.Required),
 		valid.Field(&req.ImmunizationAt, valid.Required),
 		valid.Field(&req.ImmunizationAt, valid.Required),
 		valid.Field(&req.Usage, valid.Required),
 		valid.Field(&req.Usage, valid.Required),
 	); err != nil {
 	); err != nil {

+ 10 - 11
model/event_immunization_plan.go

@@ -100,16 +100,16 @@ func (e EventImmunizationPlanSlice) ToPB() []*pasturePb.ImmunizationItems {
 			planDay = time.Unix(v.PlanDay, 0).Format(LayoutDate2)
 			planDay = time.Unix(v.PlanDay, 0).Format(LayoutDate2)
 		}
 		}
 		res[i] = &pasturePb.ImmunizationItems{
 		res[i] = &pasturePb.ImmunizationItems{
-			Id:               int32(v.Id),
-			CowId:            int32(v.CowId),
-			EarNumber:        v.EarNumber,
-			Lact:             v.Lact,
-			PenName:          v.PenName,
-			DayAge:           v.DayAge,
-			PlanDay:          planDay,
-			Status:           v.Status,
-			ImmunizationName: v.PlanName,
-			ImmunizationId:   int32(v.PlanId),
+			Id:        int32(v.Id),
+			CowId:     int32(v.CowId),
+			EarNumber: v.EarNumber,
+			Lact:      v.Lact,
+			PenName:   v.PenName,
+			DayAge:    v.DayAge,
+			PlanDay:   planDay,
+			Status:    v.Status,
+			PlanName:  v.PlanName,
+			PlanId:    int32(v.PlanId),
 		}
 		}
 	}
 	}
 	return res
 	return res
@@ -124,7 +124,6 @@ func (e EventImmunizationPlanSlice) ToPB2() []*pasturePb.ImmunizationItem {
 			OperationId:    int32(v.OperationId),
 			OperationId:    int32(v.OperationId),
 			OperationName:  v.OperationName,
 			OperationName:  v.OperationName,
 			Remarks:        v.Remarks,
 			Remarks:        v.Remarks,
-			CowIds:         make([]int32, 0),
 			DrugsId:        int32(v.DrugsId),
 			DrugsId:        int32(v.DrugsId),
 			DrugsName:      v.DrugsName,
 			DrugsName:      v.DrugsName,
 			Unit:           v.Unit,
 			Unit:           v.Unit,

+ 2 - 0
model/event_weaning.go

@@ -11,6 +11,7 @@ type EventWeaning struct {
 	Id            int64                 `json:"id"`
 	Id            int64                 `json:"id"`
 	PastureId     int64                 `json:"pastureId"`
 	PastureId     int64                 `json:"pastureId"`
 	CowId         int64                 `json:"cowId"`
 	CowId         int64                 `json:"cowId"`
+	EarNumber     string                `json:"earNumber"`
 	MotherId      int64                 `json:"motherId"`
 	MotherId      int64                 `json:"motherId"`
 	BullNumber    string                `json:"bullNumber"`
 	BullNumber    string                `json:"bullNumber"`
 	PlanDay       int64                 `json:"planDay"`
 	PlanDay       int64                 `json:"planDay"`
@@ -52,6 +53,7 @@ func NewEventWeaning(pastureId int64, cowInfo *Cow, startDay, endDay string) *Ev
 		MotherId:    motherId,
 		MotherId:    motherId,
 		BullNumber:  cowInfo.LastBullNumber,
 		BullNumber:  cowInfo.LastBullNumber,
 		CowId:       cowInfo.Id,
 		CowId:       cowInfo.Id,
+		EarNumber:   cowInfo.EarNumber,
 		PlanDay:     util.TimeParseLocalUnix(startDay),
 		PlanDay:     util.TimeParseLocalUnix(startDay),
 		EndDay:      util.TimeParseLocalEndUnix(endDay),
 		EndDay:      util.TimeParseLocalEndUnix(endDay),
 		Status:      pasturePb.IsShow_No,
 		Status:      pasturePb.IsShow_No,

+ 4 - 0
model/indicators_data.go

@@ -9,6 +9,7 @@ import (
 
 
 const (
 const (
 	AllCow            = "all_cow"
 	AllCow            = "all_cow"
+	AdultCow          = "adult_cow"
 	CalvingInterval   = "calving_interval"
 	CalvingInterval   = "calving_interval"
 	OutputNumber      = "output_number"
 	OutputNumber      = "output_number"
 	InputNumber       = "input_number"
 	InputNumber       = "input_number"
@@ -21,6 +22,9 @@ const (
 	CureNumber        = "cure_number"
 	CureNumber        = "cure_number"
 	OutNumber         = "out_number"
 	OutNumber         = "out_number"
 	CalfDieNumber     = "calf_die_number"
 	CalfDieNumber     = "calf_die_number"
+	LactationCow      = "lactation_cow"
+	DryMilkCow        = "dry_milk_cow"
+	ReserveCow        = "reserve_cow"
 )
 )
 
 
 type IndicatorsData struct {
 type IndicatorsData struct {

+ 22 - 9
model/milk_hall.go

@@ -1,19 +1,36 @@
 package model
 package model
 
 
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
 const (
 const (
 	AFIMilk = "afimilk"
 	AFIMilk = "afimilk"
 	GEA     = "gea"
 	GEA     = "gea"
 	AFI     = "afi"
 	AFI     = "afi"
 )
 )
 
 
+type MilkHall struct {
+	Id        int64                 `json:"id"`
+	PastureId int64                 `json:"pasture_id"`
+	Name      string                `json:"name"`
+	Brand     string                `json:"brand"`
+	Kind      string                `json:"kind"`
+	Field     int32                 `json:"field"`
+	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
+	CreatedAt int64                 `json:"created_at"`
+	UpdatedAt int64                 `json:"updated_at"`
+}
+
+func (m *MilkHall) TableName() string {
+	return "milk_hall"
+}
+
 type MilkHallBody struct {
 type MilkHallBody struct {
-	MilkHallNumber string `json:"milkHallNumber"`
-	Brand          string `json:"brand"`
-	Content        []byte `json:"content"`
-	FarmId         string `json:"farmId"`
+	MilkHallNumber string        `json:"milkHallNumber"`
+	Brand          string        `json:"brand"`
+	Content        []interface{} `json:"content"`
+	FarmId         string        `json:"farmId"`
 }
 }
 
 
-// AFIMilkHallOriginal 阿菲金奶厅原始数据结构
 type AFIMilkHallOriginal struct {
 type AFIMilkHallOriginal struct {
 	UID                     int     `json:"uid"`
 	UID                     int     `json:"uid"`
 	SessionNumber           int32   `json:"sessionNumber"`
 	SessionNumber           int32   `json:"sessionNumber"`
@@ -75,7 +92,3 @@ type AfiHallOriginal struct {
 	Flow30to60       int     `json:"flow30to60"`
 	Flow30to60       int     `json:"flow30to60"`
 	Flow60to120      int     `json:"flow60to120"`
 	Flow60to120      int     `json:"flow60to120"`
 }
 }
-
-type GEAMilkHallOriginal struct {
-	Vstr string `json:"vstr"`
-}

+ 21 - 21
model/milk_original.go

@@ -10,7 +10,7 @@ type MilkOriginal struct {
 	PenName          string  `json:"penName"`
 	PenName          string  `json:"penName"`
 	MilkHallBrand    string  `json:"milkHallBrand"`
 	MilkHallBrand    string  `json:"milkHallBrand"`
 	MilkDate         string  `json:"milkDate"`
 	MilkDate         string  `json:"milkDate"`
-	MilkWeight       int64   `json:"milkWeight"`
+	MilkWeight       float64 `json:"milkWeight"`
 	StartTime        string  `json:"startTime"`
 	StartTime        string  `json:"startTime"`
 	InitialTime      string  `json:"initialTime"`
 	InitialTime      string  `json:"initialTime"`
 	AttachTime       string  `json:"attachTime"`
 	AttachTime       string  `json:"attachTime"`
@@ -30,7 +30,7 @@ type MilkOriginal struct {
 	PeakFlow         float64 `json:"peakFlow"`
 	PeakFlow         float64 `json:"peakFlow"`
 	AvgFlow          float64 `json:"avgFlow"`
 	AvgFlow          float64 `json:"avgFlow"`
 	Duration         float64 `json:"duration"`
 	Duration         float64 `json:"duration"`
-	PearFlowTime     int32   `json:"pearFlowTime"`
+	PeakFlowTime     int32   `json:"peakFlowTime"`
 	LowFlowTime      int32   `json:"lowFlowTime"`
 	LowFlowTime      int32   `json:"lowFlowTime"`
 	YieldPercentage  int32   `json:"yieldPercentage"`
 	YieldPercentage  int32   `json:"yieldPercentage"`
 	ActualMilkTime   string  `json:"actualMilkTime"`
 	ActualMilkTime   string  `json:"actualMilkTime"`
@@ -40,15 +40,15 @@ type MilkOriginal struct {
 	ManualDetach     int8    `json:"manualDetach"`
 	ManualDetach     int8    `json:"manualDetach"`
 	TakeOffFlow      float64 `json:"takeOffFlow"`
 	TakeOffFlow      float64 `json:"takeOffFlow"`
 	LowMilkFlowPc    int64   `json:"lowMilkFlowPc"`
 	LowMilkFlowPc    int64   `json:"lowMilkFlowPc"`
-	Flow0To15        int64   `json:"flow0To15"`
-	Flow15To30       int64   `json:"flow15To30"`
-	Flow30To60       int64   `json:"flow30To60"`
-	Flow60To120      int64   `json:"flow60To120"`
+	Flow0to15        int64   `json:"flow0To15"`
+	Flow15to30       int64   `json:"flow15To30"`
+	Flow30to60       int64   `json:"flow30To60"`
+	Flow60to120      int64   `json:"flow60To120"`
 	CreatedAt        int64   `json:"createdAt"`
 	CreatedAt        int64   `json:"createdAt"`
 	UpdatedAt        int64   `json:"updatedAt"`
 	UpdatedAt        int64   `json:"updatedAt"`
 }
 }
 
 
-func (m *MilkOriginal) tableName() string {
+func (m *MilkOriginal) TableName() string {
 	return "milk_original"
 	return "milk_original"
 }
 }
 
 
@@ -62,7 +62,7 @@ func NewAFIMilkOriginal(pastureId int64, milkHallNumber string, req *AFIMilkHall
 		PenId:            0,
 		PenId:            0,
 		PenName:          "",
 		PenName:          "",
 		MilkDate:         req.SessionDate,
 		MilkDate:         req.SessionDate,
-		MilkWeight:       req.Yield,
+		MilkWeight:       0, // req.Yield,
 		StartTime:        "",
 		StartTime:        "",
 		InitialTime:      "",
 		InitialTime:      "",
 		AttachTime:       "",
 		AttachTime:       "",
@@ -80,7 +80,7 @@ func NewAFIMilkOriginal(pastureId int64, milkHallNumber string, req *AFIMilkHall
 		RecognitionTime:  "",
 		RecognitionTime:  "",
 		IsYieldLow:       0,
 		IsYieldLow:       0,
 		PeakFlow:         float64(req.PeakFlowRate) / 1000,
 		PeakFlow:         float64(req.PeakFlowRate) / 1000,
-		PearFlowTime:     req.PeakFlowRate,
+		PeakFlowTime:     req.PeakFlowRate,
 		AvgFlow:          0,
 		AvgFlow:          0,
 		Duration:         float64(req.MilkingTime) / 60,
 		Duration:         float64(req.MilkingTime) / 60,
 		LowFlowTime:      req.LowFlowRateTime,
 		LowFlowTime:      req.LowFlowRateTime,
@@ -92,15 +92,15 @@ func NewAFIMilkOriginal(pastureId int64, milkHallNumber string, req *AFIMilkHall
 		ManualDetach:     0,
 		ManualDetach:     0,
 		TakeOffFlow:      float64(req.RemovalFlowRate) / 1000,
 		TakeOffFlow:      float64(req.RemovalFlowRate) / 1000,
 		LowMilkFlowPc:    0,
 		LowMilkFlowPc:    0,
-		Flow0To15:        req.FlowRate0To15,
-		Flow15To30:       req.FlowRate15To30,
-		Flow30To60:       req.FlowRate30To60,
-		Flow60To120:      req.FlowRate60To120,
+		Flow0to15:        req.FlowRate0To15,
+		Flow15to30:       req.FlowRate15To30,
+		Flow30to60:       req.FlowRate30To60,
+		Flow60to120:      req.FlowRate60To120,
 	}
 	}
 }
 }
 
 
 func NewGEAMilkOriginal(
 func NewGEAMilkOriginal(
-	pastureId int64, milkHallNumber string, detachTime, earNumber, milkDate, attachTime string, milkWeight, detacherAddress int64,
+	pastureId int64, milkHallBrand, milkHallNumber string, detachTime, earNumber, milkDate, attachTime, recognitionTime string, milkWeight float64, detacherAddress int64,
 	duration, peakFlow float64, conductivity int32, eId string, f0t15, f15t30, f30t60, f60t120 int64, manualDetach int8,
 	duration, peakFlow float64, conductivity int32, eId string, f0t15, f15t30, f30t60, f60t120 int64, manualDetach int8,
 ) *MilkOriginal {
 ) *MilkOriginal {
 	return &MilkOriginal{
 	return &MilkOriginal{
@@ -110,7 +110,7 @@ func NewGEAMilkOriginal(
 		EleEarNumber:     eId,
 		EleEarNumber:     eId,
 		PenId:            0,
 		PenId:            0,
 		PenName:          "",
 		PenName:          "",
-		MilkHallBrand:    "",
+		MilkHallBrand:    milkHallBrand,
 		MilkDate:         milkDate,
 		MilkDate:         milkDate,
 		MilkWeight:       milkWeight,
 		MilkWeight:       milkWeight,
 		StartTime:        "",
 		StartTime:        "",
@@ -127,12 +127,12 @@ func NewGEAMilkOriginal(
 		Shifts:           0,
 		Shifts:           0,
 		Load:             0,
 		Load:             0,
 		Nattach:          0,
 		Nattach:          0,
-		RecognitionTime:  "",
+		RecognitionTime:  recognitionTime,
 		IsYieldLow:       0,
 		IsYieldLow:       0,
 		PeakFlow:         peakFlow,
 		PeakFlow:         peakFlow,
 		AvgFlow:          0,
 		AvgFlow:          0,
 		Duration:         duration,
 		Duration:         duration,
-		PearFlowTime:     0,
+		PeakFlowTime:     0,
 		LowFlowTime:      0,
 		LowFlowTime:      0,
 		YieldPercentage:  0,
 		YieldPercentage:  0,
 		ActualMilkTime:   "",
 		ActualMilkTime:   "",
@@ -142,9 +142,9 @@ func NewGEAMilkOriginal(
 		ManualDetach:     manualDetach,
 		ManualDetach:     manualDetach,
 		TakeOffFlow:      0,
 		TakeOffFlow:      0,
 		LowMilkFlowPc:    0,
 		LowMilkFlowPc:    0,
-		Flow0To15:        f0t15,
-		Flow15To30:       f15t30,
-		Flow30To60:       f30t60,
-		Flow60To120:      f60t120,
+		Flow0to15:        f0t15,
+		Flow15to30:       f15t30,
+		Flow30to60:       f30t60,
+		Flow60to120:      f60t120,
 	}
 	}
 }
 }

+ 0 - 10
model/pasture_list.go

@@ -1,10 +0,0 @@
-package model
-
-type PastureList struct {
-	Id       int64  `json:"id"`
-	Name     string `json:"name"`
-	Province string `json:"province"`
-	City     string `json:"city"`
-	County   string `json:"county"`
-	Address  string `json:"address"`
-}

+ 0 - 2
model/same_time.go

@@ -16,7 +16,6 @@ type SameTime struct {
 	WeekType            pasturePb.Week_Kind            `json:"weekType"`
 	WeekType            pasturePb.Week_Kind            `json:"weekType"`
 	CowType             pasturePb.SameTimeCowType_Kind `json:"cowType"`
 	CowType             pasturePb.SameTimeCowType_Kind `json:"cowType"`
 	IsShow              pasturePb.IsShow_Kind          `json:"isShow"`
 	IsShow              pasturePb.IsShow_Kind          `json:"isShow"`
-	IsDelete            pasturePb.IsShow_Kind          `json:"isDelete"`
 	PostpartumDaysStart int32                          `json:"postpartumDaysStart"`
 	PostpartumDaysStart int32                          `json:"postpartumDaysStart"`
 	PostpartumDaysEnd   int32                          `json:"postpartumDaysEnd"`
 	PostpartumDaysEnd   int32                          `json:"postpartumDaysEnd"`
 	CollateNodes        string                         `json:"collateNodes"`
 	CollateNodes        string                         `json:"collateNodes"`
@@ -41,7 +40,6 @@ func NewSameTime(pastureId int64, currentUser *SystemUser, req *pasturePb.Search
 		WeekType:            req.WeekType,
 		WeekType:            req.WeekType,
 		CowType:             req.CowType,
 		CowType:             req.CowType,
 		IsShow:              pasturePb.IsShow_Ok,
 		IsShow:              pasturePb.IsShow_Ok,
-		IsDelete:            pasturePb.IsShow_Ok,
 		PostpartumDaysStart: req.PostpartumDaysStart,
 		PostpartumDaysStart: req.PostpartumDaysStart,
 		PostpartumDaysEnd:   req.PostpartumDaysEnd,
 		PostpartumDaysEnd:   req.PostpartumDaysEnd,
 		CollateNodes:        string(collateNodes),
 		CollateNodes:        string(collateNodes),

+ 2 - 3
module/backend/analysis.go

@@ -6,7 +6,6 @@ import (
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"kpt-pasture/util"
 	"net/http"
 	"net/http"
-	"strings"
 	"time"
 	"time"
 
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
@@ -26,8 +25,8 @@ func (s *StoreEntry) WeightScatterPlot(ctx context.Context, req *pasturePb.Searc
 	pref := s.DB.Model(new(model.Cow)).
 	pref := s.DB.Model(new(model.Cow)).
 		Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
 		Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
 		Where("pasture_id = ?", userModel.AppPasture.Id)
 		Where("pasture_id = ?", userModel.AppPasture.Id)
-	if req.GetCowId() != "" {
-		pref.Where("id IN ?", strings.Split(req.CowId, ","))
+	if req.EarNumber != "" {
+		pref.Where("ear_number = ?", req.EarNumber)
 	}
 	}
 
 
 	if len(req.BirthDate) == 2 && req.BirthDate[0] != "" && req.BirthDate[1] != "" {
 	if len(req.BirthDate) == 2 && req.BirthDate[0] != "" && req.BirthDate[1] != "" {

+ 31 - 20
module/backend/calendar.go

@@ -35,25 +35,35 @@ func (s *StoreEntry) CalendarToDoHistoryList(ctx context.Context, pastureId int6
 	if earNumber != "" {
 	if earNumber != "" {
 		whereSql += fmt.Sprintf(` AND ear_number = '%s' `, earNumber)
 		whereSql += fmt.Sprintf(` AND ear_number = '%s' `, earNumber)
 	}
 	}
-	whereSql += fmt.Sprintf(" AND pasture_id = %d AND end_day <= %d ", pastureId, util.TimeParseLocalEndUnix(time.Now().Format(model.LayoutDate2)))
+	whereSql += fmt.Sprintf(" AND pasture_id = %d ", pastureId)
+	whereSql1 := whereSql + fmt.Sprintf(` AND end_day <= %d `, util.TimeParseLocalEndUnix(time.Now().Format(model.LayoutDate2)))
 
 
 	calendarToDoList := make([]*pasturePb.CalendarToDoList, 0)
 	calendarToDoList := make([]*pasturePb.CalendarToDoList, 0)
-	sql := `SELECT a.cow_id,b.pen_name,a.calendar_type_name,a.calendar_type_kind as calendar_type,DATE_FORMAT(FROM_UNIXTIME(a.plan_day), '%Y-%m-%d') AS plan_day,a.remaining_days,b.lact,b.ear_number FROM (
-		SELECT cow_id,plan_day,'免疫' as calendar_type_name,1 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_immunization_plan WHERE status = 2` + whereSql + `
+	sql := `SELECT a.cow_id,b.pen_name,a.calendar_type_name,a.calendar_type_kind as calendar_type,DATE_FORMAT(FROM_UNIXTIME(a.plan_day), '%Y-%m-%d') AS plan_day,
+		a.remaining_days,b.lact,b.ear_number FROM (
+		SELECT cow_id,plan_day,'免疫' as calendar_type_name,1 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_immunization_plan WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'同期' as calendar_type_name,2 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_cow_same_time WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'同期' as calendar_type_name,2 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_cow_same_time WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'孕检' as calendar_type_name,4 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_pregnant_check WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'孕检' as calendar_type_name,4 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_pregnant_check WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'断奶' as calendar_type_name,6 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_weaning WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'断奶' as calendar_type_name,6 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_weaning WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'配种' as calendar_type_name,8 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_mating WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'配种' as calendar_type_name,8 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_mating WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'产犊' as calendar_type_name,9 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_calving WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'产犊' as calendar_type_name,9 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_calving WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,plan_day,'干奶' as calendar_type_name,9 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_dry_milk WHERE status = 2` + whereSql + `
+		SELECT cow_id,plan_day,'干奶' as calendar_type_name,9 as calendar_type_kind,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days 
+			FROM event_dry_milk WHERE status = 2` + whereSql1 + `
 		UNION ALL
 		UNION ALL
-		SELECT cow_id,disease_at as plan_day,'疾病' as calendar_type_name,7 as calendar_type_kind,0 AS remaining_days FROM event_cow_disease WHERE diagnosed_result IN (2,3) AND pasture_id = ` + fmt.Sprintf("%d", pastureId) + `
+		SELECT cow_id,disease_at as plan_day,'疾病' as calendar_type_name,7 as calendar_type_kind,0 AS remaining_days 
+			FROM event_cow_disease WHERE health_status IN (2,3) ` + whereSql + `
 	) as a JOIN cow b ON a.cow_id = b.id WHERE 1 = 1 `
 	) as a JOIN cow b ON a.cow_id = b.id WHERE 1 = 1 `
 
 
 	completeSql := fmt.Sprintf("%s ORDER BY a.plan_day DESC", sql)
 	completeSql := fmt.Sprintf("%s ORDER BY a.plan_day DESC", sql)
@@ -206,7 +216,7 @@ func (s *StoreEntry) ImmunisationCowList(ctx context.Context, req *pasturePb.Ite
 	eventImmunizationPlanList := make([]*model.EventImmunizationPlan, 0)
 	eventImmunizationPlanList := make([]*model.EventImmunizationPlan, 0)
 	count := int64(0)
 	count := int64(0)
 	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventImmunizationPlan).TableName())).
 	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventImmunizationPlan).TableName())).
-		Select("a.id,a.cow_id,a.plan_day,a.plan_name as immunization_plan_name,b.pen_name,b.day_age,b.ear_number").
+		Select("a.id,a.cow_id,a.plan_day,a.plan_name,b.pen_name,b.day_age,b.ear_number,a.plan_id").
 		Joins(fmt.Sprintf("JOIN %s AS b on a.cow_id = b.id", new(model.Cow).TableName())).
 		Joins(fmt.Sprintf("JOIN %s AS b on a.cow_id = b.id", new(model.Cow).TableName())).
 		Where("a.status = ?", pasturePb.IsShow_No).
 		Where("a.status = ?", pasturePb.IsShow_No).
 		Where("a.pasture_id = ?", userModel.AppPasture.Id)
 		Where("a.pasture_id = ?", userModel.AppPasture.Id)
@@ -220,8 +230,8 @@ func (s *StoreEntry) ImmunisationCowList(ctx context.Context, req *pasturePb.Ite
 		pref.Where("a.cow_id = ?", req.CowId)
 		pref.Where("a.cow_id = ?", req.CowId)
 	}
 	}
 
 
-	if req.ImmunizationId > 0 {
-		pref.Where("a.plan_id = ?", req.ImmunizationId)
+	if req.PlanId > 0 {
+		pref.Where("a.plan_id = ?", req.PlanId)
 	}
 	}
 
 
 	if req.PenId > 0 {
 	if req.PenId > 0 {
@@ -244,13 +254,14 @@ func (s *StoreEntry) ImmunisationCowList(ctx context.Context, req *pasturePb.Ite
 			Page:     pagination.Page,
 			Page:     pagination.Page,
 			PageSize: pagination.PageSize,
 			PageSize: pagination.PageSize,
 			Header: map[string]string{
 			Header: map[string]string{
-				"id":                   "编号",
-				"cowId":                "牛号",
-				"earNumber":            "耳标号",
-				"penName":              "栏舍",
-				"dayAge":               "日龄",
-				"planDay":              "免疫时间",
-				"immunizationPlanName": "免疫名称",
+				"id":        "编号",
+				"cowId":     "牛号",
+				"earNumber": "耳标号",
+				"penName":   "栏舍",
+				"dayAge":    "日龄",
+				"planDay":   "免疫时间",
+				"planName":  "免疫名称",
+				"planId":    "免疫Id",
 			},
 			},
 			List: model.EventImmunizationPlanSlice(eventImmunizationPlanList).ToPB(),
 			List: model.EventImmunizationPlanSlice(eventImmunizationPlanList).ToPB(),
 		},
 		},

+ 4 - 8
module/backend/event_base_more.go

@@ -5,6 +5,7 @@ import (
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"kpt-pasture/util"
 	"net/http"
 	"net/http"
+	"strings"
 
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
@@ -293,25 +294,20 @@ func (s *StoreEntry) ImmunizationBatch(ctx context.Context, req *pasturePb.Immun
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 
 
-	if len(req.CowIds) <= 0 {
+	if len(req.EarNumbers) <= 0 {
 		return xerr.Custom("请选择相关牛只数据")
 		return xerr.Custom("请选择相关牛只数据")
 	}
 	}
 
 
-	cowIds := make([]int64, len(req.CowIds))
-	for i, v := range req.CowIds {
-		cowIds[i] = int64(v)
-	}
-
 	eventImmunizationList := make([]*model.EventImmunizationPlan, 0)
 	eventImmunizationList := make([]*model.EventImmunizationPlan, 0)
 	if err = s.DB.Model(new(model.EventImmunizationPlan)).
 	if err = s.DB.Model(new(model.EventImmunizationPlan)).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
 		Where("plan_id = ?", req.PlanId).
 		Where("plan_id = ?", req.PlanId).
-		Where("cow_id IN (?)", cowIds).
+		Where("ear_number IN (?)", strings.Join(req.EarNumbers, ",")).
 		Find(&eventImmunizationList).Error; err != nil {
 		Find(&eventImmunizationList).Error; err != nil {
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 
 
-	if len(eventImmunizationList) != len(req.CowIds) {
+	if len(eventImmunizationList) != len(req.EarNumbers) {
 		return xerr.Custom("数据异常")
 		return xerr.Custom("数据异常")
 	}
 	}
 
 

+ 2 - 2
module/backend/event_breed_more_more.go

@@ -152,7 +152,7 @@ func (s *StoreEntry) ForbiddenMatingBatch(ctx context.Context, req *pasturePb.Ev
 			// 更新牛只信息
 			// 更新牛只信息
 			item.Cow.ForbiddenMatingUpdate(item.ForbiddenMatingAt)
 			item.Cow.ForbiddenMatingUpdate(item.ForbiddenMatingAt)
 			if err = tx.Model(new(model.Cow)).
 			if err = tx.Model(new(model.Cow)).
-				Select("is_forbidden_mating", "last_forbidden_mating_at").
+				Select("is_forbidden_mating", "last_forbidden_mating_at", "breed_status").
 				Updates(item.Cow).Error; err != nil {
 				Updates(item.Cow).Error; err != nil {
 				return xerr.WithStack(err)
 				return xerr.WithStack(err)
 			}
 			}
@@ -255,7 +255,7 @@ func (s *StoreEntry) UnForbiddenMating(ctx context.Context, req *pasturePb.Event
 			// 牛只解配更新
 			// 牛只解配更新
 			cowInfo.UnForbiddenMatingUpdate()
 			cowInfo.UnForbiddenMatingUpdate()
 			if err = tx.Model(new(model.Cow)).
 			if err = tx.Model(new(model.Cow)).
-				Select("is_forbidden_mating", "last_forbidden_mating_at").
+				Select("is_forbidden_mating", "last_forbidden_mating_at", "breed_status").
 				Updates(cowInfo).Error; err != nil {
 				Updates(cowInfo).Error; err != nil {
 				return xerr.WithStack(err)
 				return xerr.WithStack(err)
 			}
 			}

+ 17 - 2
module/backend/event_health.go

@@ -2,6 +2,7 @@ package backend
 
 
 import (
 import (
 	"context"
 	"context"
+	"errors"
 	"fmt"
 	"fmt"
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"net/http"
 	"net/http"
@@ -478,7 +479,8 @@ func (s *StoreEntry) DiseaseSuggestPrescription(ctx context.Context, diseaseId i
 }
 }
 
 
 // CowDiseaseTreatmentDetail 发病牛只治疗详情列表
 // CowDiseaseTreatmentDetail 发病牛只治疗详情列表
-func (s *StoreEntry) CowDiseaseTreatmentDetail(ctx context.Context, req *pasturePb.EventCowTreatmentDetailRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventCowTreatmentDetailResponse, error) {
+func (s *StoreEntry) CowDiseaseTreatmentDetail(ctx context.Context, req *pasturePb.EventCowTreatmentDetailRequest,
+	pagination *pasturePb.PaginationModel) (*pasturePb.EventCowTreatmentDetailResponse, error) {
 	userModel, err := s.GetUserModel(ctx)
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
 	if err != nil {
 		return nil, xerr.WithStack(err)
 		return nil, xerr.WithStack(err)
@@ -504,7 +506,20 @@ func (s *StoreEntry) CowDiseaseTreatmentDetail(ctx context.Context, req *pasture
 		Offset(int(pagination.PageOffset)).
 		Offset(int(pagination.PageOffset)).
 		Order("id desc").
 		Order("id desc").
 		First(&eventCowDisease).Error; err != nil {
 		First(&eventCowDisease).Error; err != nil {
-		return nil, xerr.WithStack(err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return &pasturePb.EventCowTreatmentDetailResponse{
+				Code: http.StatusOK,
+				Msg:  "ok",
+				Data: &pasturePb.EventCowTreatmentDetail{
+					List:     make([]*pasturePb.EventCowTreatment, 0),
+					Total:    0,
+					PageSize: pagination.PageSize,
+					Page:     pagination.Page,
+				},
+			}, nil
+		} else {
+			return nil, xerr.WithStack(err)
+		}
 	}
 	}
 
 
 	eventCowTreatmentList := make([]*model.EventCowTreatment, 0)
 	eventCowTreatmentList := make([]*model.EventCowTreatment, 0)

+ 14 - 12
module/backend/milk_afimilk.go

@@ -11,28 +11,29 @@ import (
 // AFIMILK 阿菲金品牌实现
 // AFIMILK 阿菲金品牌实现
 type AFIMILK struct {
 type AFIMILK struct {
 	store *StoreEntry
 	store *StoreEntry
+	body  *model.MilkHallBody
 }
 }
 
 
-func (a *AFIMILK) SaveData(ctx context.Context, body *model.MilkHallBody) error {
-	content := body.Content
-	if len(content) <= 0 {
+func (a *AFIMILK) SaveData(ctx context.Context) error {
+	contentList := a.body.Content
+	if len(contentList) <= 0 {
 		return nil
 		return nil
 	}
 	}
 
 
-	afiMilkList := make([]*model.AFIMilkHallOriginal, 0)
-	if err := json.Unmarshal(content, &afiMilkList); err != nil {
-		return xerr.WithStack(err)
-	}
-	pastureData := &model.PastureList{}
+	pastureData := &model.AppPastureList{}
 	if err := a.store.DB.Model(pastureData).
 	if err := a.store.DB.Model(pastureData).
-		Where("farm_id = ?", body.FarmId).
+		Where("farm_id = ?", a.body.FarmId).
 		First(pastureData).Error; err != nil {
 		First(pastureData).Error; err != nil {
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 
 
 	milkOriginalList := make([]*model.MilkOriginal, 0)
 	milkOriginalList := make([]*model.MilkOriginal, 0)
-	for _, afiMilk := range afiMilkList {
-		milkOriginalList = append(milkOriginalList, model.NewAFIMilkOriginal(pastureData.Id, body.MilkHallNumber, afiMilk))
+	for _, content := range contentList {
+		afiMilkOriginalData := &model.AFIMilkHallOriginal{}
+		if err := json.Unmarshal([]byte(content.(string)), afiMilkOriginalData); err != nil {
+			return xerr.WithStack(err)
+		}
+		milkOriginalList = append(milkOriginalList, model.NewAFIMilkOriginal(pastureData.Id, a.body.MilkHallNumber, afiMilkOriginalData))
 	}
 	}
 
 
 	if len(milkOriginalList) > 0 {
 	if len(milkOriginalList) > 0 {
@@ -47,8 +48,9 @@ func (a *AFIMILK) SaveData(ctx context.Context, body *model.MilkHallBody) error
 
 
 type AFI struct {
 type AFI struct {
 	store *StoreEntry
 	store *StoreEntry
+	body  *model.MilkHallBody
 }
 }
 
 
-func (a *AFI) SaveData(ctx context.Context, body *model.MilkHallBody) error {
+func (a *AFI) SaveData(ctx context.Context) error {
 	return nil
 	return nil
 }
 }

+ 41 - 36
module/backend/milk_gea.go

@@ -2,7 +2,6 @@ package backend
 
 
 import (
 import (
 	"context"
 	"context"
-	"encoding/json"
 	"fmt"
 	"fmt"
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"kpt-pasture/util"
@@ -10,42 +9,49 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
-	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
-	"go.uber.org/zap"
-
 	"gitee.com/xuyiping_admin/pkg/xerr"
 	"gitee.com/xuyiping_admin/pkg/xerr"
 )
 )
 
 
 const (
 const (
-	eidStart  = 7
-	eidEndLen = 64 + 7 - eidStart
+	eidEndLen = 8
+	eidStart  = 63 + 7 - eidEndLen
 )
 )
 
 
 // GEAMILK gea品牌实现
 // GEAMILK gea品牌实现
 type GEAMILK struct {
 type GEAMILK struct {
 	store *StoreEntry
 	store *StoreEntry
+	body  *model.MilkHallBody
 }
 }
 
 
-func (a *GEAMILK) SaveData(ctx context.Context, body *model.MilkHallBody) error {
-	gEAMilkHallOriginalList := make([]*model.GEAMilkHallOriginal, 0)
-	if err := json.Unmarshal(body.Content, &gEAMilkHallOriginalList); err != nil {
-		return xerr.WithStack(err)
+func (a *GEAMILK) SaveData(ctx context.Context) error {
+	if len(a.body.Content) <= 0 {
+		return nil
 	}
 	}
-	nowTime := time.Now()
-	zaplog.Info("GEAMILK", zap.String("nowTime", nowTime.Format(model.LayoutTime)), zap.Any("body", body))
-	pastureData := &model.PastureList{}
-	if err := a.store.DB.Model(new(model.PastureList)).
-		Where("farm_id = ?", body.FarmId).
+
+	pastureData := &model.AppPastureList{}
+	if err := a.store.DB.Model(new(model.AppPastureList)).
+		Where("farm_id = ?", a.body.FarmId).
 		First(pastureData).Error; err != nil {
 		First(pastureData).Error; err != nil {
 		return xerr.WithStack(err)
 		return xerr.WithStack(err)
 	}
 	}
 
 
+	nowTime := time.Now()
 	gEAOriginalList := make([]*model.MilkOriginal, 0)
 	gEAOriginalList := make([]*model.MilkOriginal, 0)
-	for _, gea := range gEAMilkHallOriginalList {
+	for _, v := range a.body.Content {
+		content, ok := v.(map[string]interface{})
+		if !ok {
+			continue
+		}
 
 
-		text := gea.Vstr
+		t, ok := content["vstr"]
+		if !ok {
+			continue
+		}
+		text := t.(string)
 		s1 := strings.TrimSpace(util.Substr(text, 0, 6))
 		s1 := strings.TrimSpace(util.Substr(text, 0, 6))
-		milkWeight, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 25, 4)), 10, 64)
+		milkWeight, _ := strconv.ParseFloat(strings.TrimSpace(util.Substr(text, 25, 4)), 64)
+
+		fmt.Println("milkWeight:", milkWeight, strings.TrimSpace(util.Substr(text, 25, 4)))
 
 
 		if len(s1) == 0 && milkWeight == 0 {
 		if len(s1) == 0 && milkWeight == 0 {
 			continue
 			continue
@@ -63,25 +69,23 @@ func (a *GEAMILK) SaveData(ctx context.Context, body *model.MilkHallBody) error
 		hour2 := strings.TrimSpace(util.Substr(text, 44, 2))
 		hour2 := strings.TrimSpace(util.Substr(text, 44, 2))
 		minute2 := strings.TrimSpace(util.Substr(text, 46, 2))
 		minute2 := strings.TrimSpace(util.Substr(text, 46, 2))
 		second2 := strings.TrimSpace(util.Substr(text, 49, 2))
 		second2 := strings.TrimSpace(util.Substr(text, 49, 2))
-		if hour == "00" {
-			if hour1 == "23" {
-				milkDate = nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
-			} else {
-				milkDate = nowTime.Format(model.LayoutDate2)
-			}
-
-			if hour2 == "23" {
-				attachTime = nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
-			} else {
-				attachTime = nowTime.Format(model.LayoutTime)
-			}
+		if hour == "00" && hour1 == "23" {
+			milkDate = nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
+		} else {
+			milkDate = nowTime.Format(model.LayoutDate2)
+		}
+
+		if hour == "00" && hour2 == "23" {
+			attachTime = nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
+		} else {
+			attachTime = nowTime.Format(model.LayoutDate2)
 		}
 		}
-		milkDate = fmt.Sprintf("%s %s:%s:%s", milkDate, hour1, minute1, second1)
-		attachTime = fmt.Sprintf("%s %s:%s:%s", attachTime, hour2, minute2, second2)
 
 
-		detachTime := fmt.Sprintf("%s %s:%s:%s", nowTime, hour, minute, second)
+		recognitionTime := fmt.Sprintf("%s %02s:%02s:%02s", nowTime.Format(model.LayoutDate2), hour1, minute1, second1)
+		attachTime = fmt.Sprintf("%s %02s:%02s:%02s", attachTime, hour2, minute2, second2)
+		detachTime := fmt.Sprintf("%s %02s:%02s:%02s", nowTime.Format(model.LayoutDate2), hour, minute, second)
 		earNumber := fmt.Sprintf("%s", strings.TrimSpace(util.Substr(text, 7, 6)))
 		earNumber := fmt.Sprintf("%s", strings.TrimSpace(util.Substr(text, 7, 6)))
-		detacherAddress, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 20, 2)), 10, 64)
+		detachAddress, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 20, 2)), 10, 64)
 
 
 		duration, _ := strconv.ParseFloat(strings.TrimSpace(util.Substr(text, 31, 4)), 64)
 		duration, _ := strconv.ParseFloat(strings.TrimSpace(util.Substr(text, 31, 4)), 64)
 		peakFlow, _ := strconv.ParseFloat(strings.TrimSpace(util.Substr(text, 52, 4)), 64)
 		peakFlow, _ := strconv.ParseFloat(strings.TrimSpace(util.Substr(text, 52, 4)), 64)
@@ -99,8 +103,9 @@ func (a *GEAMILK) SaveData(ctx context.Context, body *model.MilkHallBody) error
 		f60t120, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 105, 3)), 10, 64)
 		f60t120, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 105, 3)), 10, 64)
 		manualDetach, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 109, 1)), 10, 64)
 		manualDetach, _ := strconv.ParseInt(strings.TrimSpace(util.Substr(text, 109, 1)), 10, 64)
 
 
-		newGEAOriginal := model.NewGEAMilkOriginal(pastureData.Id, body.MilkHallNumber, detachTime, earNumber, milkDate, attachTime,
-			milkWeight, detacherAddress, duration, peakFlow, int32(conductivity), eId, f0t15, f15t30, f30t60, f60t120, int8(manualDetach))
+		newGEAOriginal := model.NewGEAMilkOriginal(
+			pastureData.Id, a.body.Brand, a.body.MilkHallNumber, detachTime, earNumber, milkDate, attachTime, recognitionTime, milkWeight,
+			detachAddress, duration, peakFlow, int32(conductivity), eId, f0t15, f15t30, f30t60, f60t120, int8(manualDetach))
 		gEAOriginalList = append(gEAOriginalList, newGEAOriginal)
 		gEAOriginalList = append(gEAOriginalList, newGEAOriginal)
 	}
 	}
 
 

+ 5 - 5
module/backend/milk_hall.go

@@ -10,7 +10,7 @@ import (
 
 
 // MilkBrand 奶厅品牌接口
 // MilkBrand 奶厅品牌接口
 type MilkBrand interface {
 type MilkBrand interface {
-	SaveData(ctx context.Context, body *model.MilkHallBody) error
+	SaveData(ctx context.Context) error
 }
 }
 
 
 func (s *StoreEntry) MilkHallOriginal(ctx context.Context, req []byte) error {
 func (s *StoreEntry) MilkHallOriginal(ctx context.Context, req []byte) error {
@@ -21,15 +21,15 @@ func (s *StoreEntry) MilkHallOriginal(ctx context.Context, req []byte) error {
 	var milkBrand MilkBrand
 	var milkBrand MilkBrand
 	switch body.Brand {
 	switch body.Brand {
 	case model.AFIMilk:
 	case model.AFIMilk:
-		milkBrand = &AFIMILK{store: s}
+		milkBrand = &AFIMILK{store: s, body: body}
 	case model.AFI:
 	case model.AFI:
-		milkBrand = &AFI{store: s}
+		milkBrand = &AFI{store: s, body: body}
 	case model.GEA:
 	case model.GEA:
-		milkBrand = &GEAMILK{store: s}
+		milkBrand = &GEAMILK{store: s, body: body}
 	default:
 	default:
 		return xerr.Customf("不支持的品牌: %s", body.Brand)
 		return xerr.Customf("不支持的品牌: %s", body.Brand)
 	}
 	}
 
 
 	// 调用品牌的 SaveData 方法
 	// 调用品牌的 SaveData 方法
-	return milkBrand.SaveData(ctx, body)
+	return milkBrand.SaveData(ctx)
 }
 }

+ 8 - 0
module/crontab/cow_cron.go

@@ -69,6 +69,8 @@ func (e *Entry) Indicators() error {
 		switch indicatorsDetail.Kind {
 		switch indicatorsDetail.Kind {
 		case model.AllCow:
 		case model.AllCow:
 			pastureIndicatorList = e.FindPastureAllCow(pastureList)
 			pastureIndicatorList = e.FindPastureAllCow(pastureList)
+		case model.AdultCow:
+			pastureIndicatorList = e.FindPastureAdultCow(pastureList)
 		case model.CalvingInterval:
 		case model.CalvingInterval:
 			pastureIndicatorList = e.FindCalvingInterval(pastureList, startTime, endTime)
 			pastureIndicatorList = e.FindCalvingInterval(pastureList, startTime, endTime)
 		case model.OutputNumber:
 		case model.OutputNumber:
@@ -93,6 +95,12 @@ func (e *Entry) Indicators() error {
 			pastureIndicatorList = e.FindDepartureNumber(pastureList, pasturePb.DepartureType_Out, startTime, endTime)
 			pastureIndicatorList = e.FindDepartureNumber(pastureList, pasturePb.DepartureType_Out, startTime, endTime)
 		case model.CalfDieNumber:
 		case model.CalfDieNumber:
 			pastureIndicatorList = e.FindCalfDieNumber(pastureList, pasturePb.DepartureType_Death, startTime, endTime)
 			pastureIndicatorList = e.FindCalfDieNumber(pastureList, pasturePb.DepartureType_Death, startTime, endTime)
+		case model.LactationCow:
+			pastureIndicatorList = e.LactationCow(pastureList, pasturePb.CowMilk_Lactation)
+		case model.DryMilkCow:
+			pastureIndicatorList = e.LactationCow(pastureList, pasturePb.CowMilk_Dry_Milk)
+		case model.ReserveCow:
+			pastureIndicatorList = e.LactationCow(pastureList, pasturePb.CowMilk_Reserve)
 		}
 		}
 
 
 		for pastureId, value := range pastureIndicatorList {
 		for pastureId, value := range pastureIndicatorList {

+ 16 - 0
module/crontab/cow_indicators_base.go

@@ -30,6 +30,22 @@ func (e *Entry) FindPastureAllCow(pastureList []*model.AppPastureList) map[int64
 	return res
 	return res
 }
 }
 
 
+func (e *Entry) FindPastureAdultCow(pastureList []*model.AppPastureList) map[int64]string {
+	res := make(map[int64]string)
+	for _, pasture := range pastureList {
+		var count int64
+		if err := e.DB.Model(new(model.Cow)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+			Where("lact > ?", 0).
+			Count(&count).Error; err != nil {
+			zaplog.Error("FindPastureAdultCow", zap.Any("pasture_id", pasture.Id), zap.Any("err", err))
+		}
+		res[pasture.Id] = fmt.Sprintf("%d", count)
+	}
+	return res
+}
+
 // FindCalvingInterval 产犊间隔
 // FindCalvingInterval 产犊间隔
 func (e *Entry) FindCalvingInterval(pastureList []*model.AppPastureList, startTime, endTime int64) map[int64]string {
 func (e *Entry) FindCalvingInterval(pastureList []*model.AppPastureList, startTime, endTime int64) map[int64]string {
 	res := make(map[int64]string)
 	res := make(map[int64]string)

+ 16 - 0
module/crontab/cow_indicators_breed.go

@@ -25,3 +25,19 @@ func (e *Entry) FindCalvingNumber(pastureList []*model.AppPastureList, startTime
 	}
 	}
 	return res
 	return res
 }
 }
+
+func (e *Entry) LactationCow(pastureList []*model.AppPastureList, milkKind pasturePb.CowMilk_Kind) map[int64]string {
+	res := make(map[int64]string)
+	for _, pasture := range pastureList {
+		var count int64
+		if err := e.DB.Model(new(model.Cow)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("admission_status = ?", pasturePb.AdmissionStatus_Admission).
+			Where("milk_kind = ?", milkKind).
+			Count(&count).Error; err != nil {
+			zaplog.Error("LactationCow", zap.Any("pasture_id", pasture.Id), zap.Any("err", err))
+		}
+		res[pasture.Id] = fmt.Sprintf("%d", count)
+	}
+	return res
+}

+ 122 - 73
module/crontab/milk_original.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"fmt"
 	"kpt-pasture/model"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"kpt-pasture/util"
+	"sort"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"time"
 	"time"
@@ -75,7 +76,21 @@ func (e *Entry) ProcessMilkOriginal(pastureId int64) {
 		zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
 		zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
 		return
 		return
 	}
 	}
-	e.DeleteRepeatMilkData(pastureId, deleteModel, milkClassConfig)
+
+	milkOriginalList := make([]*model.MilkOriginal, 0)
+	if err = e.DB.Model(new(model.MilkOriginal)).
+		Where("pasture_id = ?", pastureId).
+		Where("id BETWEEN ? AND ?", milkClassConfig.OldUpdateMaxId+1, milkClassConfig.CurrentMaxId).
+		Find(&milkOriginalList).Error; err != nil {
+		zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
+		return
+	}
+
+	e.DeleteRepeatMilkData(pastureId, deleteModel, milkClassConfig, milkOriginalList)
+	e.MilkHallData(pastureId)
+	e.UpdateRepeatCupSet1(milkOriginalList)
+	e.UpdateMilkOriginCowInfo(milkOriginalList)
+	e.UpdateRepeatCupSet2(milkOriginalList)
 }
 }
 
 
 // UpdateShifts 更新班次
 // UpdateShifts 更新班次
@@ -184,7 +199,7 @@ func (e *Entry) UpdateMilkDate(pastureId int64, xDBeg int) {
 }
 }
 
 
 // DeleteRepeatMilkData 删除重复数据
 // DeleteRepeatMilkData 删除重复数据
-func (e *Entry) DeleteRepeatMilkData(pastureId int64, deleteModel *DeleteMilkOriginal, cfg *MilkClassConfig) {
+func (e *Entry) DeleteRepeatMilkData(pastureId int64, deleteModel *DeleteMilkOriginal, cfg *MilkClassConfig, milkOriginalList []*model.MilkOriginal) {
 	// 获取最小日期对应的最小wid
 	// 获取最小日期对应的最小wid
 	var oriWid int64
 	var oriWid int64
 	if err := e.DB.Model(new(model.MilkOriginal)).
 	if err := e.DB.Model(new(model.MilkOriginal)).
@@ -196,83 +211,117 @@ func (e *Entry) DeleteRepeatMilkData(pastureId int64, deleteModel *DeleteMilkOri
 		return
 		return
 	}
 	}
 
 
+	for _, v := range milkOriginalList {
+		e.delete1(v, deleteModel.XMind, cfg)
+		e.delete2(v, deleteModel.XMind, cfg)
+		e.delete3(v, deleteModel.XMind, cfg)
+		e.delete4(v, deleteModel.XMind, cfg)
+	}
+}
+
+func (e *Entry) MilkHallData(pastureId int64) {
+	milkHallList := e.FindMilkHallList(pastureId)
+	if len(milkHallList) == 0 {
+		return
+	}
+
+	for _, v := range milkHallList {
+		e.UpdateRecognitionTime(pastureId, v)
+	}
+}
+
+// UpdateRecognitionTime 识别时间超过40分钟未套杯牛只,识别改为未识别
+func (e *Entry) UpdateRecognitionTime(pastureId int64, hall *model.MilkHall) {
 	milkOriginalList := make([]*model.MilkOriginal, 0)
 	milkOriginalList := make([]*model.MilkOriginal, 0)
 	if err := e.DB.Model(new(model.MilkOriginal)).
 	if err := e.DB.Model(new(model.MilkOriginal)).
 		Where("pasture_id = ?", pastureId).
 		Where("pasture_id = ?", pastureId).
-		Where("id BETWEEN ? AND ?", cfg.OldUpdateMaxId+1, cfg.CurrentMaxId).
+		Where("milk_hall_number = ?", hall.Name).
+		Where("milk_hall_brand = ?", hall.Brand).
+		Where("load = ?", 0).
 		Find(&milkOriginalList).Error; err != nil {
 		Find(&milkOriginalList).Error; err != nil {
-		zaplog.Error("DeleteRepeatMilkData", zap.Any("pastureId", pastureId), zap.Any("err", err))
+		zaplog.Error("MilkHallData", zap.Any("err", err))
 	}
 	}
 
 
 	for _, v := range milkOriginalList {
 	for _, v := range milkOriginalList {
-		e.Delete1(v, deleteModel.XMind, cfg)
-		e.Delete2(v, deleteModel.XMind, cfg)
-		e.Delete3(v, deleteModel.XMind, cfg)
-		e.Delete4(v, deleteModel.XMind, cfg)
-	}
-
-	/*// 2. 删除重复记录(除第一条外)
-	if err := e.DB.Exec(`
-		DELETE FROM milk_original
-		WHERE wid IN (
-			SELECT m.wid FROM (
-				SELECT m1.wid, m1.milk_date, m1.shifts, m1.detacher_address, m1.attach_time, m1.milk_weight, m1.pasture_id
-				FROM milk_original m1
-				WHERE m1.wid BETWEEN ? AND ?
-				AND m1.milk_date >= ?
-				AND EXISTS (
-					SELECT 1 FROM milk_original m2
-					WHERE m2.wid BETWEEN ? AND ?
-					AND m2.milk_date = m1.milk_date
-					AND m2.shifts = m1.shifts
-					AND m2.detacher_address = m1.detacher_address
-					AND m2.attach_time = m1.attach_time
-					AND m2.milk_weight = m1.milk_weight
-					AND m2.pasture_id = m1.pasture_id
-					AND m2.wid < m1.wid
-				)
-			) m
-		)`,
-		oriWid, maxWid, minDate, oriWid, maxWid).Error; err != nil {
-		zaplog.Error("DeleteRepeatMilkData DeleteDuplicates", zap.Any("err", err))
-	}
-
-	// 4. 删除各班次开始前无奶量记录
-	if err := e.DB.Exec(`
-		DELETE FROM milk_original
-		WHERE wid IN (
-			SELECT m.wid FROM (
-				SELECT m1.wid, m1.milk_date, m1.shifts, m1.milk_weight,
-						@tot := IF(@tot + m1.milk_weight > 100, 100,
-							IF(m1.shifts = @shifts, @tot, 0) + m1.milk_weight) m_tot,
-						@shifts := m1.shifts
-				FROM milk_original m1, (SELECT @tot := 0, @shifts := 0) aa
-				WHERE m1.wid BETWEEN ? AND ?
-				AND m1.milk_date >= ?
-				AND m1.pasture_id = ?
-				ORDER BY m1.milk_date, m1.shifts, STR_TO_DATE(m1.attach_time, '%Y-%m-%d %H:%i:%s')
-			) m
-			WHERE m.m_tot = 0
-		)`,
-		minWid, maxWid, minDate, pastureId).Error; err != nil {
-		zaplog.Error("DeleteRepeatMilkData DeleteNoMilkAtShift", zap.Any("err", err))
-	}
-
-	// 5. 删除时间异常数据
-	if err := e.DB.Exec(`
-		DELETE FROM milk_original
-		WHERE wid BETWEEN ? AND ?
-		AND milk_date >= '2020-10-01'
-		AND STR_TO_DATE(milk_date_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
-		AND STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s') > STR_TO_DATE(detacher_time, '%Y-%m-%d %H:%i:%s')
-		AND HOUR(STR_TO_DATE(attach_time, '%Y-%m-%d %H:%i:%s')) = 23
-		AND pasture_id = ?`,
-		minWid, maxWid, pastureId).Error; err != nil {
-		zaplog.Error("DeleteRepeatMilkData DeleteAbnormalTime", zap.Any("err", err))
-	}*/
+		t1, _ := util.TimeParseLocal(model.LayoutTime, v.AttachTime)
+		t2, _ := util.TimeParseLocal(model.LayoutTime, v.RecognitionTime)
+		diff := t1.Sub(t2)
+		minute := int(diff.Minutes())
+
+		if util.Substr(v.RecognitionTime, -1, 8) != "00:00:00" && minute > 40 {
+			if err := e.DB.Model(new(model.MilkOriginal)).
+				Where("id = ?", v.Id).
+				Updates(map[string]interface{}{
+					"cow_id":           0,
+					"ele_ear_number":   "",
+					"recognition_time": fmt.Sprintf("%s 00:00:00", util.Substr(v.RecognitionTime, 0, 10)),
+				}).Error; err != nil {
+				zaplog.Error("MilkHallData", zap.Any("err", err))
+			}
+		}
+	}
+}
+
+// UpdateRepeatCupSet1 更新重复套杯1, 识别时间相同,且不为0为重复套杯
+func (e *Entry) UpdateRepeatCupSet1(milkOriginalList []*model.MilkOriginal) {
+	if len(milkOriginalList) == 0 {
+		return
+	}
+
+	milkOriginalMap := make(map[string][]*model.MilkOriginal)
+	for _, v := range milkOriginalList {
+		if strings.HasSuffix(v.RecognitionTime, "00:00:00") {
+			continue
+		}
+		key := fmt.Sprintf("%s_%d_%d_%s", v.MilkDate, v.Shifts, v.DetacherAddress, v.RecognitionTime)
+		milkOriginalMap[key] = append(milkOriginalMap[key], v)
+	}
+
+	for _, originalList := range milkOriginalMap {
+		if len(originalList) >= 2 {
+			// 按照Id升序排序(保留第一条)
+			sort.Slice(originalList, func(i, j int) bool {
+				return originalList[i].Id < originalList[j].Id
+			})
+
+			for i, v := range originalList {
+				if i == 0 {
+					continue
+				}
+				if err := e.DB.Model(new(model.MilkOriginal)).
+					Select("").Where("id = ?", v.Id).
+					Update("nattach", 2).Error; err != nil {
+					zaplog.Error("UpdateRepeatCupSet1", zap.Any("err", err))
+				}
+			}
+		}
+	}
+}
+
+func (e *Entry) UpdateMilkOriginCowInfo(milkOriginalList []*model.MilkOriginal) {
+
+}
+
+// UpdateRepeatCupSet2  非标准重复套杯
+func (e *Entry) UpdateRepeatCupSet2(milkOriginalList []*model.MilkOriginal) {
+	for _, v := range milkOriginalList {
+		if v.AttachTime == "" || v.InitialTime == "" {
+			continue
+		}
+		attchTime, _ := util.TimeParseLocal(model.LayoutTime, v.AttachTime)
+		initialTime, _ := util.TimeParseLocal(model.LayoutTime, v.InitialTime)
+		if util.Substr(v.InitialTime, -1, 5) != "00:00" && v.Nattach == 0 && attchTime.Sub(initialTime).Minutes() <= 1 {
+			if err := e.DB.Model(new(model.MilkOriginal)).
+				Select("nattach").
+				Where("id = ?", v.Id).
+				Update("nattach", 2).Error; err != nil {
+				zaplog.Error("UpdateRepeatCupSet2", zap.Any("err", err))
+			}
+		}
+	}
 }
 }
 
 
-func (e *Entry) Delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
+func (e *Entry) delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
 	// 1. 删除attach_time为00:00:00的记录
 	// 1. 删除attach_time为00:00:00的记录
 	acctchStr := util.Substr(data.AttachTime, -1, 8)
 	acctchStr := util.Substr(data.AttachTime, -1, 8)
 	if data.MilkDate < xMinD || acctchStr != "00:00:00" {
 	if data.MilkDate < xMinD || acctchStr != "00:00:00" {
@@ -303,7 +352,7 @@ func (e *Entry) Delete1(data *model.MilkOriginal, xMinD string, cfg *MilkClassCo
 	}
 	}
 }
 }
 
 
-func (e *Entry) Delete2(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
+func (e *Entry) delete2(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
 	// 1. 检查记录是否在时间范围内
 	// 1. 检查记录是否在时间范围内
 	if data.MilkDate < xMinD {
 	if data.MilkDate < xMinD {
 		return
 		return
@@ -335,7 +384,7 @@ func (e *Entry) Delete2(data *model.MilkOriginal, xMinD string, cfg *MilkClassCo
 	}
 	}
 }
 }
 
 
-func (e *Entry) Delete3(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
+func (e *Entry) delete3(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
 	// 1. 检查记录是否在时间范围内
 	// 1. 检查记录是否在时间范围内
 	if data.MilkDate < xMinD {
 	if data.MilkDate < xMinD {
 		return
 		return
@@ -372,7 +421,7 @@ func (e *Entry) Delete3(data *model.MilkOriginal, xMinD string, cfg *MilkClassCo
 	}
 	}
 }
 }
 
 
-func (e *Entry) Delete4(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
+func (e *Entry) delete4(data *model.MilkOriginal, xMinD string, cfg *MilkClassConfig) {
 	// 1. 检查记录是否在时间范围内
 	// 1. 检查记录是否在时间范围内
 	if data.MilkDate < "2020-10-01" {
 	if data.MilkDate < "2020-10-01" {
 		return
 		return

+ 13 - 0
module/crontab/sql.go

@@ -348,3 +348,16 @@ func (e *Entry) FindNeckRingEstrusByFirstTimeEmpty(pastureId int64) []*model.Nec
 	}
 	}
 	return neckRingEstrusList
 	return neckRingEstrusList
 }
 }
+
+func (e *Entry) FindMilkHallList(pastureId int64) []*model.MilkHall {
+	res := make([]*model.MilkHall, 0)
+	if err := e.DB.Model(new(model.MilkHall)).
+		Where("pasture_id = ?", pastureId).
+		Where("is_show = ?", pasturePb.IsShow_Ok).
+		Find(&res).Error; err != nil {
+		zaplog.Error("FindMilkHallList", zap.Any("err", err))
+		return res
+	}
+
+	return res
+}

+ 4 - 3
service/milk/find_date_service.go

@@ -110,9 +110,10 @@ func (s *FindDataService) Run(fileList []string) {
 
 
 func (s *FindDataService) HandleFileContent(contentBody []byte) {
 func (s *FindDataService) HandleFileContent(contentBody []byte) {
 	requestBody := model.MilkHallBody{
 	requestBody := model.MilkHallBody{
-		Brand:   s.cfg.Brand,
-		FarmId:  s.cfg.FarmId,
-		Content: contentBody,
+		MilkHallNumber: s.cfg.MilkHallNumber,
+		Brand:          s.cfg.Brand,
+		FarmId:         s.cfg.FarmId,
+		Content:        []interface{}{string(contentBody)},
 	}
 	}
 	// 将内容转换为 JSON 字节
 	// 将内容转换为 JSON 字节
 	jsonData, err := json.Marshal(requestBody)
 	jsonData, err := json.Marshal(requestBody)

+ 8 - 2
util/util_test.go

@@ -2,6 +2,7 @@ package util
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"strconv"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
 	"time"
 	"time"
@@ -519,10 +520,15 @@ func TestSubstr(t *testing.T) {
 	s1 := strings.TrimSpace(Substr(text, 0, 6))
 	s1 := strings.TrimSpace(Substr(text, 0, 6))
 	s2 := strings.TrimSpace(Substr(text, 25, 4))
 	s2 := strings.TrimSpace(Substr(text, 25, 4))
 	fmt.Println("detachTime", detachTime, varCowCode, detacherAddress, milkWeight, s1, s2)
 	fmt.Println("detachTime", detachTime, varCowCode, detacherAddress, milkWeight, s1, s2)
+
+	fmt.Println("milkWeight:", milkWeight, strings.TrimSpace(Substr(text, 25, 4)))
+
+	milkWeight1, err := strconv.ParseInt(strings.TrimSpace(Substr(text, 25, 4)), 10, 64)
+	fmt.Println("milkWeight1:", milkWeight1, err)
 }
 }
 
 
 func Test_demo(t *testing.T) {
 func Test_demo(t *testing.T) {
 
 
-	var max time.Time
-	fmt.Println(max)
+	initialTime, err := TimeParseLocal(LayoutTime, "")
+	fmt.Println(initialTime, err)
 }
 }