Browse Source

Merge branch 'feature/bug-list' of xuyiping/kpt-tmr-group into develop

xuyiping 1 year ago
parent
commit
b7a1f2fd5d

+ 15 - 12
backend/operation/pasture.proto

@@ -134,11 +134,12 @@ message SearchForageCategoryData {
 // 饲料列表
 message AddForageRequest {
   int32 id = 1;
-  string name = 2;                // 饲料名称
-  int32 category_id = 3;          // 饲料分类id
-  string category_name = 4;       // 饲料分类名称
-  int32 material_type = 5;        // 物料类型
-  string unique_encode = 7;       // 唯一编码
+  string name = 2;                      // 饲料名称
+  int32 category_id = 3;                // 饲料分类id
+  string category_name = 4;             // 饲料分类名称
+  string material_type_key = 5;        // 物料类型key
+  string material_type_name = 6;        // 物料类型名称
+  string unique_encode = 7;              // 唯一编码
   ForageSource.Kind forage_source_id = 8;       // 饲料来源id
   string forage_source_name = 9;                // 饲料来源名称
   ForagePlanType.Kind plan_type_id = 10;       // 计划类型id
@@ -161,14 +162,14 @@ message AddForageRequest {
 }
 
 message SearchForageListRequest {
-  string name = 1;   // 饲料名称
-  int32 category_id = 2;   // 饲料分类id
+  string name = 1;              // 饲料名称
+  int32 category_id = 2;        // 饲料分类id
   uint32 forage_source_id = 3;   // 饲料来源
-  IsShow.Kind is_show = 4;    // 是否启用
-  uint32 allow_error = 5;      // 允许误差
-  uint32 jump_weight = 6;      // 跳转重量域
+  IsShow.Kind is_show = 4;       // 是否启用
+  uint32 allow_error = 5;        // 允许误差
+  uint32 jump_weight = 6;        // 跳转重量域
   JumpDelaType.Kind  jump_delay = 7;   // 跳转延迟
-  PaginationModel pagination = 8; // 分页
+  PaginationModel pagination = 8;   // 分页
 }
 
 message ForageListSortRequest {
@@ -289,5 +290,7 @@ message CategoryDeleteRequest {
 }
 
 message FeedFormulaSyncRequest {
-  int32 pasture_id = 1;
+  int32 pasture_id = 1;    // 牧场id
+  int32 page = 2;          // 返回数据条数
+  int32 page_size = 3;     // 返回数据条数
 }

+ 27 - 27
go.mod

@@ -5,7 +5,7 @@ go 1.17
 require (
 	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
-	github.com/getsentry/sentry-go v0.20.0
+	github.com/getsentry/sentry-go v0.23.0
 	github.com/gin-contrib/cors v1.4.0
 	github.com/gin-contrib/gzip v0.0.6
 	github.com/gin-contrib/requestid v0.0.6
@@ -23,57 +23,58 @@ require (
 	github.com/magiconair/properties v1.8.7
 	github.com/mitchellh/mapstructure v1.5.0
 	github.com/nyaruka/phonenumbers v1.1.7
-	github.com/sirupsen/logrus v1.9.0
+	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/viper v1.15.0
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.4
 	github.com/xuri/excelize/v2 v2.7.1
 	go.uber.org/dig v1.15.0
-	go.uber.org/zap v1.21.0
-	golang.org/x/sync v0.1.0
-	google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef
-	google.golang.org/grpc v1.52.0
-	google.golang.org/protobuf v1.30.0
-	gopkg.in/natefinch/lumberjack.v2 v2.2.1
-	gorm.io/driver/mysql v1.5.0
-	gorm.io/gorm v1.25.0
+	go.uber.org/multierr v1.8.0
+	go.uber.org/zap v1.24.0
+	golang.org/x/sync v0.2.0
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf
+	google.golang.org/grpc v1.57.0
+	google.golang.org/protobuf v1.31.0
+	gorm.io/driver/mysql v1.5.1
+	gorm.io/gorm v1.25.2
 )
 
 require (
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20230802054950-77dee3d12065 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/bytedance/sonic v1.8.0 // indirect
+	github.com/bytedance/sonic v1.9.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
-	github.com/go-playground/validator/v10 v10.11.2 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
 	github.com/go-sql-driver/mysql v1.7.0 // indirect
-	github.com/goccy/go-json v0.10.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/google/uuid v1.3.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
-	github.com/jonboulle/clockwork v0.4.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
-	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
 	github.com/lestrrat-go/strftime v1.0.6 // indirect
-	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_golang v1.14.0 // indirect
+	github.com/prometheus/client_golang v1.16.0 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
 	github.com/prometheus/common v0.42.0 // indirect
-	github.com/prometheus/procfs v0.9.0 // indirect
+	github.com/prometheus/procfs v0.10.1 // indirect
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
@@ -82,15 +83,14 @@ require (
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
-	github.com/ugorji/go/codec v1.2.9 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
 	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
-	go.uber.org/multierr v1.8.0 // indirect
-	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
-	golang.org/x/crypto v0.8.0 // indirect
-	golang.org/x/net v0.9.0 // indirect
-	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/net v0.10.0 // indirect
+	golang.org/x/sys v0.8.0 // indirect
 	golang.org/x/text v0.9.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect

+ 60 - 55
go.sum

@@ -36,6 +36,8 @@ 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-20230802054950-77dee3d12065 h1:ITJlIE5ITvh3FiOw6QOrVDgAYOtuimwMBiHM0prmVbQ=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20230802054950-77dee3d12065/go.mod h1:cxbPefIf1o+cyQwvFaM3ndaoUeaK5aWzPV/eZQGJPgE=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
@@ -45,8 +47,8 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
-github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
-github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -77,8 +79,10 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/getsentry/sentry-go v0.20.0 h1:bwXW98iMRIWxn+4FgPW7vMrjmbym6HblXALmhjHmQaQ=
-github.com/getsentry/sentry-go v0.20.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE=
+github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
 github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
 github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
 github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
@@ -105,8 +109,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
-github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
-github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
 github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI=
@@ -115,8 +119,8 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
-github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -205,27 +209,28 @@ 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/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
 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/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 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
 github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
@@ -235,8 +240,8 @@ github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -257,8 +262,8 @@ github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
-github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
 github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -267,15 +272,15 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
 github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
 github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
 github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
+github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
 github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
 github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
@@ -283,12 +288,12 @@ github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN
 github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
@@ -314,16 +319,18 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
-github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
-github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
 github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI=
@@ -334,7 +341,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -349,15 +355,15 @@ 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=
 go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
-go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
-go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
-golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -367,8 +373,9 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
 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=
@@ -404,7 +411,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -440,11 +446,11 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
 golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 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=
@@ -464,10 +470,10 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-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 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
+golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 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=
@@ -503,21 +509,21 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 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=
@@ -586,7 +592,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -656,8 +661,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 v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
-google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
+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/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=
@@ -674,8 +679,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.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
-google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
+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/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=
@@ -689,8 +694,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.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=
 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=
@@ -701,8 +706,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -715,11 +718,11 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM=
-gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo=
-gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
-gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
-gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
+gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
+gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
+gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -727,6 +730,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+kpt-tmr-group/pkg v0.0.0-20230802061948-5b07cd8c16e6 h1:K4RrKDO1SG1NOCoqNO0jnlGKmY7AfOmuqzDIw94KCTk=
+kpt-tmr-group/pkg v0.0.0-20230802061948-5b07cd8c16e6/go.mod h1:h3kdB9CyxmW6duxLLA6fJezVCHa0g5+erAQ60iv+S58=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

+ 11 - 0
http/debug/debug.go

@@ -4,6 +4,7 @@ import (
 	"kpt-tmr-group/http/middleware"
 	"kpt-tmr-group/pkg/apierr"
 	"kpt-tmr-group/pkg/ginutil"
+	"kpt-tmr-group/pkg/valid"
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 
@@ -27,6 +28,7 @@ func FeedFormulaSync(c *gin.Context) {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
+
 	ginutil.JSONResp(c, &operationPb.CommonOK{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -41,6 +43,15 @@ func FeedSync(c *gin.Context) {
 		return
 	}
 
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.PastureId, valid.Required),
+		valid.Field(&req.Page, valid.Required),
+		valid.Field(&req.PageSize, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
 	if err := middleware.BackendOperation(c).OpsService.FeedSyncData(c, &req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return

+ 0 - 24
http/handler/default.go

@@ -1,10 +1,6 @@
 package handler
 
 import (
-	"compress/gzip"
-	"fmt"
-	"io/ioutil"
-	"kpt-tmr-group/pkg/xerr"
 	"net/http"
 
 	"github.com/gin-gonic/gin"
@@ -17,23 +13,3 @@ func Health(c *gin.Context) {
 func Handle404(c *gin.Context) {
 	c.String(http.StatusNotFound, "404 NotFound")
 }
-
-func dumpPerfEventBody(c *gin.Context) ([]byte, error) {
-	if c.ContentType() != "application/octet-stream" {
-		return nil, fmt.Errorf("invalid Content-Type:  %s ", c.ContentType())
-	}
-	if c.GetHeader("Content-Encoding") != "gzip" {
-		return nil, fmt.Errorf("invalid Content-Encoding:  %s ", c.GetHeader("Content-Encoding"))
-	}
-	if c.Request.Body == nil || int(c.Request.ContentLength) < 1 {
-		return nil, fmt.Errorf("invalid body:  %v ", int(c.Request.ContentLength))
-	}
-
-	reader, err := gzip.NewReader(c.Request.Body)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	defer reader.Close()
-
-	return ioutil.ReadAll(reader)
-}

+ 1 - 0
http/handler/feed/feed_formula.go

@@ -260,6 +260,7 @@ func MixedFeedFormula(c *gin.Context) {
 	}
 
 	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required),
 		valid.Field(&req.Name, valid.Required),
 		valid.Field(&req.Colour, valid.Required),
 		valid.Field(&req.CattleCategoryId, valid.Required),

+ 1 - 4
http/handler/pasture/forage_list.go

@@ -29,10 +29,8 @@ func AddForage(c *gin.Context) {
 		valid.Field(&req.UniqueEncode, valid.Required),
 		valid.Field(&req.ForageSourceId, valid.Required),
 		valid.Field(&req.ForageSourceName, valid.Required),
-		//valid.Field(&req.PlanTypeId, valid.Required, valid.Min(0), valid.Max(2)),
 		valid.Field(&req.PlanTypeName, valid.Required),
-		valid.Field(&req.MaterialType, valid.Required),
-		//valid.Field(&req.JumpWeight, valid.Required, valid.Min(0), valid.Max(50)),
+		//valid.Field(&req.MaterialTypeKey, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -63,7 +61,6 @@ func EditForage(c *gin.Context) {
 		valid.Field(&req.CategoryName, valid.Required),
 		valid.Field(&req.UniqueEncode, valid.Required),
 		valid.Field(&req.ForageSourceId, valid.Required),
-		valid.Field(&req.MaterialType, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return

+ 12 - 0
model/feed.go

@@ -0,0 +1,12 @@
+package model
+
+type FeedPasture struct {
+	Id            int64  `json:"id"`
+	PastureId     int64  `json:"pasture_id"`
+	PastureName   string `json:"pasture_name"`
+	PastureDataId int64  `json:"pasture_data_id"`
+}
+
+func (f *FeedPasture) TableName() string {
+	return "feed_pasture"
+}

+ 19 - 1
model/feed_formula.go

@@ -44,7 +44,7 @@ func NewFeedFormula(req *operationPb.AddFeedFormulaRequest) *FeedFormula {
 		DataSourceId:       req.DataSourceId,
 		DataSourceName:     req.DataSourceName,
 		Remarks:            req.Remarks,
-		Version:            0,
+		Version:            1,
 		PastureId:          0,
 		PastureName:        "集团",
 		IsShow:             req.IsShow,
@@ -86,3 +86,21 @@ type DistributeData struct {
 	FeedFormulaList   []*FeedFormula
 	FeedFormulaDetail []*FeedFormulaDetail
 }
+
+func NewNewFeedFormulaByMixed(req *operationPb.MixedFeedFormulaRequest) *FeedFormula {
+	return &FeedFormula{
+		Name:               req.Name,
+		Colour:             req.Colour,
+		CattleCategoryId:   operationPb.CattleCategoryParent_Kind(req.CattleCategoryId),
+		CattleCategoryName: req.CattleCategoryName,
+		FormulaTypeId:      req.FormulaTypeId,
+		FormulaTypeName:    req.FormulaTypeName,
+		DataSourceId:       operationPb.DataSource_Kind(req.DataSourceId),
+		DataSourceName:     operationPb.DataSource_Kind_name[req.DataSourceId],
+		Remarks:            req.Remarks,
+		PastureName:        "集团",
+		IsShow:             operationPb.IsShow_OK,
+		IsModify:           operationPb.IsShow_OK,
+		IsDelete:           operationPb.IsShow_OK,
+	}
+}

+ 52 - 3
model/forage.go

@@ -13,7 +13,8 @@ type Forage struct {
 	Name               string                          `json:"name"`
 	CategoryId         int64                           `json:"category_id"`
 	CategoryName       string                          `json:"category_name"`
-	MaterialType       int32                           `json:"material_type"`
+	MaterialTypeKey    string                          `json:"material_type_key"`
+	MaterialTypeName   string                          `json:"material_type_name"`
 	UniqueEncode       string                          `json:"unique_encode"`
 	ForageSourceId     operationPb.ForageSource_Kind   `json:"forage_source_id"`
 	ForageSourceName   string                          `json:"forage_source_name"`
@@ -54,7 +55,8 @@ func NewForage(req *operationPb.AddForageRequest) *Forage {
 		ForageSourceName:   req.ForageSourceName,
 		PlanTypeId:         req.PlanTypeId,
 		PlanTypeName:       req.PlanTypeName,
-		MaterialType:       req.MaterialType,
+		MaterialTypeKey:    req.MaterialTypeKey,
+		MaterialTypeName:   req.MaterialTypeName,
 		SmallMaterialScale: req.SmallMaterialScale,
 		AllowError:         int64(req.AllowError),
 		PackageWeight:      int64(req.PackageWeight),
@@ -83,7 +85,8 @@ func (f ForageSlice) ToPB() []*operationPb.AddForageRequest {
 			Name:               v.Name,
 			CategoryId:         int32(v.CategoryId),
 			CategoryName:       v.CategoryName,
-			MaterialType:       int32(v.MaterialType),
+			MaterialTypeKey:    v.MaterialTypeKey,
+			MaterialTypeName:   v.MaterialTypeName,
 			UniqueEncode:       v.UniqueEncode,
 			ForageSourceId:     v.ForageSourceId,
 			ForageSourceName:   v.ForageSourceName,
@@ -108,3 +111,49 @@ func (f ForageSlice) ToPB() []*operationPb.AddForageRequest {
 	}
 	return res
 }
+
+func NewForageByPastureFeed(groupPasture *GroupPasture, data *Feed) *Forage {
+	forageSourceName := data.Source
+	forageSourceId := operationPb.ForageSource_SYSTEM_BUILT_IN
+	if forageSourceName == "用户自定义" {
+		forageSourceId = operationPb.ForageSource_USER_DEFINED
+	}
+
+	confirmStart := operationPb.IsShow_INVALID
+	if data.ConfirmStart == 0 {
+		confirmStart = operationPb.IsShow_NO
+	}
+
+	if data.ConfirmStart == 1 {
+		confirmStart = operationPb.IsShow_OK
+	}
+
+	return &Forage{
+		Name:               data.FName,
+		CategoryId:         data.FClassId,
+		CategoryName:       data.FClass,
+		MaterialTypeKey:    "", // 部分牧场有该字段
+		MaterialTypeName:   "", //
+		UniqueEncode:       data.FeedCode,
+		ForageSourceId:     forageSourceId,
+		ForageSourceName:   forageSourceName,
+		PlanTypeId:         operationPb.ForagePlanType_Kind(data.PrintGroupId),
+		PlanTypeName:       data.PrintGroup,
+		SmallMaterialScale: data.SmtMrName,
+		AllowError:         data.AllowRatio,
+		PackageWeight:      data.UnitWeight,
+		Price:              int64(data.UPrice * 100),
+		JumpWeight:         data.AutoZone,
+		JumpDelay:          operationPb.JumpDelaType_Kind(data.AutoSecond),
+		ConfirmStart:       confirmStart,
+		RelayLocations:     int64(data.TrgAddress),
+		Jmp:                operationPb.IsShow_Kind(data.Jmp),
+		DataSource:         operationPb.DataSource_FROM_PASTURE,
+		Sort:               int64(data.Sort),
+		PastureId:          groupPasture.PastureId,
+		PastureName:        groupPasture.Name,
+		PastureDataId:      data.Id,
+		IsShow:             operationPb.IsShow_Kind(data.Enable),
+		IsDelete:           operationPb.IsShow_OK,
+	}
+}

+ 130 - 0
model/formula_estimate.go

@@ -1,5 +1,10 @@
 package model
 
+import (
+	"fmt"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+)
+
 type PastureCommonRequest struct {
 	Name       string      `json:"name"`
 	Page       int32       `json:"page,omitempty"`
@@ -95,6 +100,23 @@ type FeedStatisticsParams struct {
 	Times     string `json:"times"`
 }
 
+func NewFeedStatisticsParams(pastureId int64, req *operationPb.SearchFeedStatisticsRequest) *FeedStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &FeedStatisticsParams{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		StartTime: req.StartTime,
+		StopTime:  req.EndTime,
+		Date:      req.StartTime,
+		FeedTName: req.FormulaTemplate,
+		BarName:   req.BarnName,
+		CowClass:  req.CattleCategoryName,
+		Times:     times,
+	}
+}
+
 // FeedChartParams 饲喂效率-图形统计
 type FeedChartParams struct {
 	ParamMaps interface{} `json:"parammaps"`
@@ -127,6 +149,31 @@ type MixFeedStatisticsParams struct {
 	Error       bool   `json:"error,omitempty"`
 }
 
+func NewMixFeedStatisticsParams(pastureId int64, req *operationPb.MixFeedStatisticsRequest) *MixFeedStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &MixFeedStatisticsParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.StartTime,
+		TmrTName:    req.EquipmentName,
+		ProjName:    req.TrainNumber,
+		Times:       times,
+		ButtonType:  req.ButtonType,
+		TempletName: req.FormulationName,
+		Isuse:       req.IsUse,
+		Hlwc1:       req.Hlwc1,
+		Hlwc2:       req.Hlwc2,
+		Hlzq1:       req.Hlzq1,
+		Hlzq2:       req.Hlzq2,
+		Hlzql1:      req.Hlzql1,
+		Hlzql2:      req.Hlzql2,
+		Error:       req.IsError,
+	}
+}
+
 // SprinkleStatisticsParams 准确性分析-撒料统计
 type SprinkleStatisticsParams struct {
 	PastureId   string `json:"pastureid"`
@@ -148,6 +195,32 @@ type SprinkleStatisticsParams struct {
 	Error       bool   `json:"error,omitempty"`
 }
 
+func NewSprinkleStatisticsParams(pastureId int64, req *operationPb.SprinkleStatisticsRequest) *SprinkleStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &SprinkleStatisticsParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.StartTime,
+		TmrTName:    req.EquipmentName,
+		ProjName:    req.TrainNumber,
+		Times:       times,
+		ButtonType:  req.ButtonType,
+		TempletName: req.FormulationName,
+		Isuse:       req.IsUse,
+		Fname:       req.BarnName,
+		Slwc1:       req.Slwc1,
+		Slwc2:       req.Slwc2,
+		Slzq2:       req.Slzq2,
+		Slzq1:       req.Slzq1,
+		Slzql1:      req.Slzql1,
+		Slzql2:      req.Slzql2,
+		Error:       req.IsError,
+	}
+}
+
 // ProcessAnalysisParams 过程分析
 type ProcessAnalysisParams struct {
 	PastureId   string   `json:"pastureid"`
@@ -168,6 +241,27 @@ type ProcessAnalysisParams struct {
 	Error       string   `json:"error,omitempty"`
 }
 
+func NewProcessAnalysisParams(pastureId int64, req *operationPb.ProcessAnalysisRequest) *ProcessAnalysisParams {
+	return &ProcessAnalysisParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.StartTime,
+		TmrTName:    req.TmrName,
+		IsCompleted: "",
+		LpPlanType:  fmt.Sprintf("%d", req.PlanType),
+		FClassId:    req.MixFeedType,
+		Hlzq1:       req.Hlzq1,
+		Hlzq2:       req.Hlzq2,
+		Hlwc1:       req.Hlwc1,
+		Hlwc2:       req.Hlwc2,
+		Slwc1:       req.Slwc1,
+		Slwc2:       req.Slwc2,
+		Slzq2:       req.Slzq2,
+		Slzq1:       req.Slzq1,
+		Error:       req.ErrorRange,
+	}
+}
+
 // AccuracyAggParams 准确性分析-汇总统计
 type AccuracyAggParams struct {
 	PastureId string `json:"pastureid"`
@@ -194,6 +288,33 @@ type AccuracyAggParams struct {
 	Error     bool   `json:"error,omitempty"`
 }
 
+func NewAccuracyAggParams(pastureId int64, req *operationPb.AccuracyAggStatisticsRequest) *AccuracyAggParams {
+	return &AccuracyAggParams{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		StartTime: req.StartTime,
+		StopTime:  req.EndTime,
+		FName:     req.Fname,
+		Sort:      req.Sort,
+		Status:    req.Status,
+		Times:     req.Times,
+		Genre:     req.Genre,
+		IsDate:    req.Isdate,
+		Hlwc1:     req.Hlwc1,
+		Hlwc2:     req.Hlwc2,
+		Hlzq1:     req.Hlzq1,
+		Hlzq2:     req.Hlzq2,
+		Hlzql1:    req.Hlzql1,
+		Hlzql2:    req.Hlzql2,
+		Slwc1:     req.Slwc1,
+		Slwc2:     req.Slwc2,
+		Slzq1:     req.Slzq1,
+		Slzq2:     req.Slzq2,
+		Slzql1:    req.Slzql1,
+		Slzql2:    req.Slzql2,
+		Error:     req.IsError,
+	}
+}
+
 // TrainNumberParams 班次
 type TrainNumberParams struct {
 	PastureId string `json:"pastureid"`
@@ -255,3 +376,12 @@ type MixedSprinkleDetailRequest struct {
 	PId       string `json:"pid"`
 	FClassId  string `json:"fclassid"`
 }
+
+func NewMixedSprinkleDetailRequest(pastureId int64, req *operationPb.ProcessMixedSprinkleDetailRequest) *MixedSprinkleDetailRequest {
+	return &MixedSprinkleDetailRequest{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		FClassId:  req.FclassId,
+		PId:       req.Pid,
+		Id:        req.Id,
+	}
+}

+ 1 - 0
model/group_pasture.go

@@ -40,6 +40,7 @@ const (
 	CattleCategoryDeleteURl        = "pasture/cattle_category/delete"
 	ForageCategoryDeleteURl        = "pasture/cattle_category/delete"
 	FeedUsageURl                   = "pasture/feed/usage"
+	FeedFormulaVersionUpdateUrl    = "pasture/feed_formula/version"
 )
 
 var (

+ 14 - 0
model/pasture_data.go

@@ -202,3 +202,17 @@ type FeedTemplateDetail struct {
 	SplitFtPreId   int64   `json:"split_ft_pre_id"`
 	Deviation      int32   `json:"deviation"`
 }
+
+type FeedFormulaUpdateVersionRequest struct {
+	FeedTemplateId int64 `json:"feed_template_id"` // 配方id
+	Version        int64 `json:"version"`          // 版本号
+	Belong         int32 `json:"belong"`           // 配方归属  0 无效 1 归属集团端 2 归属牧场端
+}
+
+type FeedFormulaUpdateVersionResponse struct {
+	Code int32  `json:"code"`
+	Msg  string `json:"msg"`
+	Data struct {
+		Success bool `json:"success"`
+	} `json:"data"`
+}

+ 15 - 0
module/backend/edit_record_service.go

@@ -0,0 +1,15 @@
+package backend
+
+import (
+	"context"
+	"kpt-tmr-group/model"
+	"kpt-tmr-group/pkg/xerr"
+)
+
+func (s *StoreEntry) GetEditRecordLastGroupId(ctx context.Context) (*model.FeedFormulaEditRecord, error) {
+	editRecord := &model.FeedFormulaEditRecord{}
+	if err := s.DB.Model(new(model.FeedFormulaEditRecord)).Order("group_id desc").Take(editRecord).Error; err != nil {
+		return editRecord, xerr.WithStack(err)
+	}
+	return editRecord, nil
+}

+ 99 - 26
module/backend/feed_service.go

@@ -49,14 +49,15 @@ func (s *StoreEntry) CreateFeedFormula(ctx context.Context, req *operationPb.Add
 
 // EditFeedFormula 编辑数据
 func (s *StoreEntry) EditFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error {
-	forage := model.FeedFormula{Id: int64(req.Id)}
-	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(&forage).Error; err != nil {
+	feedFormula := &model.FeedFormula{Id: int64(req.Id)}
+	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(feedFormula).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return xerr.Custom("该数据不存在")
 		}
 		return xerr.WithStack(err)
 	}
-
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormula)
 	updateData := &model.FeedFormula{
 		Name:               req.Name,
 		Colour:             req.Colour,
@@ -70,7 +71,7 @@ func (s *StoreEntry) EditFeedFormula(ctx context.Context, req *operationPb.AddFe
 		IsShow:             req.IsShow,
 	}
 	if err := s.DB.Model(new(model.FeedFormula)).
-		Omit("is_show", "is_delete", "encode_number", "formula_type_id", "formula_type_name", "data_source", "version", "is_modify").
+		Omit("is_show", "is_delete", "encode_number", "formula_type_id", "formula_type_name", "data_source", "is_modify").
 		Where("id = ?", req.Id).
 		Updates(updateData).Error; err != nil {
 		return xerr.WithStack(err)
@@ -84,8 +85,10 @@ func (s *StoreEntry) AddFeedByFeedFormula(ctx context.Context, req *operationPb.
 	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
 		return xerr.WithStack(err)
 	}
+	// 更新修改记录
 	defer s.addFeedFormulaDetailAddRecode(ctx, req)
-
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
 	insertData := make([]*model.FeedFormulaDetail, 0)
 	for _, v := range req.List {
 		feedData := &model.Forage{Id: int64(v.ForageId)}
@@ -113,12 +116,12 @@ func (s *StoreEntry) AddFeedByFeedFormula(ctx context.Context, req *operationPb.
 	if err := s.DB.Model(new(model.FeedFormulaDetail)).Save(insertData).Error; err != nil {
 		return xerr.WithStack(err)
 	}
-
 	return nil
 }
 
 // addFeedFormulaDetailAddRecode 添加配方记录
 func (s *StoreEntry) addFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) {
+	editRecord, _ := s.GetEditRecordLastGroupId(ctx)
 	editRecordList := make([]*model.FeedFormulaEditRecord, 0)
 	for _, v := range req.List {
 		editRecordList = append(editRecordList, &model.FeedFormulaEditRecord{
@@ -126,6 +129,7 @@ func (s *StoreEntry) addFeedFormulaDetailAddRecode(ctx context.Context, req *ope
 			PastureName:   "集团",
 			ForageName:    v.ForageName,
 			Status:        operationPb.FeedFormulaEditRecordType_INSERT,
+			GroupId:       editRecord.GroupId + 1,
 		})
 	}
 
@@ -148,7 +152,8 @@ func (s *StoreEntry) EditFeedByFeedFormula(ctx context.Context, req *operationPb
 	}
 	// 添加修改记录
 	defer s.editFeedFormulaDetailAddRecode(ctx, req, feedFormulaDetail)
-
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
 	// 更新数据
 	updateData := &model.FeedFormulaDetail{
 		ForageId:        int64(req.ForageId),
@@ -247,7 +252,8 @@ func (s *StoreEntry) FeedFormulaDetailBySort(ctx context.Context, req *operation
 	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
 		return xerr.WithStack(err)
 	}
-
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
 	tx := s.DB.Transaction(func(tx *gorm.DB) error {
 		for _, v := range req.List {
 			if err := tx.Model(new(model.FeedFormulaDetail)).
@@ -269,6 +275,9 @@ func (s *StoreEntry) FeedFormulaDetailIsModify(ctx context.Context, req *operati
 	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
 		return xerr.WithStack(err)
 	}
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
+
 	return s.DB.Model(new(model.FeedFormulaDetail)).
 		Where("id = ?", req.Id).
 		Where("feed_formula_id = ?", req.FeedFormulaId).
@@ -382,30 +391,17 @@ func (s *StoreEntry) MixedFeedFormula(ctx context.Context, req *operationPb.Mixe
 	}
 
 	tr := s.DB.Transaction(func(tx *gorm.DB) error {
-		feedFormulaData := &model.FeedFormula{
-			Name:               req.Name,
-			Colour:             req.Colour,
-			EncodeNumber:       s.EncodeNumber(ctx),
-			CattleCategoryId:   operationPb.CattleCategoryParent_Kind(req.CattleCategoryId),
-			CattleCategoryName: req.CattleCategoryName,
-			FormulaTypeId:      req.FormulaTypeId,
-			FormulaTypeName:    req.FormulaTypeName,
-			DataSourceId:       operationPb.DataSource_Kind(req.DataSourceId),
-			DataSourceName:     operationPb.DataSource_Kind_name[req.DataSourceId],
-			Remarks:            req.Remarks,
-			PastureName:        "集团",
-			IsShow:             operationPb.IsShow_OK,
-			IsModify:           operationPb.IsShow_OK,
-			IsDelete:           operationPb.IsShow_OK,
-		}
-		if err := s.DB.Model(new(model.FeedFormula)).Create(feedFormulaData).Error; err != nil {
+		newFeedFormulaData := model.NewNewFeedFormulaByMixed(req)
+		newFeedFormulaData.EncodeNumber = s.EncodeNumber(ctx)
+
+		if err := s.DB.Model(new(model.FeedFormula)).Create(newFeedFormulaData).Error; err != nil {
 			return xerr.WithStack(err)
 		}
 		feedFormulaDetailList := make([]*model.FeedFormulaDetail, 0)
 		for _, v := range req.FeedList {
 			feedFormulaDetailList = append(feedFormulaDetailList, &model.FeedFormulaDetail{
 				PastureName:     "集团",
-				FeedFormulaId:   feedFormulaData.Id,
+				FeedFormulaId:   newFeedFormulaData.Id,
 				ForageId:        int64(v.ForageId),
 				ForageName:      v.ForageName,
 				ForageGroupName: v.ForageGroupName,
@@ -1034,3 +1030,80 @@ func (s *StoreEntry) SearchFeedFormalDetailById(ctx context.Context, feedFormula
 	}
 	return res, nil
 }
+
+// UpdateFeedFormalVersion 更新版本库并通知牧场端
+func (s *StoreEntry) UpdateFeedFormalVersion(ctx context.Context, req *model.FeedFormula) {
+	if err := s.DB.Model(req).UpdateColumn("version", gorm.Expr("version + ?", 1)).Error; err != nil {
+		zaplog.Error("UpdateFeedFormalVersion-UpdateColumn", zap.Any("err", err))
+	}
+
+	// 获取该配方下发记录表
+	feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
+	if err := s.DB.Table(new(model.FeedFormulaDistributeLog).TableName()).
+		Where("feed_formula_id = ?", req.Id).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		Group("pasture_id").
+		Find(&feedFormulaDistributeLogList).Debug().Error; err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			zaplog.Error("UpdateFeedFormalVersion-feedFormulaDistributeLog", zap.Any("err", err))
+		}
+		return
+	}
+	if len(feedFormulaDistributeLogList) > 0 {
+		wg := sync.WaitGroup{}
+		wg.Add(len(feedFormulaDistributeLogList))
+		for _, v := range feedFormulaDistributeLogList {
+			go func(feedFormulaDistributeLog *model.FeedFormulaDistributeLog) {
+				defer wg.Done()
+				// 更新牧场端配方版本
+				s.UpdatePastureFeedDetailVersionLog(ctx, feedFormulaDistributeLog, req)
+			}(v)
+		}
+		wg.Wait()
+	}
+}
+
+func (s *StoreEntry) UpdatePastureFeedDetailVersionLog(ctx context.Context, distributeLog *model.FeedFormulaDistributeLog, req *model.FeedFormula) {
+	pastureId := distributeLog.PastureId
+	groupPasture, err := s.GetGroupPastureById(ctx, pastureId)
+	if err != nil {
+		zaplog.Error("UpdateFeedFormalVersion", zap.Any("GetGroupPastureById", pastureId), zap.Any("err", err))
+		return
+	}
+	if groupPasture.IsDistribution != operationPb.IsShow_OK {
+		return
+	}
+	var (
+		belong         int32 = 1
+		feedTemplateId       = req.Id
+	)
+
+	if req.PastureDataId > 0 {
+		belong = 2
+		feedTemplateId = req.PastureDataId
+	}
+
+	response := &model.FeedFormulaUpdateVersionResponse{}
+	body := &model.FeedFormulaUpdateVersionRequest{
+		FeedTemplateId: feedTemplateId,
+		Version:        req.Version,
+		Belong:         belong,
+	}
+
+	zaplog.Info("UpdateFeedFormalVersion", zap.Any("body", body))
+	if _, err = s.PastureHttpClient(ctx, model.FeedFormulaVersionUpdateUrl, pastureId, body, response); err != nil {
+		zaplog.Error("UpdateFeedFormalVersion-http",
+			zap.String("url", model.FeedFormulaVersionUpdateUrl),
+			zap.Any("pasture", groupPasture), zap.Any("body", body),
+			zap.Any("err", err), zap.Any("response", response))
+		return
+	}
+
+	if response.Code != http.StatusOK {
+		zaplog.Error("UpdateFeedFormalVersion-response",
+			zap.String("url", model.DashboardExecTimeUrl),
+			zap.Any("pasture", groupPasture), zap.Any("body", body),
+			zap.Any("err", err), zap.Any("response", response))
+		return
+	}
+}

+ 5 - 0
module/backend/interface.go

@@ -50,6 +50,7 @@ type KptService interface {
 	PastureSyncService // 牧场端数据同步
 }
 
+//go:generate mockgen -destination mock/PastureService.go -package kptservicemock kpt-tmr-group/module/backend PastureService
 type PastureService interface {
 	// CreateGroupPasture 牧场管理相关
 	CreateGroupPasture(ctx context.Context, req *operationPb.AddPastureRequest) error
@@ -110,6 +111,7 @@ type PastureService interface {
 	FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error)
 }
 
+//go:generate mockgen -destination mock/SystemService.go -package kptservicemock kpt-tmr-group/module/backend SystemService
 type SystemService interface {
 	// Auth 系统用户相关
 	Auth(ctx context.Context, auth *operationPb.UserAuthData) (*operationPb.SystemToken, error)
@@ -142,6 +144,7 @@ type SystemService interface {
 	SearchMobileList(ctx context.Context, req *operationPb.SearchMobileRequest) (*operationPb.SearchMobileResponse, error)
 }
 
+//go:generate mockgen -destination mock/StatisticService.go -package kptservicemock kpt-tmr-group/module/backend StatisticService
 type StatisticService interface {
 	SearchFormulaEstimateList(ctx context.Context, req *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error)
 	SearchInventoryStatistics(ctx context.Context, req *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error)
@@ -169,10 +172,12 @@ type StatisticService interface {
 	FeedMixedAndTmrName(ctx context.Context, req *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error)
 }
 
+//go:generate mockgen -destination mock/WxAppletService.go -package kptservicemock kpt-tmr-group/module/backend WxAppletService
 type WxAppletService interface {
 	GetOpenId(ctx context.Context, jsCode string) (*operationPb.WxOpenId, error)
 }
 
+//go:generate mockgen -destination mock/PastureSyncService.go -package kptservicemock kpt-tmr-group/module/backend PastureSyncService
 type PastureSyncService interface {
 	CategorySyncData(ctx context.Context, req *operationPb.CategorySyncRequest) error
 	CategoryDeleteData(ctx context.Context, req *operationPb.CategoryDeleteRequest) error

+ 725 - 0
module/backend/mock/PastureService.go

@@ -0,0 +1,725 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: PastureService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	bytes "bytes"
+	context "context"
+	io "io"
+	model "kpt-tmr-group/model"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockPastureService is a mock of PastureService interface.
+type MockPastureService struct {
+	ctrl     *gomock.Controller
+	recorder *MockPastureServiceMockRecorder
+}
+
+// MockPastureServiceMockRecorder is the mock recorder for MockPastureService.
+type MockPastureServiceMockRecorder struct {
+	mock *MockPastureService
+}
+
+// NewMockPastureService creates a new mock instance.
+func NewMockPastureService(ctrl *gomock.Controller) *MockPastureService {
+	mock := &MockPastureService{ctrl: ctrl}
+	mock.recorder = &MockPastureServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockPastureService) EXPECT() *MockPastureServiceMockRecorder {
+	return m.recorder
+}
+
+// AddCattleCategory mocks base method.
+func (m *MockPastureService) AddCattleCategory(arg0 context.Context, arg1 *operationPb.AddCattleCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddCattleCategory indicates an expected call of AddCattleCategory.
+func (mr *MockPastureServiceMockRecorder) AddCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddCattleCategory", reflect.TypeOf((*MockPastureService)(nil).AddCattleCategory), arg0, arg1)
+}
+
+// AddFeedByFeedFormula mocks base method.
+func (m *MockPastureService) AddFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddFeedByFeedFormula indicates an expected call of AddFeedByFeedFormula.
+func (mr *MockPastureServiceMockRecorder) AddFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFeedByFeedFormula", reflect.TypeOf((*MockPastureService)(nil).AddFeedByFeedFormula), arg0, arg1)
+}
+
+// AddForageCategory mocks base method.
+func (m *MockPastureService) AddForageCategory(arg0 context.Context, arg1 *operationPb.AddForageCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddForageCategory indicates an expected call of AddForageCategory.
+func (mr *MockPastureServiceMockRecorder) AddForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddForageCategory", reflect.TypeOf((*MockPastureService)(nil).AddForageCategory), arg0, arg1)
+}
+
+// CancelDistributeFeedFormula mocks base method.
+func (m *MockPastureService) CancelDistributeFeedFormula(arg0 context.Context, arg1 *operationPb.DistributeFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CancelDistributeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CancelDistributeFeedFormula indicates an expected call of CancelDistributeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) CancelDistributeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelDistributeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).CancelDistributeFeedFormula), arg0, arg1)
+}
+
+// CreateFeedFormula mocks base method.
+func (m *MockPastureService) CreateFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateFeedFormula indicates an expected call of CreateFeedFormula.
+func (mr *MockPastureServiceMockRecorder) CreateFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFeedFormula", reflect.TypeOf((*MockPastureService)(nil).CreateFeedFormula), arg0, arg1)
+}
+
+// CreateForage mocks base method.
+func (m *MockPastureService) CreateForage(arg0 context.Context, arg1 *operationPb.AddForageRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateForage indicates an expected call of CreateForage.
+func (mr *MockPastureServiceMockRecorder) CreateForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateForage", reflect.TypeOf((*MockPastureService)(nil).CreateForage), arg0, arg1)
+}
+
+// CreateGroupPasture mocks base method.
+func (m *MockPastureService) CreateGroupPasture(arg0 context.Context, arg1 *operationPb.AddPastureRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateGroupPasture indicates an expected call of CreateGroupPasture.
+func (mr *MockPastureServiceMockRecorder) CreateGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGroupPasture", reflect.TypeOf((*MockPastureService)(nil).CreateGroupPasture), arg0, arg1)
+}
+
+// DeleteCattleCategory mocks base method.
+func (m *MockPastureService) DeleteCattleCategory(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteCattleCategory indicates an expected call of DeleteCattleCategory.
+func (mr *MockPastureServiceMockRecorder) DeleteCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCattleCategory", reflect.TypeOf((*MockPastureService)(nil).DeleteCattleCategory), arg0, arg1)
+}
+
+// DeleteFeedFormula mocks base method.
+func (m *MockPastureService) DeleteFeedFormula(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteFeedFormula indicates an expected call of DeleteFeedFormula.
+func (mr *MockPastureServiceMockRecorder) DeleteFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormula", reflect.TypeOf((*MockPastureService)(nil).DeleteFeedFormula), arg0, arg1)
+}
+
+// DeleteFeedFormulaDetail mocks base method.
+func (m *MockPastureService) DeleteFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteFeedFormulaDetail indicates an expected call of DeleteFeedFormulaDetail.
+func (mr *MockPastureServiceMockRecorder) DeleteFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormulaDetail", reflect.TypeOf((*MockPastureService)(nil).DeleteFeedFormulaDetail), arg0, arg1)
+}
+
+// DeleteForageCategory mocks base method.
+func (m *MockPastureService) DeleteForageCategory(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteForageCategory indicates an expected call of DeleteForageCategory.
+func (mr *MockPastureServiceMockRecorder) DeleteForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteForageCategory", reflect.TypeOf((*MockPastureService)(nil).DeleteForageCategory), arg0, arg1)
+}
+
+// DeleteForageList mocks base method.
+func (m *MockPastureService) DeleteForageList(arg0 context.Context, arg1 []int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteForageList", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteForageList indicates an expected call of DeleteForageList.
+func (mr *MockPastureServiceMockRecorder) DeleteForageList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteForageList", reflect.TypeOf((*MockPastureService)(nil).DeleteForageList), arg0, arg1)
+}
+
+// DeleteGroupPasture mocks base method.
+func (m *MockPastureService) DeleteGroupPasture(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteGroupPasture indicates an expected call of DeleteGroupPasture.
+func (mr *MockPastureServiceMockRecorder) DeleteGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteGroupPasture", reflect.TypeOf((*MockPastureService)(nil).DeleteGroupPasture), arg0, arg1)
+}
+
+// DistributeFeedFormula mocks base method.
+func (m *MockPastureService) DistributeFeedFormula(arg0 context.Context, arg1 *operationPb.DistributeFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DistributeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DistributeFeedFormula indicates an expected call of DistributeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) DistributeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DistributeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).DistributeFeedFormula), arg0, arg1)
+}
+
+// EditCattleCategory mocks base method.
+func (m *MockPastureService) EditCattleCategory(arg0 context.Context, arg1 *operationPb.AddCattleCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditCattleCategory indicates an expected call of EditCattleCategory.
+func (mr *MockPastureServiceMockRecorder) EditCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditCattleCategory", reflect.TypeOf((*MockPastureService)(nil).EditCattleCategory), arg0, arg1)
+}
+
+// EditFeedByFeedFormula mocks base method.
+func (m *MockPastureService) EditFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditFeedByFeedFormula indicates an expected call of EditFeedByFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditFeedByFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditFeedByFeedFormula), arg0, arg1)
+}
+
+// EditFeedFormula mocks base method.
+func (m *MockPastureService) EditFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditFeedFormula indicates an expected call of EditFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditFeedFormula), arg0, arg1)
+}
+
+// EditForage mocks base method.
+func (m *MockPastureService) EditForage(arg0 context.Context, arg1 *operationPb.AddForageRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditForage indicates an expected call of EditForage.
+func (mr *MockPastureServiceMockRecorder) EditForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditForage", reflect.TypeOf((*MockPastureService)(nil).EditForage), arg0, arg1)
+}
+
+// EditForageCategory mocks base method.
+func (m *MockPastureService) EditForageCategory(arg0 context.Context, arg1 *operationPb.AddForageCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditForageCategory indicates an expected call of EditForageCategory.
+func (mr *MockPastureServiceMockRecorder) EditForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditForageCategory", reflect.TypeOf((*MockPastureService)(nil).EditForageCategory), arg0, arg1)
+}
+
+// EditGroupPasture mocks base method.
+func (m *MockPastureService) EditGroupPasture(arg0 context.Context, arg1 *operationPb.AddPastureRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditGroupPasture indicates an expected call of EditGroupPasture.
+func (mr *MockPastureServiceMockRecorder) EditGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditGroupPasture", reflect.TypeOf((*MockPastureService)(nil).EditGroupPasture), arg0, arg1)
+}
+
+// EditRecodeFeedFormula mocks base method.
+func (m *MockPastureService) EditRecodeFeedFormula(arg0 context.Context, arg1 *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditRecodeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.EditRecodeFeedFormulaResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// EditRecodeFeedFormula indicates an expected call of EditRecodeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditRecodeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditRecodeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditRecodeFeedFormula), arg0, arg1)
+}
+
+// EncodeNumber mocks base method.
+func (m *MockPastureService) EncodeNumber(arg0 context.Context) string {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EncodeNumber", arg0)
+	ret0, _ := ret[0].(string)
+	return ret0
+}
+
+// EncodeNumber indicates an expected call of EncodeNumber.
+func (mr *MockPastureServiceMockRecorder) EncodeNumber(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncodeNumber", reflect.TypeOf((*MockPastureService)(nil).EncodeNumber), arg0)
+}
+
+// ExcelExportFeedFormula mocks base method.
+func (m *MockPastureService) ExcelExportFeedFormula(arg0 context.Context, arg1 *operationPb.SearchFeedFormulaRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelExportFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelExportFeedFormula indicates an expected call of ExcelExportFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelExportFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelExportFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelExportFeedFormula), arg0, arg1)
+}
+
+// ExcelExportForage mocks base method.
+func (m *MockPastureService) ExcelExportForage(arg0 context.Context, arg1 *operationPb.SearchForageListRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelExportForage", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelExportForage indicates an expected call of ExcelExportForage.
+func (mr *MockPastureServiceMockRecorder) ExcelExportForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelExportForage", reflect.TypeOf((*MockPastureService)(nil).ExcelExportForage), arg0, arg1)
+}
+
+// ExcelImportFeedFormula mocks base method.
+func (m *MockPastureService) ExcelImportFeedFormula(arg0 context.Context, arg1 io.Reader) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelImportFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ExcelImportFeedFormula indicates an expected call of ExcelImportFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelImportFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelImportFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelImportFeedFormula), arg0, arg1)
+}
+
+// ExcelImportForage mocks base method.
+func (m *MockPastureService) ExcelImportForage(arg0 context.Context, arg1 io.Reader) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelImportForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ExcelImportForage indicates an expected call of ExcelImportForage.
+func (mr *MockPastureServiceMockRecorder) ExcelImportForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelImportForage", reflect.TypeOf((*MockPastureService)(nil).ExcelImportForage), arg0, arg1)
+}
+
+// ExcelTemplateFeedFormula mocks base method.
+func (m *MockPastureService) ExcelTemplateFeedFormula(arg0 context.Context) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelTemplateFeedFormula", arg0)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelTemplateFeedFormula indicates an expected call of ExcelTemplateFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelTemplateFeedFormula(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelTemplateFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelTemplateFeedFormula), arg0)
+}
+
+// ExcelTemplateForage mocks base method.
+func (m *MockPastureService) ExcelTemplateForage(arg0 context.Context) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelTemplateForage", arg0)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelTemplateForage indicates an expected call of ExcelTemplateForage.
+func (mr *MockPastureServiceMockRecorder) ExcelTemplateForage(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelTemplateForage", reflect.TypeOf((*MockPastureService)(nil).ExcelTemplateForage), arg0)
+}
+
+// FeedFormulaDetailBySort mocks base method.
+func (m *MockPastureService) FeedFormulaDetailBySort(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailBySort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailBySort indicates an expected call of FeedFormulaDetailBySort.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailBySort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailBySort", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailBySort), arg0, arg1)
+}
+
+// FeedFormulaDetailIsModify mocks base method.
+func (m *MockPastureService) FeedFormulaDetailIsModify(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailIsModify", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailIsModify indicates an expected call of FeedFormulaDetailIsModify.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailIsModify(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailIsModify", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailIsModify), arg0, arg1)
+}
+
+// FeedFormulaDetailList mocks base method.
+func (m *MockPastureService) FeedFormulaDetailList(arg0 context.Context, arg1 *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaDetailList indicates an expected call of FeedFormulaDetailList.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailList", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailList), arg0, arg1)
+}
+
+// FeedFormulaUsage mocks base method.
+func (m *MockPastureService) FeedFormulaUsage(arg0 context.Context, arg1 *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaUsage", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaUsageResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaUsage indicates an expected call of FeedFormulaUsage.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaUsage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaUsage", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaUsage), arg0, arg1)
+}
+
+// ForageEnumList mocks base method.
+func (m *MockPastureService) ForageEnumList(arg0 context.Context) *operationPb.ForageEnumListResponse {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ForageEnumList", arg0)
+	ret0, _ := ret[0].(*operationPb.ForageEnumListResponse)
+	return ret0
+}
+
+// ForageEnumList indicates an expected call of ForageEnumList.
+func (mr *MockPastureServiceMockRecorder) ForageEnumList(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageEnumList", reflect.TypeOf((*MockPastureService)(nil).ForageEnumList), arg0)
+}
+
+// ForageListSort mocks base method.
+func (m *MockPastureService) ForageListSort(arg0 context.Context, arg1 *operationPb.ForageListSortRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ForageListSort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ForageListSort indicates an expected call of ForageListSort.
+func (mr *MockPastureServiceMockRecorder) ForageListSort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageListSort", reflect.TypeOf((*MockPastureService)(nil).ForageListSort), arg0, arg1)
+}
+
+// IsShowCattleCategory mocks base method.
+func (m *MockPastureService) IsShowCattleCategory(arg0 context.Context, arg1 *operationPb.IsShowCattleCategory) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowCattleCategory indicates an expected call of IsShowCattleCategory.
+func (mr *MockPastureServiceMockRecorder) IsShowCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowCattleCategory", reflect.TypeOf((*MockPastureService)(nil).IsShowCattleCategory), arg0, arg1)
+}
+
+// IsShowFeedFormula mocks base method.
+func (m *MockPastureService) IsShowFeedFormula(arg0 context.Context, arg1 *operationPb.IsShowModifyFeedFormula) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowFeedFormula indicates an expected call of IsShowFeedFormula.
+func (mr *MockPastureServiceMockRecorder) IsShowFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowFeedFormula", reflect.TypeOf((*MockPastureService)(nil).IsShowFeedFormula), arg0, arg1)
+}
+
+// IsShowForage mocks base method.
+func (m *MockPastureService) IsShowForage(arg0 context.Context, arg1 *operationPb.IsShowForage) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowForage indicates an expected call of IsShowForage.
+func (mr *MockPastureServiceMockRecorder) IsShowForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowForage", reflect.TypeOf((*MockPastureService)(nil).IsShowForage), arg0, arg1)
+}
+
+// IsShowForageCategory mocks base method.
+func (m *MockPastureService) IsShowForageCategory(arg0 context.Context, arg1 *operationPb.IsShowForageCategory) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowForageCategory indicates an expected call of IsShowForageCategory.
+func (mr *MockPastureServiceMockRecorder) IsShowForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowForageCategory", reflect.TypeOf((*MockPastureService)(nil).IsShowForageCategory), arg0, arg1)
+}
+
+// IsShowGroupPasture mocks base method.
+func (m *MockPastureService) IsShowGroupPasture(arg0 context.Context, arg1 *operationPb.IsShowGroupPasture) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowGroupPasture indicates an expected call of IsShowGroupPasture.
+func (mr *MockPastureServiceMockRecorder) IsShowGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowGroupPasture", reflect.TypeOf((*MockPastureService)(nil).IsShowGroupPasture), arg0, arg1)
+}
+
+// MixedFeedFormula mocks base method.
+func (m *MockPastureService) MixedFeedFormula(arg0 context.Context, arg1 *operationPb.MixedFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MixedFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MixedFeedFormula indicates an expected call of MixedFeedFormula.
+func (mr *MockPastureServiceMockRecorder) MixedFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MixedFeedFormula", reflect.TypeOf((*MockPastureService)(nil).MixedFeedFormula), arg0, arg1)
+}
+
+// ResetPasswordGroupPasture mocks base method.
+func (m *MockPastureService) ResetPasswordGroupPasture(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ResetPasswordGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ResetPasswordGroupPasture indicates an expected call of ResetPasswordGroupPasture.
+func (mr *MockPastureServiceMockRecorder) ResetPasswordGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPasswordGroupPasture", reflect.TypeOf((*MockPastureService)(nil).ResetPasswordGroupPasture), arg0, arg1)
+}
+
+// SearchCattleCategoryList mocks base method.
+func (m *MockPastureService) SearchCattleCategoryList(arg0 context.Context, arg1 *operationPb.SearchCattleCategoryRequest) (*operationPb.SearchCattleCategoryResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchCattleCategoryList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchCattleCategoryResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchCattleCategoryList indicates an expected call of SearchCattleCategoryList.
+func (mr *MockPastureServiceMockRecorder) SearchCattleCategoryList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchCattleCategoryList", reflect.TypeOf((*MockPastureService)(nil).SearchCattleCategoryList), arg0, arg1)
+}
+
+// SearchFeedFormulaDetail mocks base method.
+func (m *MockPastureService) SearchFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedFormulaDetail indicates an expected call of SearchFeedFormulaDetail.
+func (mr *MockPastureServiceMockRecorder) SearchFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedFormulaDetail", reflect.TypeOf((*MockPastureService)(nil).SearchFeedFormulaDetail), arg0, arg1)
+}
+
+// SearchFeedFormulaList mocks base method.
+func (m *MockPastureService) SearchFeedFormulaList(arg0 context.Context, arg1 *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedFormulaList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchFeedFormulaListResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedFormulaList indicates an expected call of SearchFeedFormulaList.
+func (mr *MockPastureServiceMockRecorder) SearchFeedFormulaList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedFormulaList", reflect.TypeOf((*MockPastureService)(nil).SearchFeedFormulaList), arg0, arg1)
+}
+
+// SearchForageCategoryList mocks base method.
+func (m *MockPastureService) SearchForageCategoryList(arg0 context.Context, arg1 *operationPb.SearchForageCategoryRequest) (*operationPb.SearchForageCategoryResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchForageCategoryList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchForageCategoryResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchForageCategoryList indicates an expected call of SearchForageCategoryList.
+func (mr *MockPastureServiceMockRecorder) SearchForageCategoryList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchForageCategoryList", reflect.TypeOf((*MockPastureService)(nil).SearchForageCategoryList), arg0, arg1)
+}
+
+// SearchForageList mocks base method.
+func (m *MockPastureService) SearchForageList(arg0 context.Context, arg1 *operationPb.SearchForageListRequest) (*operationPb.SearchForageListResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchForageList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchForageListResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchForageList indicates an expected call of SearchForageList.
+func (mr *MockPastureServiceMockRecorder) SearchForageList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchForageList", reflect.TypeOf((*MockPastureService)(nil).SearchForageList), arg0, arg1)
+}
+
+// SearchGroupPastureList mocks base method.
+func (m *MockPastureService) SearchGroupPastureList(arg0 context.Context, arg1 *operationPb.SearchPastureRequest) (*operationPb.SearchPastureResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchGroupPastureList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchPastureResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchGroupPastureList indicates an expected call of SearchGroupPastureList.
+func (mr *MockPastureServiceMockRecorder) SearchGroupPastureList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchGroupPastureList", reflect.TypeOf((*MockPastureService)(nil).SearchGroupPastureList), arg0, arg1)
+}
+
+// SmallMaterial mocks base method.
+func (m *MockPastureService) SmallMaterial(arg0 context.Context, arg1 *operationPb.SmallMaterialRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SmallMaterial", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SmallMaterial indicates an expected call of SmallMaterial.
+func (mr *MockPastureServiceMockRecorder) SmallMaterial(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SmallMaterial", reflect.TypeOf((*MockPastureService)(nil).SmallMaterial), arg0, arg1)
+}

+ 106 - 0
module/backend/mock/PastureSyncService.go

@@ -0,0 +1,106 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: PastureSyncService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockPastureSyncService is a mock of PastureSyncService interface.
+type MockPastureSyncService struct {
+	ctrl     *gomock.Controller
+	recorder *MockPastureSyncServiceMockRecorder
+}
+
+// MockPastureSyncServiceMockRecorder is the mock recorder for MockPastureSyncService.
+type MockPastureSyncServiceMockRecorder struct {
+	mock *MockPastureSyncService
+}
+
+// NewMockPastureSyncService creates a new mock instance.
+func NewMockPastureSyncService(ctrl *gomock.Controller) *MockPastureSyncService {
+	mock := &MockPastureSyncService{ctrl: ctrl}
+	mock.recorder = &MockPastureSyncServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockPastureSyncService) EXPECT() *MockPastureSyncServiceMockRecorder {
+	return m.recorder
+}
+
+// CategoryDeleteData mocks base method.
+func (m *MockPastureSyncService) CategoryDeleteData(arg0 context.Context, arg1 *operationPb.CategoryDeleteRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategoryDeleteData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategoryDeleteData indicates an expected call of CategoryDeleteData.
+func (mr *MockPastureSyncServiceMockRecorder) CategoryDeleteData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategoryDeleteData", reflect.TypeOf((*MockPastureSyncService)(nil).CategoryDeleteData), arg0, arg1)
+}
+
+// CategorySyncData mocks base method.
+func (m *MockPastureSyncService) CategorySyncData(arg0 context.Context, arg1 *operationPb.CategorySyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategorySyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategorySyncData indicates an expected call of CategorySyncData.
+func (mr *MockPastureSyncServiceMockRecorder) CategorySyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategorySyncData", reflect.TypeOf((*MockPastureSyncService)(nil).CategorySyncData), arg0, arg1)
+}
+
+// FeedFormulaDetailListSyncData mocks base method.
+func (m *MockPastureSyncService) FeedFormulaDetailListSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailListSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailListSyncData indicates an expected call of FeedFormulaDetailListSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedFormulaDetailListSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailListSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedFormulaDetailListSyncData), arg0, arg1)
+}
+
+// FeedFormulaSyncData mocks base method.
+func (m *MockPastureSyncService) FeedFormulaSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaSyncData indicates an expected call of FeedFormulaSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedFormulaSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedFormulaSyncData), arg0, arg1)
+}
+
+// FeedSyncData mocks base method.
+func (m *MockPastureSyncService) FeedSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedSyncData indicates an expected call of FeedSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedSyncData), arg0, arg1)
+}

