Kaynağa Gözat

event(calving): 产犊事件新增

Yi 10 ay önce
ebeveyn
işleme
81e4069312

+ 1 - 1
Dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.17-alpine as build
+FROM golang:1.19-alpine as build
 WORKDIR /app/kpt-pasture
 
 COPY . .

+ 11 - 11
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20240513085831-3da9e28378d7
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20240521091607-ad013b639fe0
 	gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/getsentry/sentry-go v0.23.0
@@ -14,7 +14,7 @@ require (
 	github.com/go-redis/redis v6.15.9+incompatible
 	github.com/go-redis/redis/v7 v7.4.1
 	github.com/golang/mock v1.6.0
-	github.com/golang/protobuf v1.5.3
+	github.com/golang/protobuf v1.5.4
 	github.com/mitchellh/mapstructure v1.5.0
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/viper v1.16.0
@@ -22,7 +22,7 @@ require (
 	github.com/xuri/excelize/v2 v2.8.0
 	go.uber.org/dig v1.15.0
 	go.uber.org/zap v1.24.0
-	golang.org/x/sync v0.3.0
+	golang.org/x/sync v0.6.0
 	gorm.io/driver/mysql v1.5.1
 	gorm.io/gorm v1.25.2
 )
@@ -42,7 +42,7 @@ require (
 	github.com/go-playground/validator/v10 v10.15.5 // indirect
 	github.com/go-sql-driver/mysql v1.7.0 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
-	github.com/google/uuid v1.3.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
 	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
@@ -84,13 +84,13 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.8.0 // indirect
 	golang.org/x/arch v0.5.0 // indirect
-	golang.org/x/crypto v0.14.0 // indirect
-	golang.org/x/net v0.16.0 // indirect
-	golang.org/x/sys v0.13.0 // indirect
-	golang.org/x/text v0.13.0 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf // indirect
-	google.golang.org/grpc v1.57.0 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
+	golang.org/x/crypto v0.21.0 // indirect
+	golang.org/x/net v0.22.0 // indirect
+	golang.org/x/sys v0.18.0 // indirect
+	golang.org/x/text v0.15.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect
+	google.golang.org/grpc v1.64.0 // indirect
+	google.golang.org/protobuf v1.34.1 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 36 - 53
go.sum

@@ -36,38 +36,16 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240506084300-6d0267e74122 h1:vqc20q4RvQ3ommNWGRN1h+61phXEllZdSwQIyrz8Mzg=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240506084300-6d0267e74122/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240506090538-9d6beda359cb h1:XZr1IuVNq6q9/KaoN/RiYHuy66BtJJ8cbOpeH8YXV2E=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240506090538-9d6beda359cb/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508060326-e5f376dcfe85 h1:nuD30H9Y2R8oSteyeOLSs+PjMhKMM+CdEMuoS5liFC8=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508060326-e5f376dcfe85/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508062143-1087f5b5588f h1:NTSDl7nwFGWfZVuqSpH40IlLfkfboTTHvNhxhZ4ztfc=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508062143-1087f5b5588f/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508064026-1bdb0320dc5f h1:O5d+gv6uqCmSTsSPAX0EStWP1QdXTEVxQCXhphxJ0ik=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508064026-1bdb0320dc5f/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508070519-7040a3cce5cb h1:9pcF+F4SY9WwnyHW1MRcegJQ3Q63Z5D8idE1KVq/1Bc=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508070519-7040a3cce5cb/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508080006-64977b5c321d h1:4mvRqpIybdhodr8Idd/brpBl65U7EXBWPhFstH3nM2I=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240508080006-64977b5c321d/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509085711-c8276ecbc7ce h1:dqyKcy6tEWAt8NTY2EfkQ7VMygqlRcaobR03tj64Xyo=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509085711-c8276ecbc7ce/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509090708-1d93c51763e0 h1:MHyu/pHpYajBlpXX6YDhgU4qCt7aJMzPjsxlRpos5ys=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509090708-1d93c51763e0/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509092618-b272821a426b h1:M8NazQv/F580VSNUp+cJ/A+BEzTxArfu5Ycg05q8QXE=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509092618-b272821a426b/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509093937-40d0124cdcc6 h1:TMyoyrhi4FV6Rih+smHyDrWzaAwYWfEvoI1fzDtkjKE=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240509093937-40d0124cdcc6/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240510075137-e44046757a95 h1:TgTRGVSWZK/csFc7g5IM0A8gq6xBqBrj12/QYpGT/bI=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240510075137-e44046757a95/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511061932-cc92d4da4504 h1:TH+jY6anSWvB8SUv0tR8X70bToA84ehgTWJ6A9X6vx0=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511061932-cc92d4da4504/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511063932-87bb586873ec h1:xFue7pGVKPAPOyus0RUpoY09hwfeXFW+ThcDIQN1NWc=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511063932-87bb586873ec/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511081455-b5ea1fc3fb2c h1:W/2ntkrh7zdntmfSKlnOv1Zt+Yu+/pjngE79Y8BLm3o=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240511081455-b5ea1fc3fb2c/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240513085831-3da9e28378d7 h1:pFs2rZAvWu0jxaUm9vuHNRW4FFEgaNRbP1Be4OoFUHM=
-gitee.com/xuyiping_admin/go_proto v0.0.0-20240513085831-3da9e28378d7/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520051609-736b1cb9d0ea h1:fl36JzXaKTn1gmF2VPbZshs9DzxFxZ1lOj+q/tqjKu0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520051609-736b1cb9d0ea/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520075338-f40b9b38dafc h1:9vGQuhLKcO2fLKpVbY9FLsf5SA6FH9epyPhfZN5iTqw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520075338-f40b9b38dafc/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520080603-c4313f534ec3 h1:82C9/Q7S7VtOWLqVKC/5bEwGpczA/5wJ2Wyy/c59oiY=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240520080603-c4313f534ec3/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240521083839-0e1283556e66 h1:5ZWXi7XVmlhOrmMWRVcioWah9dXBw5I/criBEk5xpl0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240521083839-0e1283556e66/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240521091607-ad013b639fe0 h1:bfdyAcAfrWDcRJYp3Ym7NPeoLwLPUAestp5YL74Hvbo=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240521091607-ad013b639fe0/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=
@@ -135,6 +113,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
@@ -185,8 +164,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -199,7 +178,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -216,8 +195,9 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -242,10 +222,12 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
 github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -287,6 +269,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nyaruka/phonenumbers v1.1.7 h1:5UUI9hE79Kk0dymSquXbMYB7IlNDNhvu2aNlJpm9et8=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
@@ -392,6 +375,7 @@ go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE=
 go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM=
 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
 go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
@@ -411,8 +395,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -490,8 +474,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
-golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
-golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
+golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -514,8 +498,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -567,8 +551,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -585,8 +569,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -710,8 +694,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf h1:guOdSPaeFgN+jEJwTo1dQ71hdBm+yKSCCKuTRkJzcVo=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -728,8 +712,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
-google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -741,10 +725,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

+ 14 - 0
http/handler/config/config.go

@@ -97,3 +97,17 @@ func SystemUserOptions(c *gin.Context) {
 	}
 	ginutil.JSONResp(c, res)
 }
+
+func SystemBaseConfigOptions(c *gin.Context) {
+	optionName := c.Query("option_name")
+	if err := valid.Validate(optionName, valid.Required, valid.Length(1, 20)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.SystemBaseConfigOptions(c, optionName)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}

+ 60 - 0
http/handler/event/event.go

@@ -171,3 +171,63 @@ func BodyScoreEventCreate(c *gin.Context) {
 		Data: &operationPb.Success{Success: true},
 	})
 }
+
+func CalvingEventList(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.CalvingList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func CalvingEventCreate(c *gin.Context) {
+	var req pasturePb.CalvingEventRequest
+	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.CalvingAt, valid.Required),
+		valid.Field(&req.ChildNumber, valid.Required),
+		valid.Field(&req.CalvingLevel, valid.Required),
+		valid.Field(&req.CalfItemList, valid.Required, valid.Each(valid.By(func(value interface{}) error {
+			s := value.(pasturePb.CalfItem)
+			return valid.ValidateStruct(&s,
+				valid.Field(&s.Sex, valid.Required),
+				valid.Field(&s.Weight, valid.Required),
+				valid.Field(&s.IsLive, valid.Required),
+				valid.Field(&s.IsAdoption, valid.Required),
+			)
+		}))),
+		valid.Field(&req.StaffMemberId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.CalvingCreate(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 1 - 0
http/route/config_api.go

@@ -22,5 +22,6 @@ func ConfigAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		pastureRoute.GET("/cow/type/options", config.CowTypeOptions)
 		pastureRoute.GET("/cow/transfer/pen/reason/options", config.CowTransferPenReasonOptions)
 		pastureRoute.GET("/system/user/options", config.SystemUserOptions)
+		pastureRoute.GET("/system/base/config/options", config.SystemBaseConfigOptions)
 	}
 }

+ 3 - 0
http/route/event_api.go

@@ -21,5 +21,8 @@ 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("/calving/list", event.CalvingEventList)
+		eventRoute.POST("/calving/create", event.CalvingEventCreate)
 	}
 }

