Browse Source

work: 发情清单增加发情开始和结束时间字段

ping 3 weeks ago
parent
commit
041c8984f8

+ 1 - 0
config/app.develop.yaml

@@ -44,6 +44,7 @@ cron:
   update_same_time: "0 20 1 * * ?"      # 每天凌晨1点20分执行
   system_basic_crontab: "0 25 1 * * ?"  # 每天凌晨1点25分执行
   delete_old_original: "0 30 1 * * ?"   # 每天凌晨1点30分执行
+  update_disease_to_calendar: "0 05 1 * * ?" # 每天凌晨1点05分执行
   cow_pregnant: "0 00 15 * * ?"         # 每天15点执行
   neck_ring_estrus: "0 45 * * * ?"      # 更新脖环发情数据
   neck_ring_merge: "*/5 * * * * ?"      # 合并脖环原始2小时数据(5分钟)

+ 15 - 14
config/app.go

@@ -50,20 +50,21 @@ type CronSetting struct {
 	// 是否启动任务时先跑一次
 	CrontabStartRun bool `yaml:"crontab_start_run"`
 	// CRONTAB 表达式
-	UpdateCowInfo      string `yaml:"update_cow_info"`      //  更新牛只信息
-	Indicators         string `yaml:"indicators"`           //  牛只指标
-	GenerateWorkOrder  string `yaml:"generate_work_order"`  //  生成工作单
-	ImmunizationPlan   string `yaml:"immunization_plan"`    //  免疫计划
-	SameTimePlan       string `yaml:"same_time_plan"`       //  同期
-	UpdateSameTime     string `yaml:"update_same_time"`     //  更新同期
-	SystemBasicCrontab string `yaml:"system_basic_crontab"` //  系统基础定时任务
-	DeleteOldOriginal  string `yaml:"delete_old_original"`  // 删除脖环历史数据
-	CowPregnant        string `yaml:"cow_pregnant"`         //  月度牛只怀孕清单
-	UpdateActiveHabit  string `yaml:"update_active_habit"`  //  脖环2小时数据重新整合
-	NeckRingEstrus     string `yaml:"neck_ring_estrus"`     //  脖环牛只发情
-	NeckRingMerge      string `yaml:"neck_ring_merge"`      //  脖环原始数据合并
-	NeckRingCalculate  string `yaml:"neck_ring_calculate"`  //  脖环数据计算
-	NeckRingWarning    string `yaml:"neck_ring_warning"`    //  脖环预警
+	UpdateCowInfo           string `yaml:"update_cow_info"`            //  更新牛只信息
+	Indicators              string `yaml:"indicators"`                 //  牛只指标
+	GenerateWorkOrder       string `yaml:"generate_work_order"`        //  生成工作单
+	ImmunizationPlan        string `yaml:"immunization_plan"`          //  免疫计划
+	SameTimePlan            string `yaml:"same_time_plan"`             //  同期
+	UpdateSameTime          string `yaml:"update_same_time"`           //  更新同期
+	SystemBasicCrontab      string `yaml:"system_basic_crontab"`       //  系统基础定时任务
+	DeleteOldOriginal       string `yaml:"delete_old_original"`        // 删除脖环历史数据
+	UpdateDiseaseToCalendar string `yaml:"update_disease_to_calendar"` // 更新每天治疗中牛头数到日历表中
+	CowPregnant             string `yaml:"cow_pregnant"`               //  月度牛只怀孕清单
+	UpdateActiveHabit       string `yaml:"update_active_habit"`        //  脖环2小时数据重新整合
+	NeckRingEstrus          string `yaml:"neck_ring_estrus"`           //  脖环牛只发情
+	NeckRingMerge           string `yaml:"neck_ring_merge"`            //  脖环原始数据合并
+	NeckRingCalculate       string `yaml:"neck_ring_calculate"`        //  脖环数据计算
+	NeckRingWarning         string `yaml:"neck_ring_warning"`          //  脖环预警
 }
 
 type JwtTokenKeyConfig struct {

+ 6 - 0
dep/di_crontab.go

@@ -80,6 +80,12 @@ func EntryCrontab(dependency CrontabDependency) *cron.Crontab {
 		panic(err)
 	}
 
+	err = newCrontab.Bind("UpdateDiseaseToCalendar", cs.UpdateDiseaseToCalendar, dependency.CrontabHub.UpdateDiseaseToCalendar)
+	if err != nil {
+		zaplog.Error("EntryCrontab", zap.Any("UpdateCowEstrus", err))
+		panic(err)
+	}
+
 	err = newCrontab.Bind("UpdateCowEstrus", cs.NeckRingEstrus, dependency.CrontabHub.UpdateCowEstrus)
 	if err != nil {
 		zaplog.Error("EntryCrontab", zap.Any("UpdateCowEstrus", err))

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250303092843-e61a247edc34
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250305093352-5acd87c93e37
 	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

+ 14 - 0
go.sum

@@ -281,6 +281,20 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250303084040-e9be94c74c2a h1:vJXz6WZY
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250303084040-e9be94c74c2a/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250303092843-e61a247edc34 h1:7AgTMu6xEV/YjLtE2folQZwNZc0DWPUMWEVX1h18/2g=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250303092843-e61a247edc34/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250304111146-e555a797cab7 h1:dO2ztuxGme88Jxg68f1IR3fpZDIG/ZKCg9EwnpdoEss=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250304111146-e555a797cab7/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250304112845-3373faaec7ac h1:m7JV7qhf8D32HFxT+XLdOi1+ie4c1beRVCSd0LOhgYA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250304112845-3373faaec7ac/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305011349-1c6814a960ae h1:lmQOMWaC3Ccaaoejw+BccqlHVOHUZ2jWLr+G7zpIt0M=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305011349-1c6814a960ae/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305064639-4b9734707396 h1:xm6PExB8ww1BHw8GLJ+lRVIEGH68p1fNxlKOTr7b5FQ=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305064639-4b9734707396/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305080621-428c3913a7fc h1:O4LcrVeIKmS4MTbrGiIu/FIoAeoRT+oeLsHUN+ln8K0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305080621-428c3913a7fc/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305082022-ecb715590604 h1:o1DvM98KD8g1HJAcThjnrQmCntUwxdvdMN4ueHRbMzI=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305082022-ecb715590604/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305093352-5acd87c93e37 h1:/81LuiezVCXETpE3itLvDlCbQTeVGb4CeTU707s/lu4=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250305093352-5acd87c93e37/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=

+ 13 - 8
http/handler/event/event_breed.go

@@ -149,25 +149,30 @@ func MatingEventList(c *gin.Context) {
 	ginutil.JSONResp(c, res)
 }
 
-func MatingCreate(c *gin.Context) {
-	var req pasturePb.EventMating
+func MatingBatch(c *gin.Context) {
+	var req pasturePb.EventMatingBatch
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
 	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.CowIds, valid.Required),
-		valid.Field(&req.OperationId, valid.Required),
-		valid.Field(&req.FrozenSemenNumber, valid.Required),
-		valid.Field(&req.MatingAt, valid.Required),
-		valid.Field(&req.FrozenSemenCount, valid.Required, valid.Min(1)),
+		valid.Field(&req.Items, valid.Required, valid.Each(valid.By(func(value interface{}) error {
+			item := value.(pasturePb.EventMating)
+			return valid.ValidateStruct(&item,
+				valid.Field(&item.EarNumber, valid.Required),
+				valid.Field(&item.OperationId, valid.Required),
+				valid.Field(&item.FrozenSemenNumber, valid.Required),
+				valid.Field(&item.MatingAt, valid.Required),
+				valid.Field(&item.FrozenSemenCount, valid.Required, valid.Min(1)),
+			)
+		}))),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.MatingCreate(c, &req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.MatingBatch(c, &req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}

+ 1 - 1
http/route/event_api.go

@@ -33,7 +33,7 @@ func EventAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		eventRoute.POST("/pregnant/check/batch", event.PregnantCheckEventCreateBatch)
 		// 配种
 		eventRoute.POST("/mating/list", event.MatingEventList)
-		eventRoute.POST("/mating/create", event.MatingCreate)
+		eventRoute.POST("/mating/batch", event.MatingBatch)
 		// 发情
 		eventRoute.POST("/estrus/list", event.EstrusEventList)
 		eventRoute.POST("/estrus/mating/batch", event.EstrusBatchMating)

+ 33 - 10
model/calendar.go

@@ -12,7 +12,8 @@ type Calendar struct {
 	Name         string                      `json:"name"`
 	CalendarType pasturePb.CalendarType_Kind `json:"calendarType"`
 	Count        int32                       `json:"count"`
-	ShowDay      string                      `json:"showDay"`
+	StartDay     string                      `json:"startDay"`
+	EndDay       string                      `json:"endDay"`
 	IsShow       pasturePb.IsShow_Kind       `json:"isShow"`
 	Backup       string                      `json:"backup"`
 	CreatedAt    int64                       `json:"createdAt"`
@@ -23,24 +24,40 @@ func (w *Calendar) TableName() string {
 	return "calendar"
 }
 
-func NewCalendar(pastureId int64, name string, calendarType pasturePb.CalendarType_Kind, showDay string, count int32) *Calendar {
+func NewCalendar(pastureId int64, name string, calendarType pasturePb.CalendarType_Kind, startDay, endDay string, count int32) *Calendar {
 	return &Calendar{
 		PastureId:    pastureId,
 		Name:         name,
 		Count:        count,
 		CalendarType: calendarType,
-		ShowDay:      showDay,
+		StartDay:     startDay,
+		EndDay:       endDay,
 		IsShow:       pasturePb.IsShow_Ok,
 	}
 }
 
 var CalendarTypeColorMap = map[pasturePb.CalendarType_Kind]string{
-	pasturePb.CalendarType_Immunisation:    "#85c1e9",
-	pasturePb.CalendarType_PG:              "#48C9B0",
-	pasturePb.CalendarType_RnGH:            "#d35400",
-	pasturePb.CalendarType_Pregnancy_Check: "#8E44AD",
+	pasturePb.CalendarType_Immunisation:    "#00B42A",
+	pasturePb.CalendarType_PG:              "#722ED1",
+	pasturePb.CalendarType_RnGH:            "#722ED1",
+	pasturePb.CalendarType_Pregnancy_Check: "#F5319D",
 	pasturePb.CalendarType_WorkOrder:       "#5d6d7e",
-	pasturePb.CalendarType_Treatment:       "#c0392b",
+	pasturePb.CalendarType_Disease:         "#00B42A",
+	pasturePb.CalendarType_Calving:         "#F5319D",
+	pasturePb.CalendarType_Weaning:         "#F5319D",
+	pasturePb.CalendarType_Mating:          "#F5319D",
+}
+
+var CalendarTypeCycleMap = map[pasturePb.CalendarType_Kind]int{
+	pasturePb.CalendarType_Immunisation:    6,
+	pasturePb.CalendarType_PG:              0,
+	pasturePb.CalendarType_RnGH:            0,
+	pasturePb.CalendarType_Pregnancy_Check: 6,
+	pasturePb.CalendarType_WorkOrder:       -1,
+	pasturePb.CalendarType_Disease:         -1,
+	pasturePb.CalendarType_Calving:         14,
+	pasturePb.CalendarType_Weaning:         6,
+	pasturePb.CalendarType_Mating:          0,
 }
 
 type CalendarSlice []*Calendar
@@ -53,13 +70,19 @@ func (c CalendarSlice) ToPB() []*pasturePb.Calendar {
 			Title:   fmt.Sprintf("%s - %d", v.Name, v.Count),
 			GroupId: v.CalendarType,
 			Count:   v.Count,
-			Start:   v.ShowDay,
+			Start:   v.StartDay,
+			End:     v.EndDay,
 			Color:   CalendarTypeColorMap[v.CalendarType],
 			ExtendedProps: &pasturePb.ExtendedProps{
-				StartDay: v.ShowDay,
+				StartDay: v.StartDay,
 				Backup:   v.Backup,
 			},
 		}
 	}
 	return res
 }
+
+type TodayCompletedData struct {
+	Count            int32
+	CalendarTypeName string
+}

+ 5 - 6
model/event_calving.go

@@ -2,7 +2,6 @@ package model
 
 import (
 	"kpt-pasture/util"
-	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
@@ -60,7 +59,7 @@ func (e *EventCalving) EventUpdate(operationUser, currentUser *SystemUser, req *
 	e.MessageName = currentUser.Name
 }
 
-func NewEventCalving(pastureId int64, cow *Cow) *EventCalving {
+func NewEventCalving(pastureId int64, cow *Cow, startDay, endDay string) *EventCalving {
 	return &EventCalving{
 		PastureId:  pastureId,
 		CowId:      cow.Id,
@@ -71,15 +70,15 @@ func NewEventCalving(pastureId int64, cow *Cow) *EventCalving {
 		PenId:      cow.PenId,
 		BullNumber: cow.LastBullNumber,
 		Status:     pasturePb.IsShow_No,
-		PlanDay:    util.TimeParseLocalUnix(time.Now().Format(LayoutTime)),
-		EndDay:     util.TimeParseLocalEndUnix(time.Now().Format(LayoutTime)),
+		PlanDay:    util.TimeParseLocalUnix(startDay),
+		EndDay:     util.TimeParseLocalEndUnix(endDay),
 	}
 }
 
-func NewEventCalvingList(pastureId int64, cowList []*Cow) []*EventCalving {
+func NewEventCalvingList(pastureId int64, cowList []*Cow, startDay, endDay string) []*EventCalving {
 	eventCalvingList := make([]*EventCalving, 0)
 	for _, cow := range cowList {
-		eventCalvingList = append(eventCalvingList, NewEventCalving(pastureId, cow))
+		eventCalvingList = append(eventCalvingList, NewEventCalving(pastureId, cow, startDay, endDay))
 	}
 	return eventCalvingList
 }

+ 4 - 3
model/event_estrus.go

@@ -21,6 +21,7 @@ type EventEstrus struct {
 	IsMating            pasturePb.IsShow_Kind           `json:"isMating"`
 	UnMatingReasonsKind pasturePb.UnMatingReasons_Kind  `json:"unMatingReasonsKind"`
 	UnMatingReasonsName string                          `json:"unMatingReasonsName"`
+	Level               pasturePb.EstrusLevel_Kind      `json:"level"`
 	Remarks             string                          `json:"remarks"`
 	IsShow              pasturePb.IsShow_Kind           `json:"isShow"`
 	OperationId         int64                           `json:"operationId"`
@@ -41,7 +42,7 @@ func NewEventEstrus(
 	exposeEstrusType pasturePb.ExposeEstrusType_Kind,
 	isShow pasturePb.IsShow_Kind,
 	isMating pasturePb.IsShow_Kind,
-	PlanDay int32,
+	PlanDay int64,
 	operationUser, currentUser *SystemUser,
 ) *EventEstrus {
 	return &EventEstrus{
@@ -53,8 +54,8 @@ func NewEventEstrus(
 		NeckRingNumber:   cow.NeckRingNumber,
 		EarNumber:        cow.EarNumber,
 		ExposeEstrusType: exposeEstrusType,
-		PlanDay:          int64(PlanDay),
-		RealityDay:       int64(PlanDay),
+		PlanDay:          PlanDay,
+		RealityDay:       PlanDay,
 		IsMating:         isMating,
 		IsShow:           isShow,
 		OperationId:      operationUser.Id,

+ 3 - 3
model/event_immunization_plan.go

@@ -61,9 +61,9 @@ func (e *EventImmunizationPlan) EventUpdate(immunizationAt int64, cowInfo *Cow,
 }
 
 func NewEventImmunizationPlan(cow *Cow, immunizationPlan *ImmunizationPlan) *EventImmunizationPlan {
-	todayTime := time.Now().Format(LayoutDate2)
-	todayStartTime := util.TimeParseLocalUnix(todayTime)
-	todayEndTime := util.TimeParseLocalEndUnix(todayTime)
+	todayTime := time.Now()
+	todayStartTime := util.TimeParseLocalUnix(todayTime.Format(LayoutDate2))
+	todayEndTime := util.TimeParseLocalEndUnix(todayTime.AddDate(0, 0, 6).Format(LayoutDate2))
 	return &EventImmunizationPlan{
 		PastureId: immunizationPlan.PastureId,
 		CowId:     cow.Id,

+ 27 - 16
model/event_mating.go

@@ -120,29 +120,29 @@ func NewEventMating(pastureId int64, cow *Cow, planDay int64, exposeEstrusType p
 }
 
 // NewEventMatingNaturalEstrus 自然发情的牛只
-func NewEventMatingNaturalEstrus(pastureId int64, cow *Cow, req *pasturePb.EventMating, currentUser *SystemUser) *EventMating {
+func NewEventMatingNaturalEstrus(pastureId int64, item *EventMatingCheckBatchModel, currentUser *SystemUser) *EventMating {
 	return &EventMating{
 		PastureId:         pastureId,
-		CowId:             cow.Id,
-		EarNumber:         cow.EarNumber,
-		Lact:              cow.Lact,
-		DayAge:            cow.GetDayAge(),
-		CowType:           cow.CowType,
-		CowKind:           cow.CowKind,
-		CalvingAt:         cow.LastMatingAt,
-		PlanDay:           int64(req.MatingAt),
-		RealityDay:        int64(req.MatingAt),
-		EndDay:            int64(req.MatingAt),
+		CowId:             item.Cow.Id,
+		EarNumber:         item.Cow.EarNumber,
+		Lact:              item.Cow.Lact,
+		DayAge:            item.Cow.GetDayAge(),
+		CowType:           item.Cow.CowType,
+		CowKind:           item.Cow.CowKind,
+		CalvingAt:         item.Cow.LastMatingAt,
+		PlanDay:           item.MatingAt,
+		RealityDay:        item.MatingAt,
+		EndDay:            item.MatingAt,
 		MatingResult:      pasturePb.MatingResult_Unknown,
 		ExposeEstrusType:  pasturePb.ExposeEstrusType_Natural_Estrus,
 		Status:            pasturePb.IsShow_Ok,
-		OperationId:       int64(req.OperationId),
-		OperationName:     req.OperationName,
+		OperationId:       item.OperationUser.Id,
+		OperationName:     item.OperationUser.Name,
 		MessageId:         currentUser.Id,
 		MessageName:       currentUser.Name,
-		FrozenSemenNumber: req.FrozenSemenNumber,
-		Remarks:           req.Remarks,
-		MatingTimes:       cow.MatingTimes + 1,
+		FrozenSemenNumber: item.FrozenSemen.BullId,
+		Remarks:           item.Remarks,
+		MatingTimes:       item.Cow.MatingTimes + 1,
 	}
 }
 
@@ -317,3 +317,14 @@ type CowPregnantMonth struct {
 	Month    string `json:"month"`
 	CowCount int32  `json:"cowCount"`
 }
+
+// EventMatingCheckBatchModel 批量配种
+type EventMatingCheckBatchModel struct {
+	Cow              *Cow
+	FrozenSemen      *FrozenSemen
+	OperationUser    *SystemUser
+	MatingAt         int64
+	FrozenSemenCount int32
+	Remarks          string
+	ExposeEstrusType pasturePb.ExposeEstrusType_Kind
+}

+ 5 - 5
model/event_pregnant_check.go

@@ -57,7 +57,7 @@ func (e *EventPregnantCheck) EventUpdate(
 	e.Status = pasturePb.IsShow_Ok
 }
 
-func NewEventPregnantCheck(pastureId int64, cow *Cow, penMap map[int32]*Pen, pregnantCheckName string) *EventPregnantCheck {
+func NewEventPregnantCheck(pastureId int64, cow *Cow, penMap map[int32]*Pen, pregnantCheckName, startDay, endDay string) *EventPregnantCheck {
 	penName := ""
 	if pen, ok := penMap[cow.PenId]; ok {
 		penName = pen.Name
@@ -71,21 +71,21 @@ func NewEventPregnantCheck(pastureId int64, cow *Cow, penMap map[int32]*Pen, pre
 		PenName:           penName,
 		DayAge:            cow.GetDayAge(),
 		Lact:              int8(cow.Lact),
-		PlanDay:           util.TimeParseLocalUnix(time.Now().Format(LayoutDate2)),
-		EndDay:            util.TimeParseLocalEndUnix(time.Now().Format(LayoutDate2)),
+		PlanDay:           util.TimeParseLocalUnix(startDay),
+		EndDay:            util.TimeParseLocalEndUnix(endDay),
 		PregnantCheckName: pregnantCheckName,
 		BullId:            cow.LastBullNumber,
 		Status:            pasturePb.IsShow_No,
 	}
 }
 
-func NewEventPregnantCheckList(pastureId int64, cowList []*Cow, penMap map[int32]*Pen, pregnantCheckName string) []*EventPregnantCheck {
+func NewEventPregnantCheckList(pastureId int64, cowList []*Cow, penMap map[int32]*Pen, pregnantCheckName, startDay, endDay string) []*EventPregnantCheck {
 	res := make([]*EventPregnantCheck, len(cowList))
 	for i, cow := range cowList {
 		if cow.BreedStatus != pasturePb.BreedStatus_Breeding && cow.BreedStatus != pasturePb.BreedStatus_Pregnant {
 			continue
 		}
-		res[i] = NewEventPregnantCheck(pastureId, cow, penMap, pregnantCheckName)
+		res[i] = NewEventPregnantCheck(pastureId, cow, penMap, pregnantCheckName, startDay, endDay)
 	}
 	return res
 }

+ 5 - 6
model/event_weaning.go

@@ -3,7 +3,6 @@ package model
 import (
 	"kpt-pasture/util"
 	"strconv"
-	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
@@ -46,25 +45,25 @@ func (e *EventWeaning) EventUpdate(weaningAt int64, weight int32, remarks string
 	e.Weight = weight
 }
 
-func NewEventWeaning(pastureId int64, cowInfo *Cow) *EventWeaning {
+func NewEventWeaning(pastureId int64, cowInfo *Cow, startDay, endDay string) *EventWeaning {
 	motherId, _ := strconv.ParseInt(cowInfo.MotherNumber, 10, 64)
 	return &EventWeaning{
 		PastureId:   pastureId,
 		MotherId:    motherId,
 		BullNumber:  cowInfo.LastBullNumber,
 		CowId:       cowInfo.Id,
-		PlanDay:     util.TimeParseLocalUnix(time.Now().Format(LayoutDate2)),
-		EndDay:      util.TimeParseLocalEndUnix(time.Now().Format(LayoutDate2)),
+		PlanDay:     util.TimeParseLocalUnix(startDay),
+		EndDay:      util.TimeParseLocalEndUnix(endDay),
 		Status:      pasturePb.IsShow_No,
 		BeforePenId: cowInfo.PenId,
 		Weight:      0,
 	}
 }
 
-func NewEventWeaningList(pastureId int64, cowList []*Cow) []*EventWeaning {
+func NewEventWeaningList(pastureId int64, cowList []*Cow, startDay, endDay string) []*EventWeaning {
 	var weaningList = make([]*EventWeaning, 0)
 	for _, cow := range cowList {
-		weaningList = append(weaningList, NewEventWeaning(pastureId, cow))
+		weaningList = append(weaningList, NewEventWeaning(pastureId, cow, startDay, endDay))
 	}
 	return weaningList
 }

+ 11 - 23
model/frozen_semen_log.go

@@ -1,17 +1,11 @@
 package model
 
-import (
-	"fmt"
-	"strings"
-
-	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
-)
-
 type FrozenSemenLog struct {
 	Id            int64  `json:"id"`
 	PastureId     int64  `json:"pastureId"`
 	BullId        string `json:"bullId"`
-	CowIds        string `json:"cowId"`
+	CowId         int64  `json:"cowId"`
+	EarNumber     string `json:"earNumber"`
 	Quantity      int32  `json:"quantity"`
 	MatingAt      int64  `json:"matingAt"`
 	OperationId   int64  `json:"operationId"`
@@ -25,22 +19,16 @@ func (e *FrozenSemenLog) TableName() string {
 	return "frozen_semen_log"
 }
 
-func NewEventFrozenSemenLog(pastureId int64, req *pasturePb.EventMating) *FrozenSemenLog {
-	cowIds := ""
-	for _, v := range req.CowIds {
-		cowIds += fmt.Sprintf("%d,", v)
-	}
-	if len(cowIds) > 0 {
-		cowIds = strings.TrimRight(cowIds, ",")
-	}
+func NewEventFrozenSemenLog(pastureId int64, item *EventMatingCheckBatchModel) *FrozenSemenLog {
 	return &FrozenSemenLog{
 		PastureId:     pastureId,
-		BullId:        req.FrozenSemenNumber,
-		CowIds:        cowIds,
-		OperationId:   int64(req.OperationId),
-		OperationName: req.OperationName,
-		Quantity:      req.FrozenSemenCount,
-		MatingAt:      int64(req.MatingAt),
-		Remarks:       req.Remarks,
+		BullId:        item.FrozenSemen.BullId,
+		CowId:         item.Cow.Id,
+		EarNumber:     item.Cow.EarNumber,
+		OperationId:   item.OperationUser.Id,
+		OperationName: item.OperationUser.Name,
+		Quantity:      item.FrozenSemenCount,
+		MatingAt:      item.MatingAt,
+		Remarks:       item.Remarks,
 	}
 }

+ 1 - 1
model/neck_active_habit.go

@@ -115,7 +115,7 @@ func (n NeckActiveHabitSlice) Less(i, j int) bool {
 	return n[i].Frameid < n[j].Frameid
 }
 
-func (n NeckActiveHabitSlice) ToPB(curveName, startDateTime, endDateTime string) *CowBehaviorCurveData {
+func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {
 	res := &CowBehaviorCurveData{
 		OriginalDateList: make([]int32, 0),
 		ChangeDateList:   make([]int32, 0),

+ 9 - 1
model/neck_ring_estrus_warning.go

@@ -86,6 +86,12 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 		}
 
 		pzHour := v.calculatePzHour(cow.Lact)
+		estrusInterval := int32(0)
+		if v.LastTime != "" {
+			lastTime, _ := time.Parse(LayoutTime, v.LastTime)
+			diff := pzHour.Sub(lastTime)
+			estrusInterval = int32(diff.Hours() / 24)
+		}
 		res[i] = &pasturePb.EstrusItems{
 			Id:                     int32(v.Id),
 			CowId:                  int32(v.CowId),
@@ -101,8 +107,10 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 			OptimumMatingEndTime:   pzHour.Add(4 * time.Hour).Format(LayoutTime),
 			LastBreedEventDetails:  lastBreedEventDetails,
 			Level:                  v.Level,
-			EstrusInterval:         0,
+			EstrusInterval:         estrusInterval,
 			BestMatingTime:         pzHour.Format(LayoutTime),
+			EstrusStartTime:        pzHour.Add(-8 * time.Hour).Format(LayoutTime),
+			EstrusEndTime:          pzHour.Add(8 * time.Hour).Format(LayoutTime),
 		}
 	}
 	return res

+ 66 - 12
module/backend/calendar.go

@@ -7,6 +7,8 @@ import (
 	"kpt-pasture/util"
 	"net/http"
 	"regexp"
+	"strconv"
+	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/xerr"
@@ -36,19 +38,21 @@ func (s *StoreEntry) CalendarToDoList(ctx context.Context, req *pasturePb.Calend
 		}
 	}
 
-	sql := `SELECT a.cow_id,b.pen_name,a.calendar_type_name,DATE_FORMAT(FROM_UNIXTIME(a.plan_day), '%Y-%m-%d') AS plan_day,b.lact,
-	b.ear_number FROM (
-		SELECT cow_id,plan_day,'免疫' as calendar_type_name FROM event_immunization_plan WHERE status = 2 ` + pastureWhereSql + `
+	sql := `SELECT a.cow_id,b.pen_name,a.calendar_type_name,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,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_immunization_plan WHERE status = 2 ` + pastureWhereSql + `
 		UNION ALL
-		SELECT cow_id,plan_day ,'同期' as calendar_type_name FROM event_cow_same_time WHERE status = 2 ` + pastureWhereSql + `
+		SELECT cow_id,plan_day,'同期' as calendar_type_name,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_cow_same_time WHERE status = 2 ` + pastureWhereSql + `
 		UNION ALL
-		SELECT cow_id,plan_day ,'孕检' as calendar_type_name FROM event_pregnant_check WHERE status = 2 ` + pastureWhereSql + `
+		SELECT cow_id,plan_day,'孕检' as calendar_type_name,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_pregnant_check WHERE status = 2 ` + pastureWhereSql + `
 		UNION ALL
-		SELECT cow_id,plan_day ,'断奶' as calendar_type_name FROM event_weaning WHERE status = 2 ` + pastureWhereSql + `
+		SELECT cow_id,plan_day,'断奶' as calendar_type_name,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_weaning WHERE status = 2 ` + pastureWhereSql + `
 		UNION ALL
-		SELECT cow_id,plan_day ,'配种' as calendar_type_name FROM event_mating WHERE status = 2 ` + pastureWhereSql + `
+		SELECT cow_id,plan_day,'配种' as calendar_type_name,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_mating WHERE status = 2 ` + pastureWhereSql + `
 		UNION ALL
-		SELECT cow_id,plan_day ,'产犊' as calendar_type_name FROM event_calving WHERE status = 2 ` + pastureWhereSql + `
+		SELECT cow_id,plan_day,'产犊' as calendar_type_name,TIMESTAMPDIFF(DAY, NOW(), FROM_UNIXTIME(end_day)) AS remaining_days FROM event_calving WHERE status = 2 ` + pastureWhereSql + `
+		UNION ALL
+		SELECT cow_id,disease_at as plan_day,'疾病' as calendar_type_name,0 AS remaining_days FROM event_cow_disease WHERE diagnosed_result IN (2,3) ` + pastureWhereSql + `
 	) as a JOIN cow b ON a.cow_id = b.id WHERE 1 = 1 `
 
 	completeSql := fmt.Sprintf("%s %s ORDER BY a.plan_day DESC", sql, whereSql)
@@ -56,12 +60,40 @@ func (s *StoreEntry) CalendarToDoList(ctx context.Context, req *pasturePb.Calend
 		return nil, err
 	}
 
+	nowTime := time.Now().Format(model.LayoutDate2)
+	todayCompletedSql := `SELECT a.count as count,a.calendar_type_name as calendar_type_name FROM (
+		SELECT count('cow_id') as count,'免疫' as calendar_type_name FROM event_immunization_plan WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'同期' as calendar_type_name FROM event_cow_same_time WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'孕检' as calendar_type_name FROM event_pregnant_check WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'断奶' as calendar_type_name FROM event_weaning WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'配种' as calendar_type_name FROM event_mating WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'产犊' as calendar_type_name FROM event_calving WHERE status = 1 AND DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m-%d') = ?
+		UNION ALL
+		SELECT count('cow_id') as count,'疾病' as calendar_type_name FROM event_cow_disease WHERE diagnosed_result = 4 AND DATE_FORMAT(FROM_UNIXTIME(curable_at), '%Y-%m-%d') = ?
+	) as a `
+
+	toDayCompletedList := make([]*model.TodayCompletedData, 0)
+	if err = s.DB.Raw(todayCompletedSql, nowTime, nowTime, nowTime, nowTime, nowTime, nowTime, nowTime).Find(&toDayCompletedList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	toDayCompletedCountMap := make(map[string]int32)
+	for _, v := range toDayCompletedList {
+		toDayCompletedCountMap[v.CalendarTypeName] = v.Count
+	}
+
 	list := Paginate(calendarToDoList, pagination.Page, pagination.PageSize)
 	return &pasturePb.CalendarToDoResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.CalendarToDoData{
 			List:     list,
+			Progress: ProgressList(calendarToDoList, toDayCompletedCountMap),
 			Total:    int32(len(calendarToDoList)),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -75,9 +107,8 @@ func (s *StoreEntry) CalendarList(ctx context.Context, req *pasturePb.CalendarRe
 	}
 
 	calendarList := make([]*model.Calendar, 0)
-	if err = s.DB.Model(&model.Calendar{}).
-		Where("show_day >= ?", req.ShowStartDay).
-		Where("show_day <= ?", req.ShowEndDay).
+	if err = s.DB.Model(new(model.Calendar)).
+		Where("start_day BETWEEN ? AND ?", req.ShowStartDay, req.ShowEndDay).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
 		Where("is_show = ?", pasturePb.IsShow_Ok).
 		Find(&calendarList).Error; err != nil {
@@ -131,7 +162,7 @@ func (s *StoreEntry) getCalendarCowList(
 		return s.WorkOrderCowList(ctx, req, pagination)
 	case pasturePb.CalendarType_Weaning: // 断奶
 		return s.WeaningCowList(ctx, req, pagination)
-	case pasturePb.CalendarType_Treatment: // 治疗
+	case pasturePb.CalendarType_Disease: // 治疗
 		return s.TreatmentCowList(ctx, req, pagination)
 	case pasturePb.CalendarType_Mating: // 配种
 		return s.MatingCowList(ctx, req, pagination)
@@ -573,3 +604,26 @@ func Paginate(slice []*pasturePb.CalendarToDoList, page int32, pageSize int32) [
 	// 返回分页后的切片
 	return slice[start:end]
 }
+
+func ProgressList(dataList []*pasturePb.CalendarToDoList, toDayCompletedCountMap map[string]int32) map[int32]*pasturePb.ProgressList {
+	res := make(map[int32]*pasturePb.ProgressList)
+	incompleteTotalMap := make(map[int32]int32)
+	for _, v := range dataList {
+		incompleteTotalMap[int32(v.CalendarType)] += 1
+		calendarName := CalendarTypeMap()[v.CalendarType]
+		res[int32(v.CalendarType)] = &pasturePb.ProgressList{
+			CalendarName:     calendarName,
+			CalendarTypeKind: v.CalendarType,
+			CompletedCount:   toDayCompletedCountMap[calendarName],
+		}
+	}
+
+	for k, v := range incompleteTotalMap {
+		res[k].IncompleteTotal = v
+		res[k].Progress = fmt.Sprintf("0%")
+		if v > 0 && res[k].CompletedCount > 0 {
+			res[k].Progress = strconv.FormatFloat(float64(res[k].CompletedCount)/float64(v)*100, 'f', 2, 64) //fmt.Sprintf("%d%%", int32(float32(res[k].CompletedCount)/float32(v)*100))
+		}
+	}
+	return res
+}

+ 4 - 0
module/backend/config_data_breed.go

@@ -355,6 +355,10 @@ func CalendarTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 		Value:    int32(pasturePb.CalendarType_Weaning),
 		Label:    "断奶",
 		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.CalendarType_Disease),
+		Label:    "疾病",
+		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.CalendarType_Mating),
 		Label:    "配种",

+ 4 - 0
module/backend/config_data_other.go

@@ -532,6 +532,10 @@ func (s *StoreEntry) EventTypeEnumList(isAll string) []*pasturePb.ConfigOptionsL
 		Value:    int32(pasturePb.EventType_Insect_Repellent),
 		Label:    "驱虫",
 		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.EventType_Disease),
+		Label:    "疾病",
+		Disabled: true,
 	})
 	return configOptions
 }

+ 14 - 15
module/backend/cow.go

@@ -155,7 +155,8 @@ func (s *StoreEntry) EventList(ctx context.Context, req *pasturePb.SearchCowEven
 
 	eventCowLog := &model.EventCowLog{CowId: cowInfo.Id}
 	pref := s.DB.Table(eventCowLog.TableName()).
-		Where("pasture_id = ?", userModel.AppPasture.Id)
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("cow_id = ?", cowInfo.Id)
 
 	if req.Lact >= 0 {
 		pref.Where("lact = ?", req.Lact)
@@ -194,8 +195,8 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 	if err != nil {
 		return nil, xerr.Customf("错误的牛只信息: %d", req.CowId)
 	}
-	nowTime := time.Now()
 
+	nowTime := time.Now()
 	nowDayZero := util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2))
 	endDataTime := nowTime.Format(model.LayoutDate2)
 	startDataTime := nowTime.AddDate(0, 0, -30).Format(model.LayoutDate2)
@@ -211,6 +212,8 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 		return nil, xerr.WithStack(err)
 	}
 
+	data := model.NeckActiveHabitSlice(neckActiveHabitList).ToPB(req.CurveName)
+	data.EventMap = s.EventTypeMap()
 	// 牛只事件列表
 	eventLogList := make([]*model.EventCowLog, 0)
 	eventLog := &model.EventCowLog{CowId: cowInfo.Id}
@@ -222,8 +225,6 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 		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)
@@ -234,26 +235,24 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 	}
 
 	// 发情数据
-	estrusList := make([]*model.NeckRingEstrus, 0)
-	if err = s.DB.Table(new(model.NeckRingEstrus).TableName()).
+	estrusList := make([]*model.EventEstrus, 0)
+	if err = s.DB.Table(new(model.EventEstrus).TableName()).
 		Where("cow_id = ?", cowInfo.Id).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("first_time >= ?", startDataTime).
-		Where("first_time <= ?", endDataTime).
-		Order("first_time").
+		Where("reality_day BETWEEN ? AND ?", startDataTime, endDataTime).
+		Order("reality_day").
 		Find(&estrusList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 
 	for _, v := range estrusList {
-		if data.EstrusList[v.ActiveLevel] == nil {
-			data.EstrusList[v.ActiveLevel] = make([]string, 0)
+		if data.EstrusList[v.Level] == nil {
+			data.EstrusList[v.Level] = make([]string, 0)
 		}
-		if len(v.FirstTime) > 0 {
+		if v.RealityDay > 0 {
 			// 格式化为到小时的字符串
-			parsedTime, _ := time.Parse(model.LayoutTime, v.FirstTime)
-			hourStr := parsedTime.Format(model.LayoutHour)
-			data.EstrusList[v.ActiveLevel] = append(data.EstrusList[v.ActiveLevel], hourStr)
+			hourStr := time.Unix(v.RealityDay, 0).Format(model.LayoutHour)
+			data.EstrusList[v.Level] = append(data.EstrusList[v.Level], hourStr)
 		}
 	}
 

+ 7 - 3
module/backend/event_base.go

@@ -99,7 +99,7 @@ func (s *StoreEntry) CreateEnter(ctx context.Context, req *pasturePb.EventEnterR
 	newCow := model.NewEnterCow(userModel.AppPasture.Id, req, penMap)
 	defer func() {
 		if err == nil {
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, newCow, pasturePb.EventType_Enter, pasturePb.ExposeEstrusType_Invalid, req)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, newCow, pasturePb.EventType_Enter, req)
 			s.DB.Table(cowLogs.TableName()).Create(cowLogs)
 		}
 	}()
@@ -223,7 +223,7 @@ func (s *StoreEntry) CreateGroupTransfer(ctx context.Context, req *pasturePb.Tra
 			}
 
 			// 事件日志
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Transfer_Ben, pasturePb.ExposeEstrusType_Invalid, newEventTransferGroup)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Transfer_Ben, newEventTransferGroup)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -319,6 +319,10 @@ func (s *StoreEntry) WeightList(ctx context.Context, req *pasturePb.SearchEventR
 		pref.Where("a.ear_number = ?", req.EarNumber)
 	}
 
+	if req.StartDayAt > 0 && req.EndDayAt > 0 && req.EndDayAt >= req.StartDayAt {
+		pref.Where("a.weight_at BETWEEN ? AND ?", req.StartDayAt, req.EndDayAt)
+	}
+
 	if err = pref.Order("a.id desc").
 		Count(&count).Limit(int(pagination.PageSize)).
 		Offset(int(pagination.PageOffset)).
@@ -377,7 +381,7 @@ func (s *StoreEntry) WeightBatch(ctx context.Context, req *pasturePb.BatchEventW
 				return xerr.WithStack(err)
 			}
 
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Weight, pasturePb.ExposeEstrusType_Invalid, item)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Weight, item)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}

+ 3 - 3
module/backend/event_base_more.go

@@ -79,7 +79,7 @@ func (s *StoreEntry) DepartureBatch(ctx context.Context, req *pasturePb.EventDep
 			}
 
 			// 记录事件日志
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, eventType, pasturePb.ExposeEstrusType_Invalid, item)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, eventType, item)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -156,7 +156,7 @@ func (s *StoreEntry) CowSaleCreate(ctx context.Context, req *pasturePb.EventCowS
 	newEventSale := model.NewEventSale(userModel.AppPasture.Id, dealerInfo, cowIdsStr, req, operationUser, userModel.SystemUser)
 	eventCowLogList := make([]*model.EventCowLog, 0)
 	for _, cow := range cowList {
-		newEventCowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Sale, pasturePb.ExposeEstrusType_Invalid, req)
+		newEventCowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Sale, req)
 		eventCowLogList = append(eventCowLogList, newEventCowLog)
 	}
 
@@ -346,7 +346,7 @@ func (s *StoreEntry) ImmunizationBatch(ctx context.Context, req *pasturePb.Immun
 			}
 
 			// 记录日志
-			cowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cowInfo, pasturePb.EventType_Immunication, pasturePb.ExposeEstrusType_Invalid, eventImmunization)
+			cowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cowInfo, pasturePb.EventType_Immunication, eventImmunization)
 			if err = tx.Table(cowLog.TableName()).Create(cowLog).Error; err != nil {
 				return xerr.WithStack(err)
 			}

+ 33 - 34
module/backend/event_breed.go

@@ -136,7 +136,7 @@ func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalv
 			}
 
 			// 犊牛日志
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, newCalfCow, pasturePb.EventType_Birth, pasturePb.ExposeEstrusType_Invalid, calf)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, newCalfCow, pasturePb.EventType_Birth, calf)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -152,7 +152,7 @@ func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalv
 		}
 
 		// 母牛事件日志
-		cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Calving, pasturePb.ExposeEstrusType_Invalid, req)
+		cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Calving, req)
 		if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 			return xerr.WithStack(err)
 		}
@@ -174,6 +174,7 @@ func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSam
 	if err != nil {
 		return xerr.WithStack(err)
 	}
+	req.OperationName = operationUser.Name
 
 	eventCowSameTime, err := s.GetEventCowSameTimeByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId))
 	if err != nil {
@@ -189,21 +190,24 @@ func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSam
 	req.DrugsName = drugs.Name
 	eventCowSameTime.EventUpdate(drugs, req.Usage, req.Remarks, operationUser, userModel.SystemUser)
 
-	defer func() {
-		if err == nil {
-			// 记录牛只事件日志
-			cow, _ := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, eventCowSameTime.CowId)
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Seme_Time, pasturePb.ExposeEstrusType_Same_Time, req)
-			s.DB.Table(cowLogs.TableName()).Create(cowLogs)
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		if err = tx.Model(new(model.EventCowSameTime)).
+			Select("status", "drugs_id", "unit", "usage", "remarks", "operation_id", "operation_name").
+			Where("id = ?", eventCowSameTime.Id).
+			Updates(eventCowSameTime).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		// 记录牛只事件日志
+		cow, _ := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, eventCowSameTime.CowId)
+		cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Seme_Time, req)
+		if err = s.DB.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
+			return xerr.WithStack(err)
 		}
-	}()
+		return nil
+	}); err != nil {
 
-	if err = s.DB.Model(new(model.EventCowSameTime)).
-		Select("status", "drugs_id", "unit", "usage", "remarks", "operation_id", "operation_name").
-		Where("id = ?", eventCowSameTime.Id).
-		Updates(eventCowSameTime).Error; err != nil {
-		return xerr.WithStack(err)
 	}
+
 	return nil
 }
 
@@ -252,25 +256,20 @@ func (s *StoreEntry) SameTimeBatch(ctx context.Context, req *pasturePb.EventSame
 			}
 
 			cow, _ := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, v.CowId)
-			cowLogs := s.SubmitEventLog(
-				ctx,
-				userModel.AppPasture.Id,
-				cow,
-				pasturePb.EventType_Seme_Time,
-				pasturePb.ExposeEstrusType_Same_Time,
-				&pasturePb.EventSameTime{
-					Id:               int32(v.Id),
-					CowId:            int32(v.CowId),
-					SameTimeId:       int32(v.SameTimeId),
-					SameTimeType:     v.SameTimeType,
-					SameTimeTypeName: v.SameTimeName,
-					DrugsId:          int32(v.DrugsId),
-					DrugsName:        drugs.Name,
-					Usage:            req.Usage,
-					OperationId:      int32(operationUser.Id),
-					OperationName:    operationUser.Name,
-					SameTimeAt:       req.SameTimeAt,
-				})
+			logItem := &pasturePb.EventSameTime{
+				Id:               int32(v.Id),
+				CowId:            int32(v.CowId),
+				SameTimeId:       int32(v.SameTimeId),
+				SameTimeType:     v.SameTimeType,
+				SameTimeTypeName: v.SameTimeName,
+				DrugsId:          int32(v.DrugsId),
+				DrugsName:        drugs.Name,
+				Usage:            req.Usage,
+				OperationId:      int32(operationUser.Id),
+				OperationName:    operationUser.Name,
+				SameTimeAt:       req.SameTimeAt,
+			}
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Seme_Time, logItem)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -411,7 +410,7 @@ func (s *StoreEntry) EstrusBatchMating(ctx context.Context, req *pasturePb.Event
 				Updates(cow).Error; err != nil {
 				return xerr.WithStack(err)
 			}
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Estrus, v.ExposeEstrusType, v)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Estrus, v)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}

+ 107 - 87
module/backend/event_breed_more.go

@@ -153,7 +153,7 @@ func (s *StoreEntry) PregnantCheckCreateBatch(ctx context.Context, req *pastureP
 				}
 			}
 			// 记录日志
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, pasturePb.EventType_Pregnancy_Check, pasturePb.ExposeEstrusType_Invalid, item)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, pasturePb.EventType_Pregnancy_Check, item)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -215,7 +215,7 @@ func (s *StoreEntry) AbortionCreateBatch(ctx context.Context, req *pasturePb.Eve
 			}
 
 			// 记录日志
-			cowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, pasturePb.EventType_Abort, pasturePb.ExposeEstrusType_Invalid, item)
+			cowLog := s.SubmitEventLog(ctx, userModel.AppPasture.Id, item.Cow, pasturePb.EventType_Abort, item)
 			if err = tx.Table(cowLog.TableName()).Create(cowLog).Error; err != nil {
 				return xerr.WithStack(err)
 			}
@@ -318,114 +318,134 @@ func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventR
 	}, nil
 }
 
-// MatingCreate 牛只配种
-func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMating) (err error) {
+// MatingBatch 牛只配种
+func (s *StoreEntry) MatingBatch(ctx context.Context, req *pasturePb.EventMatingBatch) (err error) {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
 		return xerr.WithStack(err)
 	}
 
-	eventMatingCheckModel, err := s.MatingCreateCheck(ctx, userModel.AppPasture.Id, req)
+	eventMatingCheckModelList, err := s.MatingCreateCheck(ctx, userModel.AppPasture.Id, req)
 	if err != nil {
 		return xerr.WithStack(err)
 	}
 
-	req.OperationName = eventMatingCheckModel.OperationUser.Name
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
-		for _, cow := range eventMatingCheckModel.CowList {
-			// 获取牛只最近一次配种信息
-			lastEventMating, err := s.FindLastEventMatingByCowId(ctx, userModel.AppPasture.Id, cow.Id)
-			if err != nil {
-				// 1. 没有配种信息,(第一次参加配种的牛只,并且没有参与同期的牛只 )
-				if errors.Is(err, gorm.ErrRecordNotFound) {
-					newMating := model.NewEventMatingNaturalEstrus(userModel.AppPasture.Id, cow, req, userModel.SystemUser)
-
-					if err = tx.Create(newMating).Error; err != nil {
+		for _, item := range eventMatingCheckModelList {
+			// 脖环发情揭发数据
+			if item.ExposeEstrusType == pasturePb.ExposeEstrusType_Neck_Ring {
+				// 新增发情事件数据
+				newEstrus := model.NewEventEstrus(
+					userModel.AppPasture.Id, item.Cow, pasturePb.ExposeEstrusType_Neck_Ring,
+					pasturePb.IsShow_Ok, pasturePb.IsShow_Ok, item.MatingAt,
+					item.OperationUser, userModel.SystemUser,
+				)
+				if err = tx.Create(newEstrus).Error; err != nil {
+					return xerr.WithStack(err)
+				}
+				// 新增配种事件数据
+				newMating := model.NewEventMating(userModel.AppPasture.Id, item.Cow, item.MatingAt, pasturePb.ExposeEstrusType_Neck_Ring)
+				newMating.EventUpdate(item.MatingAt, item.FrozenSemen.BullId, false, item.OperationUser, userModel.SystemUser)
+				if err = s.MatingCowUpdate(ctx, userModel.AppPasture.Id, item, false); err != nil {
+					return xerr.WithStack(err)
+				}
+				if err = tx.Model(newMating).Create(newMating).Error; err != nil {
+					return xerr.WithStack(err)
+				}
+			} else {
+				// 获取牛只最近一次配种信息
+				lastEventMating, err := s.FindLastEventMatingByCowId(ctx, userModel.AppPasture.Id, item.Cow.Id)
+				if err != nil {
+					// 1. 没有配种信息,(第一次参加配种的牛只,并且没有参与同期的牛只 )
+					if errors.Is(err, gorm.ErrRecordNotFound) {
+						newMating := model.NewEventMatingNaturalEstrus(userModel.AppPasture.Id, item, userModel.SystemUser)
+						if err = tx.Create(newMating).Error; err != nil {
+							return xerr.WithStack(err)
+						}
+						if err = s.MatingCowUpdate(ctx, userModel.AppPasture.Id, item, false); err != nil {
+							return xerr.WithStack(err)
+						}
+						continue
+					} else {
 						return xerr.WithStack(err)
 					}
+				}
+
+				// 2. 所有有配种数据的牛只
+				if lastEventMating == nil || lastEventMating.Id <= 0 || lastEventMating.Status != pasturePb.IsShow_No {
+					zaplog.Error("MatingCreate", zap.Any("cow", item.Cow), zap.Any("UserModel", userModel))
+					return xerr.Customf("牛只配种数据异常: %d", item.Cow.EarNumber)
+				}
 
-					if err = s.MatingCowUpdate(ctx, userModel.AppPasture.Id, cow, req, false); err != nil {
+				// 2.1 复配 => 本胎次配次不加1
+				isReMating := lastEventMating.IsReMating(item.Cow, item.MatingAt)
+				if isReMating {
+					lastEventMating.EventReMatingUpdate(item.MatingAt)
+					if err = tx.Model(lastEventMating).
+						Select("mating_result", "mating_result_at", "status").
+						Where("id = ?", lastEventMating.Id).
+						Updates(lastEventMating).Error; err != nil {
+					}
+				}
+
+				// 2.2.  同期初配
+				IsMatingUpdate := lastEventMating.IsMatingUpdate()
+				if IsMatingUpdate {
+					lastEventMating.EventUpdate(item.MatingAt, item.FrozenSemen.BullId, isReMating, item.OperationUser, userModel.SystemUser)
+					if err = tx.Model(lastEventMating).
+						Select("mating_at", "status", "reality_day", "frozen_semen_number", "operation_id", "operation_name", "message_id", "message_name").
+						Where("id = ?", lastEventMating.Id).
+						Updates(lastEventMating).Error; err != nil {
 						return xerr.WithStack(err)
 					}
-					continue
-				} else {
-					return xerr.WithStack(err)
 				}
-			}
 
-			// 2. 所有有配种数据的牛只
-			if lastEventMating == nil || lastEventMating.Id <= 0 || lastEventMating.Status != pasturePb.IsShow_No {
-				zaplog.Error("MatingCreate", zap.Any("cow", cow), zap.Any("UserModel", userModel))
-				return xerr.Customf("牛只配种数据异常: %d", cow.EarNumber)
-			}
+				// 2.3. 提交的配种数据中,定位出空怀的牛只,
+				isEmptyMating := lastEventMating.IsEmptyMating(item.Cow, item.MatingAt)
+				if isEmptyMating {
+					// 把上次配种结果信息更新成空怀
+					lastEventMating.EventMatingResultUpdate(pasturePb.MatingResult_Empty, item.MatingAt)
+					if err = tx.Model(lastEventMating).
+						Select("mating_result", "mating_result_at").
+						Where("id = ?", lastEventMating.Id).
+						Updates(lastEventMating).Error; err != nil {
+						return xerr.WithStack(err)
+					}
+					// 先创建一条新的配种数据
+					newMating := model.NewEventMating(userModel.AppPasture.Id, item.Cow, item.MatingAt, pasturePb.ExposeEstrusType_Natural_Estrus)
+					newMating.EventUpdate(item.MatingAt, item.FrozenSemen.BullId, isReMating, item.OperationUser, userModel.SystemUser)
+					if err = tx.Model(newMating).Create(newMating).Error; err != nil {
+						return xerr.WithStack(err)
+					}
 
-			// 2.1 复配 => 本胎次配次不加1
-			isReMating := lastEventMating.IsReMating(cow, int64(req.MatingAt))
-			if isReMating {
-				lastEventMating.EventReMatingUpdate(int64(req.MatingAt))
-				if err = tx.Model(lastEventMating).
-					Select("mating_result", "mating_result_at", "status").
-					Where("id = ?", lastEventMating.Id).
-					Updates(lastEventMating).Error; err != nil {
+					// 更新牛只配种结果日志
+					if err = s.UpdateMatingResultEventCowLogByCowId(ctx, item.Cow.Id, s.MatingResultMap()[pasturePb.MatingResult_Empty]); err != nil {
+						zaplog.Error("MatingCreate", zap.Any("UpdateEventCowLogByCowId", err), zap.Any("cow", item.Cow))
+					}
 				}
-			}
 
-			// 2.2.  同期初配
-			IsMatingUpdate := lastEventMating.IsMatingUpdate()
-			if IsMatingUpdate {
-				lastEventMating.EventUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating, eventMatingCheckModel.OperationUser, userModel.SystemUser)
-				if err = tx.Model(lastEventMating).
-					Select("mating_at", "status", "reality_day", "frozen_semen_number", "operation_id", "operation_name", "message_id", "message_name").
-					Where("id = ?", lastEventMating.Id).
-					Updates(lastEventMating).Error; err != nil {
+				// 牛只基本中配种信息更新
+				if err = s.MatingCowUpdate(ctx, userModel.AppPasture.Id, item, isReMating); err != nil {
 					return xerr.WithStack(err)
 				}
 			}
 
-			// 2.3. 提交的配种数据中,定位出空怀的牛只,
-			isEmptyMating := lastEventMating.IsEmptyMating(cow, int64(req.MatingAt))
-			if isEmptyMating {
-				// 把上次配种结果信息更新成空怀
-				lastEventMating.EventMatingResultUpdate(pasturePb.MatingResult_Empty, int64(req.MatingAt))
-				if err = tx.Model(lastEventMating).
-					Select("mating_result", "mating_result_at").
-					Where("id = ?", lastEventMating.Id).
-					Updates(lastEventMating).Error; err != nil {
-					return xerr.WithStack(err)
-				}
-				// 先创建一条新的配种数据
-				newMating := model.NewEventMating(userModel.AppPasture.Id, cow, int64(req.MatingAt), req.ExposeEstrusType)
-				newMating.EventUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating, eventMatingCheckModel.OperationUser, userModel.SystemUser)
-				if err = tx.Model(newMating).Create(newMating).Error; err != nil {
-					return xerr.WithStack(err)
-				}
-
-				// 更新牛只配种结果日志
-				if err = s.UpdateMatingResultEventCowLogByCowId(ctx, cow.Id, s.MatingResultMap()[pasturePb.MatingResult_Empty]); err != nil {
-					zaplog.Error("MatingCreate", zap.Any("UpdateEventCowLogByCowId", err), zap.Any("cow", cow))
-				}
+			// 减去精液的数量
+			item.FrozenSemen.EventQuantityUpdate(item.FrozenSemenCount)
+			if err = tx.Model(item.FrozenSemen).
+				Select("quantity").
+				Where("id = ?", item.FrozenSemen.Id).
+				Updates(item.FrozenSemen).Error; err != nil {
+				return xerr.WithStack(err)
 			}
 
-			// 牛只基本中配种信息更新
-			if err = s.MatingCowUpdate(ctx, userModel.AppPasture.Id, cow, req, isReMating); err != nil {
+			// 创建冻精使用记录日志
+			itemFrozenSemenLog := model.NewEventFrozenSemenLog(userModel.AppPasture.Id, item)
+			if err = tx.Create(itemFrozenSemenLog).Error; err != nil {
 				return xerr.WithStack(err)
 			}
 		}
 
-		// 创建冻精使用记录日志
-		itemFrozenSemenLog := model.NewEventFrozenSemenLog(eventMatingCheckModel.FrozenSemen.PastureId, req)
-		if err = tx.Create(itemFrozenSemenLog).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		// 减去精液的数量
-		eventMatingCheckModel.FrozenSemen.EventQuantityUpdate(req.FrozenSemenCount)
-		if err = tx.Model(eventMatingCheckModel.FrozenSemen).
-			Select("quantity").
-			Where("id = ?", eventMatingCheckModel.FrozenSemen.Id).
-			Updates(eventMatingCheckModel.FrozenSemen).Error; err != nil {
-			return xerr.WithStack(err)
-		}
 		return nil
 	}); err != nil {
 		return xerr.WithStack(err)
@@ -434,17 +454,17 @@ func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMatin
 	return nil
 }
 
-func (s *StoreEntry) MatingCowUpdate(ctx context.Context, pastureId int64, cow *model.Cow, req *pasturePb.EventMating, isReMating bool) error {
+func (s *StoreEntry) MatingCowUpdate(ctx context.Context, pastureId int64, item *model.EventMatingCheckBatchModel, isReMating bool) error {
 	// 牛只基本中配种信息更新
-	cow.EventMatingUpdate(int64(req.MatingAt), req.FrozenSemenNumber, isReMating)
-	if err := s.DB.Model(cow).
+	item.Cow.EventMatingUpdate(item.MatingAt, item.FrozenSemen.BullId, isReMating)
+	if err := s.DB.Model(item.Cow).
 		Select("last_mating_at", "mating_times", "last_bull_number", "first_mating_at", "is_pregnant", "breed_status").
-		Where("id = ?", cow.Id).
-		Updates(cow).Error; err != nil {
+		Where("id = ?", item.Cow.Id).
+		Updates(item.Cow).Error; err != nil {
 		return xerr.WithStack(err)
 	}
 	// 记录日志
-	cowLogs := s.SubmitEventLog(ctx, pastureId, cow, pasturePb.EventType_Mating, req.ExposeEstrusType, req)
+	cowLogs := s.SubmitEventLog(ctx, pastureId, item.Cow, pasturePb.EventType_Mating, item)
 	if err := s.DB.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 		return xerr.WithStack(err)
 	}
@@ -516,7 +536,7 @@ func (s *StoreEntry) WeaningBatch(ctx context.Context, req *pasturePb.EventWeani
 				return xerr.WithStack(err)
 			}
 			// 记录事件日志
-			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cowInfo, pasturePb.EventType_Weaning, pasturePb.ExposeEstrusType_Invalid, req)
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cowInfo, pasturePb.EventType_Weaning, req)
 			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
 				return xerr.WithStack(err)
 			}

+ 44 - 50
module/backend/event_check.go

@@ -13,13 +13,6 @@ import (
 	"gitee.com/xuyiping_admin/pkg/xerr"
 )
 
-// EventMatingCheckBatchModel 批量配种
-type EventMatingCheckBatchModel struct {
-	CowList       []*model.Cow
-	FrozenSemen   *model.FrozenSemen
-	OperationUser *model.SystemUser
-}
-
 // PregnantCheckBatchModel 批量孕检
 type PregnantCheckBatchModel struct {
 	EventPregnancyCheck *model.EventPregnantCheck
@@ -57,71 +50,72 @@ func (s *StoreEntry) EnterCheck(ctx context.Context, req *pasturePb.EventEnterRe
 	return nil
 }
 
-func (s *StoreEntry) MatingCreateCheck(ctx context.Context, pastureId int64, req *pasturePb.EventMating) (*EventMatingCheckBatchModel, error) {
-	if len(req.CowIds) <= 0 {
+func (s *StoreEntry) MatingCreateCheck(ctx context.Context, pastureId int64, req *pasturePb.EventMatingBatch) ([]*model.EventMatingCheckBatchModel, error) {
+	if len(req.Items) <= 0 {
 		return nil, xerr.Custom("请选择相关牛只")
 	}
 
-	cowIds := make([]int64, 0)
-	for _, v := range req.CowIds {
-		cowIds = append(cowIds, int64(v))
-	}
-
-	if len(cowIds) > 50 {
+	if len(req.Items) > 50 {
 		return nil, xerr.Custom("最多只能选择50只牛只")
 	}
+	eventMatingCheckBatchModelList := make([]*model.EventMatingCheckBatchModel, 0)
 
-	cowList, err := s.GetCowInfoByCowIds(ctx, pastureId, cowIds)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
+	for _, v := range req.Items {
+		cowInfo, err := s.GetCowInfoByEarNumber(ctx, pastureId, v.EarNumber)
+		if err != nil {
+			return nil, xerr.WithStack(err)
+		}
 
-	operationUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
+		operationUser, err := s.GetSystemUserById(ctx, int64(v.OperationId))
+		if err != nil {
+			return nil, xerr.WithStack(err)
+		}
 
-	frozenSemen := &model.FrozenSemen{}
-	if err = s.DB.Where("bull_id = ?", req.FrozenSemenNumber).
-		First(frozenSemen).Error; err != nil {
-		return nil, xerr.Custom("未找到冻精信息")
-	}
+		frozenSemen := &model.FrozenSemen{}
+		if err = s.DB.Where("bull_id = ?", v.FrozenSemenNumber).
+			First(frozenSemen).Error; err != nil {
+			return nil, xerr.Custom("未找到冻精信息")
+		}
 
-	if frozenSemen.Quantity < req.FrozenSemenCount {
-		return nil, xerr.Custom("冻精数量不足")
-	}
+		if frozenSemen.Quantity < v.FrozenSemenCount {
+			return nil, xerr.Custom("冻精数量不足")
+		}
 
-	for _, cow := range cowList {
-		if cow.Sex != pasturePb.Genders_Female {
-			return nil, xerr.Customf("牛只: %d,不是母牛", cow.Id)
+		if cowInfo.Sex != pasturePb.Genders_Female {
+			return nil, xerr.Customf("牛只: %d,不是母牛", cowInfo.EarNumber)
 		}
 
-		if int64(req.MatingAt) < cow.LastMatingAt {
-			return nil, xerr.Customf("牛只: %d,最近一次配种时间: %d,不能小于本次配种时间: %d", cow.Id, cow.LastMatingAt, req.MatingAt)
+		if int64(v.MatingAt) < cowInfo.LastMatingAt {
+			return nil, xerr.Customf("牛只: %s,最近一次配种时间: %d,不能小于本次配种时间: %d", cowInfo.EarNumber, cowInfo.LastMatingAt, v.MatingAt)
 		}
 
-		if int64(req.MatingAt) < cow.LastPregnantCheckAt {
-			return nil, xerr.Customf("牛只: %d,最近一次孕检时间: %d,不能小于本次配种时间: %d", cow.Id, cow.LastPregnantCheckAt, req.MatingAt)
+		if int64(v.MatingAt) < cowInfo.LastPregnantCheckAt {
+			return nil, xerr.Customf("牛只: %s,最近一次孕检时间: %d,不能小于本次配种时间: %d", cowInfo.EarNumber, cowInfo.LastPregnantCheckAt, v.MatingAt)
 		}
 
-		if int64(req.MatingAt) < cow.LastAbortionAt {
-			return nil, xerr.Customf("牛只: %d,最近一次流产时间: %d,不能小于本次配种时间: %d", cow.Id, cow.LastAbortionAt, req.MatingAt)
+		if int64(v.MatingAt) < cowInfo.LastAbortionAt {
+			return nil, xerr.Customf("牛只: %s,最近一次流产时间: %d,不能小于本次配种时间: %d", cowInfo.EarNumber, cowInfo.LastAbortionAt, v.MatingAt)
 		}
 
-		if int64(req.MatingAt) < cow.BirthAt {
-			return nil, xerr.Customf("牛只: %d,出生时间: %d,不能小于本次配种时间: %d", cow.Id, cow.BirthAt, req.MatingAt)
+		if int64(v.MatingAt) < cowInfo.BirthAt {
+			return nil, xerr.Customf("牛只: %s,出生时间: %d,不能小于本次配种时间: %d", cowInfo.EarNumber, cowInfo.BirthAt, v.MatingAt)
 		}
 
-		if cow.BreedStatus == pasturePb.BreedStatus_Pregnant || cow.BreedStatus == pasturePb.BreedStatus_No_Mating {
-			return nil, xerr.Customf("牛只: %d,当前状态为: %s,不能进行配种", cow.Id, cow.BreedStatus.String())
+		if cowInfo.BreedStatus == pasturePb.BreedStatus_Pregnant || cowInfo.BreedStatus == pasturePb.BreedStatus_No_Mating {
+			return nil, xerr.Customf("牛只: %s,当前状态为: %s,不能进行配种", cowInfo.EarNumber, cowInfo.BreedStatus.String())
 		}
+		eventMatingCheckBatchModelList = append(eventMatingCheckBatchModelList, &model.EventMatingCheckBatchModel{
+			Cow:              cowInfo,
+			FrozenSemen:      frozenSemen,
+			OperationUser:    operationUser,
+			MatingAt:         int64(v.MatingAt),
+			FrozenSemenCount: v.FrozenSemenCount,
+			Remarks:          v.Remarks,
+			ExposeEstrusType: v.ExposeEstrusType,
+		})
 	}
 
-	return &EventMatingCheckBatchModel{
-		CowList:       cowList,
-		FrozenSemen:   frozenSemen,
-		OperationUser: operationUser,
-	}, nil
+	return eventMatingCheckBatchModelList, nil
 }
 
 func (s *StoreEntry) PregnantCheckDataCheck(ctx context.Context, pastureId int64, req *pasturePb.EventPregnantCheckBatch) ([]*PregnantCheckBatchModel, error) {
@@ -242,7 +236,7 @@ func (s *StoreEntry) EstrusCheckDataCheck(ctx context.Context, userModel *model.
 		operationUser, _ := s.GetSystemUserById(ctx, int64(item.OperationId))
 		item.OperationName = operationUser.Name
 		newEventEstrus := model.NewEventEstrus(userModel.AppPasture.Id, cowInfo, pasturePb.ExposeEstrusType_Natural_Estrus,
-			pasturePb.IsShow_Ok, item.IsMating, item.EstrusAt, operationUser, userModel.SystemUser)
+			pasturePb.IsShow_Ok, item.IsMating, int64(item.EstrusAt), operationUser, userModel.SystemUser)
 
 		if item.IsMating == pasturePb.IsShow_Ok {
 			newEventMating := model.NewEventMating(userModel.AppPasture.Id, cowInfo, time.Now().Unix(), pasturePb.ExposeEstrusType_Natural_Estrus)

+ 15 - 15
module/backend/event_cow_log.go

@@ -13,14 +13,7 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
-func (s *StoreEntry) SubmitEventLog(
-	ctx context.Context,
-	pastureId int64,
-	cow *model.Cow,
-	eventType pasturePb.EventType_Kind,
-	exposeEstrusType pasturePb.ExposeEstrusType_Kind,
-	req interface{},
-) *model.EventCowLog {
+func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *model.Cow, eventType pasturePb.EventType_Kind, req interface{}) *model.EventCowLog {
 	var (
 		desc, remarks    = "", ""
 		eventTypeName    = s.EventTypeMap()[eventType]
@@ -52,6 +45,13 @@ func (s *StoreEntry) SubmitEventLog(
 		operationUser.Name = data.OperationName
 		desc = fmt.Sprintf("转出栏舍: %s; 转入栏舍: %s", penMap[data.PenOutId].Name, penMap[data.PenInId].Name)
 	case pasturePb.EventType_Body_Score:
+	case pasturePb.EventType_Disease:
+		data := req.(*model.EventCowDisease)
+		eventAt = data.DiseaseAt
+		remarks = data.Remarks
+		operationUser.Id = int64(data.OperationId)
+		operationUser.Name = data.OperationName
+		desc = fmt.Sprintf("疾病名称: %s; 状态: 治疗中;", data.DiseaseName)
 	case pasturePb.EventType_Pregnancy_Check:
 		data := req.(*PregnantCheckBatchModel)
 		eventAt = int64(data.PregnantCheckAt)
@@ -77,8 +77,8 @@ func (s *StoreEntry) SubmitEventLog(
 		if data.IsMating == pasturePb.IsShow_Ok {
 			isMating = "是"
 		}
-		desc = fmt.Sprintf("发情揭发方式:%s;是否配种:%s;", s.ExposeEstrusTypeMap()[exposeEstrusType], isMating)
-		operationUser.Id = int64(data.OperationId)
+		desc = fmt.Sprintf("发情揭发方式:%s;是否配种:%s;", s.ExposeEstrusTypeMap()[data.ExposeEstrusType], isMating)
+		operationUser.Id = data.OperationId
 		operationUser.Name = data.OperationName
 		remarks = data.Remarks
 	case pasturePb.EventType_Calving:
@@ -116,11 +116,11 @@ func (s *StoreEntry) SubmitEventLog(
 		operationUser.Name = data.OperationName
 		remarks = data.Remarks
 	case pasturePb.EventType_Mating:
-		data := req.(*pasturePb.EventMating)
-		eventAt = int64(data.MatingAt)
-		desc = fmt.Sprintf("配种公牛: %s;配种结果:未知", data.FrozenSemenNumber)
-		operationUser.Id = int64(data.OperationId)
-		operationUser.Name = data.OperationName
+		data := req.(*model.EventMatingCheckBatchModel)
+		eventAt = data.MatingAt
+		desc = fmt.Sprintf("配种公牛: %s;配种结果:未知", data.FrozenSemen.BullId)
+		operationUser.Id = data.OperationUser.Id
+		operationUser.Name = data.OperationUser.Name
 		remarks = data.Remarks
 	case pasturePb.EventType_Birth:
 		eventAt = cow.BirthAt

+ 33 - 2
module/backend/event_health.go

@@ -111,6 +111,7 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 		if req.PrescriptionId > 0 {
 			prescription.EventUseCountUpdate()
 			if err = tx.Model(new(model.Prescription)).
+				Select("use_count").
 				Where("id = ?", prescription.Id).
 				Updates(prescription).Error; err != nil {
 				return xerr.WithStack(err)
@@ -144,6 +145,12 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 			if err = tx.Model(new(model.PrescriptionDrugs)).Create(newPrescriptionDrugs).Error; err != nil {
 				return xerr.WithStack(err)
 			}
+
+			// 记录事件日志
+			cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Disease, newEventCowDisease)
+			if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
+				return xerr.WithStack(err)
+			}
 		}
 
 		// 创建 CowDisease
@@ -368,6 +375,12 @@ func (s *StoreEntry) CowDiseaseDiagnose(ctx context.Context, req *pasturePb.CowD
 			Updates(cow).Error; err != nil {
 			return xerr.WithStack(err)
 		}
+
+		// 记录事件日志
+		cowLogs := s.SubmitEventLog(ctx, userModel.AppPasture.Id, cow, pasturePb.EventType_Disease, eventCowDisease)
+		if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
+			return xerr.WithStack(err)
+		}
 		return nil
 	}); err != nil {
 		return xerr.WithStack(err)
@@ -613,7 +626,6 @@ func (s *StoreEntry) CowDiseaseCurable(ctx context.Context, req *pasturePb.Event
 	}
 
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
-		cow := &model.Cow{}
 		for _, eventCowDisease := range eventCowDiseaseList {
 			eventCowDisease.EventCurableUpdate(int64(req.CurableAt))
 			if err = tx.Model(eventCowDisease).
@@ -624,7 +636,7 @@ func (s *StoreEntry) CowDiseaseCurable(ctx context.Context, req *pasturePb.Event
 				return xerr.WithStack(err)
 			}
 
-			cow, err = s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, eventCowDisease.CowId)
+			cow, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, eventCowDisease.CowId)
 			if err != nil {
 				return xerr.WithStack(err)
 			}
@@ -636,11 +648,30 @@ func (s *StoreEntry) CowDiseaseCurable(ctx context.Context, req *pasturePb.Event
 				Updates(cow).Error; err != nil {
 				return xerr.WithStack(err)
 			}
+
+			// 更新发病事件日志
+			cowLogs := &model.EventCowLog{CowId: cow.Id}
+			curableAtFormat := ""
+			if eventCowDisease.CurableAt > 0 {
+				curableAtFormat = time.Unix(eventCowDisease.CurableAt, 0).Format(model.LayoutDate2)
+			}
+			curableAtParse := time.Unix(eventCowDisease.CurableAt, 0)
+			diseaseAtParse := time.Unix(eventCowDisease.DiseaseAt, 0)
+			curableDays := int64(curableAtParse.Sub(diseaseAtParse).Hours() / 24)
+
+			if err = tx.Table(cowLogs.TableName()).
+				Where("event_type = ?", pasturePb.EventType_Disease).
+				Where("event_at = ?", eventCowDisease.DiseaseAt).
+				Update("desc", fmt.Sprintf("疾病名称: %s; 状态: 已治愈; 治愈时间: %s; 治疗天数: %d;", eventCowDisease.DiseaseName, curableAtFormat, curableDays)).
+				Error; err != nil {
+				return xerr.WithStack(err)
+			}
 		}
 
 		if err = tx.Model(new(model.EventCowTreatment)).Create(eventCowTreatmentList).Error; err != nil {
 			return xerr.WithStack(err)
 		}
+
 		return nil
 	}); err != nil {
 		return xerr.WithStack(err)

+ 2 - 2
module/backend/interface.go

@@ -174,7 +174,7 @@ type EventService interface {
 	PregnantCheckCreateBatch(ctx context.Context, req *pasturePb.EventPregnantCheckBatch) error
 	// MatingList 配种
 	MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventMatingResponse, error)
-	MatingCreate(ctx context.Context, req *pasturePb.EventMating) error
+	MatingBatch(ctx context.Context, req *pasturePb.EventMatingBatch) error
 	// EstrusBatchMating 发情批量处理配种
 	EstrusBatchMating(ctx context.Context, req *pasturePb.EventNaturalEstrusBatch) error
 	EstrusList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchEventEstrusResponse, error)
@@ -209,7 +209,7 @@ type EventService interface {
 	// CowEarNumberUpdate 修改耳号
 	CowEarNumberUpdate(ctx context.Context, req *pasturePb.EventReplaceEarNumber) error
 	// SubmitEventLog 记录提交事件结果日志
-	SubmitEventLog(ctx context.Context, pastureId int64, cow *model.Cow, eventType pasturePb.EventType_Kind, exposeEstrusType pasturePb.ExposeEstrusType_Kind, req interface{}) *model.EventCowLog
+	SubmitEventLog(ctx context.Context, pastureId int64, cow *model.Cow, eventType pasturePb.EventType_Kind, req interface{}) *model.EventCowLog
 
 	// CowSaleCreate 销售
 	CowSaleCreate(ctx context.Context, req *pasturePb.EventCowSale) error

+ 43 - 11
module/crontab/cow_cron.go

@@ -144,14 +144,14 @@ func (e *Entry) ImmunizationPlan() error {
 	}
 	var todayCount int32 = 0
 
-	nowTime := time.Now().Unix()
+	nowTime := time.Now()
 	for _, plan := range planList {
 		cowList := make([]*model.Cow, 0)
 		pref := e.DB.Table(fmt.Sprintf("%s as a", new(model.Cow).TableName())).
 			Select("a.*").
 			Where("a.pasture_id = ?", plan.PastureId).
 			Where("a.admission_status = ?", pasturePb.AdmissionStatus_Admission).
-			Where("NOT EXISTS ( select 1 from event_immunization_plan b where b.pen_id = a.id and b.status = ? and b.plan_day > ?)", pasturePb.IsShow_No, nowTime)
+			Where("NOT EXISTS ( select 1 from event_immunization_plan b where b.pen_id = a.id and b.status = ? and b.plan_day > ?)", pasturePb.IsShow_No, nowTime.Unix())
 		if plan.CowType > 0 {
 			pref.Where("a.cow_type = ?", plan.CowType)
 		}
@@ -197,7 +197,8 @@ func (e *Entry) ImmunizationPlan() error {
 
 		todayCount = int32(len(newImmunizationPlanCowList))
 		if todayCount > 0 {
-			e.CreatedCalendar(plan.PastureId, pasturePb.CalendarType_Immunisation, time.Now().Format(model.LayoutDate2), todayCount)
+			endDay := nowTime.AddDate(0, 0, model.CalendarTypeCycleMap[pasturePb.CalendarType_Immunisation])
+			e.CreatedCalendar(plan.PastureId, pasturePb.CalendarType_Immunisation, nowTime.Format(model.LayoutDate2), endDay.Format(model.LayoutDate2), todayCount)
 		}
 		e.CreateCrontabLog(ImmunizationPlan)
 	}
@@ -319,6 +320,7 @@ func (e *Entry) SystemBasicCrontab() error {
 	defer func() {
 		e.CreateCrontabLog(SystemBasicCrontab)
 	}()
+
 	systemBasicList := make([]*model.SystemBasic, 0)
 	if err := e.DB.Model(new(model.SystemBasic)).
 		Where("is_show = ?", pasturePb.IsShow_Ok).
@@ -378,7 +380,6 @@ func (e *Entry) SystemBasicCrontab() error {
 		}
 		e.InitEventData(cowList, systemBasic)
 	}
-
 	return nil
 }
 
@@ -391,31 +392,62 @@ func (e *Entry) DeleteOldOriginal() error {
 	return nil
 }
 
+// UpdateDiseaseToCalendar 更新每天治疗中牛头数到日历表中
+func (e *Entry) UpdateDiseaseToCalendar() error {
+	pastureList := e.FindPastureList()
+	for _, pasture := range pastureList {
+		// 更新每天治疗中牛头数到日历表中
+		var count int64
+		if err := e.DB.Model(new(model.EventCowDisease)).
+			Where("pasture_id = ?", pasture.Id).
+			Where("health_status IN (?)", []pasturePb.HealthStatus_Kind{pasturePb.HealthStatus_Disease, pasturePb.HealthStatus_Treatment}).
+			Count(&count).Error; err != nil {
+			zaplog.Error("crontab", zap.Any("UpdateDisease", err))
+		}
+		if count > 0 {
+			calendarTypeName := backend.CalendarTypeMap()[pasturePb.CalendarType_Disease]
+			startDay := time.Now().Format(model.LayoutDate2)
+			newCalendar := model.NewCalendar(pasture.Id, calendarTypeName, pasturePb.CalendarType_Disease, startDay, startDay, int32(count))
+			if err := e.DB.Model(new(model.Calendar)).
+				Create(newCalendar).Error; err != nil {
+				zaplog.Error("crontab", zap.Any("UpdateDisease", err))
+			}
+		}
+	}
+
+	return nil
+}
+
 func (e *Entry) InitEventData(cowList []*model.Cow, systemBasic *model.SystemBasic) {
 	calendarType := pasturePb.CalendarType_Invalid
+	nowTime := time.Now()
+	startDay, endDay := "", ""
 	switch systemBasic.Name {
 	case model.PregnantCheckForFirst, model.PregnantCheckForSecond:
 		penMap, _ := e.GetPenMapList(systemBasic.PastureId)
-		eventPregnantCheckDataList := model.NewEventPregnantCheckList(systemBasic.PastureId, cowList, penMap, systemBasic.Name)
+		calendarType = pasturePb.CalendarType_Pregnancy_Check
+		startDay, endDay = nowTime.Format(model.LayoutDate2), nowTime.AddDate(0, 0, model.CalendarTypeCycleMap[calendarType]).Format(model.LayoutDate2)
+		eventPregnantCheckDataList := model.NewEventPregnantCheckList(systemBasic.PastureId, cowList, penMap, systemBasic.Name, startDay, endDay)
 		if err := e.DB.Model(new(model.EventPregnantCheck)).Create(eventPregnantCheckDataList).Error; err != nil {
 			zaplog.Error("crontab", zap.Any("InitEventData", err), zap.Any("eventPregnantCheckDataList", eventPregnantCheckDataList))
 			return
 		}
-		calendarType = pasturePb.CalendarType_Pregnancy_Check
 	case model.WeaningAge:
-		eventWeaningDataList := model.NewEventWeaningList(systemBasic.PastureId, cowList)
+		calendarType = pasturePb.CalendarType_Weaning
+		startDay, endDay = nowTime.Format(model.LayoutDate2), nowTime.AddDate(0, 0, model.CalendarTypeCycleMap[calendarType]).Format(model.LayoutDate2)
+		eventWeaningDataList := model.NewEventWeaningList(systemBasic.PastureId, cowList, startDay, endDay)
 		if err := e.DB.Model(new(model.EventWeaning)).Create(eventWeaningDataList).Error; err != nil {
 			zaplog.Error("crontab", zap.Any("InitEventData", err), zap.Any("eventWeaningDataList", eventWeaningDataList))
 			return
 		}
-		calendarType = pasturePb.CalendarType_Weaning
 	case model.PregnancyAge:
-		eventCalvingList := model.NewEventCalvingList(systemBasic.PastureId, cowList)
+		calendarType = pasturePb.CalendarType_Calving
+		startDay, endDay = nowTime.Format(model.LayoutDate2), nowTime.AddDate(0, 0, model.CalendarTypeCycleMap[calendarType]).Format(model.LayoutDate2)
+		eventCalvingList := model.NewEventCalvingList(systemBasic.PastureId, cowList, startDay, endDay)
 		if err := e.DB.Model(new(model.EventCalving)).Create(eventCalvingList).Error; err != nil {
 			zaplog.Error("crontab", zap.Any("InitEventData", err), zap.Any("eventCalvingList", eventCalvingList))
 			return
 		}
-		calendarType = pasturePb.CalendarType_Calving
 	}
-	e.CreatedCalendar(systemBasic.PastureId, calendarType, time.Now().Format(model.LayoutDate2), int32(len(cowList)))
+	e.CreatedCalendar(systemBasic.PastureId, calendarType, startDay, endDay, int32(len(cowList)))
 }

+ 1 - 0
module/crontab/interface.go

@@ -33,6 +33,7 @@ type Crontab interface {
 	UpdateSameTime() error
 	SystemBasicCrontab() error
 	DeleteOldOriginal() error
+	UpdateDiseaseToCalendar() error
 
 	// UpdateCowEstrus 脖环数据
 	UpdateCowEstrus() error           // 获取牛只疑似发情数据

+ 5 - 1
module/crontab/neck_ring_estrus.go

@@ -200,7 +200,11 @@ func (e *Entry) UpdateEstrusFirstTime1(pastureId int64, xToday time.Time) {
 			if err := e.DB.Model(new(model.NeckRingEstrus)).
 				Where("id = ?", v.Id).
 				Update("first_time", cowEstrusStartData.FirstTime).Error; err != nil {
-				zaplog.Error("UpdateEstrusFirstTime1", zap.Any("v", v), zap.Any("err", err), zap.Any("cowEstrusStartData", cowEstrusStartData))
+				zaplog.Error("UpdateEstrusFirstTime1",
+					zap.Any("v", v),
+					zap.Any("err", err),
+					zap.Any("cowEstrusStartData", cowEstrusStartData),
+				)
 			}
 		}
 	}

+ 5 - 24
module/crontab/other.go

@@ -49,32 +49,13 @@ func (e *Entry) DeleteCrontabLog(name string) {
 }
 
 // CreatedCalendar 创建当天工单日历记录
-func (e *Entry) CreatedCalendar(pastureId int64, calendarType pasturePb.CalendarType_Kind, showDay string, count int32) {
+func (e *Entry) CreatedCalendar(pastureId int64, calendarType pasturePb.CalendarType_Kind, startDay, endDay string, count int32) {
 	calendarTypeName := backend.CalendarTypeMap()[calendarType]
-	newCalendar := model.NewCalendar(pastureId, calendarTypeName, calendarType, showDay, count)
-	historyCalendar := &model.Calendar{}
-	historyCount := int64(0)
-	if err := e.DB.Model(&model.Calendar{}).
-		Where("calendar_type = ?", calendarType).
-		Where("show_day = ?", showDay).
-		Where("pasture_id = ?", pastureId).
-		Count(&historyCount).
-		First(historyCalendar).Error; err != nil {
-		zaplog.Error("CreatedCalendar", zap.Any("err", err), zap.Any("historyCalendar", historyCalendar))
-	}
+	newCalendar := model.NewCalendar(pastureId, calendarTypeName, calendarType, startDay, endDay, count)
 
-	if historyCount <= 0 {
-		if err := e.DB.Model(&model.Calendar{}).
-			Create(newCalendar).Error; err != nil {
-			zaplog.Error("CreatedCalendar", zap.Any("err", err), zap.Any("workOrderCalendar", newCalendar))
-		}
-		return
-	} else {
-		if err := e.DB.Model(&model.Calendar{}).
-			Where("id = ?", historyCalendar.Id).
-			Update("count", count+int32(historyCount)).Error; err != nil {
-			zaplog.Error("CreatedCalendar", zap.Any("err", err), zap.Any("historyCalendar", historyCalendar))
-		}
+	if err := e.DB.Model(&model.Calendar{}).
+		Create(newCalendar).Error; err != nil {
+		zaplog.Error("CreatedCalendar", zap.Any("err", err), zap.Any("workOrderCalendar", newCalendar))
 	}
 }
 

+ 1 - 1
module/crontab/work_cron.go

@@ -69,7 +69,7 @@ func (e *Entry) GenerateCalendarBySameTimePlan(cowList []*model.Cow, sameTime *m
 		}
 
 		allCount := int32(len(newCowList)) + int32(histCount)
-		e.CreatedCalendar(sameTime.PastureId, calendarType, showDay.Format(model.LayoutDate2), allCount)
+		e.CreatedCalendar(sameTime.PastureId, calendarType, showDay.Format(model.LayoutDate2), showDay.Format(model.LayoutDate2), allCount)
 	}
 
 	zaplog.Info("GenerateCalendarBySameTimePlan",