+ 353 - 0
module/backend/mock/StatisticService.go

@@ -0,0 +1,353 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: StatisticService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	bytes "bytes"
+	context "context"
+	model "kpt-tmr-group/model"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockStatisticService is a mock of StatisticService interface.
+type MockStatisticService struct {
+	ctrl     *gomock.Controller
+	recorder *MockStatisticServiceMockRecorder
+}
+
+// MockStatisticServiceMockRecorder is the mock recorder for MockStatisticService.
+type MockStatisticServiceMockRecorder struct {
+	mock *MockStatisticService
+}
+
+// NewMockStatisticService creates a new mock instance.
+func NewMockStatisticService(ctrl *gomock.Controller) *MockStatisticService {
+	mock := &MockStatisticService{ctrl: ctrl}
+	mock.recorder = &MockStatisticServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockStatisticService) EXPECT() *MockStatisticServiceMockRecorder {
+	return m.recorder
+}
+
+// AnalysisMixedSprinkleDetail mocks base method.
+func (m *MockStatisticService) AnalysisMixedSprinkleDetail(arg0 context.Context, arg1 *operationPb.ProcessMixedSprinkleDetailRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AnalysisMixedSprinkleDetail", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// AnalysisMixedSprinkleDetail indicates an expected call of AnalysisMixedSprinkleDetail.
+func (mr *MockStatisticServiceMockRecorder) AnalysisMixedSprinkleDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnalysisMixedSprinkleDetail", reflect.TypeOf((*MockStatisticService)(nil).AnalysisMixedSprinkleDetail), arg0, arg1)
+}
+
+// CowsAnalysis mocks base method.
+func (m *MockStatisticService) CowsAnalysis(arg0 context.Context, arg1 *operationPb.CowsAnalysisRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CowsAnalysis", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// CowsAnalysis indicates an expected call of CowsAnalysis.
+func (mr *MockStatisticServiceMockRecorder) CowsAnalysis(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CowsAnalysis", reflect.TypeOf((*MockStatisticService)(nil).CowsAnalysis), arg0, arg1)
+}
+
+// ExecutionTime mocks base method.
+func (m *MockStatisticService) ExecutionTime(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExecutionTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.ExecTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExecutionTime indicates an expected call of ExecutionTime.
+func (mr *MockStatisticServiceMockRecorder) ExecutionTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecutionTime", reflect.TypeOf((*MockStatisticService)(nil).ExecutionTime), arg0, arg1)
+}
+
+// FeedChartStatistics mocks base method.
+func (m *MockStatisticService) FeedChartStatistics(arg0 context.Context, arg1 *operationPb.FeedChartStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedChartStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedChartStatistics indicates an expected call of FeedChartStatistics.
+func (mr *MockStatisticServiceMockRecorder) FeedChartStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedChartStatistics", reflect.TypeOf((*MockStatisticService)(nil).FeedChartStatistics), arg0, arg1)
+}
+
+// FeedMixedAndTmrName mocks base method.
+func (m *MockStatisticService) FeedMixedAndTmrName(arg0 context.Context, arg1 *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedMixedAndTmrName", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedMixedAndTmrName indicates an expected call of FeedMixedAndTmrName.
+func (mr *MockStatisticServiceMockRecorder) FeedMixedAndTmrName(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedMixedAndTmrName", reflect.TypeOf((*MockStatisticService)(nil).FeedMixedAndTmrName), arg0, arg1)
+}
+
+// GetDataByName mocks base method.
+func (m *MockStatisticService) GetDataByName(arg0 context.Context, arg1 *operationPb.GetDataByNameRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetDataByName", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetDataByName indicates an expected call of GetDataByName.
+func (mr *MockStatisticServiceMockRecorder) GetDataByName(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDataByName", reflect.TypeOf((*MockStatisticService)(nil).GetDataByName), arg0, arg1)
+}
+
+// GetTrainNumber mocks base method.
+func (m *MockStatisticService) GetTrainNumber(arg0 context.Context, arg1 *operationPb.TrainNumberRequest) (*operationPb.TrainNumberResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetTrainNumber", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.TrainNumberResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetTrainNumber indicates an expected call of GetTrainNumber.
+func (mr *MockStatisticServiceMockRecorder) GetTrainNumber(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTrainNumber", reflect.TypeOf((*MockStatisticService)(nil).GetTrainNumber), arg0, arg1)
+}
+
+// InventoryStatisticsExcelExport mocks base method.
+func (m *MockStatisticService) InventoryStatisticsExcelExport(arg0 context.Context, arg1 *operationPb.SearchInventoryStatisticsRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "InventoryStatisticsExcelExport", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// InventoryStatisticsExcelExport indicates an expected call of InventoryStatisticsExcelExport.
+func (mr *MockStatisticServiceMockRecorder) InventoryStatisticsExcelExport(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InventoryStatisticsExcelExport", reflect.TypeOf((*MockStatisticService)(nil).InventoryStatisticsExcelExport), arg0, arg1)
+}
+
+// SearchAccuracyAggStatistics mocks base method.
+func (m *MockStatisticService) SearchAccuracyAggStatistics(arg0 context.Context, arg1 *operationPb.AccuracyAggStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchAccuracyAggStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchAccuracyAggStatistics indicates an expected call of SearchAccuracyAggStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchAccuracyAggStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchAccuracyAggStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchAccuracyAggStatistics), arg0, arg1)
+}
+
+// SearchAnalysisAccuracy mocks base method.
+func (m *MockStatisticService) SearchAnalysisAccuracy(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchAnalysisAccuracy", arg0, arg1)
+	ret0, _ := ret[0].(*model.SearchAnalysisAccuracyResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchAnalysisAccuracy indicates an expected call of SearchAnalysisAccuracy.
+func (mr *MockStatisticServiceMockRecorder) SearchAnalysisAccuracy(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchAnalysisAccuracy", reflect.TypeOf((*MockStatisticService)(nil).SearchAnalysisAccuracy), arg0, arg1)
+}
+
+// SearchFeedStatistics mocks base method.
+func (m *MockStatisticService) SearchFeedStatistics(arg0 context.Context, arg1 *operationPb.SearchFeedStatisticsRequest) (*model.FeedStatisticsResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.FeedStatisticsResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedStatistics indicates an expected call of SearchFeedStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchFeedStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchFeedStatistics), arg0, arg1)
+}
+
+// SearchFormulaEstimateList mocks base method.
+func (m *MockStatisticService) SearchFormulaEstimateList(arg0 context.Context, arg1 *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFormulaEstimateList", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFormulaEstimateList indicates an expected call of SearchFormulaEstimateList.
+func (mr *MockStatisticServiceMockRecorder) SearchFormulaEstimateList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFormulaEstimateList", reflect.TypeOf((*MockStatisticService)(nil).SearchFormulaEstimateList), arg0, arg1)
+}
+
+// SearchInventoryStatistics mocks base method.
+func (m *MockStatisticService) SearchInventoryStatistics(arg0 context.Context, arg1 *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchInventoryStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchInventoryStatistics indicates an expected call of SearchInventoryStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchInventoryStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchInventoryStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchInventoryStatistics), arg0, arg1)
+}
+
+// SearchMixFeedStatistics mocks base method.
+func (m *MockStatisticService) SearchMixFeedStatistics(arg0 context.Context, arg1 *operationPb.MixFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchMixFeedStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchMixFeedStatistics indicates an expected call of SearchMixFeedStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchMixFeedStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMixFeedStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchMixFeedStatistics), arg0, arg1)
+}
+
+// SearchPriceStatistics mocks base method.
+func (m *MockStatisticService) SearchPriceStatistics(arg0 context.Context, arg1 *operationPb.SearchPriceStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchPriceStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchPriceStatistics indicates an expected call of SearchPriceStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchPriceStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchPriceStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchPriceStatistics), arg0, arg1)
+}
+
+// SearchProcessAnalysis mocks base method.
+func (m *MockStatisticService) SearchProcessAnalysis(arg0 context.Context, arg1 *operationPb.ProcessAnalysisRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchProcessAnalysis", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchProcessAnalysis indicates an expected call of SearchProcessAnalysis.
+func (mr *MockStatisticServiceMockRecorder) SearchProcessAnalysis(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchProcessAnalysis", reflect.TypeOf((*MockStatisticService)(nil).SearchProcessAnalysis), arg0, arg1)
+}
+
+// SearchSprinkleStatistics mocks base method.
+func (m *MockStatisticService) SearchSprinkleStatistics(arg0 context.Context, arg1 *operationPb.SprinkleStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSprinkleStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSprinkleStatistics indicates an expected call of SearchSprinkleStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchSprinkleStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSprinkleStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchSprinkleStatistics), arg0, arg1)
+}
+
+// SearchUserMaterialsStatistics mocks base method.
+func (m *MockStatisticService) SearchUserMaterialsStatistics(arg0 context.Context, arg1 *operationPb.SearchUserMaterialsStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchUserMaterialsStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchUserMaterialsStatistics indicates an expected call of SearchUserMaterialsStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchUserMaterialsStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchUserMaterialsStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchUserMaterialsStatistics), arg0, arg1)
+}
+
+// SprinkleFeedTime mocks base method.
+func (m *MockStatisticService) SprinkleFeedTime(arg0 context.Context, arg1 *operationPb.SprinkleFeedTimeRequest) (*model.SprinkleFeedTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SprinkleFeedTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.SprinkleFeedTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SprinkleFeedTime indicates an expected call of SprinkleFeedTime.
+func (mr *MockStatisticServiceMockRecorder) SprinkleFeedTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SprinkleFeedTime", reflect.TypeOf((*MockStatisticService)(nil).SprinkleFeedTime), arg0, arg1)
+}
+
+// TopPasture mocks base method.
+func (m *MockStatisticService) TopPasture(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "TopPasture", arg0, arg1)
+	ret0, _ := ret[0].(*model.GetPastureTopResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// TopPasture indicates an expected call of TopPasture.
+func (mr *MockStatisticServiceMockRecorder) TopPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopPasture", reflect.TypeOf((*MockStatisticService)(nil).TopPasture), arg0, arg1)
+}
+
+// UserMaterialsStatisticsExcelExport mocks base method.
+func (m *MockStatisticService) UserMaterialsStatisticsExcelExport(arg0 context.Context, arg1 *operationPb.SearchUserMaterialsStatisticsRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UserMaterialsStatisticsExcelExport", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UserMaterialsStatisticsExcelExport indicates an expected call of UserMaterialsStatisticsExcelExport.
+func (mr *MockStatisticServiceMockRecorder) UserMaterialsStatisticsExcelExport(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserMaterialsStatisticsExcelExport", reflect.TypeOf((*MockStatisticService)(nil).UserMaterialsStatisticsExcelExport), arg0, arg1)
+}

+ 354 - 0
module/backend/mock/SystemService.go

@@ -0,0 +1,354 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: SystemService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockSystemService is a mock of SystemService interface.
+type MockSystemService struct {
+	ctrl     *gomock.Controller
+	recorder *MockSystemServiceMockRecorder
+}
+
+// MockSystemServiceMockRecorder is the mock recorder for MockSystemService.
+type MockSystemServiceMockRecorder struct {
+	mock *MockSystemService
+}
+
+// NewMockSystemService creates a new mock instance.
+func NewMockSystemService(ctrl *gomock.Controller) *MockSystemService {
+	mock := &MockSystemService{ctrl: ctrl}
+	mock.recorder = &MockSystemServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockSystemService) EXPECT() *MockSystemServiceMockRecorder {
+	return m.recorder
+}
+
+// Auth mocks base method.
+func (m *MockSystemService) Auth(arg0 context.Context, arg1 *operationPb.UserAuthData) (*operationPb.SystemToken, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Auth", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SystemToken)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// Auth indicates an expected call of Auth.
+func (mr *MockSystemServiceMockRecorder) Auth(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Auth", reflect.TypeOf((*MockSystemService)(nil).Auth), arg0, arg1)
+}
+
+// CreateSystemMenu mocks base method.
+func (m *MockSystemService) CreateSystemMenu(arg0 context.Context, arg1 *operationPb.AddMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemMenu indicates an expected call of CreateSystemMenu.
+func (mr *MockSystemServiceMockRecorder) CreateSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemMenu", reflect.TypeOf((*MockSystemService)(nil).CreateSystemMenu), arg0, arg1)
+}
+
+// CreateSystemRole mocks base method.
+func (m *MockSystemService) CreateSystemRole(arg0 context.Context, arg1 *operationPb.AddRoleRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemRole indicates an expected call of CreateSystemRole.
+func (mr *MockSystemServiceMockRecorder) CreateSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemRole", reflect.TypeOf((*MockSystemService)(nil).CreateSystemRole), arg0, arg1)
+}
+
+// CreateSystemUser mocks base method.
+func (m *MockSystemService) CreateSystemUser(arg0 context.Context, arg1 *operationPb.AddSystemUser) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemUser indicates an expected call of CreateSystemUser.
+func (mr *MockSystemServiceMockRecorder) CreateSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemUser", reflect.TypeOf((*MockSystemService)(nil).CreateSystemUser), arg0, arg1)
+}
+
+// DeleteSystemMenu mocks base method.
+func (m *MockSystemService) DeleteSystemMenu(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemMenu indicates an expected call of DeleteSystemMenu.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemMenu", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemMenu), arg0, arg1)
+}
+
+// DeleteSystemRole mocks base method.
+func (m *MockSystemService) DeleteSystemRole(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemRole indicates an expected call of DeleteSystemRole.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemRole", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemRole), arg0, arg1)
+}
+
+// DeleteSystemUser mocks base method.
+func (m *MockSystemService) DeleteSystemUser(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemUser indicates an expected call of DeleteSystemUser.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemUser", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemUser), arg0, arg1)
+}
+
+// DetailsSystemUser mocks base method.
+func (m *MockSystemService) DetailsSystemUser(arg0 context.Context, arg1 int64) (*operationPb.UserDetails, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DetailsSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.UserDetails)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// DetailsSystemUser indicates an expected call of DetailsSystemUser.
+func (mr *MockSystemServiceMockRecorder) DetailsSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetailsSystemUser", reflect.TypeOf((*MockSystemService)(nil).DetailsSystemUser), arg0, arg1)
+}
+
+// EditSystemMenu mocks base method.
+func (m *MockSystemService) EditSystemMenu(arg0 context.Context, arg1 *operationPb.AddMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemMenu indicates an expected call of EditSystemMenu.
+func (mr *MockSystemServiceMockRecorder) EditSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemMenu", reflect.TypeOf((*MockSystemService)(nil).EditSystemMenu), arg0, arg1)
+}
+
+// EditSystemRole mocks base method.
+func (m *MockSystemService) EditSystemRole(arg0 context.Context, arg1 *operationPb.AddRoleRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemRole indicates an expected call of EditSystemRole.
+func (mr *MockSystemServiceMockRecorder) EditSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemRole", reflect.TypeOf((*MockSystemService)(nil).EditSystemRole), arg0, arg1)
+}
+
+// EditSystemUser mocks base method.
+func (m *MockSystemService) EditSystemUser(arg0 context.Context, arg1 *operationPb.AddSystemUser) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemUser indicates an expected call of EditSystemUser.
+func (mr *MockSystemServiceMockRecorder) EditSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemUser", reflect.TypeOf((*MockSystemService)(nil).EditSystemUser), arg0, arg1)
+}
+
+// GetCurrentUserName mocks base method.
+func (m *MockSystemService) GetCurrentUserName(arg0 context.Context) (string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetCurrentUserName", arg0)
+	ret0, _ := ret[0].(string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetCurrentUserName indicates an expected call of GetCurrentUserName.
+func (mr *MockSystemServiceMockRecorder) GetCurrentUserName(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentUserName", reflect.TypeOf((*MockSystemService)(nil).GetCurrentUserName), arg0)
+}
+
+// GetRolePermissions mocks base method.
+func (m *MockSystemService) GetRolePermissions(arg0 context.Context, arg1 int64) (*operationPb.RolePermissionsList, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetRolePermissions", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.RolePermissionsList)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetRolePermissions indicates an expected call of GetRolePermissions.
+func (mr *MockSystemServiceMockRecorder) GetRolePermissions(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRolePermissions", reflect.TypeOf((*MockSystemService)(nil).GetRolePermissions), arg0, arg1)
+}
+
+// GetSystemUserPermissions mocks base method.
+func (m *MockSystemService) GetSystemUserPermissions(arg0 context.Context, arg1 string) (*operationPb.SystemUserMenuPermissions, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetSystemUserPermissions", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SystemUserMenuPermissions)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetSystemUserPermissions indicates an expected call of GetSystemUserPermissions.
+func (mr *MockSystemServiceMockRecorder) GetSystemUserPermissions(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSystemUserPermissions", reflect.TypeOf((*MockSystemService)(nil).GetSystemUserPermissions), arg0, arg1)
+}
+
+// GetUserInfo mocks base method.
+func (m *MockSystemService) GetUserInfo(arg0 context.Context, arg1 string) (*operationPb.UserAuth, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetUserInfo", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.UserAuth)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetUserInfo indicates an expected call of GetUserInfo.
+func (mr *MockSystemServiceMockRecorder) GetUserInfo(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserInfo", reflect.TypeOf((*MockSystemService)(nil).GetUserInfo), arg0, arg1)
+}
+
+// IsShowSystemMenu mocks base method.
+func (m *MockSystemService) IsShowSystemMenu(arg0 context.Context, arg1 *operationPb.IsShowSystemMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowSystemMenu indicates an expected call of IsShowSystemMenu.
+func (mr *MockSystemServiceMockRecorder) IsShowSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowSystemMenu", reflect.TypeOf((*MockSystemService)(nil).IsShowSystemMenu), arg0, arg1)
+}
+
+// IsShowSystemUser mocks base method.
+func (m *MockSystemService) IsShowSystemUser(arg0 context.Context, arg1 *operationPb.IsShowSystemUserRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowSystemUser indicates an expected call of IsShowSystemUser.
+func (mr *MockSystemServiceMockRecorder) IsShowSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowSystemUser", reflect.TypeOf((*MockSystemService)(nil).IsShowSystemUser), arg0, arg1)
+}
+
+// ResetPasswordSystemUser mocks base method.
+func (m *MockSystemService) ResetPasswordSystemUser(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ResetPasswordSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ResetPasswordSystemUser indicates an expected call of ResetPasswordSystemUser.
+func (mr *MockSystemServiceMockRecorder) ResetPasswordSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPasswordSystemUser", reflect.TypeOf((*MockSystemService)(nil).ResetPasswordSystemUser), arg0, arg1)
+}
+
+// SearchMobileList mocks base method.
+func (m *MockSystemService) SearchMobileList(arg0 context.Context, arg1 *operationPb.SearchMobileRequest) (*operationPb.SearchMobileResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchMobileList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchMobileResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchMobileList indicates an expected call of SearchMobileList.
+func (mr *MockSystemServiceMockRecorder) SearchMobileList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMobileList", reflect.TypeOf((*MockSystemService)(nil).SearchMobileList), arg0, arg1)
+}
+
+// SearchSystemMenuList mocks base method.
+func (m *MockSystemService) SearchSystemMenuList(arg0 context.Context, arg1 *operationPb.SearchMenuRequest) (*operationPb.SearchMenuResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemMenuList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchMenuResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemMenuList indicates an expected call of SearchSystemMenuList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemMenuList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemMenuList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemMenuList), arg0, arg1)
+}
+
+// SearchSystemRoleList mocks base method.
+func (m *MockSystemService) SearchSystemRoleList(arg0 context.Context, arg1 *operationPb.SearchRoleRequest) (*operationPb.SearchRoleResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemRoleList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchRoleResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemRoleList indicates an expected call of SearchSystemRoleList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemRoleList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemRoleList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemRoleList), arg0, arg1)
+}
+
+// SearchSystemUserList mocks base method.
+func (m *MockSystemService) SearchSystemUserList(arg0 context.Context, arg1 *operationPb.SearchUserRequest) (*operationPb.SearchUserResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemUserList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchUserResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemUserList indicates an expected call of SearchSystemUserList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemUserList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemUserList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemUserList), arg0, arg1)
+}