+ 11 - 2
model/barn.go

@@ -1,6 +1,8 @@
 package model
 
 import (
+	"fmt"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
@@ -58,12 +60,19 @@ func (p PenSlice) ToPB(configBarnTypes []*ConfigPenType) []*pasturePb.SearchBarn
 	return res
 }
 
-func (p PenSlice) ToPB2() []*pasturePb.ConfigOptionsList {
+func (p PenSlice) ToPB2(req []*ConfigPenType) []*pasturePb.ConfigOptionsList {
 	res := make([]*pasturePb.ConfigOptionsList, len(p))
 	for i, d := range p {
+		label := d.Name
+		for _, r := range req {
+			if r.Id != int64(d.PenType) {
+				continue
+			}
+			label = fmt.Sprintf("%s-%s", label, r.Name)
+		}
 		res[i] = &pasturePb.ConfigOptionsList{
 			Value:    int32(d.Id),
-			Label:    d.Name,
+			Label:    label,
 			Disabled: true,
 		}
 	}

+ 5 - 0
model/cow.go

@@ -32,6 +32,7 @@ type Cow struct {
 	LastEstrusAt        int64                  `json:"last_estrus_at"`
 	LastCalvingAt       int64                  `json:"last_calving_at"`
 	LastMatingAt        int64                  `json:"last_mating_at"`
+	LastBullId          int64                  `json:"last_bull_id"`
 	LastPregnantCheckAt int64                  `json:"last_pregnant_check_at"`
 	LastDryMilkAt       int64                  `json:"last_dry_milk_at"`
 	CreatedAt           int64                  `json:"created_at"`
@@ -78,3 +79,7 @@ func NewCow(req *pasturePb.SearchEnterData) *Cow {
 func (c *Cow) GetDayAge() int32 {
 	return int32(math.Floor(float64(time.Now().Unix()-c.BirthAt) / 86400))
 }
+
+func (c *Cow) GetDaysPregnant() int32 {
+	return int32(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
+}

+ 95 - 0
model/event_calving.go

@@ -0,0 +1,95 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type EventCalving struct {
+	Id                   int64                       `json:"int_64"`
+	CowId                int64                       `json:"cow_id"`
+	EarNumber            string                      `json:"ear_number"`
+	Lact                 int32                       `json:"lact"`
+	DayAge               int32                       `json:"day_age"`
+	PenId                int32                       `json:"pen_id"`
+	CalvingAt            int64                       `json:"calving_at"`
+	ChildNumber          int8                        `json:"child_number"`
+	BullId               int64                       `json:"bull_id"`
+	DaysPregnant         int32                       `json:"days_pregnant"`
+	CalvingLevel         pasturePb.CalvingLevel_Kind `json:"calving_level"`
+	IsInducingChildbirth pasturePb.IsShow_Kind       `json:"is_inducing_childbirth"`
+	StaffMemberId        int64                       `json:"staff_member_id"`
+	Remarks              string                      `json:"remarks"`
+	CreatedAt            int64                       `json:"created_at"`
+	UpdatedAt            int64                       `json:"updated_at"`
+}
+
+func (e *EventCalving) TableName() string {
+	return "event_calving"
+}
+
+func NewEventCalving(cow *Cow, req *pasturePb.CalvingEventRequest) *EventCalving {
+	return &EventCalving{
+		CowId:                cow.Id,
+		EarNumber:            cow.EarNumber,
+		Lact:                 cow.Lact,
+		DayAge:               cow.GetDayAge(),
+		PenId:                int32(cow.PenId),
+		CalvingAt:            int64(req.CalvingAt),
+		BullId:               cow.LastBullId,
+		CalvingLevel:         req.CalvingLevel,
+		DaysPregnant:         cow.GetDaysPregnant(),
+		ChildNumber:          int8(req.ChildNumber),
+		IsInducingChildbirth: req.IsInducingChildbirth,
+		Remarks:              req.Remarks,
+		StaffMemberId:        int64(req.StaffMemberId),
+	}
+}
+
+type EventCalvingList struct {
+	EventCalving
+	PenName         string `json:"pen_name"`
+	StaffMemberName string `json:"staff_member_name"`
+}
+
+type EventCalvingListSlice []*EventCalvingList
+
+func (e EventCalvingListSlice) ToPB(req []*EventCalvingCalf) []*pasturePb.SearchLavingList {
+	var list []*pasturePb.SearchLavingList
+	for _, item := range e {
+		CalfItemList := make([]*pasturePb.CalfItem, 0)
+		for _, v := range req {
+			if v.CalvingId != item.Id {
+				continue
+			}
+			CalfItemList = append(CalfItemList, &pasturePb.CalfItem{
+				EarNumber:  v.EarNumber,
+				Sex:        v.Sex,
+				Weight:     float32(v.Weight) / 100,
+				IsAdoption: v.IsAdoption,
+				IsLive:     v.IsLive,
+				CreatedAt:  int32(v.CreatedAt),
+				UpdatedAt:  int32(v.UpdatedAt),
+				PenId:      int32(v.PenId),
+				Remarks:    v.Remarks,
+				MotherId:   int32(v.MotherId),
+			})
+		}
+		list = append(list, &pasturePb.SearchLavingList{
+			Id:                   int32(item.Id),
+			CowId:                int32(item.CowId),
+			Lact:                 item.Lact,
+			PenId:                item.PenId,
+			PenName:              item.PenName,
+			CalvingAt:            int32(item.CalvingAt),
+			ChildNumber:          int32(item.ChildNumber),
+			DaysPregnant:         item.DaysPregnant,
+			IsInducingChildbirth: item.IsInducingChildbirth,
+			StaffMemberId:        int32(item.StaffMemberId),
+			StaffMemberName:      item.StaffMemberName,
+			CalvingLevel:         item.CalvingLevel,
+			Remarks:              item.Remarks,
+			CreatedAt:            int32(item.CreatedAt),
+			UpdatedAt:            int32(item.UpdatedAt),
+			CalfItemList:         CalfItemList,
+		})
+	}
+	return list
+}

+ 42 - 0
model/event_calving_calf.go

@@ -0,0 +1,42 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type EventCalvingCalf struct {
+	Id         int64                  `json:"id"`
+	CalvingId  int64                  `json:"calving_id"`
+	CowId      int64                  `json:"cow_id"`
+	MotherId   int64                  `json:"mother_id"`
+	EarNumber  string                 `json:"ear_number"`
+	Sex        pasturePb.Genders_Kind `json:"sex"`
+	Weight     int64                  `json:"weight"`
+	IsLive     pasturePb.IsShow_Kind  `json:"is_live"`
+	IsAdoption pasturePb.IsShow_Kind  `json:"is_adoption"`
+	PenId      int64                  `json:"pen_id"`
+	Remarks    string                 `json:"remarks"`
+	CreatedAt  int64                  `json:"created_at"`
+	UpdatedAt  int64                  `json:"updated_at"`
+}
+
+func (e *EventCalvingCalf) TableName() string {
+	return "event_calving_calf"
+}
+
+func NewEventCalvingCalf(motherId, calvingId int64, req *pasturePb.CalvingEventRequest) []*EventCalvingCalf {
+	calvingCalfList := make([]*EventCalvingCalf, 0)
+	for _, v := range req.CalfItemList {
+		calvingCalfList = append(calvingCalfList, &EventCalvingCalf{
+			CowId:      0,  // TODO: cowId
+			EarNumber:  "", // TODO: 耳号
+			CalvingId:  calvingId,
+			PenId:      0, // TODO:  penId
+			Weight:     int64(v.Weight * 100),
+			Sex:        v.Sex,
+			MotherId:   motherId,
+			Remarks:    v.Remarks,
+			IsAdoption: v.IsAdoption,
+			IsLive:     v.IsLive,
+		})
+	}
+	return calvingCalfList
+}

+ 51 - 2
module/backend/config_data.go

@@ -12,7 +12,6 @@ import (
 
 func (s *StoreEntry) BarnTypeOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error) {
 	configBarnTypeList := make([]*model.ConfigPenType, 0)
-
 	if err := s.DB.Table(new(model.ConfigPenType).TableName()).Find(&configBarnTypeList).Error; err != nil {
 		return nil, err
 	}
@@ -32,10 +31,15 @@ func (s *StoreEntry) BarnListOptions(ctx context.Context) (*pasturePb.ConfigOpti
 		return nil, err
 	}
 
+	configBarnTypeList := make([]*model.ConfigPenType, 0)
+	if err := s.DB.Table(new(model.ConfigPenType).TableName()).Find(&configBarnTypeList).Error; err != nil {
+		return nil, err
+	}
+
 	return &pasturePb.ConfigOptionsListResponse{
 		Code:    http.StatusOK,
 		Message: "ok",
-		Data:    model.PenSlice(penList).ToPB2(),
+		Data:    model.PenSlice(penList).ToPB2(configBarnTypeList),
 	}, nil
 }
 
@@ -126,3 +130,48 @@ func (s *StoreEntry) SystemUserOptions(ctx context.Context, depId int) (*pasture
 		Data:    model.SystemUserSlice(systemUserList).ToPB2(),
 	}, nil
 }
+
+func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName string) (*pasturePb.ConfigOptionsListResponse, error) {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	switch optionsName {
+	case "childNumber":
+		configOptions = append(configOptions,
+			&pasturePb.ConfigOptionsList{
+				Value:    1,
+				Label:    "单胎",
+				Disabled: true,
+			}, &pasturePb.ConfigOptionsList{
+				Value:    2,
+				Label:    "双胎",
+				Disabled: true,
+			}, &pasturePb.ConfigOptionsList{
+				Value:    3,
+				Label:    "三胎",
+				Disabled: true,
+			}, &pasturePb.ConfigOptionsList{
+				Value:    4,
+				Label:    "四胎",
+				Disabled: true,
+			})
+	case "calvingLevel":
+		configOptions = append(configOptions,
+			&pasturePb.ConfigOptionsList{
+				Value:    int32(pasturePb.CalvingLevel_Natural_Childbirth),
+				Label:    "自然分娩",
+				Disabled: true,
+			}, &pasturePb.ConfigOptionsList{
+				Value:    int32(pasturePb.CalvingLevel_Artificial_Midwifery_UnUse),
+				Label:    "人工助产-未使用医疗器械",
+				Disabled: true,
+			}, &pasturePb.ConfigOptionsList{
+				Value:    int32(pasturePb.CalvingLevel_Artificial_Midwifery_Use),
+				Label:    "人工助产-使用医疗器械",
+				Disabled: true,
+			})
+	}
+	return &pasturePb.ConfigOptionsListResponse{
+		Code:    http.StatusOK,
+		Message: "ok",
+		Data:    configOptions,
+	}, nil
+}

+ 67 - 0
module/backend/event.go

@@ -233,3 +233,70 @@ func (s *StoreEntry) CreateBodyScore(ctx context.Context, req *pasturePb.BodySco
 
 	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.EventCalvingCalf, 0)
+	if err := s.DB.Model(new(model.EventCalvingCalf)).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)
+		if err = tx.Create(newCalvingCalfList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}

+ 3 - 0
module/backend/interface.go

@@ -117,6 +117,7 @@ type ConfigDataService interface {
 	CowTypeOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error)
 	CowTransferPenReasonOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error)
 	SystemUserOptions(ctx context.Context, depId int) (*pasturePb.ConfigOptionsListResponse, error)
+	SystemBaseConfigOptions(ctx context.Context, optionName string) (*pasturePb.ConfigOptionsListResponse, error)
 }
 
 //go:generate mockgen -destination mock/EventService.go -package kptservicemock kpt-pasture/module/backend EventService
@@ -127,6 +128,8 @@ type EventService interface {
 	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
 }
 
 //go:generate mockgen -destination mock/CowService.go -package kptservicemock kpt-pasture/module/backend CowService