Browse Source

cow: 项目同期梳理

Yi 6 months ago
parent
commit
cac90e0aa4

+ 3 - 3
.drone.yml

@@ -23,19 +23,19 @@ steps:
       - name: docker-sock
         path: /var/run/docker.sock
     settings:
-      #dockerfile: /drone/src/kpt-pasture/Dockerfile
+      dockerfile: /drone/src/Dockerfile
       username:
         from_secret: aliyuncs_username
       password:
         from_secret: aliyuncs_password
       repo: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-pasture
       registry: registry.cn-hangzhou.aliyuncs.com
-      tags: [ 1.0.0,latest ]
+      tags: [ test ]
 
 trigger:
   branch:
     include:
-    - develop
+    - feature/*
   event:
     include:
     - push

+ 3 - 3
Dockerfile

@@ -10,7 +10,7 @@ RUN go env -w GO111MODULE=on && \
     go env -w CGO_ENABLED=0 && \
     go env -w GOARCH=amd64 && \
     go env -w GOOS=linux && \
-    go build -o ./bin/kptTmrGroup -ldflags "-X kpt.kptyun.cn:3000/kpt-event/kpt-pasture/pod.appVersion=tmrGroup" main.go
+    go build -o ./bin/kptTmrGroup -ldflags "-X kpt.kptyun.cn:3000/kpt-event/kpt-pasture/pod.appVersion=beef" main.go
 
 
 FROM alpine:latest
@@ -22,9 +22,9 @@ WORKDIR /app/kpt-pasture
 
 
 COPY --from=0 /app/kpt-pasture/config/ /app/kpt-pasture/bin/config/
-COPY --from=0  /app/kpt-pasture/bin/kptTmrGroup /app/kpt-pasture/bin/kptTmrGroup
+COPY --from=0  /app/kpt-pasture/bin/kptPasture /app/kpt-pasture/bin/kptPasture
 
 EXPOSE 8090
 VOLUME ["/app/kpt-pasture/logger","/app/kpt-pasture/bin/config","/app/kpt-pasture/files"]
 
-CMD ["/app/kpt-pasture/bin/kptTmrGroup","http"]
+CMD ["/app/kpt-pasture/bin/kptPasture","http"]

+ 1 - 1
config/app.develop.yaml

@@ -35,7 +35,7 @@ side_work_setting:
       default: 5
 cron:
   crontab_start_run: false
-  update_cow_dayAge: "0 * * * * ?"
+  update_cow_info: "0 * * * * ?"
   generate_work_order: "0 0 22 * * ?"
   immunization_plan: "0 * * * * ?"
   same_Time_plan: "0 */1 * * * ?"

+ 1 - 1
config/app.go

@@ -49,7 +49,7 @@ type CronSetting struct {
 	// 是否启动任务时先跑一次
 	CrontabStartRun bool `yaml:"crontab_start_run"`
 	// CRONTAB 表达式
-	UpdateCowDayAge   string `yaml:"update_cow_dayAge"`
+	UpdateCowInfo     string `yaml:"update_cow_info"`
 	GenerateWorkOrder string `yaml:"generate_work_order"`
 	ImmunizationPlan  string `yaml:"immunization_plan"`
 	SameTimePlan      string `yaml:"same_time_plan"`

+ 1 - 1
config/app.test.yaml

@@ -34,7 +34,7 @@ side_work_setting:
       default: 5
 cron:
   crontab_start_run: false
-  update_cow_dayAge: "0 */1 * * * ?"
+  update_cow_info: "0 */1 * * * ?"
   generate_work_order: "0 0 22 * * ?"
   immunization_plan: "0 * * * * ?"
   same_Time_plan: "0 */1 * * * ?"

+ 1 - 1
dep/di_crontab.go

@@ -41,7 +41,7 @@ func EntryCrontab(dependency CrontabDependency) *cron.Crontab {
 	cfg := config.Options()
 	cs := cfg.CronSetting
 	newCrontab := cron.NewCrontab(DataCenterCrontabCounterVec)
-	err := newCrontab.Bind("UpdateCowDayAge", cs.UpdateCowDayAge, dependency.CrontabHub.UpdateCowInfo)
+	err := newCrontab.Bind("UpdateCowInfo", cs.UpdateCowInfo, dependency.CrontabHub.UpdateCowInfo)
 	if err != nil {
 		panic(err)
 	}

+ 29 - 0
docker-compose.yml

@@ -0,0 +1,29 @@
+version : '3'
+services:
+  kpt-dtm-crontab:
+    privileged: true
+    container_name: xdmy001_kpt_pasture_crontab
+    restart: always
+    image: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-pasture:test
+    volumes:
+      - /var/logger/kpt-dtm/:/app/kpt-dtm/logger
+      - /etc/localtime:/etc/localtime
+      - /data/docker-compose/kpt-pasture/config:/app/kpt-pasture/config
+    environment:
+      - APP_ENVIRONMENT=production
+      - DTM_WORK_DIR=/app/kpt-pasture/bin
+    command: [ "/app/kpt-pasture/bin/kptPasture","crontab" ]
+  kpt-dtm-http:
+    privileged: true
+    container_name: xdmy001_kpt_pasture_http
+    restart: always
+    image: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-dtm:test
+    volumes:
+      - /var/logger/kpt-dtm/:/app/kpt-dtm/logger
+      - /etc/localtime:/etc/localtime
+      - /data/docker-compose/kpt-dtm/config:/app/kpt-dtm/config
+      - /data/docker-compose/kpt-pasture/files:/app/kpt-pasture/files
+    environment:
+      - APP_ENVIRONMENT=production
+      - DTM_WORK_DIR=/app/kpt-pasture/bin
+    command: [ "/app/kpt-pasture/bin/kptPasture","http" ]

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20240906085821-e407cf34db4d
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20240909083429-fbc0524f090a
 	gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eko/gocache v1.1.0

+ 10 - 0
go.sum

@@ -42,6 +42,16 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20240906022358-d28cc0317fcc h1:q5QHNfCR
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240906022358-d28cc0317fcc/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240906085821-e407cf34db4d h1:vUz+UjLU0FgtH0EWdm2B7DWImbY/KF5R0DaCRY1B5Ao=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240906085821-e407cf34db4d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909032240-4bb8d1ae9a74 h1:EiIqP3VKAgfxAfTcYb0pahRDF8HTJszMS+6FT69kx5o=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909032240-4bb8d1ae9a74/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909053609-bc77419ef76f h1:oRK0jUyGYwyF2hnMPskhWLvlMqlTkUeNwuI/HlTROZ0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909053609-bc77419ef76f/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909054215-306813604abd h1:j34BDfJy91vtzhhEYHU0k5cANdMerKj7Ctjg+n1XwBg=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909054215-306813604abd/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909070422-d8e24115eea0 h1:WlkXLe5NFBAg57PLasrp3XvO/TB25+UqKGSXnWrbFBI=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909070422-d8e24115eea0/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909083429-fbc0524f090a h1:Vz40n7q51ZKrI2P5BCT0eY1I2Du5ApRaaFkkzqDO1bg=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240909083429-fbc0524f090a/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015 h1:dfb5dRd57L2HKjdwLT93UFmPYFPOmEl56gtZmqcNnaE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015/go.mod h1:Fk4GYI/v0IK3XFrm1Gn+VkgCz5Y7mfswD5hsTJYOG6A=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 228 - 0
http/handler/event/event_base.go

@@ -0,0 +1,228 @@
+package event
+
+import (
+	"kpt-pasture/http/middleware"
+	"net/http"
+
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/valid"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"github.com/gin-gonic/gin"
+)
+
+func EnterEventList(c *gin.Context) {
+	var req pasturePb.SearchEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	pagination := &pasturePb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.EnterList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func EnterEventCreate(c *gin.Context) {
+	var req pasturePb.EventEnterData
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.EarNumber, valid.Required),
+		valid.Field(&req.BirthAt, valid.Required),
+		valid.Field(&req.Sex, valid.Required),
+		valid.Field(&req.CowTypeId, valid.Required),
+		valid.Field(&req.CowKindId, valid.Required),
+		valid.Field(&req.CowSourceId, valid.Required),
+		valid.Field(&req.Lact, valid.Required),
+		valid.Field(&req.EnterAt, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.CreateEnter(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func GroupTransferEventList(c *gin.Context) {
+	var req pasturePb.SearchEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	pagination := &pasturePb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.GroupTransferList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func GroupTransferEventCreate(c *gin.Context) {
+	var req pasturePb.TransferGroupEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.Body, valid.Required, valid.Each(valid.By(func(value interface{}) error {
+			s := value.(pasturePb.TransferGroupEventData)
+			return valid.ValidateStruct(&s,
+				valid.Field(&s.CowId, valid.Required),
+				valid.Field(&s.TransferDate, valid.Required),
+				valid.Field(&s.TransferInPenId, valid.Required),
+				valid.Field(&s.TransferReasonId, valid.Required),
+				valid.Field(&s.StaffMemberId, valid.Required),
+			)
+		}))),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.CreateGroupTransfer(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func BodyScoreEventList(c *gin.Context) {
+	var req pasturePb.SearchEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	pagination := &pasturePb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.BodyScoreList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func BodyScoreEventCreate(c *gin.Context) {
+	var req pasturePb.BodyScoreEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.CowId, valid.Required),
+		valid.Field(&req.ScoreAt, valid.Required),
+		valid.Field(&req.Score, valid.Required),
+		valid.Field(&req.StaffMemberId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.CreateBodyScore(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func WeightEventList(c *gin.Context) {
+	var req pasturePb.SearchEventRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	pagination := &pasturePb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.WeightList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func WeightEventCreate(c *gin.Context) {
+	var req pasturePb.EventWeight
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.CowId, valid.Required),
+		valid.Field(&req.WeightAt, valid.Required),
+		valid.Field(&req.StaffMemberId, valid.Required),
+		valid.Field(&req.WeightItems, valid.Required, valid.Each(valid.By(func(value interface{}) error {
+			s := value.(pasturePb.WeightItem)
+			return valid.ValidateStruct(&s,
+				valid.Field(&s.Weight, valid.Required),
+			)
+		}))),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.WeightCreate(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 17 - 199
http/handler/event/event.go → http/handler/event/event_breed.go

@@ -4,174 +4,14 @@ import (
 	"kpt-pasture/http/middleware"
 	"net/http"
 
-	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
-	"gitee.com/xuyiping_admin/pkg/valid"
-
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"gitee.com/xuyiping_admin/pkg/apierr"
 	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"github.com/gin-gonic/gin"
 )
 
-func EnterEventList(c *gin.Context) {
-	var req pasturePb.SearchEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	pagination := &pasturePb.PaginationModel{
-		Page:       int32(c.GetInt(middleware.Page)),
-		PageSize:   int32(c.GetInt(middleware.PageSize)),
-		PageOffset: int32(c.GetInt(middleware.PageOffset)),
-	}
-
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.EnterList(c, &req, pagination)
-	if err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-	ginutil.JSONResp(c, res)
-}
-
-func EnterEventCreate(c *gin.Context) {
-	var req pasturePb.SearchEnterData
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.EarNumber, valid.Required),
-		valid.Field(&req.BirthAt, valid.Required),
-		valid.Field(&req.Sex, valid.Required),
-		valid.Field(&req.CowTypeId, valid.Required),
-		valid.Field(&req.CowKindId, valid.Required),
-		valid.Field(&req.CowSourceId, valid.Required),
-		valid.Field(&req.Lact, valid.Required),
-		valid.Field(&req.EnterAt, valid.Required),
-	); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := middleware.BackendOperation(c).OpsService.CreateEnter(c, &req); err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-
-	ginutil.JSONResp(c, &operationPb.CommonOK{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &operationPb.Success{Success: true},
-	})
-}
-
-func GroupTransferEventList(c *gin.Context) {
-	var req pasturePb.SearchEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	pagination := &pasturePb.PaginationModel{
-		Page:       int32(c.GetInt(middleware.Page)),
-		PageSize:   int32(c.GetInt(middleware.PageSize)),
-		PageOffset: int32(c.GetInt(middleware.PageOffset)),
-	}
-
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.GroupTransferList(c, &req, pagination)
-	if err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-	ginutil.JSONResp(c, res)
-}
-
-func GroupTransferEventCreate(c *gin.Context) {
-	var req pasturePb.TransferGroupEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.Body, valid.Required, valid.Each(valid.By(func(value interface{}) error {
-			s := value.(pasturePb.TransferGroupEventData)
-			return valid.ValidateStruct(&s,
-				valid.Field(&s.CowId, valid.Required),
-				valid.Field(&s.TransferDate, valid.Required),
-				valid.Field(&s.TransferInPenId, valid.Required),
-				valid.Field(&s.TransferReasonId, valid.Required),
-				valid.Field(&s.StaffMemberId, valid.Required),
-			)
-		}))),
-	); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := middleware.BackendOperation(c).OpsService.CreateGroupTransfer(c, &req); err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-	ginutil.JSONResp(c, &operationPb.CommonOK{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &operationPb.Success{Success: true},
-	})
-}
-
-func BodyScoreEventList(c *gin.Context) {
-	var req pasturePb.SearchEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	pagination := &pasturePb.PaginationModel{
-		Page:       int32(c.GetInt(middleware.Page)),
-		PageSize:   int32(c.GetInt(middleware.PageSize)),
-		PageOffset: int32(c.GetInt(middleware.PageOffset)),
-	}
-
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.BodyScoreList(c, &req, pagination)
-	if err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-	ginutil.JSONResp(c, res)
-}
-
-func BodyScoreEventCreate(c *gin.Context) {
-	var req pasturePb.BodyScoreEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.CowId, valid.Required),
-		valid.Field(&req.ScoreAt, valid.Required),
-		valid.Field(&req.Score, valid.Required),
-		valid.Field(&req.StaffMemberId, valid.Required),
-	); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	if err := middleware.BackendOperation(c).OpsService.CreateBodyScore(c, &req); err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-
-	ginutil.JSONResp(c, &operationPb.CommonOK{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &operationPb.Success{Success: true},
-	})
-}
-
 func CalvingEventList(c *gin.Context) {
 	var req pasturePb.SearchEventRequest
 	if err := ginutil.BindProto(c, &req); err != nil {
@@ -194,7 +34,7 @@ func CalvingEventList(c *gin.Context) {
 }
 
 func CalvingEventCreate(c *gin.Context) {
-	var req pasturePb.CalvingEventRequest
+	var req pasturePb.EventCalving
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -254,7 +94,7 @@ func PregnantCheckEventList(c *gin.Context) {
 }
 
 func PregnantCheckEventCreate(c *gin.Context) {
-	var req pasturePb.PregnantCheckEventRequest
+	var req pasturePb.EventPregnantCheck
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -305,7 +145,7 @@ func MatingEventList(c *gin.Context) {
 }
 
 func MatingCreate(c *gin.Context) {
-	var req pasturePb.MatingEventRequest
+	var req pasturePb.EventMating
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -356,7 +196,7 @@ func EstrusEventList(c *gin.Context) {
 }
 
 func EstrusCreate(c *gin.Context) {
-	var req pasturePb.EstrusEventRequest
+	var req pasturePb.EventEstrus
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -435,50 +275,23 @@ func FrozenSemeCreate(c *gin.Context) {
 	})
 }
 
-func WeightEventList(c *gin.Context) {
-	var req pasturePb.SearchEventRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
-	pagination := &pasturePb.PaginationModel{
-		Page:       int32(c.GetInt(middleware.Page)),
-		PageSize:   int32(c.GetInt(middleware.PageSize)),
-		PageOffset: int32(c.GetInt(middleware.PageOffset)),
-	}
-
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.WeightList(c, &req, pagination)
-	if err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-	ginutil.JSONResp(c, res)
-}
-
-func WeightEventCreate(c *gin.Context) {
-	var req pasturePb.WeightEventRequest
+func SameTimeCreate(c *gin.Context) {
+	var req pasturePb.EventSameTime
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
 	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.CowId, valid.Required),
-		valid.Field(&req.WeightAt, valid.Required),
-		valid.Field(&req.StaffMemberId, valid.Required),
-		valid.Field(&req.WeightItems, valid.Required, valid.Each(valid.By(func(value interface{}) error {
-			s := value.(pasturePb.WeightItem)
-			return valid.ValidateStruct(&s,
-				valid.Field(&s.Weight, valid.Required),
-			)
-		}))),
+		valid.Field(&req.SameTimeId, valid.Required),
+		valid.Field(&req.SameTimeType, valid.Required),
+		valid.Field(&req.SameTimeAt, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.CreateWeight(c, &req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.SameTimeCreate(c, &req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
@@ -488,4 +301,9 @@ func WeightEventCreate(c *gin.Context) {
 		Msg:  "ok",
 		Data: &operationPb.Success{Success: true},
 	})
+
+}
+
+func SameTimeList(c *gin.Context) {
+
 }

+ 1 - 0
http/handler/event/event_vet.go

@@ -0,0 +1 @@
+package event

+ 7 - 3
http/route/event_api.go

@@ -22,6 +22,10 @@ func EventAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		// 体况评分
 		eventRoute.POST("/body/score/list", event.BodyScoreEventList)
 		eventRoute.POST("/body/score/create", event.BodyScoreEventCreate)
+		// 称重
+		eventRoute.POST("/weight/list", event.WeightEventList)
+		eventRoute.POST("/weight/create", event.WeightEventCreate)
+
 		// 产犊
 		eventRoute.POST("/calving/list", event.CalvingEventList)
 		eventRoute.POST("/calving/create", event.CalvingEventCreate)
@@ -37,9 +41,9 @@ func EventAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		// 冻精
 		eventRoute.POST("/frozen/seme/list", event.FrozenSemeList)
 		eventRoute.POST("/frozen/seme/create", event.FrozenSemeCreate)
+		// 同期
+		eventRoute.POST("/same/time/list", event.SameTimeList)
+		eventRoute.POST("/same/time/create", event.SameTimeCreate)
 
-		// 称重
-		eventRoute.POST("/weight/list", event.WeightEventList)
-		eventRoute.POST("/weight/create", event.WeightEventCreate)
 	}
 }

+ 1 - 1
model/calving_calf.go

@@ -25,7 +25,7 @@ func (e *CalvingCalf) TableName() string {
 	return "calving_calf"
 }
 
-func NewEventCalvingCalf(motherId, calvingId int64, req *pasturePb.CalvingEventRequest) []*CalvingCalf {
+func NewEventCalvingCalf(motherId, calvingId int64, req *pasturePb.EventCalving) []*CalvingCalf {
 	calvingCalfList := make([]*CalvingCalf, 0)
 	for _, v := range req.CalfItemList {
 		isAdoption := v.IsAdoption

+ 1 - 1
model/cow.go

@@ -92,7 +92,7 @@ func (c CowSlice) ToPB(
 	return res
 }
 
-func NewCow(req *pasturePb.SearchEnterData) *Cow {
+func NewCow(req *pasturePb.EventEnterData) *Cow {
 	var isPregnant = pasturePb.IsShow_No
 	if req.BreedStatusId == pasturePb.BreedStatus_Pregnant {
 		isPregnant = pasturePb.IsShow_Ok

+ 1 - 1
model/cow_weight.go

@@ -23,7 +23,7 @@ func (c *EventWeight) TableName() string {
 	return "event_weight"
 }
 
-func NewEventWeight(cow *Cow, systemUser *SystemUser, weight int32, req *pasturePb.WeightEventRequest) *EventWeight {
+func NewEventWeight(cow *Cow, systemUser *SystemUser, weight int32, req *pasturePb.EventWeight) *EventWeight {
 	return &EventWeight{
 		CowId:         cow.Id,
 		EarNumber:     cow.EarNumber,

+ 4 - 4
model/event_calving.go

@@ -25,7 +25,7 @@ func (e *EventCalving) TableName() string {
 	return "event_calving"
 }
 
-func NewEventCalving(cow *Cow, req *pasturePb.CalvingEventRequest) *EventCalving {
+func NewEventCalving(cow *Cow, req *pasturePb.EventCalving) *EventCalving {
 	return &EventCalving{
 		CowId:          cow.Id,
 		EarNumber:      cow.EarNumber,
@@ -51,8 +51,8 @@ type EventCalvingList struct {
 
 type EventCalvingListSlice []*EventCalvingList
 
-func (e EventCalvingListSlice) ToPB(req []*CalvingCalf) []*pasturePb.SearchLavingList {
-	var list []*pasturePb.SearchLavingList
+func (e EventCalvingListSlice) ToPB(req []*CalvingCalf) []*pasturePb.LavingList {
+	var list []*pasturePb.LavingList
 	for _, item := range e {
 		CalfItemList := make([]*pasturePb.CalfItem, 0)
 		for _, v := range req {
@@ -73,7 +73,7 @@ func (e EventCalvingListSlice) ToPB(req []*CalvingCalf) []*pasturePb.SearchLavin
 				Id:         int32(v.Id),
 			})
 		}
-		list = append(list, &pasturePb.SearchLavingList{
+		list = append(list, &pasturePb.LavingList{
 			Id:              int32(item.Id),
 			CowId:           int32(item.CowId),
 			Lact:            item.Lact,

+ 4 - 4
model/event_enter.go

@@ -42,7 +42,7 @@ type EventEnter struct {
 func (e *EventEnter) TableName() string {
 	return "event_enter"
 }
-func NewEventEnter(cowId, operationId int64, req *pasturePb.SearchEnterData) *EventEnter {
+func NewEventEnter(cowId, operationId int64, req *pasturePb.EventEnterData) *EventEnter {
 	return &EventEnter{
 		EarNumber:        req.EarNumber,
 		CowId:            cowId,
@@ -73,10 +73,10 @@ func NewEventEnter(cowId, operationId int64, req *pasturePb.SearchEnterData) *Ev
 
 type EventEnterSlice []*EventEnter
 
-func (e EventEnterSlice) ToPB() []*pasturePb.SearchEnterData {
-	res := make([]*pasturePb.SearchEnterData, len(e))
+func (e EventEnterSlice) ToPB() []*pasturePb.EventEnterData {
+	res := make([]*pasturePb.EventEnterData, len(e))
 	for i, d := range e {
-		res[i] = &pasturePb.SearchEnterData{
+		res[i] = &pasturePb.EventEnterData{
 			Id:               int32(d.Id),
 			EarNumber:        d.EarNumber,
 			CowId:            int32(d.CowId),

+ 1 - 1
model/event_estrus.go

@@ -20,7 +20,7 @@ func (e *EventEstrus) TableName() string {
 	return "event_estrus"
 }
 
-func NewEventEstrus(cow *Cow, currentUser *SystemUser, req *pasturePb.EstrusEventRequest) *EventEstrus {
+func NewEventEstrus(cow *Cow, currentUser *SystemUser, req *pasturePb.EventEstrus) *EventEstrus {
 	return &EventEstrus{
 		CowId:         cow.Id,
 		DayAge:        cow.GetDayAge(),

+ 1 - 1
model/event_mating.go

@@ -23,7 +23,7 @@ func (e *EventMating) TableName() string {
 	return "event_mating"
 }
 
-func NewEventMating(cow *Cow, currentUser *SystemUser, req *pasturePb.MatingEventRequest) *EventMating {
+func NewEventMating(cow *Cow, currentUser *SystemUser, req *pasturePb.EventMating) *EventMating {
 	return &EventMating{
 		CowId:             cow.Id,
 		DayAge:            int64(cow.GetDayAge()),

+ 1 - 1
model/event_pregnant_check.go

@@ -21,7 +21,7 @@ func (e *EventPregnantCheck) TableName() string {
 	return "event_pregnant_check"
 }
 
-func NewEventPregnantCheck(cow *Cow, systemUser *SystemUser, req *pasturePb.PregnantCheckEventRequest) *EventPregnantCheck {
+func NewEventPregnantCheck(cow *Cow, systemUser *SystemUser, req *pasturePb.EventPregnantCheck) *EventPregnantCheck {
 	return &EventPregnantCheck{
 		CowId:               cow.Id,
 		DayAge:              cow.GetDayAge(),

+ 46 - 0
model/event_same_time.go

@@ -0,0 +1,46 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type EventSameTime struct {
+	Id               int64                       `json:"id"`
+	CowId            int64                       `json:"cowId"`
+	Lact             int32                       `json:"lact"`
+	DayAge           int32                       `json:"dayAge"`
+	CalvingAge       int64                       `json:"calvingAge"`
+	SameTimeId       int64                       `json:"sameTimeId"`
+	SameTimeType     pasturePb.SameTimeType_Kind `json:"sameTimeType"`
+	SameTimeTypeName string                      `json:"sameTimeTypeName"`
+	DrugsId          int64                       `json:"drugsId"`
+	DrugsName        string                      `json:"drugsName"`
+	Unit             pasturePb.Unit_Kind         `json:"unit"`
+	Usage            int32                       `json:"usage"`
+	Remarks          string                      `json:"remarks"`
+	StallNumberId    int64                       `json:"stallNumberId"`
+	OperationId      int64                       `json:"operation_id"`
+	CreatedAt        int64                       `json:"created_at"`
+	UpdatedAt        int64                       `json:"updated_at"`
+}
+
+func (e *EventSameTime) TableName() string {
+	return "event_same_time"
+}
+
+func NewEventSameTime(cow *Cow, req *pasturePb.EventSameTime, drugs *Drugs) *EventSameTime {
+	eventSameTime := &EventSameTime{
+		CowId:            cow.Id,
+		CalvingAge:       cow.CalvingAge,
+		SameTimeId:       int64(req.SameTimeId),
+		SameTimeType:     req.SameTimeType,
+		SameTimeTypeName: req.SameTimeTypeName,
+		Remarks:          req.Remarks,
+	}
+
+	if drugs != nil && drugs.Id > 0 {
+		eventSameTime.DrugsId = drugs.Id
+		eventSameTime.DrugsName = drugs.Name
+		eventSameTime.Unit = drugs.Unit
+		eventSameTime.Usage = req.Usage
+	}
+	return eventSameTime
+}

+ 14 - 1
model/same_time_cow.go

@@ -1,6 +1,10 @@
 package model
 
-import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+import (
+	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+)
 
 type SameTimeCow struct {
 	Id         int64                 `json:"id"`
@@ -12,3 +16,12 @@ type SameTimeCow struct {
 	CreatedAt  int64                 `json:"createdAt"`
 	UpdatedAt  int64                 `json:"updatedAt"`
 }
+
+func NewSameTimeCow(cowId, sameTimeId int64) *SameTimeCow {
+	return &SameTimeCow{
+		CowId:      cowId,
+		SameTimeId: sameTimeId,
+		Status:     pasturePb.IsShow_Ok,
+		StartAt:    time.Now().Unix(),
+	}
+}

+ 36 - 42
module/backend/enum_options.go

@@ -2,6 +2,7 @@ package backend
 
 import (
 	"context"
+	"fmt"
 	"kpt-pasture/model"
 	"net/http"
 
@@ -132,48 +133,41 @@ func (s *StoreEntry) BullOptions(ctx context.Context) (*pasturePb.BullOptionsLis
 }
 
 func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName string) (*pasturePb.ConfigOptionsListResponse, error) {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	switch optionsName {
-	case "childNumber":
-		configOptions = s.ChildNumberEnumList()
-	case "calvingLevel":
-		configOptions = s.CalvingLevelEnumList()
-	case "dystociaReason":
-		configOptions = s.DystociaReasonEnumList()
-	case "drugCategory":
-		configOptions = s.DrugCategoryEnumList()
-	case "drugUsage":
-		configOptions = s.DrugUsageEnumList()
-	case "unit":
-		configOptions = s.UnitEnumList()
-	case "pregnantCheckResult":
-		configOptions = s.PregnantCheckResultEnumList()
-	case "pregnantCheckMethod":
-		configOptions = s.PregnantCheckMethodEnumList()
-	case "exposeEstrusType":
-		configOptions = s.ExposeEstrusTypeEnumList()
-	case "frozenSemenType":
-		configOptions = s.FrozenSemenTypeEnumList()
-	case "week":
-		configOptions = s.WeekEnumList()
-	case "month":
-		configOptions = s.MonthEnumList()
-	case "sameTimeCowType":
-		configOptions = s.SemeTimeCowTypeEnumList()
-	case "sameTimeType":
-		configOptions = s.SameTimeTypeEnumList()
-	case "immunizationCowType":
-		configOptions = s.ImmunizationCowTypeEnumList()
-	case "workOrderFrequency":
-		configOptions = s.WorkOrderFrequencyEnumList()
-	case "workOrderSubUnit":
-		configOptions = s.WorkOrderSubUnitEnumList()
-	case "workOrderPriority":
-		configOptions = s.WorkOrderPriorityEnumList()
-	case "workOrderCategory":
-		configOptions = s.WorkOrderCategoryEnumList()
-	case "immunizationConditions":
-		configOptions = s.ImmunizationConditionsEnumList()
+	if optionsName == "" {
+		return nil, xerr.New("optionsName is empty")
+	}
+
+	getConfigFuncMap := map[string]func() []*pasturePb.ConfigOptionsList{
+		"childNumber":            s.ChildNumberEnumList,
+		"calvingLevel":           s.CalvingLevelEnumList,
+		"dystociaReason":         s.DystociaReasonEnumList,
+		"drugCategory":           s.DrugCategoryEnumList,
+		"drugUsage":              s.DrugUsageEnumList,
+		"unit":                   s.UnitEnumList,
+		"pregnantCheckResult":    s.PregnantCheckResultEnumList,
+		"pregnantCheckMethod":    s.PregnantCheckMethodEnumList,
+		"exposeEstrusType":       s.ExposeEstrusTypeEnumList,
+		"frozenSemenType":        s.FrozenSemenTypeEnumList,
+		"week":                   s.WeekEnumList,
+		"month":                  s.MonthEnumList,
+		"sameTimeCowType":        s.SemeTimeCowTypeEnumList,
+		"sameTimeType":           s.SameTimeTypeEnumList,
+		"immunizationCowType":    s.ImmunizationCowTypeEnumList,
+		"workOrderFrequency":     s.WorkOrderFrequencyEnumList,
+		"workOrderSubUnit":       s.WorkOrderSubUnitEnumList,
+		"workOrderPriority":      s.WorkOrderPriorityEnumList,
+		"workOrderCategory":      s.WorkOrderCategoryEnumList,
+		"immunizationConditions": s.ImmunizationConditionsEnumList,
+	}
+
+	getConfigFunc, ok := getConfigFuncMap[optionsName]
+	if !ok {
+		return nil, fmt.Errorf("invalid optionsName: %s", optionsName)
+	}
+
+	configOptions := getConfigFunc()
+	if configOptions == nil {
+		return nil, fmt.Errorf("failed to retrieve configOptions for %s", optionsName)
 	}
 
 	return &pasturePb.ConfigOptionsListResponse{

+ 0 - 613
module/backend/event.go

@@ -1,613 +0,0 @@
-package backend
-
-import (
-	"context"
-	"fmt"
-	"kpt-pasture/model"
-	"net/http"
-	"strconv"
-	"strings"
-
-	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
-	"gitee.com/xuyiping_admin/pkg/xerr"
-	"gorm.io/gorm"
-)
-
-func (s *StoreEntry) EventTemplate(ctx context.Context, req *pasturePb.SearchEventRequest) {
-
-}
-
-func (s *StoreEntry) CreateEventTemplate(ctx context.Context, req *pasturePb.SearchEventRequest) *pasturePb.EventData {
-	return nil
-}
-
-func (s *StoreEntry) EnterList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchEnterEventResponse, error) {
-	eventEnterList := make([]*pasturePb.SearchEnterData, 0)
-	var count int64 = 0
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventEnter).TableName())).
-		Select(`a.id,a.birth_at,a.weaning_at,a.dry_milk_at,a.cow_source_id,a.remarks,a.mating_at,a.lact,
-		a.breed_status,a.mother_id,a.cow_kind,a.cow_id,a.ear_number,a.sex,a.created_at,a.updated_at,a.enter_at,
-		a.weight / 100 as weight,a.price / 100 as price,b.name as breed_status_name,c.name as cow_source_name,d.name as cow_type_name,
-		e.name as cow_kind_name,f.name as pen_name,g.name as operation_name,h.name as staff_member_name`).
-		Joins(fmt.Sprintf("JOIN %s AS b ON a.breed_status = b.id", new(model.ConfigBreedStatus).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS c on a.cow_source_id = c.id", new(model.ConfigCowSource).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS d on a.cow_type = d.id", new(model.ConfigCowType).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS e ON a.cow_kind = e.id", new(model.ConfigCowKind).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS f on a.pen_id = f.id", new(model.Pen).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS g on a.operation_id = g.id", new(model.SystemUser).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS h on a.staff_member_id = h.id", new(model.SystemUser).TableName()))
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("a.cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("a.id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&eventEnterList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.SearchEnterEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchEnterEventData{
-			List:     eventEnterList,
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) CreateEnter(ctx context.Context, req *pasturePb.SearchEnterData) error {
-	if err := s.DB.Transaction(func(tx *gorm.DB) error {
-		newCowData := model.NewCow(req)
-		if err := tx.Create(newCowData).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		operationUser, _ := s.GetCurrentSystemUser(ctx)
-		if err := tx.Create(model.NewEventEnter(newCowData.Id, operationUser.Id, req)).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		return nil
-	}); err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func (s *StoreEntry) GroupTransferList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchTransferGroupEventResponse, error) {
-	eventGroupTransferList := make([]*pasturePb.SearchTransferGroupData, 0)
-	var count int64 = 0
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventTransferGroup).TableName())).
-		Select(`a.id,a.cow_id,a.transfer_in_pen_id,a.transfer_out_pen_id,a.lact,a.remarks,a.transfer_reason_id,
-			a.transfer_date,a.created_at,a.staff_member_id,b.name as transfer_in_pen_name,c.name as transfer_out_pen_name,
-			d.name as transfer_reason_name,e.name as staff_member_name,f.lact,f.ear_number`).
-		Joins(fmt.Sprintf("JOIN %s AS b ON a.transfer_in_pen_id = b.id", new(model.Pen).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS c on a.transfer_out_pen_id = c.id", new(model.Pen).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS d on a.transfer_reason_id = d.id", new(model.ConfigTransferPenReason).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS e ON a.staff_member_id = e.id", new(model.SystemUser).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS f ON a.cow_id = f.id", new(model.Cow).TableName()))
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("a.cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("a.id desc").Group("a.id").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&eventGroupTransferList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.SearchTransferGroupEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchTransferGroupEventData{
-			List:     eventGroupTransferList,
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) CreateGroupTransfer(ctx context.Context, req *pasturePb.TransferGroupEventRequest) error {
-	system, _ := s.GetCurrentSystemUser(ctx)
-	res := make([]*model.EventTransferGroup, 0)
-	for _, v := range req.Body {
-		cow, err := s.GetCowInfo(ctx, int64(v.CowId))
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		// 转去栏舍和当前栏舍相同,则不处理
-		if cow.PenId == int64(v.TransferInPenId) {
-			continue
-		}
-		pen, err := s.GetPenInfo(ctx, int64(v.TransferInPenId))
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-
-		transferReasonData, err := s.GetTransferReasonInfo(ctx, int64(v.TransferReasonId))
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-
-		staffMemberData, err := s.GetSystemUserInfo(ctx, int64(v.StaffMemberId))
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-
-		res = append(res, &model.EventTransferGroup{
-			CowId:            int64(v.CowId),
-			TransferInPenId:  int64(v.TransferInPenId),
-			TransferOutPenId: pen.Id,
-			Lact:             cow.Lact,
-			DayAge:           cow.GetDayAge(),
-			TransferDate:     v.TransferDate,
-			TransferReasonId: transferReasonData.Id,
-			Remarks:          v.Remarks,
-			StaffMemberId:    staffMemberData.Id,
-			OperationId:      system.Id,
-		})
-	}
-	if len(res) <= 0 {
-		return nil
-	}
-
-	if err := s.DB.Transaction(func(tx *gorm.DB) error {
-		if err := tx.Create(res).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		for _, v := range res {
-			cow, err := s.GetCowInfo(ctx, v.CowId)
-			if err != nil {
-				return xerr.WithStack(err)
-			}
-			if err = s.DB.Model(cow).Update("pen_id", v.TransferInPenId).Error; err != nil {
-				return xerr.WithStack(err)
-			}
-		}
-		return nil
-	}); err != nil {
-		return xerr.WithStack(err)
-	}
-
-	return nil
-}
-
-func (s *StoreEntry) BodyScoreList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBodyScoreEventResponse, error) {
-	bodyScoreList := make([]*pasturePb.SearchBodyScoreList, 0)
-	var count int64 = 0
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventBodyScore).TableName())).
-		Select(`a.id,a.cow_id,a.ear_number,a.score as body_score,a.lact,a.day_age,a.score_at,a.remarks,a.created_at,
-		a.updated_at,a.staff_member_id,a.operation_id,b.name as staff_member_name,c.name as operation_name`).
-		Joins(fmt.Sprintf("JOIN %s AS b on a.staff_member_id = b.id", new(model.SystemUser).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName()))
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("a.cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("a.id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&bodyScoreList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.SearchBodyScoreEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchBodyScoreData{
-			List:     bodyScoreList,
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) CreateBodyScore(ctx context.Context, req *pasturePb.BodyScoreEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-	currentSystemUser, _ := s.GetCurrentSystemUser(ctx)
-
-	cowList := strings.Split(req.CowId, ",")
-	bodyScourEvent := make([]*model.EventBodyScore, 0)
-	for _, cowIdStr := range cowList {
-		cowId, _ := strconv.ParseInt(cowIdStr, 10, 64)
-		cow, err := s.GetCowInfo(ctx, cowId)
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		bodyScourEvent = append(bodyScourEvent, model.NewEventBodyScore(cow, currentSystemUser.Id, req))
-	}
-	if len(bodyScourEvent) <= 0 {
-		return nil
-	}
-
-	return s.DB.Create(bodyScourEvent).Error
-}
-
-func (s *StoreEntry) CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error) {
-	lavingList := make([]*model.EventCalvingList, 0)
-	var count int64 = 0
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())).
-		Select(`a.*,b.name as pen_name,c.name as staff_member_name`).
-		Joins(fmt.Sprintf("JOIN %s AS b on a.pen_id = b.id", new(model.Pen).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS c on a.staff_member_id = c.id", new(model.SystemUser).TableName()))
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("a.cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("a.id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&lavingList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	calvingIds := make([]int64, 0)
-	for _, v := range lavingList {
-		calvingIds = append(calvingIds, v.Id)
-	}
-	calvingCalfList := make([]*model.CalvingCalf, 0)
-	if err := s.DB.Model(new(model.CalvingCalf)).Where("calving_id IN ?", calvingIds).Find(&calvingCalfList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.SearchLavingEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchLavingData{
-			List:     model.EventCalvingListSlice(lavingList).ToPB(calvingCalfList),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.CalvingEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-
-	cowList := strings.Split(req.CowId, ",")
-	cowId, _ := strconv.ParseInt(cowList[0], 10, 64)
-	cow, err := s.GetCowInfo(ctx, cowId)
-	if err != nil {
-		return xerr.WithStack(err)
-	}
-	if err = s.DB.Transaction(func(tx *gorm.DB) error {
-		// 母牛信息
-		newCalving := model.NewEventCalving(cow, req)
-		if err = tx.Create(newCalving).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		// 犊牛信息
-		newCalvingCalfList := model.NewEventCalvingCalf(cow.Id, newCalving.Id, req)
-		for _, v := range newCalvingCalfList {
-			if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No {
-				continue
-			}
-			// 留养犊牛
-			newCow := model.NewCalfCow(cow.Id, cow.LastBullId, v)
-			if err = tx.Create(newCow).Error; err != nil {
-				return xerr.WithStack(err)
-			}
-			v.CowId = newCow.Id
-		}
-		if err = tx.Create(newCalvingCalfList).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		return nil
-	}); err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func (s *StoreEntry) PregnantCheckList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnantCheckEventResponse, error) {
-	pregnantCheckList := make([]*model.EventPregnantCheck, 0)
-	var count int64 = 0
-	pref := s.DB.Table(new(model.EventPregnantCheck).TableName())
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&pregnantCheckList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	systemUserList, _ := s.SystemUserList(ctx)
-	pregnantCheckResult := s.PregnantCheckResultEnumList()
-	pregnantCheckMethod := s.PregnantCheckMethodEnumList()
-
-	return &pasturePb.PregnantCheckEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchPregnantCheckData{
-			List:     model.EventPregnantCheckSlice(pregnantCheckList).ToPB(systemUserList, pregnantCheckResult, pregnantCheckMethod),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) PregnantCheckCreate(ctx context.Context, req *pasturePb.PregnantCheckEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-	cowList := strings.Split(req.CowId, ",")
-	eventPregnantCheckList := make([]*model.EventPregnantCheck, 0)
-	currentUser, _ := s.GetCurrentSystemUser(ctx)
-
-	for _, v := range cowList {
-		cowId, _ := strconv.ParseInt(v, 10, 64)
-		cow, err := s.GetCowInfo(ctx, cowId)
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		eventPregnantCheckList = append(eventPregnantCheckList, model.NewEventPregnantCheck(cow, currentUser, req))
-	}
-
-	if err := s.DB.Create(eventPregnantCheckList).Error; err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) {
-	matingList := make([]*model.EventMating, 0)
-	var count int64 = 0
-	pref := s.DB.Table(new(model.EventMating).TableName())
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&matingList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	systemUserList, _ := s.SystemUserList(ctx)
-	exposeEstrusTypeMap := s.ExposeEstrusTypeMap()
-	return &pasturePb.MatingEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchMatingData{
-			List:     model.EventMatingSlice(matingList).ToPB(systemUserList, exposeEstrusTypeMap),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.MatingEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-	cowList := strings.Split(req.CowId, ",")
-	matingList := make([]*model.EventMating, 0)
-	eventFrozenSemenLogList := make([]*model.EventFrozenSemenLog, 0)
-	currentUser, _ := s.GetCurrentSystemUser(ctx)
-
-	for _, v := range cowList {
-		cowId, _ := strconv.ParseInt(v, 10, 64)
-		cow, err := s.GetCowInfo(ctx, cowId)
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		matingList = append(matingList, model.NewEventMating(cow, currentUser, req))
-		eventFrozenSemenLogList = append(eventFrozenSemenLogList, model.NewEventFrozenSemenLog(req.BullId, cow, int64(req.StaffMemberId)))
-	}
-
-	frozenSemen := &model.EventFrozenSemen{}
-	if err := s.DB.Where("bull_id = ?", req.BullId).First(frozenSemen).Error; err != nil {
-		return xerr.WithStack(err)
-	}
-
-	if err := s.DB.Transaction(func(tx *gorm.DB) error {
-		if err := tx.Create(matingList).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		// 创建冻精使用记录日志
-		if err := tx.Create(eventFrozenSemenLogList).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		if err := tx.Table(new(model.EventFrozenSemen).TableName()).
-			Where("bull_id = ?", req.BullId).
-			Where("quantity > 0").UpdateColumn("quantity", gorm.Expr("quantity - ?", len(matingList))).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		return nil
-	}); err != nil {
-		return xerr.WithStack(err)
-	}
-
-	return nil
-}
-
-func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusEventResponse, error) {
-	estrusList := make([]*model.EventEstrus, 0)
-	var count int64 = 0
-	pref := s.DB.Table(new(model.EventEstrus).TableName())
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&estrusList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	systemUserList, _ := s.SystemUserList(ctx)
-	return &pasturePb.EstrusEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchEstrusData{
-			List:     model.EstrusSlice(estrusList).ToPB(systemUserList),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) EstrusCreate(ctx context.Context, req *pasturePb.EstrusEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-	cowList := strings.Split(req.CowId, ",")
-	estrusList := make([]*model.EventEstrus, 0)
-	currentUser, _ := s.GetCurrentSystemUser(ctx)
-
-	for _, v := range cowList {
-		cowId, _ := strconv.ParseInt(v, 10, 64)
-		cow, err := s.GetCowInfo(ctx, cowId)
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		estrusList = append(estrusList, model.NewEventEstrus(cow, currentUser, req))
-	}
-
-	if err := s.DB.Create(estrusList).Error; err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func (s *StoreEntry) FrozenSemenList(ctx context.Context, req *pasturePb.FrozenSemenRequest, pagination *pasturePb.PaginationModel) (*pasturePb.FrozenSemenResponse, error) {
-	frozenSemenList := make([]*model.EventFrozenSemen, 0)
-	var count int64 = 0
-	pref := s.DB.Table(new(model.EventFrozenSemen).TableName())
-	if req.BullId != "" {
-		pref.Where("bull_id = ?", req.BullId)
-	}
-
-	if req.Producer != "" {
-		pref.Where("producer = ?", req.Producer)
-	}
-
-	if err := pref.Order("id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&frozenSemenList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	frozenSemenTypeMap := s.FrozenSemenTypeMap()
-	unitMap := s.UnitMap()
-
-	return &pasturePb.FrozenSemenResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchFrozenSemenData{
-			List:     model.EventFrozenSemenSlice(frozenSemenList).ToPB(frozenSemenTypeMap, unitMap),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) FrozenSemenCreate(ctx context.Context, req *pasturePb.SearchFrozenSemenList) error {
-	currentUser, _ := s.GetCurrentSystemUser(ctx)
-	req.CowKindName = s.CowKindMap()[req.CowKind]
-	newFrozenSemen := model.NewEventFrozenSemen(req, currentUser)
-	if err := s.DB.Create(newFrozenSemen).Error; err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func (s *StoreEntry) WeightList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWeightEventResponse, error) {
-	weightList := make([]*pasturePb.SearchWeightList, 0)
-	var count int64 = 0
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventWeight).TableName())).
-		Select(`a.id,a.cow_id,a.ear_number,a.weight / 100 as weight,a.lact,a.day_age,a.weight_at,a.remarks,a.created_at,
-		a.updated_at,a.staff_member_id,a.operation_id,b.name as staff_member_name,c.name as operation_name`).
-		Joins(fmt.Sprintf("JOIN %s AS b on a.staff_member_id = b.id", new(model.SystemUser).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName()))
-	if len(req.CowId) > 0 {
-		cowIds := strings.Split(req.CowId, ",")
-		pref.Where("a.cow_id IN ?", cowIds)
-	}
-
-	if err := pref.Order("a.id desc").
-		Count(&count).Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&weightList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.SearchWeightEventResponse{
-		Code:    http.StatusOK,
-		Message: "ok",
-		Data: &pasturePb.SearchWeightData{
-			List:     weightList,
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
-func (s *StoreEntry) CreateWeight(ctx context.Context, req *pasturePb.WeightEventRequest) error {
-	if len(req.CowId) <= 0 {
-		return xerr.Custom("请选择相关牛只")
-	}
-	currentSystemUser, _ := s.GetCurrentSystemUser(ctx)
-	weightEvent := make([]*model.EventWeight, 0)
-	for _, item := range req.WeightItems {
-		cow, err := s.GetCowInfo(ctx, int64(item.CowId))
-		if err != nil {
-			return xerr.WithStack(err)
-		}
-		var weight = int32(item.Weight * 100)
-		weightEvent = append(weightEvent, model.NewEventWeight(cow, currentSystemUser, weight, req))
-	}
-	if len(weightEvent) <= 0 {
-		return nil
-	}
-
-	if err := s.DB.Transaction(func(tx *gorm.DB) error {
-		for _, item := range weightEvent {
-			if err := tx.Model(new(model.Cow)).Where("id = ?", item.CowId).Updates(map[string]interface{}{
-				"last_weight_at": item.WeightAt,
-				"current_weight": item.Weight,
-			}).Error; err != nil {
-				return xerr.WithStack(err)
-			}
-		}
-		if err := tx.Create(weightEvent).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-		return nil
-	}); err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}

+ 320 - 0
module/backend/event_base.go

@@ -0,0 +1,320 @@
+package backend
+
+import (
+	"context"
+	"fmt"
+	"kpt-pasture/model"
+	"net/http"
+	"strconv"
+	"strings"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+	"gorm.io/gorm"
+)
+
+func (s *StoreEntry) EventTemplate(ctx context.Context, req *pasturePb.SearchEventRequest) {
+
+}
+
+func (s *StoreEntry) CreateEventTemplate(ctx context.Context, req *pasturePb.SearchEventRequest) *pasturePb.EventData {
+	return nil
+}
+
+func (s *StoreEntry) ParseCowIds(ctx context.Context, cowId string) ([]*model.Cow, error) {
+	if len(cowId) == 0 {
+		return nil, xerr.Custom("cow id is required")
+	}
+
+	var cowIds = make([]*model.Cow, 0)
+	for _, v := range strings.Split(cowId, ",") {
+		cowId, err := strconv.ParseInt(v, 10, 64)
+		cow, err := s.GetCowInfoByCowId(ctx, cowId)
+		if err != nil {
+			return nil, xerr.WithStack(err)
+		}
+		cowIds = append(cowIds, cow)
+	}
+	return cowIds, nil
+}
+
+func (s *StoreEntry) EnterList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchEnterEventResponse, error) {
+	eventEnterList := make([]*pasturePb.EventEnterData, 0)
+	var count int64 = 0
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventEnter).TableName())).
+		Select(`a.id,a.birth_at,a.weaning_at,a.dry_milk_at,a.cow_source_id,a.remarks,a.mating_at,a.lact,
+		a.breed_status,a.mother_id,a.cow_kind,a.cow_id,a.ear_number,a.sex,a.created_at,a.updated_at,a.enter_at,
+		a.weight / 100 as weight,a.price / 100 as price,b.name as breed_status_name,c.name as cow_source_name,d.name as cow_type_name,
+		e.name as cow_kind_name,f.name as pen_name,g.name as operation_name,h.name as staff_member_name`).
+		Joins(fmt.Sprintf("JOIN %s AS b ON a.breed_status = b.id", new(model.ConfigBreedStatus).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS c on a.cow_source_id = c.id", new(model.ConfigCowSource).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS d on a.cow_type = d.id", new(model.ConfigCowType).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS e ON a.cow_kind = e.id", new(model.ConfigCowKind).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS f on a.pen_id = f.id", new(model.Pen).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS g on a.operation_id = g.id", new(model.SystemUser).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS h on a.staff_member_id = h.id", new(model.SystemUser).TableName()))
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("a.cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("a.id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&eventEnterList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.SearchEnterEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchEnterEventData{
+			List:     eventEnterList,
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) CreateEnter(ctx context.Context, req *pasturePb.EventEnterData) error {
+	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+		newCowData := model.NewCow(req)
+		if err := tx.Create(newCowData).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		operationUser, _ := s.GetCurrentSystemUser(ctx)
+		if err := tx.Create(model.NewEventEnter(newCowData.Id, operationUser.Id, req)).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) GroupTransferList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchTransferGroupEventResponse, error) {
+	eventGroupTransferList := make([]*pasturePb.EventTransferGroupData, 0)
+	var count int64 = 0
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventTransferGroup).TableName())).
+		Select(`a.id,a.cow_id,a.transfer_in_pen_id,a.transfer_out_pen_id,a.lact,a.remarks,a.transfer_reason_id,
+			a.transfer_date,a.created_at,a.staff_member_id,b.name as transfer_in_pen_name,c.name as transfer_out_pen_name,
+			d.name as transfer_reason_name,e.name as staff_member_name,f.lact,f.ear_number`).
+		Joins(fmt.Sprintf("JOIN %s AS b ON a.transfer_in_pen_id = b.id", new(model.Pen).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS c on a.transfer_out_pen_id = c.id", new(model.Pen).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS d on a.transfer_reason_id = d.id", new(model.ConfigTransferPenReason).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS e ON a.staff_member_id = e.id", new(model.SystemUser).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS f ON a.cow_id = f.id", new(model.Cow).TableName()))
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("a.cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("a.id desc").Group("a.id").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&eventGroupTransferList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.SearchTransferGroupEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchTransferGroupEventData{
+			List:     eventGroupTransferList,
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) CreateGroupTransfer(ctx context.Context, req *pasturePb.TransferGroupEventRequest) error {
+	system, _ := s.GetCurrentSystemUser(ctx)
+	res := make([]*model.EventTransferGroup, 0)
+	for _, v := range req.Body {
+		cow, err := s.GetCowInfoByCowId(ctx, int64(v.CowId))
+		if err != nil {
+			return xerr.WithStack(err)
+		}
+		// 转去栏舍和当前栏舍相同,则不处理
+		if cow.PenId == int64(v.TransferInPenId) {
+			continue
+		}
+		pen, err := s.GetPenById(ctx, int64(v.TransferInPenId))
+		if err != nil {
+			return xerr.WithStack(err)
+		}
+
+		transferReasonData, err := s.GetTransferReasonInfo(ctx, int64(v.TransferReasonId))
+		if err != nil {
+			return xerr.WithStack(err)
+		}
+
+		staffMemberData, err := s.GetSystemUserById(ctx, int64(v.StaffMemberId))
+		if err != nil {
+			return xerr.WithStack(err)
+		}
+
+		res = append(res, &model.EventTransferGroup{
+			CowId:            int64(v.CowId),
+			TransferInPenId:  int64(v.TransferInPenId),
+			TransferOutPenId: pen.Id,
+			Lact:             cow.Lact,
+			DayAge:           cow.GetDayAge(),
+			TransferDate:     v.TransferDate,
+			TransferReasonId: transferReasonData.Id,
+			Remarks:          v.Remarks,
+			StaffMemberId:    staffMemberData.Id,
+			OperationId:      system.Id,
+		})
+	}
+	if len(res) <= 0 {
+		return nil
+	}
+
+	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+		if err := tx.Create(res).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		for _, v := range res {
+			cow, err := s.GetCowInfoByCowId(ctx, v.CowId)
+			if err != nil {
+				return xerr.WithStack(err)
+			}
+			if err = s.DB.Model(cow).Update("pen_id", v.TransferInPenId).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+
+	return nil
+}
+
+func (s *StoreEntry) BodyScoreList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBodyScoreEventResponse, error) {
+	bodyScoreList := make([]*pasturePb.BodyScoreList, 0)
+	var count int64 = 0
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventBodyScore).TableName())).
+		Select(`a.id,a.cow_id,a.ear_number,a.score as body_score,a.lact,a.day_age,a.score_at,a.remarks,a.created_at,
+		a.updated_at,a.staff_member_id,a.operation_id,b.name as staff_member_name,c.name as operation_name`).
+		Joins(fmt.Sprintf("JOIN %s AS b on a.staff_member_id = b.id", new(model.SystemUser).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName()))
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("a.cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("a.id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&bodyScoreList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.SearchBodyScoreEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchBodyScoreData{
+			List:     bodyScoreList,
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) CreateBodyScore(ctx context.Context, req *pasturePb.BodyScoreEventRequest) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+	currentSystemUser, _ := s.GetCurrentSystemUser(ctx)
+
+	//cowList := strings.Split(req.CowId, ",")
+	bodyScourEvent := make([]*model.EventBodyScore, 0)
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	for _, cow := range cowList {
+		bodyScourEvent = append(bodyScourEvent, model.NewEventBodyScore(cow, currentSystemUser.Id, req))
+	}
+	if len(bodyScourEvent) <= 0 {
+		return nil
+	}
+
+	return s.DB.Create(bodyScourEvent).Error
+}
+
+func (s *StoreEntry) WeightList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWeightEventResponse, error) {
+	weightList := make([]*pasturePb.SearchWeightList, 0)
+	var count int64 = 0
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventWeight).TableName())).
+		Select(`a.id,a.cow_id,a.ear_number,a.weight / 100 as weight,a.lact,a.day_age,a.weight_at,a.remarks,a.created_at,
+		a.updated_at,a.staff_member_id,a.operation_id,b.name as staff_member_name,c.name as operation_name`).
+		Joins(fmt.Sprintf("JOIN %s AS b on a.staff_member_id = b.id", new(model.SystemUser).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS c on a.operation_id = c.id", new(model.SystemUser).TableName()))
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("a.cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("a.id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&weightList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.SearchWeightEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchWeightData{
+			List:     weightList,
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) WeightCreate(ctx context.Context, req *pasturePb.EventWeight) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+	currentSystemUser, _ := s.GetCurrentSystemUser(ctx)
+	weightEvent := make([]*model.EventWeight, 0)
+	for _, item := range req.WeightItems {
+		cow, err := s.GetCowInfoByCowId(ctx, int64(item.CowId))
+		if err != nil {
+			return xerr.WithStack(err)
+		}
+		var weight = int32(item.Weight * 100)
+		weightEvent = append(weightEvent, model.NewEventWeight(cow, currentSystemUser, weight, req))
+	}
+	if len(weightEvent) <= 0 {
+		return nil
+	}
+
+	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+		for _, item := range weightEvent {
+			if err := tx.Model(new(model.Cow)).Where("id = ?", item.CowId).Updates(map[string]interface{}{
+				"last_weight_at": item.WeightAt,
+				"current_weight": item.Weight,
+			}).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+		if err := tx.Create(weightEvent).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}

+ 392 - 0
module/backend/event_breed.go

@@ -0,0 +1,392 @@
+package backend
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"kpt-pasture/model"
+	"net/http"
+	"strings"
+	"time"
+
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"go.uber.org/zap"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+	"gorm.io/gorm"
+)
+
+func (s *StoreEntry) CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error) {
+	lavingList := make([]*model.EventCalvingList, 0)
+	var count int64 = 0
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventCalving).TableName())).
+		Select(`a.*,b.name as pen_name,c.name as staff_member_name`).
+		Joins(fmt.Sprintf("JOIN %s AS b on a.pen_id = b.id", new(model.Pen).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS c on a.staff_member_id = c.id", new(model.SystemUser).TableName()))
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("a.cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("a.id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&lavingList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	calvingIds := make([]int64, 0)
+	for _, v := range lavingList {
+		calvingIds = append(calvingIds, v.Id)
+	}
+	calvingCalfList := make([]*model.CalvingCalf, 0)
+	if err := s.DB.Model(new(model.CalvingCalf)).Where("calving_id IN ?", calvingIds).Find(&calvingCalfList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.SearchLavingEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchLavingData{
+			List:     model.EventCalvingListSlice(lavingList).ToPB(calvingCalfList),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) CalvingCreate(ctx context.Context, req *pasturePb.EventCalving) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	if len(cowList) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+
+	cow := cowList[0]
+
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		// 母牛信息
+		newCalving := model.NewEventCalving(cow, req)
+		if err = tx.Create(newCalving).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		// 犊牛信息
+		newCalvingCalfList := model.NewEventCalvingCalf(cow.Id, newCalving.Id, req)
+		for _, v := range newCalvingCalfList {
+			if v.IsLive == pasturePb.IsShow_No || v.IsAdoption == pasturePb.IsShow_No {
+				continue
+			}
+			// 留养犊牛
+			newCow := model.NewCalfCow(cow.Id, cow.LastBullId, v)
+			if err = tx.Create(newCow).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+			v.CowId = newCow.Id
+		}
+		if err = tx.Create(newCalvingCalfList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		if err = tx.Model(new(model.Cow)).Where("id = ?", cow).Updates(map[string]interface{}{
+			"calving_age":     0,
+			"lact":            cow.Lact + 1,
+			"breed_status":    pasturePb.BreedStatus_Calving,
+			"is_pregnant":     pasturePb.IsShow_No,
+			"calving_at":      time.Now().Unix(),
+			"last_calving_at": time.Now().Unix(),
+		}).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) PregnantCheckList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnantCheckEventResponse, error) {
+	pregnantCheckList := make([]*model.EventPregnantCheck, 0)
+	var count int64 = 0
+	pref := s.DB.Table(new(model.EventPregnantCheck).TableName())
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&pregnantCheckList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	systemUserList, _ := s.SystemUserList(ctx)
+	pregnantCheckResult := s.PregnantCheckResultEnumList()
+	pregnantCheckMethod := s.PregnantCheckMethodEnumList()
+
+	return &pasturePb.PregnantCheckEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchPregnantCheckData{
+			List:     model.EventPregnantCheckSlice(pregnantCheckList).ToPB(systemUserList, pregnantCheckResult, pregnantCheckMethod),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) PregnantCheckCreate(ctx context.Context, req *pasturePb.EventPregnantCheck) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	eventPregnantCheckList := make([]*model.EventPregnantCheck, 0)
+	currentUser, _ := s.GetCurrentSystemUser(ctx)
+
+	for _, cow := range cowList {
+		eventPregnantCheckList = append(eventPregnantCheckList, model.NewEventPregnantCheck(cow, currentUser, req))
+	}
+
+	if err := s.DB.Create(eventPregnantCheckList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error) {
+	matingList := make([]*model.EventMating, 0)
+	var count int64 = 0
+	pref := s.DB.Table(new(model.EventMating).TableName())
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&matingList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	systemUserList, _ := s.SystemUserList(ctx)
+	exposeEstrusTypeMap := s.ExposeEstrusTypeMap()
+	return &pasturePb.MatingEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchMatingData{
+			List:     model.EventMatingSlice(matingList).ToPB(systemUserList, exposeEstrusTypeMap),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) MatingCreate(ctx context.Context, req *pasturePb.EventMating) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	matingList := make([]*model.EventMating, 0)
+	eventFrozenSemenLogList := make([]*model.EventFrozenSemenLog, 0)
+	currentUser, _ := s.GetCurrentSystemUser(ctx)
+
+	frozenSemen := &model.EventFrozenSemen{}
+	if err = s.DB.Where("bull_id = ?", req.BullId).First(frozenSemen).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		if err = tx.Create(matingList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		for _, cow := range cowList {
+			matingList = append(matingList, model.NewEventMating(cow, currentUser, req))
+			eventFrozenSemenLogList = append(eventFrozenSemenLogList, model.NewEventFrozenSemenLog(req.BullId, cow, int64(req.StaffMemberId)))
+			if err = tx.Model(&model.SameTimeCow{}).Where("lact = ?", cow.Lact).Where("cow_id = ?", cow.Id).Updates(map[string]interface{}{
+				"status": pasturePb.IsShow_No,
+				"end_at": time.Now().Unix(),
+			}).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+
+		// 创建冻精使用记录日志
+		if err = tx.Create(eventFrozenSemenLogList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		if err = tx.Table(new(model.EventFrozenSemen).TableName()).
+			Where("bull_id = ?", req.BullId).
+			Where("quantity > 0").UpdateColumn("quantity", gorm.Expr("quantity - ?", len(matingList))).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+
+	return nil
+}
+
+func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusEventResponse, error) {
+	estrusList := make([]*model.EventEstrus, 0)
+	var count int64 = 0
+	pref := s.DB.Table(new(model.EventEstrus).TableName())
+	if len(req.CowId) > 0 {
+		cowIds := strings.Split(req.CowId, ",")
+		pref.Where("cow_id IN ?", cowIds)
+	}
+
+	if err := pref.Order("id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&estrusList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	systemUserList, _ := s.SystemUserList(ctx)
+	return &pasturePb.EstrusEventResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchEstrusData{
+			List:     model.EstrusSlice(estrusList).ToPB(systemUserList),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) EstrusCreate(ctx context.Context, req *pasturePb.EventEstrus) error {
+	if len(req.CowId) <= 0 {
+		return xerr.Custom("请选择相关牛只")
+	}
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	estrusList := make([]*model.EventEstrus, 0)
+	currentUser, _ := s.GetCurrentSystemUser(ctx)
+
+	for _, cow := range cowList {
+		estrusList = append(estrusList, model.NewEventEstrus(cow, currentUser, req))
+	}
+
+	if err := s.DB.Create(estrusList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) FrozenSemenList(ctx context.Context, req *pasturePb.FrozenSemenRequest, pagination *pasturePb.PaginationModel) (*pasturePb.FrozenSemenResponse, error) {
+	frozenSemenList := make([]*model.EventFrozenSemen, 0)
+	var count int64 = 0
+	pref := s.DB.Table(new(model.EventFrozenSemen).TableName())
+	if req.BullId != "" {
+		pref.Where("bull_id = ?", req.BullId)
+	}
+
+	if req.Producer != "" {
+		pref.Where("producer = ?", req.Producer)
+	}
+
+	if err := pref.Order("id desc").
+		Count(&count).Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&frozenSemenList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	frozenSemenTypeMap := s.FrozenSemenTypeMap()
+	unitMap := s.UnitMap()
+
+	return &pasturePb.FrozenSemenResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data: &pasturePb.SearchFrozenSemenData{
+			List:     model.EventFrozenSemenSlice(frozenSemenList).ToPB(frozenSemenTypeMap, unitMap),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}
+
+func (s *StoreEntry) FrozenSemenCreate(ctx context.Context, req *pasturePb.SearchFrozenSemenList) error {
+	currentUser, _ := s.GetCurrentSystemUser(ctx)
+	req.CowKindName = s.CowKindMap()[req.CowKind]
+	newFrozenSemen := model.NewEventFrozenSemen(req, currentUser)
+	if err := s.DB.Create(newFrozenSemen).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) error {
+	sameTime, err := s.GetSameTimeById(ctx, int64(req.SameTimeId))
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	zaplog.Info("SameTimeCreate", zap.Any("sameTime", sameTime), zap.Any("req", req))
+	cowList, err := s.ParseCowIds(ctx, req.CowId)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	drugs := &model.Drugs{}
+	if req.DrugsId > 0 {
+		drugs, err = s.GetDrugsById(ctx, int64(req.DrugsId))
+		if err != nil {
+			zaplog.Error("SameTimeCreate", zap.Any("GetDrugsById", err), zap.Any("req", req))
+		}
+	}
+
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		eventSameTimeList := make([]*model.EventSameTime, 0)
+		for _, cow := range cowList {
+			eventSameTimeList = append(eventSameTimeList, model.NewEventSameTime(cow, req, drugs))
+			// sameTimeCow 不存在时创建
+			if err = tx.Where("same_time_id = ? ", sameTime.Id).
+				Where("cow_id = ?", cow.Id).
+				Where("lact = ?", cow.Lact).
+				First(new(model.SameTimeCow)).Error; err != nil {
+				if errors.Is(err, gorm.ErrRecordNotFound) {
+					if err = tx.Create(model.NewSameTimeCow(cow.Id, sameTime.Id)).Error; err != nil {
+						return xerr.WithStack(err)
+					}
+				}
+			}
+		}
+		if err = tx.Create(eventSameTimeList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+
+	return nil
+}

+ 1 - 0
module/backend/event_vet.go

@@ -0,0 +1 @@
+package backend

+ 8 - 6
module/backend/interface.go

@@ -147,23 +147,25 @@ type ConfigDataService interface {
 //go:generate mockgen -destination mock/EventService.go -package kptservicemock kpt-pasture/module/backend EventService
 type EventService interface {
 	EnterList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchEnterEventResponse, error)
-	CreateEnter(ctx context.Context, req *pasturePb.SearchEnterData) error
+	CreateEnter(ctx context.Context, req *pasturePb.EventEnterData) error
 	GroupTransferList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchTransferGroupEventResponse, error)
 	CreateGroupTransfer(ctx context.Context, req *pasturePb.TransferGroupEventRequest) error
 	BodyScoreList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBodyScoreEventResponse, error)
 	CreateBodyScore(ctx context.Context, req *pasturePb.BodyScoreEventRequest) error
 	CalvingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchLavingEventResponse, error)
-	CalvingCreate(ctx context.Context, req *pasturePb.CalvingEventRequest) error
+	CalvingCreate(ctx context.Context, req *pasturePb.EventCalving) error
 	PregnantCheckList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.PregnantCheckEventResponse, error)
-	PregnantCheckCreate(ctx context.Context, req *pasturePb.PregnantCheckEventRequest) error
+	PregnantCheckCreate(ctx context.Context, req *pasturePb.EventPregnantCheck) error
 	MatingList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingEventResponse, error)
-	MatingCreate(ctx context.Context, req *pasturePb.MatingEventRequest) error
+	MatingCreate(ctx context.Context, req *pasturePb.EventMating) error
 	EstrusList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusEventResponse, error)
-	EstrusCreate(ctx context.Context, req *pasturePb.EstrusEventRequest) error
+	EstrusCreate(ctx context.Context, req *pasturePb.EventEstrus) error
 	FrozenSemenList(ctx context.Context, req *pasturePb.FrozenSemenRequest, pagination *pasturePb.PaginationModel) (*pasturePb.FrozenSemenResponse, error)
 	FrozenSemenCreate(ctx context.Context, req *pasturePb.SearchFrozenSemenList) error
 	WeightList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWeightEventResponse, error)
-	CreateWeight(ctx context.Context, req *pasturePb.WeightEventRequest) error
+	WeightCreate(ctx context.Context, req *pasturePb.EventWeight) error
+
+	SameTimeCreate(ctx context.Context, req *pasturePb.EventSameTime) error
 }
 
 //go:generate mockgen -destination mock/CowService.go -package kptservicemock kpt-pasture/module/backend CowService

+ 2 - 2
module/backend/prescription.go

@@ -247,7 +247,7 @@ func (s *StoreEntry) CreateOrUpdatePrescription(ctx context.Context, req *pastur
 			maxUseDays = v.UseDays
 		}
 
-		drugs, err := s.DrugsById(ctx, int64(v.DrugsId))
+		drugs, err := s.GetDrugsById(ctx, int64(v.DrugsId))
 		if err != nil {
 			return xerr.WithStack(err)
 		}
@@ -365,7 +365,7 @@ func (s *StoreEntry) CreatedOrUpdateImmunization(ctx context.Context, req *pastu
 	var immunization *model.ImmunizationPlan
 	var err error
 	if req.Id > 0 {
-		immunization, err = s.ImmunizationById(ctx, int64(req.Id))
+		immunization, err = s.GetImmunizationById(ctx, int64(req.Id))
 		if err != nil {
 			return xerr.WithStack(err)
 		}

+ 23 - 6
module/backend/sql.go

@@ -43,7 +43,7 @@ func (s *StoreEntry) GetCurrentSystemUser(ctx context.Context) (*model.SystemUse
 	return systemUser, nil
 }
 
-func (s *StoreEntry) GetSystemUserInfo(ctx context.Context, userId int64) (*model.SystemUser, error) {
+func (s *StoreEntry) GetSystemUserById(ctx context.Context, userId int64) (*model.SystemUser, error) {
 	systemUser := &model.SystemUser{
 		Id: userId,
 	}
@@ -64,7 +64,7 @@ func (s *StoreEntry) SystemDeptList(ctx context.Context) ([]*model.SystemDept, e
 	return deptList, nil
 }
 
-func (s *StoreEntry) GetPenInfo(ctx context.Context, penId int64) (*model.Pen, error) {
+func (s *StoreEntry) GetPenById(ctx context.Context, penId int64) (*model.Pen, error) {
 	penData := &model.Pen{
 		Id: penId,
 	}
@@ -93,9 +93,9 @@ func (s *StoreEntry) GetCowList(ctx context.Context) ([]*model.Cow, error) {
 	return cowList, nil
 }
 
-func (s *StoreEntry) GetCowInfo(ctx context.Context, cowId int64) (*model.Cow, error) {
+func (s *StoreEntry) GetCowInfoByCowId(ctx context.Context, cowId int64) (*model.Cow, error) {
 	cowData := &model.Cow{Id: cowId}
-	if err := s.DB.First(cowData).Error; err != nil {
+	if err := s.DB.Where("is_remove = ?", pasturePb.IsShow_Ok).First(cowData).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return nil, xerr.Customf("该牛只数据不存在: %d", cowId)
 		}
@@ -104,6 +104,14 @@ func (s *StoreEntry) GetCowInfo(ctx context.Context, cowId int64) (*model.Cow, e
 	return cowData, nil
 }
 
+func (s *StoreEntry) GetCowInfoByCowIds(ctx context.Context, cowIds []int64) ([]*model.Cow, error) {
+	cowList := make([]*model.Cow, 0)
+	if err := s.DB.Model(&model.Cow{}).Where("is_remove = ?", pasturePb.IsShow_Ok).Find(&cowList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return cowList, nil
+}
+
 func (s *StoreEntry) GetTransferReasonInfo(ctx context.Context, reasonId int64) (*model.ConfigTransferPenReason, error) {
 	configTransferPenReasonData := &model.ConfigTransferPenReason{
 		Id: reasonId,
@@ -136,7 +144,7 @@ func (s *StoreEntry) DiseaseTypeList(ctx context.Context) ([]*model.ConfigDiseas
 	return diseaseTypeList, nil
 }
 
-func (s *StoreEntry) DrugsById(ctx context.Context, id int64) (*model.Drugs, error) {
+func (s *StoreEntry) GetDrugsById(ctx context.Context, id int64) (*model.Drugs, error) {
 	drugs := &model.Drugs{Id: id}
 	if err := s.DB.First(drugs).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
@@ -155,7 +163,7 @@ func (s *StoreEntry) DiseaseListByIds(ctx context.Context, ids []int32) ([]*mode
 	return diseaseList, nil
 }
 
-func (s *StoreEntry) ImmunizationById(ctx context.Context, id int64) (*model.ImmunizationPlan, error) {
+func (s *StoreEntry) GetImmunizationById(ctx context.Context, id int64) (*model.ImmunizationPlan, error) {
 	immunizationPlan := &model.ImmunizationPlan{Id: id}
 	if err := s.DB.First(immunizationPlan).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
@@ -173,3 +181,12 @@ func (s *StoreEntry) GetWorkOrderSubByWorkOrderId(ctx context.Context, workOrder
 	}
 	return workOrderSubList, nil
 }
+
+func (s *StoreEntry) GetSameTimeById(ctx context.Context, id int64) (*model.SameTime, error) {
+	sameTime := &model.SameTime{Id: id}
+	if err := s.DB.Where("is_show = ?", pasturePb.IsShow_Ok).First(sameTime).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+		}
+	}
+	return sameTime, nil
+}

+ 50 - 18
module/crontab/crontab.go

@@ -2,8 +2,8 @@ package crontab
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
-	"fmt"
 	"kpt-pasture/model"
 	"kpt-pasture/module/backend"
 	"kpt-pasture/util"
@@ -123,7 +123,6 @@ func (e *Entry) SameTimePlan() error {
 
 	for _, plan := range sameTimeList {
 		cowList := make([]*model.Cow, 0)
-
 		pref.Where("calving_age >= ?", plan.PostpartumDaysStart).
 			Where("calving_age <= ?", plan.PostpartumDaysEnd)
 		if err := pref.Find(&cowList).Error; err != nil {
@@ -157,23 +156,26 @@ func (e *Entry) GenerateCalendarBySameTimePlan(cowList []*model.Cow, sameTime *m
 		cowSameTimeList = append(cowSameTimeList, newCowSameTime)
 	}
 
-	if len(cowSameTimeList) <= 0 {
-		return nil
-	}
-
+	calendarName := backend.CalendarTypeMap()[pasturePb.CalendarType_Immunisation]
 	workOrderCalendarList := make([]*model.WorkOrderCalendar, 0)
-	calendarMap := backend.CalendarTypeMap()
-	workOrderCalendarList = append(workOrderCalendarList,
-		model.NewWorkOrderCalendar(
-			calendarMap[pasturePb.CalendarType_Immunisation],
-			pasturePb.CalendarType_Immunisation,
-			int32(len(cowSameTimeList)),
-		))
 	if len(sameTime.CollateNodes) > 0 {
-		for _, collateNode := range sameTime.CollateNodes {
-			workOrderCalendarList = append(workOrderCalendarList, nil)
-			// todo 待实现待实现待实现
-			fmt.Println("==collateNode==", collateNode)
+		collateNodes := make([]*pasturePb.CollateNode, 0)
+		var _ = json.Unmarshal([]byte(sameTime.CollateNodes), &collateNodes)
+		nowTime := time.Now()
+		for i, collateNode := range collateNodes {
+			showDay := nowTime.Format(model.LayoutDate2)
+			if i > 0 {
+				showDay = nowTime.Add(time.Hour * 24 * time.Duration(collateNode.NextNodeDay)).Format(model.LayoutDate2)
+			}
+
+			histCount := e.GetTowardSameTimeCowSum(sameTime.Id, showDay)
+			workOrderCalendarList = append(workOrderCalendarList, &model.WorkOrderCalendar{
+				Name:         calendarName,
+				CalendarType: pasturePb.CalendarType_Immunisation,
+				Count:        int32(len(cowSameTimeList)) + int32(histCount),
+				ShowDay:      showDay,
+				IsShow:       pasturePb.IsShow_Ok,
+			})
 		}
 	}
 
@@ -182,6 +184,20 @@ func (e *Entry) GenerateCalendarBySameTimePlan(cowList []*model.Cow, sameTime *m
 		if err := tx.Create(cowSameTimeList).Error; err != nil {
 			return xerr.WithStack(err)
 		}
+		for _, v := range workOrderCalendarList {
+			if err := tx.Model(&model.WorkOrderCalendar{}).Where(map[string]interface{}{
+				"calendar_type": v.CalendarType,
+				"show_day":      v.ShowDay,
+			}).Assign(map[string]interface{}{
+				"name":          v.Name,
+				"calendar_type": v.CalendarType,
+				"count":         v.Count,
+				"show_day":      v.ShowDay,
+				"is_show":       v.IsShow,
+			}).FirstOrCreate(&model.Pen{}).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
 
 		return nil
 	}); err != nil {
@@ -193,7 +209,10 @@ func (e *Entry) GenerateCalendarBySameTimePlan(cowList []*model.Cow, sameTime *m
 
 func (e *Entry) createNewCowSameTime(cow *model.Cow, sameTime *model.SameTime) (*model.SameTimeCow, error) {
 	cowSameTime := &model.SameTimeCow{}
-	if err := e.DB.Where("cow_id = ?", cow.Id).Where("lact = ?", cow.Lact).First(cowSameTime).Error; err != nil {
+	if err := e.DB.Where("cow_id = ?", cow.Id).
+		Where("lact = ?", cow.Lact).
+		Where("same_time_id = ?", sameTime.Id).
+		First(cowSameTime).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return &model.SameTimeCow{
 				CowId:      cow.Id,
@@ -269,6 +288,19 @@ func (e *Entry) GenerateCalendarByImmunization(cowList []*model.Cow, plan *model
 	return nil
 }
 
+// GetTowardSameTimeCowSum 获取历史未打激素牛只总数量
+func (e *Entry) GetTowardSameTimeCowSum(sameTimeId int64, showDay string) int64 {
+	res := int64(0)
+	if err := e.DB.Model(&model.SameTimeCow{}).
+		Where("status = ?", pasturePb.IsShow_Ok).
+		Where("same_time_id = ?", sameTimeId).
+		Where("show_day = ?", showDay).
+		Count(&res).Error; err != nil {
+		zaplog.Error("GetTowardSameTimeCowSum", zap.Any("err", err))
+	}
+	return res
+}
+
 func (e *Entry) getWorkOrderCalendar(name string) []*model.WorkOrderCalendar {
 	res := make([]*model.WorkOrderCalendar, 0)
 	if err := e.DB.Where("name = ?", name).

+ 9 - 0
module/crontab/crontab_test.go

@@ -0,0 +1,9 @@
+package crontab
+
+import (
+	"testing"
+)
+
+func TestEntry_SameTimePlan(t *testing.T) {
+
+}