+ 51 - 0
module/backend/mock/WxAppletService.go

@@ -0,0 +1,51 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: WxAppletService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockWxAppletService is a mock of WxAppletService interface.
+type MockWxAppletService struct {
+	ctrl     *gomock.Controller
+	recorder *MockWxAppletServiceMockRecorder
+}
+
+// MockWxAppletServiceMockRecorder is the mock recorder for MockWxAppletService.
+type MockWxAppletServiceMockRecorder struct {
+	mock *MockWxAppletService
+}
+
+// NewMockWxAppletService creates a new mock instance.
+func NewMockWxAppletService(ctrl *gomock.Controller) *MockWxAppletService {
+	mock := &MockWxAppletService{ctrl: ctrl}
+	mock.recorder = &MockWxAppletServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockWxAppletService) EXPECT() *MockWxAppletServiceMockRecorder {
+	return m.recorder
+}
+
+// GetOpenId mocks base method.
+func (m *MockWxAppletService) GetOpenId(arg0 context.Context, arg1 string) (*operationPb.WxOpenId, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetOpenId", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.WxOpenId)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetOpenId indicates an expected call of GetOpenId.
+func (mr *MockWxAppletServiceMockRecorder) GetOpenId(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOpenId", reflect.TypeOf((*MockWxAppletService)(nil).GetOpenId), arg0, arg1)
+}

+ 14 - 0
module/backend/mock/kptservice.go

@@ -693,6 +693,20 @@ func (mr *MockKptServiceMockRecorder) FeedFormulaDetailBySort(arg0, arg1 interfa
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailBySort", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailBySort), arg0, arg1)
 }
 
+// FeedFormulaDetailIsModify mocks base method.
+func (m *MockKptService) FeedFormulaDetailIsModify(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailIsModify", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailIsModify indicates an expected call of FeedFormulaDetailIsModify.
+func (mr *MockKptServiceMockRecorder) FeedFormulaDetailIsModify(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailIsModify", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailIsModify), arg0, arg1)
+}
+
 // FeedFormulaDetailList mocks base method.
 func (m *MockKptService) FeedFormulaDetailList(arg0 context.Context, arg1 *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
 	m.ctrl.T.Helper()

+ 16 - 2
module/backend/pasture_service.go

@@ -157,6 +157,18 @@ func (s *StoreEntry) SearchGroupPastureList(ctx context.Context, req *operationP
 	}, nil
 }
 
+// GetGroupPastureById 根据id获取牧场端数据
+func (s *StoreEntry) GetGroupPastureById(ctx context.Context, id int64) (*model.GroupPasture, error) {
+	groupPasture := &model.GroupPasture{Id: id}
+	if err := s.DB.Model(new(model.GroupPasture)).
+		Where("is_delete = ?", operationPb.IsShow_OK).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		First(groupPasture).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return groupPasture, nil
+}
+
 // DataSyncGroupPastureList 用户数据下发的牧场
 func (s *StoreEntry) DataSyncGroupPastureList(ctx context.Context) ([]*model.GroupPasture, error) {
 	groupPastureList := make([]*model.GroupPasture, 0)
@@ -608,7 +620,8 @@ func (s *StoreEntry) EditForage(ctx context.Context, req *operationPb.AddForageR
 		Name:               req.Name,
 		CategoryId:         int64(req.CategoryId),
 		CategoryName:       req.CategoryName,
-		MaterialType:       req.MaterialType,
+		MaterialTypeKey:    req.MaterialTypeKey,
+		MaterialTypeName:   req.MaterialTypeName,
 		UniqueEncode:       req.UniqueEncode,
 		ForageSourceId:     req.ForageSourceId,
 		PlanTypeId:         req.PlanTypeId,
@@ -1012,7 +1025,8 @@ func (s *StoreEntry) ExcelImportForage(ctx context.Context, req io.Reader) error
 		forageItem := &model.Forage{
 			Name:               name,
 			CategoryId:         int64(categoryId),
-			MaterialType:       0,
+			MaterialTypeKey:    "",
+			MaterialTypeName:   "",
 			UniqueEncode:       uniqueEncode,
 			ForageSourceId:     operationPb.ForageSource_Kind(forageSourceId),
 			PlanTypeId:         0,

+ 26 - 64
module/backend/pasture_sync_service.go

@@ -192,6 +192,7 @@ func (s *StoreEntry) FeedSyncData(ctx context.Context, req *operationPb.FeedForm
 		ok           bool
 		groupPasture *model.GroupPasture
 	)
+
 	for _, pastureDetail := range groupPastureList {
 		if pastureDetail.Id != int64(req.PastureId) {
 			continue
@@ -201,83 +202,44 @@ func (s *StoreEntry) FeedSyncData(ctx context.Context, req *operationPb.FeedForm
 	}
 
 	if ok {
-		total := 0
-		page := 1
-		pageSize := 100
-		for i := 0; i <= total; i++ {
-			body := &model.FeedFormulaListRequest{
-				PastureId: int32(groupPasture.PastureId),
-				Page:      int32(page),
-				PageSize:  int32(pageSize),
-			}
-			response := &model.FeedListResponse{}
-			if _, err = s.PastureHttpClient(ctx, model.FeedAsyncUrl, int64(req.PastureId), body, response); err != nil {
-				return xerr.WithStack(err)
-			}
 
-			if response.Code != http.StatusOK {
-				return xerr.Customf("%s", response.Msg)
-			}
-			if response.Data.Total > 0 && response.Data.List != nil {
-				total = int(math.Ceil(float64(response.Data.Total) / float64(pageSize)))
-			}
-			if err = s.FeedInsert(ctx, groupPasture, response.Data.List); err != nil {
-				return xerr.WithStack(err)
-			}
+		if req.Page <= 0 {
+			req.Page = 1
+		}
+		if req.PageSize <= 0 {
+			req.PageSize = 1000
+		}
+
+		body := &model.FeedFormulaListRequest{
+			PastureId: int32(groupPasture.PastureId),
+			Page:      req.Page,
+			PageSize:  req.PageSize,
+		}
+		response := &model.FeedListResponse{}
+		if _, err = s.PastureHttpClient(ctx, model.FeedAsyncUrl, int64(req.PastureId), body, response); err != nil {
+			return xerr.WithStack(err)
+		}
+
+		if response.Code != http.StatusOK {
+			return xerr.Customf("%s", response.Msg)
+		}
+		if err = s.FeedInsert(ctx, groupPasture, response.Data.List); err != nil {
+			return xerr.WithStack(err)
 		}
 
 	}
 	return nil
 }
 
-// FeedInsert 饲料数据同步 todo 后面优化成有就更新,没有则新增
+// FeedInsert 饲料数据同步
 func (s *StoreEntry) FeedInsert(ctx context.Context, groupPasture *model.GroupPasture, list []*model.Feed) error {
 	res := make([]*model.Forage, 0)
 	for _, data := range list {
-		forageSourceName := data.Source
-		forageSourceId := operationPb.ForageSource_SYSTEM_BUILT_IN
-		if forageSourceName == "用户自定义" {
-			forageSourceId = operationPb.ForageSource_USER_DEFINED
-		}
-
-		confirmStart := operationPb.IsShow_INVALID
-		if data.ConfirmStart == 0 {
-			confirmStart = operationPb.IsShow_NO
-		}
-		if data.ConfirmStart == 1 {
-			confirmStart = operationPb.IsShow_OK
-		}
-
 		if data.Id <= 0 {
 			continue
 		}
-		res = append(res, &model.Forage{
-			Name:               data.FName,
-			CategoryId:         data.FClassId,
-			CategoryName:       data.FClass,
-			MaterialType:       0, // 牧场端找不到这个字段
-			UniqueEncode:       data.FeedCode,
-			ForageSourceId:     forageSourceId,
-			ForageSourceName:   forageSourceName,
-			PlanTypeId:         operationPb.ForagePlanType_Kind(data.PrintGroupId),
-			PlanTypeName:       data.PrintGroup,
-			SmallMaterialScale: data.SmtMrName,
-			AllowError:         data.AllowRatio,
-			PackageWeight:      data.UnitWeight,
-			Price:              int64(data.UPrice * 100),
-			JumpWeight:         data.AutoZone,
-			JumpDelay:          operationPb.JumpDelaType_Kind(data.AutoSecond),
-			ConfirmStart:       confirmStart,
-			RelayLocations:     int64(data.TrgAddress),
-			Jmp:                operationPb.IsShow_Kind(data.Jmp),
-			DataSource:         operationPb.DataSource_FROM_PASTURE,
-			Sort:               int64(data.Sort),
-			PastureId:          groupPasture.PastureId,
-			PastureName:        groupPasture.Name,
-			PastureDataId:      data.Id,
-			IsShow:             operationPb.IsShow_Kind(data.Enable),
-			IsDelete:           operationPb.IsShow_OK,
-		})
+
+		res = append(res, model.NewForageByPastureFeed(groupPasture, data))
 	}
 
 	if err := s.DB.Model(new(model.Forage)).Create(res).Error; err != nil {

+ 8 - 110
module/backend/statistic_service.go

@@ -307,7 +307,7 @@ func (s *StoreEntry) UserMaterialsStatisticsExcelExport(ctx context.Context, req
 	}
 
 	excelValuesKeys := make([]int, 0)
-	for k, _ := range excelValuesList {
+	for k := range excelValuesList {
 		excelValuesKeys = append(excelValuesKeys, k)
 	}
 	sort.Ints(excelValuesKeys)
@@ -378,11 +378,6 @@ func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.
 		}
 	}
 
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
-	}
-
 	wg := sync.WaitGroup{}
 	wg.Add(len(req.PastureId))
 	for _, v := range req.PastureId {
@@ -405,16 +400,7 @@ func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.
 				Offset:     req.Pagination.PageOffset,
 				PageCount:  req.Pagination.PageSize,
 				ReturnType: "Map",
-				ParamMaps: &model.FeedStatisticsParams{
-					PastureId: fmt.Sprintf("%d", pastureID),
-					StartTime: req.StartTime,
-					StopTime:  req.EndTime,
-					Date:      req.StartTime,
-					FeedTName: req.FormulaTemplate,
-					BarName:   req.BarnName,
-					CowClass:  req.CattleCategoryName,
-					Times:     times,
-				},
+				ParamMaps:  model.NewFeedStatisticsParams(int64(pastureID), req),
 			}
 			response := &model.PastureCommonResponse{
 				Data: &model.PastureCommonData{},
@@ -587,31 +573,9 @@ func (s *StoreEntry) SearchAccuracyAggStatistics(ctx context.Context, req *opera
 	}
 
 	body := &model.FeedChartParams{
-		ParamMaps: &model.AccuracyAggParams{
-			PastureId: fmt.Sprintf("%d", pastureId),
-			StartTime: req.StartTime,
-			StopTime:  req.EndTime,
-			FName:     req.Fname,
-			Sort:      req.Sort,
-			Status:    req.Status,
-			Times:     req.Times,
-			Genre:     req.Genre,
-			IsDate:    req.Isdate,
-			Hlwc1:     req.Hlwc1,
-			Hlwc2:     req.Hlwc2,
-			Hlzq1:     req.Hlzq1,
-			Hlzq2:     req.Hlzq2,
-			Hlzql1:    req.Hlzql1,
-			Hlzql2:    req.Hlzql2,
-			Slwc1:     req.Slwc1,
-			Slwc2:     req.Slwc2,
-			Slzq1:     req.Slzq1,
-			Slzq2:     req.Slzq2,
-			Slzql1:    req.Slzql1,
-			Slzql2:    req.Slzql2,
-			Error:     req.IsError,
-		},
+		ParamMaps: model.NewAccuracyAggParams(int64(pastureId), req),
 	}
+
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
 	if _, err = s.PastureHttpClient(ctx, model.UrlSummary, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
@@ -630,35 +594,13 @@ func (s *StoreEntry) SearchMixFeedStatistics(ctx context.Context, req *operation
 		pastureId = int32(groupPasture.PastureId)
 	}
 
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
-	}
-
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
 		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.MixFeedStatisticsParams{
-			PastureId:   fmt.Sprintf("%d", pastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.EquipmentName,
-			ProjName:    req.TrainNumber,
-			Times:       times,
-			ButtonType:  req.ButtonType,
-			TempletName: req.FormulationName,
-			Isuse:       req.IsUse,
-			Hlwc1:       req.Hlwc1,
-			Hlwc2:       req.Hlwc2,
-			Hlzq1:       req.Hlzq1,
-			Hlzq2:       req.Hlzq2,
-			Hlzql1:      req.Hlzql1,
-			Hlzql2:      req.Hlzql2,
-			Error:       req.IsError,
-		},
+		ParamMaps:  model.NewMixFeedStatisticsParams(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
 	if _, err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
@@ -678,35 +620,13 @@ func (s *StoreEntry) SearchSprinkleStatistics(ctx context.Context, req *operatio
 		pastureId = int32(groupPasture.PastureId)
 	}
 
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
-	}
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
 		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.SprinkleStatisticsParams{
-			PastureId:   fmt.Sprintf("%d", pastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.EquipmentName,
-			ProjName:    req.TrainNumber,
-			Times:       times,
-			ButtonType:  req.ButtonType,
-			TempletName: req.FormulationName,
-			Isuse:       req.IsUse,
-			Fname:       req.BarnName,
-			Slwc1:       req.Slwc1,
-			Slwc2:       req.Slwc2,
-			Slzq2:       req.Slzq2,
-			Slzq1:       req.Slzq1,
-			Slzql1:      req.Slzql1,
-			Slzql2:      req.Slzql2,
-			Error:       req.IsError,
-		},
+		ParamMaps:  model.NewSprinkleStatisticsParams(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
 	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
@@ -732,24 +652,7 @@ func (s *StoreEntry) SearchProcessAnalysis(ctx context.Context, req *operationPb
 		Offset:     req.Pagination.PageOffset,
 		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.ProcessAnalysisParams{
-			PastureId:   fmt.Sprintf("%d", pastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.TmrName,
-			IsCompleted: "",
-			LpPlanType:  fmt.Sprintf("%d", req.PlanType),
-			FClassId:    req.MixFeedType,
-			Hlzq1:       req.Hlzq1,
-			Hlzq2:       req.Hlzq2,
-			Hlwc1:       req.Hlwc1,
-			Hlwc2:       req.Hlwc2,
-			Slwc1:       req.Slwc1,
-			Slwc2:       req.Slwc2,
-			Slzq2:       req.Slzq2,
-			Slzq1:       req.Slzq1,
-			Error:       req.ErrorRange,
-		},
+		ParamMaps:  model.NewProcessAnalysisParams(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
 	if _, err = s.PastureHttpClient(ctx, model.UrlProcess, int64(req.PastureId), body, response); err != nil {
@@ -777,12 +680,7 @@ func (s *StoreEntry) AnalysisMixedSprinkleDetail(ctx context.Context, req *opera
 		Offset:     req.Pagination.PageOffset,
 		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.MixedSprinkleDetailRequest{
-			PastureId: fmt.Sprintf("%d", pastureId),
-			FClassId:  req.FclassId,
-			PId:       req.Pid,
-			Id:        req.Id,
-		},
+		ParamMaps:  model.NewMixedSprinkleDetailRequest(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
 

+ 315 - 285
proto/go/backend/operation/pasture.pb.go

@@ -1228,7 +1228,8 @@ type AddForageRequest struct {
 	Name               string              `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`                                                                                       // 饲料名称
 	CategoryId         int32               `protobuf:"varint,3,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"`                                                        // 饲料分类id
 	CategoryName       string              `protobuf:"bytes,4,opt,name=category_name,json=categoryName,proto3" json:"category_name,omitempty"`                                                   // 饲料分类名称
-	MaterialType       int32               `protobuf:"varint,5,opt,name=material_type,json=materialType,proto3" json:"material_type,omitempty"`                                                  // 物料类型
+	MaterialTypeKey    string              `protobuf:"bytes,5,opt,name=material_type_key,json=materialTypeKey,proto3" json:"material_type_key,omitempty"`                                        // 物料类型key
+	MaterialTypeName   string              `protobuf:"bytes,6,opt,name=material_type_name,json=materialTypeName,proto3" json:"material_type_name,omitempty"`                                     // 物料类型名称
 	UniqueEncode       string              `protobuf:"bytes,7,opt,name=unique_encode,json=uniqueEncode,proto3" json:"unique_encode,omitempty"`                                                   // 唯一编码
 	ForageSourceId     ForageSource_Kind   `protobuf:"varint,8,opt,name=forage_source_id,json=forageSourceId,proto3,enum=backend.operation.ForageSource_Kind" json:"forage_source_id,omitempty"` // 饲料来源id
 	ForageSourceName   string              `protobuf:"bytes,9,opt,name=forage_source_name,json=forageSourceName,proto3" json:"forage_source_name,omitempty"`                                     // 饲料来源名称
@@ -1311,11 +1312,18 @@ func (x *AddForageRequest) GetCategoryName() string {
 	return ""
 }
 
-func (x *AddForageRequest) GetMaterialType() int32 {
+func (x *AddForageRequest) GetMaterialTypeKey() string {
 	if x != nil {
-		return x.MaterialType
+		return x.MaterialTypeKey
 	}
-	return 0
+	return ""
+}
+
+func (x *AddForageRequest) GetMaterialTypeName() string {
+	if x != nil {
+		return x.MaterialTypeName
+	}
+	return ""
 }
 
 func (x *AddForageRequest) GetUniqueEncode() string {
@@ -2759,7 +2767,9 @@ type FeedFormulaSyncRequest struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	PastureId int32 `protobuf:"varint,1,opt,name=pasture_id,json=pastureId,proto3" json:"pasture_id,omitempty"`
+	PastureId int32 `protobuf:"varint,1,opt,name=pasture_id,json=pastureId,proto3" json:"pasture_id,omitempty"` // 牧场id
+	Page      int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"`                            // 返回数据条数
+	PageSize  int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`    // 返回数据条数
 }
 
 func (x *FeedFormulaSyncRequest) Reset() {
@@ -2801,6 +2811,20 @@ func (x *FeedFormulaSyncRequest) GetPastureId() int32 {
 	return 0
 }
 
+func (x *FeedFormulaSyncRequest) GetPage() int32 {
+	if x != nil {
+		return x.Page
+	}
+	return 0
+}
+
+func (x *FeedFormulaSyncRequest) GetPageSize() int32 {
+	if x != nil {
+		return x.PageSize
+	}
+	return 0
+}
+
 var File_backend_operation_pasture_proto protoreflect.FileDescriptor
 
 var file_backend_operation_pasture_proto_rawDesc = []byte{
@@ -2998,7 +3022,7 @@ var file_backend_operation_pasture_proto_rawDesc = []byte{
 	0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
 	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x6f,
 	0x72, 0x61, 0x67, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x9c, 0x08, 0x0a, 0x10, 0x41, 0x64,
+	0x65, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xd1, 0x08, 0x0a, 0x10, 0x41, 0x64,
 	0x64, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
 	0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12,
 	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
@@ -3006,293 +3030,299 @@ var file_backend_operation_pasture_proto_rawDesc = []byte{
 	0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
 	0x79, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x5f,
 	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x74, 0x65,
-	0x67, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x65,
-	0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
-	0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a,
-	0x0d, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x45, 0x6e, 0x63, 0x6f,
-	0x64, 0x65, 0x12, 0x4e, 0x0a, 0x10, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62,
-	0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4b, 0x69,
-	0x6e, 0x64, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10,
-	0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65,
-	0x12, 0x48, 0x0a, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, 0x64,
-	0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
-	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67,
-	0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0a,
-	0x70, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6c,
-	0x61, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65,
-	0x12, 0x30, 0x0a, 0x14, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69,
-	0x61, 0x6c, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
-	0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x53, 0x63, 0x61,
-	0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x72, 0x72, 0x6f,
-	0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x72,
-	0x72, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x77,
-	0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x70, 0x61, 0x63,
-	0x6b, 0x61, 0x67, 0x65, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72,
-	0x69, 0x63, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65,
-	0x12, 0x1f, 0x0a, 0x0b, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18,
-	0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68,
-	0x74, 0x12, 0x43, 0x0a, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18,
-	0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e,
-	0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65,
-	0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x09, 0x6a, 0x75, 0x6d,
-	0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72,
-	0x6d, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e,
-	0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0c, 0x63,
-	0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72,
-	0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x13,
-	0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x03, 0x6a, 0x6d, 0x70, 0x18, 0x14, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e,
-	0x64, 0x52, 0x03, 0x6a, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70,
-	0x31, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x31,
-	0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x32, 0x18, 0x16, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x32, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61,
-	0x63, 0x6b, 0x75, 0x70, 0x33, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x63,
-	0x6b, 0x75, 0x70, 0x33, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
-	0x61, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
-	0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
-	0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
-	0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12,
-	0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0e,
-	0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64,
-	0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x22, 0xfc, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x74, 0x65,
-	0x67, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63,
-	0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6f, 0x72,
-	0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x0d, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
-	0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e,
-	0x4b, 0x69, 0x6e, 0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x1f, 0x0a, 0x0b,
-	0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28,
-	0x0d, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a,
-	0x0b, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01,
-	0x28, 0x0d, 0x52, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x43,
-	0x0a, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01,
-	0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
-	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54,
-	0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x09, 0x6a, 0x75, 0x6d, 0x70, 0x44, 0x65,
-	0x6c, 0x61, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
-	0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x67, 0x69,
-	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0a, 0x70, 0x61, 0x67,
-	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4e, 0x0a, 0x15, 0x46, 0x6f, 0x72, 0x61, 0x67,
-	0x65, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x12, 0x35, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21,
-	0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x72,
-	0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x61, 0x67,
-	0x65, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, 0x72,
-	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, 0x6d, 0x0a,
-	0x14, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x4e, 0x61, 0x6d, 0x65,
-	0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x12,
-	0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x79, 0x0a, 0x18,
-	0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03,
-	0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x37,
-	0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62,
+	0x67, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x74, 0x65,
+	0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70,
+	0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c,
+	0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x10, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61,
+	0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x65, 0x6e, 0x63,
+	0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x75, 0x6e, 0x69, 0x71, 0x75,
+	0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x4e, 0x0a, 0x10, 0x66, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28,
+	0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x66, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x10, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
+	0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x48, 0x0a, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x74, 0x79,
+	0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x62, 0x61,
+	0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b,
+	0x69, 0x6e, 0x64, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12,
+	0x24, 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70,
+	0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x6d,
+	0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69,
+	0x61, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77,
+	0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x61, 0x6c,
+	0x6c, 0x6f, 0x77, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b,
+	0x61, 0x67, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
+	0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
+	0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x77, 0x65,
+	0x69, 0x67, 0x68, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6a, 0x75, 0x6d, 0x70,
+	0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x43, 0x0a, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x64,
+	0x65, 0x6c, 0x61, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63,
+	0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a,
+	0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64,
+	0x52, 0x09, 0x6a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x12, 0x20, 0x01,
+	0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69,
+	0x6e, 0x64, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74,
+	0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x79,
+	0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x03, 0x6a, 0x6d, 0x70,
+	0x18, 0x14, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f,
+	0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x03, 0x6a, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62,
+	0x61, 0x63, 0x6b, 0x75, 0x70, 0x31, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61,
+	0x63, 0x6b, 0x75, 0x70, 0x31, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x32,
+	0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x32, 0x12,
+	0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x33, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x33, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65,
+	0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63,
+	0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61,
+	0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x19, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x46, 0x6f,
+	0x72, 0x6d, 0x61, 0x74, 0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18,
+	0x1a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e,
+	0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77,
+	0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x22, 0xfc, 0x02,
+	0x0a, 0x17, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a,
+	0x0b, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x05, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x28,
+	0x0a, 0x10, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+	0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65,
+	0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73,
+	0x68, 0x6f, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b,
+	0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73,
+	0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f,
+	0x77, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x72, 0x72,
+	0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68,
+	0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x57, 0x65, 0x69,
+	0x67, 0x68, 0x74, 0x12, 0x43, 0x0a, 0x0a, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61,
+	0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
+	0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70,
+	0x44, 0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x09, 0x6a,
+	0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69,
+	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62,
 	0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x92, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x61, 0x72,
-	0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
-	0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65,
-	0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f,
-	0x74, 0x61, 0x6c, 0x12, 0x37, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28,
+	0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x6c,
+	0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4e, 0x0a, 0x15,
+	0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70,
+	0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69,
+	0x73, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x0e,
+	0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x72, 0x74, 0x12, 0x0e,
+	0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12,
+	0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x6f,
+	0x72, 0x74, 0x22, 0x6d, 0x0a, 0x14, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x74, 0x65, 0x72,
+	0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70,
+	0x69, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70,
+	0x69, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65,
+	0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75,
+	0x72, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d,
+	0x65, 0x22, 0x79, 0x0a, 0x18, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a,
+	0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64,
+	0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x6d, 0x73, 0x67, 0x12, 0x37, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
 	0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x64, 0x0a, 0x0c,
-	0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09,
-	0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
-	0x08, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f,
-	0x73, 0x68, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63,
-	0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49,
-	0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68,
-	0x6f, 0x77, 0x22, 0x75, 0x0a, 0x16, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x75, 0x6d,
-	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04,
-	0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65,
-	0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d,
-	0x73, 0x67, 0x12, 0x35, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x21, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x4c,
-	0x69, 0x73, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb7, 0x09, 0x0a, 0x0e, 0x46, 0x6f,
-	0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x0d,
-	0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70,
-	0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65,
-	0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65,
-	0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x25, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54,
-	0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50,
-	0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x49, 0x0a, 0x0e, 0x6a, 0x75, 0x6d, 0x70, 0x5f,
-	0x64, 0x65, 0x6c, 0x61, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65,
-	0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x6a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54, 0x79,
-	0x70, 0x65, 0x12, 0x61, 0x0a, 0x16, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x72,
-	0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
-	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x61, 0x72,
-	0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x52,
-	0x14, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74,
-	0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x61, 0x0a, 0x16, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f,
-	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18,
-	0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61,
+	0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x92, 0x01, 0x0a,
+	0x10, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73,
+	0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69,
+	0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69,
+	0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x37, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74,
+	0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x6f,
+	0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73,
+	0x74, 0x22, 0x64, 0x0a, 0x0c, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x46, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x37,
+	0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52,
+	0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x22, 0x75, 0x0a, 0x16, 0x46, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x45, 0x6e, 0x75, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x35, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e,
 	0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65,
-	0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x45, 0x6e,
-	0x75, 0x6d, 0x52, 0x14, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74,
-	0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x36, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73,
-	0x68, 0x6f, 0x77, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x63, 0x6b,
-	0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73,
-	0x53, 0x68, 0x6f, 0x77, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77,
-	0x12, 0x45, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x5f, 0x74, 0x79, 0x70, 0x65,
-	0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x45, 0x6e, 0x75, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb7,
+	0x09, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x4c, 0x69, 0x73,
+	0x74, 0x12, 0x48, 0x0a, 0x0d, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65,
+	0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72,
+	0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x66,
+	0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x66,
+	0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
+	0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e,
+	0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65,
+	0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0e, 0x66, 0x6f,
+	0x72, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x49, 0x0a, 0x0e,
+	0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f,
+	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c,
+	0x61, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x6a, 0x75, 0x6d, 0x70, 0x44,
+	0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x61, 0x0a, 0x16, 0x63, 0x61, 0x74, 0x74, 0x6c,
+	0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
+	0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
+	0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x74, 0x74,
+	0x6c, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
+	0x45, 0x6e, 0x75, 0x6d, 0x52, 0x14, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x61, 0x0a, 0x16, 0x66, 0x6f,
+	0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x65,
+	0x67, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x61, 0x63,
+	0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46,
+	0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67,
+	0x6f, 0x72, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x14, 0x66, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50,
+	0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x36, 0x0a,
+	0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d,
+	0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x69,
+	0x73, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x45, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61,
+	0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x61,
+	0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+	0x0b, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x47, 0x0a, 0x0c,
+	0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x08, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c,
+	0x61, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d,
+	0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62,
+	0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x63, 0x6f, 0x6e,
+	0x66, 0x69, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x6f, 0x72,
+	0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b,
+	0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f,
+	0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+	0x15, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x61, 0x6c,
+	0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x61,
+	0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x10, 0x75, 0x73, 0x65, 0x4d, 0x61, 0x74,
+	0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x12, 0x75, 0x73,
+	0x65, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65,
+	0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
 	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75,
-	0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x66, 0x6f, 0x72, 0x6d,
-	0x75, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, 0x75,
-	0x6c, 0x61, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
-	0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45,
-	0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4c, 0x69, 0x73, 0x74,
-	0x12, 0x42, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x72,
-	0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
+	0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x10, 0x75, 0x73,
+	0x65, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x56,
+	0x0a, 0x14, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c,
+	0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62,
+	0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e,
+	0x75, 0x6d, 0x52, 0x12, 0x70, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61,
+	0x6c, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x74,
+	0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b,
+	0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f,
+	0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+	0x08, 0x6a, 0x75, 0x6d, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x73, 0x74, 0x61,
+	0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0f, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73,
+	0x74, 0x69, 0x63, 0x73, 0x54, 0x79, 0x70, 0x65, 0x22, 0x64, 0x0a, 0x10, 0x46, 0x6f, 0x72, 0x61,
+	0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61,
+	0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4b, 0x69, 0x6e,
+	0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65,
+	0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x68,
+	0x0a, 0x12, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65,
+	0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70,
+	0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x6c,
+	0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x64, 0x0a, 0x10, 0x4a, 0x75, 0x6d, 0x70,
+	0x44, 0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61,
+	0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e,
+	0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65,
+	0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x74,
+	0x0a, 0x18, 0x43, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61,
+	0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x42, 0x0a, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x63, 0x6b,
+	0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61,
+	0x74, 0x74, 0x6c, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x50, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14,
+	0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c,
+	0x61, 0x62, 0x65, 0x6c, 0x22, 0x74, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x75, 0x6d,
+	0x12, 0x42, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x2c, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f,
+	0x72, 0x79, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x58, 0x0a, 0x0a, 0x49, 0x73,
+	0x53, 0x68, 0x6f, 0x77, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
 	0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68,
-	0x6f, 0x77, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x53,
-	0x74, 0x61, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61,
-	0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x15, 0x66, 0x6f, 0x72, 0x6d,
-	0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x12, 0x52, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61,
-	0x6c, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
-	0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45,
-	0x6e, 0x75, 0x6d, 0x52, 0x10, 0x75, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c,
-	0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74,
-	0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74,
-	0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x10, 0x75, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x65,
-	0x72, 0x69, 0x61, 0x6c, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x56, 0x0a, 0x14, 0x70, 0x72, 0x69,
-	0x63, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x5f, 0x74, 0x79, 0x70,
-	0x65, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
-	0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d,
-	0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x12, 0x70,
-	0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x54, 0x79, 0x70,
-	0x65, 0x12, 0x41, 0x0a, 0x09, 0x6a, 0x75, 0x6d, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0e,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61,
-	0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x08, 0x6a, 0x75, 0x6d, 0x70,
-	0x54, 0x79, 0x70, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69,
-	0x63, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
-	0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45,
-	0x6e, 0x75, 0x6d, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x54,
-	0x79, 0x70, 0x65, 0x22, 0x64, 0x0a, 0x10, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
-	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67,
-	0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x68, 0x0a, 0x12, 0x46, 0x6f, 0x72,
-	0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12,
-	0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26,
-	0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x54, 0x79, 0x70,
-	0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61,
-	0x62, 0x65, 0x6c, 0x22, 0x64, 0x0a, 0x10, 0x4a, 0x75, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x54,
-	0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
-	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4a, 0x75, 0x6d, 0x70, 0x44,
-	0x65, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x74, 0x0a, 0x18, 0x43, 0x61, 0x74,
-	0x74, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
-	0x79, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x42, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43,
-	0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x69,
-	0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62,
-	0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22,
-	0x74, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43,
-	0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x42, 0x0a, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x63,
-	0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46,
-	0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x50, 0x61, 0x72,
-	0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12,
-	0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
-	0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x58, 0x0a, 0x0a, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x45,
-	0x6e, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65,
-	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69,
-	0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62,
-	0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22,
-	0x62, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e,
-	0x75, 0x6d, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x54, 0x79, 0x70,
-	0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61,
-	0x62, 0x65, 0x6c, 0x22, 0x3f, 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x4f, 0x70,
-	0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14,
+	0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14,
 	0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c,
-	0x61, 0x62, 0x65, 0x6c, 0x22, 0xbf, 0x02, 0x0a, 0x13, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
-	0x79, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08,
-	0x6b, 0x65, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-	0x6b, 0x65, 0x79, 0x57, 0x6f, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x74, 0x75,
-	0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x61, 0x73,
-	0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
-	0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e,
-	0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
-	0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62,
-	0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
-	0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x07, 0x20, 0x01, 0x28,
+	0x61, 0x62, 0x65, 0x6c, 0x22, 0x62, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x54,
+	0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x75,
+	0x6c, 0x61, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3f, 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x6d,
+	0x75, 0x6c, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a,
+	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0xbf, 0x02, 0x0a, 0x13, 0x43, 0x61,
+	0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x57, 0x6f, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x0a,
+	0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70,
+	0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
+	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70,
+	0x61, 0x72, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a,
+	0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e,
+	0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x73, 0x68, 0x6f, 0x77,
+	0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f,
+	0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x3b,
+	0x0a, 0x09, 0x69, 0x73, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
 	0x0e, 0x32, 0x1e, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72,
 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e,
-	0x64, 0x52, 0x06, 0x69, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x3b, 0x0a, 0x09, 0x69, 0x73, 0x5f,
-	0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x62,
-	0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x2e, 0x49, 0x73, 0x53, 0x68, 0x6f, 0x77, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x08, 0x69, 0x73,
-	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01,
-	0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x6a, 0x0a, 0x15, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f,
-	0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x57, 0x6f, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61,
-	0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
-	0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x61, 0x74,
-	0x61, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x74, 0x61,
-	0x49, 0x64, 0x22, 0x37, 0x0a, 0x16, 0x46, 0x65, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x6d, 0x75, 0x6c,
-	0x61, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
-	0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
-	0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x42, 0x0f, 0x5a, 0x0d, 0x2e,
-	0x3b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x62, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
+	0x64, 0x52, 0x08, 0x69, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
+	0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x6a, 0x0a, 0x15, 0x43,
+	0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x57, 0x6f, 0x72, 0x64, 0x12,
+	0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x12, 0x17,
+	0x0a, 0x07, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x06, 0x64, 0x61, 0x74, 0x61, 0x49, 0x64, 0x22, 0x68, 0x0a, 0x16, 0x46, 0x65, 0x65, 0x64, 0x46,
+	0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x61, 0x73, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64,
+	0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04,
+	0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a,
+	0x65, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x3b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x50, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (