From 1a32f585154d2b79ecfa51bfd59340de80a31b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Wed, 9 Apr 2025 17:29:56 +0800 Subject: [PATCH] feat: add product item api --- client/product/product.go | 128 +- gen_result/pb/product/product.pb.go | 1312 +++++++++++++++-- gen_result/pb/product/product_grpc.pb.go | 396 ++++- generate/protobuf/product.proto | 109 +- go.mod | 2 +- internal/logic/product/create_item_logic.go | 96 ++ .../logic/product/dec_sales_count_logic.go | 35 + ...te_product_items_by_reference_i_d_logic.go | 34 + .../product/delete_product_items_logic.go | 34 + .../logic/product/get_product_item_logic.go | 83 ++ .../get_product_items_by_product_i_d_logic.go | 112 ++ .../logic/product/inc_sales_count_logic.go | 35 + internal/logic/product/update_logic.go | 37 + internal/logic/product/update_status_logic.go | 41 + internal/server/product/product_server.go | 54 + internal/svc/service_context.go | 49 +- internal/utils/encode.go | 23 + pkg/domain/product/time_series.go | 38 + pkg/domain/usecase/product_item.go | 4 +- pkg/usecase/product_item.go | 19 +- pkg/usecase/product_item_test.go | 4 +- 21 files changed, 2474 insertions(+), 171 deletions(-) create mode 100644 internal/logic/product/create_item_logic.go create mode 100644 internal/logic/product/dec_sales_count_logic.go create mode 100644 internal/logic/product/delete_product_items_by_reference_i_d_logic.go create mode 100644 internal/logic/product/delete_product_items_logic.go create mode 100644 internal/logic/product/get_product_item_logic.go create mode 100644 internal/logic/product/get_product_items_by_product_i_d_logic.go create mode 100644 internal/logic/product/inc_sales_count_logic.go create mode 100644 internal/logic/product/update_logic.go create mode 100644 internal/logic/product/update_status_logic.go create mode 100755 internal/utils/encode.go diff --git a/client/product/product.go b/client/product/product.go index 6e803d1..b6feda0 100644 --- a/client/product/product.go +++ b/client/product/product.go @@ -14,28 +14,40 @@ import ( ) type ( - Category = product.Category - CategoryReq = product.CategoryReq - CreateCategoryReq = product.CreateCategoryReq - CreateKYCReq = product.CreateKYCReq - CreateTagsReq = product.CreateTagsReq - FindKYCByIDReq = product.FindKYCByIDReq - FindLatestKYCByUIDReq = product.FindLatestKYCByUIDReq - KYC = product.KYC - ListCategoryReq = product.ListCategoryReq - ListCategoryResp = product.ListCategoryResp - ListKYCReq = product.ListKYCReq - ListKYCResp = product.ListKYCResp - ListTagsReq = product.ListTagsReq - ListTagsResp = product.ListTagsResp - ModifyCategoryReq = product.ModifyCategoryReq - ModifyTagsReq = product.ModifyTagsReq - NoneReq = product.NoneReq - OKResp = product.OKResp - Tags = product.Tags - TagsReq = product.TagsReq - UpdateKYCInfoReq = product.UpdateKYCInfoReq - UpdateKYCStatusReq = product.UpdateKYCStatusReq + Category = product.Category + CategoryReq = product.CategoryReq + CreateCategoryReq = product.CreateCategoryReq + CreateKYCReq = product.CreateKYCReq + CreateProductItemRequest = product.CreateProductItemRequest + CreateTagsReq = product.CreateTagsReq + CustomField = product.CustomField + DeleteProductItemRequest = product.DeleteProductItemRequest + DeleteProductItemsByReferenceIDReq = product.DeleteProductItemsByReferenceIDReq + FindKYCByIDReq = product.FindKYCByIDReq + FindLatestKYCByUIDReq = product.FindLatestKYCByUIDReq + GetProductItemRequest = product.GetProductItemRequest + IncDecSalesCountRequest = product.IncDecSalesCountRequest + KYC = product.KYC + ListCategoryReq = product.ListCategoryReq + ListCategoryResp = product.ListCategoryResp + ListKYCReq = product.ListKYCReq + ListKYCResp = product.ListKYCResp + ListProductItemRequest = product.ListProductItemRequest + ListProductItemResponse = product.ListProductItemResponse + ListTagsReq = product.ListTagsReq + ListTagsResp = product.ListTagsResp + Media = product.Media + ModifyCategoryReq = product.ModifyCategoryReq + ModifyTagsReq = product.ModifyTagsReq + NoneReq = product.NoneReq + OKResp = product.OKResp + ProductItem = product.ProductItem + Tags = product.Tags + TagsReq = product.TagsReq + UpdateKYCInfoReq = product.UpdateKYCInfoReq + UpdateKYCStatusReq = product.UpdateKYCStatusReq + UpdateProductItemRequest = product.UpdateProductItemRequest + UpdateStatusRequest = product.UpdateStatusRequest Product interface { // ====================== Category Service Start ====================== @@ -70,6 +82,24 @@ type ( UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) // UpdateKYCInfo 更新使用者的 KYC(尚未審核) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) + // ====================== Know You Customer Service End ====================== + CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // GetProductItem 取得 ProductItem + GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) + // GetProductItemsByProductID 使用 ProductID 取得 ProductItems + GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) + // DeleteProductItems 刪除 Delete Product Item + DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item + DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) + // IncSalesCount 增加賣出數量 + IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) + // DecSalesCount 減少賣出數量 + DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) + // Update 更新 Item + Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // UpdateStatus 更新 Item status + UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) } defaultProduct struct { @@ -178,3 +208,57 @@ func (m *defaultProduct) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq client := product.NewProductClient(m.cli.Conn()) return client.UpdateKYCInfo(ctx, in, opts...) } + +// ====================== Know You Customer Service End ====================== +func (m *defaultProduct) CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.CreateItem(ctx, in, opts...) +} + +// GetProductItem 取得 ProductItem +func (m *defaultProduct) GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.GetProductItem(ctx, in, opts...) +} + +// GetProductItemsByProductID 使用 ProductID 取得 ProductItems +func (m *defaultProduct) GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.GetProductItemsByProductID(ctx, in, opts...) +} + +// DeleteProductItems 刪除 Delete Product Item +func (m *defaultProduct) DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.DeleteProductItems(ctx, in, opts...) +} + +// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item +func (m *defaultProduct) DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.DeleteProductItemsByReferenceID(ctx, in, opts...) +} + +// IncSalesCount 增加賣出數量 +func (m *defaultProduct) IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.IncSalesCount(ctx, in, opts...) +} + +// DecSalesCount 減少賣出數量 +func (m *defaultProduct) DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.DecSalesCount(ctx, in, opts...) +} + +// Update 更新 Item +func (m *defaultProduct) Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.Update(ctx, in, opts...) +} + +// UpdateStatus 更新 Item status +func (m *defaultProduct) UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.UpdateStatus(ctx, in, opts...) +} diff --git a/gen_result/pb/product/product.pb.go b/gen_result/pb/product/product.pb.go index ef4f82b..6c3d1fc 100644 --- a/gen_result/pb/product/product.pb.go +++ b/gen_result/pb/product/product.pb.go @@ -1617,6 +1617,862 @@ func (x *UpdateKYCInfoReq) GetBankAccount() string { return "" } +type ProductItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"` + ReferenceId string `protobuf:"bytes,2,opt,name=reference_id,json=referenceId,proto3" json:"reference_id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + ShortDescription string `protobuf:"bytes,5,opt,name=short_description,json=shortDescription,proto3" json:"short_description,omitempty"` + IsUnLimit bool `protobuf:"varint,6,opt,name=is_un_limit,json=isUnLimit,proto3" json:"is_un_limit,omitempty"` + IsFree bool `protobuf:"varint,7,opt,name=is_free,json=isFree,proto3" json:"is_free,omitempty"` + Stock uint64 `protobuf:"varint,8,opt,name=stock,proto3" json:"stock,omitempty"` + Price string `protobuf:"bytes,9,opt,name=price,proto3" json:"price,omitempty"` + Sku string `protobuf:"bytes,10,opt,name=sku,proto3" json:"sku,omitempty"` + TimeSeries string `protobuf:"bytes,11,opt,name=time_series,json=timeSeries,proto3" json:"time_series,omitempty"` + Media []*Media `protobuf:"bytes,12,rep,name=media,proto3" json:"media,omitempty"` + Status string `protobuf:"bytes,13,opt,name=status,proto3" json:"status,omitempty"` + Freight []*CustomField `protobuf:"bytes,14,rep,name=freight,proto3" json:"freight,omitempty"` + CustomFields []*CustomField `protobuf:"bytes,15,rep,name=custom_fields,json=customFields,proto3" json:"custom_fields,omitempty"` + SalesCount uint64 `protobuf:"varint,16,opt,name=sales_count,json=salesCount,proto3" json:"sales_count,omitempty"` + UpdatedAt *string `protobuf:"bytes,17,opt,name=updated_at,json=updatedAt,proto3,oneof" json:"updated_at,omitempty"` + CreatedAt *string `protobuf:"bytes,18,opt,name=created_at,json=createdAt,proto3,oneof" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProductItem) Reset() { + *x = ProductItem{} + mi := &file_generate_protobuf_product_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProductItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProductItem) ProtoMessage() {} + +func (x *ProductItem) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProductItem.ProtoReflect.Descriptor instead. +func (*ProductItem) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{22} +} + +func (x *ProductItem) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *ProductItem) GetReferenceId() string { + if x != nil { + return x.ReferenceId + } + return "" +} + +func (x *ProductItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ProductItem) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ProductItem) GetShortDescription() string { + if x != nil { + return x.ShortDescription + } + return "" +} + +func (x *ProductItem) GetIsUnLimit() bool { + if x != nil { + return x.IsUnLimit + } + return false +} + +func (x *ProductItem) GetIsFree() bool { + if x != nil { + return x.IsFree + } + return false +} + +func (x *ProductItem) GetStock() uint64 { + if x != nil { + return x.Stock + } + return 0 +} + +func (x *ProductItem) GetPrice() string { + if x != nil { + return x.Price + } + return "" +} + +func (x *ProductItem) GetSku() string { + if x != nil { + return x.Sku + } + return "" +} + +func (x *ProductItem) GetTimeSeries() string { + if x != nil { + return x.TimeSeries + } + return "" +} + +func (x *ProductItem) GetMedia() []*Media { + if x != nil { + return x.Media + } + return nil +} + +func (x *ProductItem) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ProductItem) GetFreight() []*CustomField { + if x != nil { + return x.Freight + } + return nil +} + +func (x *ProductItem) GetCustomFields() []*CustomField { + if x != nil { + return x.CustomFields + } + return nil +} + +func (x *ProductItem) GetSalesCount() uint64 { + if x != nil { + return x.SalesCount + } + return 0 +} + +func (x *ProductItem) GetUpdatedAt() string { + if x != nil && x.UpdatedAt != nil { + return *x.UpdatedAt + } + return "" +} + +func (x *ProductItem) GetCreatedAt() string { + if x != nil && x.CreatedAt != nil { + return *x.CreatedAt + } + return "" +} + +type Media struct { + state protoimpl.MessageState `protogen:"open.v1"` + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Sort *uint64 `protobuf:"varint,3,opt,name=sort,proto3,oneof" json:"sort,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Media) Reset() { + *x = Media{} + mi := &file_generate_protobuf_product_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Media) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Media) ProtoMessage() {} + +func (x *Media) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Media.ProtoReflect.Descriptor instead. +func (*Media) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{23} +} + +func (x *Media) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *Media) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Media) GetSort() uint64 { + if x != nil && x.Sort != nil { + return *x.Sort + } + return 0 +} + +type CustomField struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CustomField) Reset() { + *x = CustomField{} + mi := &file_generate_protobuf_product_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CustomField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CustomField) ProtoMessage() {} + +func (x *CustomField) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CustomField.ProtoReflect.Descriptor instead. +func (*CustomField) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{24} +} + +func (x *CustomField) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *CustomField) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type CreateProductItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Item *ProductItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateProductItemRequest) Reset() { + *x = CreateProductItemRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateProductItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateProductItemRequest) ProtoMessage() {} + +func (x *CreateProductItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateProductItemRequest.ProtoReflect.Descriptor instead. +func (*CreateProductItemRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{25} +} + +func (x *CreateProductItemRequest) GetItem() *ProductItem { + if x != nil { + return x.Item + } + return nil +} + +type GetProductItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetProductItemRequest) Reset() { + *x = GetProductItemRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetProductItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProductItemRequest) ProtoMessage() {} + +func (x *GetProductItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetProductItemRequest.ProtoReflect.Descriptor instead. +func (*GetProductItemRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{26} +} + +func (x *GetProductItemRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ListProductItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PageSize int64 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageIndex int64 `protobuf:"varint,2,opt,name=page_index,json=pageIndex,proto3" json:"page_index,omitempty"` + ReferenceId string `protobuf:"bytes,3,opt,name=reference_id,json=referenceId,proto3" json:"reference_id,omitempty"` + IsUnLimit *bool `protobuf:"varint,4,opt,name=is_un_limit,json=isUnLimit,proto3,oneof" json:"is_un_limit,omitempty"` + IsFree *bool `protobuf:"varint,5,opt,name=is_free,json=isFree,proto3,oneof" json:"is_free,omitempty"` + Status *string `protobuf:"bytes,6,opt,name=status,proto3,oneof" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListProductItemRequest) Reset() { + *x = ListProductItemRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListProductItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListProductItemRequest) ProtoMessage() {} + +func (x *ListProductItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListProductItemRequest.ProtoReflect.Descriptor instead. +func (*ListProductItemRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{27} +} + +func (x *ListProductItemRequest) GetPageSize() int64 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListProductItemRequest) GetPageIndex() int64 { + if x != nil { + return x.PageIndex + } + return 0 +} + +func (x *ListProductItemRequest) GetReferenceId() string { + if x != nil { + return x.ReferenceId + } + return "" +} + +func (x *ListProductItemRequest) GetIsUnLimit() bool { + if x != nil && x.IsUnLimit != nil { + return *x.IsUnLimit + } + return false +} + +func (x *ListProductItemRequest) GetIsFree() bool { + if x != nil && x.IsFree != nil { + return *x.IsFree + } + return false +} + +func (x *ListProductItemRequest) GetStatus() string { + if x != nil && x.Status != nil { + return *x.Status + } + return "" +} + +type ListProductItemResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data []*ProductItem `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListProductItemResponse) Reset() { + *x = ListProductItemResponse{} + mi := &file_generate_protobuf_product_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListProductItemResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListProductItemResponse) ProtoMessage() {} + +func (x *ListProductItemResponse) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListProductItemResponse.ProtoReflect.Descriptor instead. +func (*ListProductItemResponse) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{28} +} + +func (x *ListProductItemResponse) GetData() []*ProductItem { + if x != nil { + return x.Data + } + return nil +} + +func (x *ListProductItemResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +type DeleteProductItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id []string `protobuf:"bytes,1,rep,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteProductItemRequest) Reset() { + *x = DeleteProductItemRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteProductItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteProductItemRequest) ProtoMessage() {} + +func (x *DeleteProductItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteProductItemRequest.ProtoReflect.Descriptor instead. +func (*DeleteProductItemRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{29} +} + +func (x *DeleteProductItemRequest) GetId() []string { + if x != nil { + return x.Id + } + return nil +} + +type DeleteProductItemsByReferenceIDReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteProductItemsByReferenceIDReq) Reset() { + *x = DeleteProductItemsByReferenceIDReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteProductItemsByReferenceIDReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteProductItemsByReferenceIDReq) ProtoMessage() {} + +func (x *DeleteProductItemsByReferenceIDReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteProductItemsByReferenceIDReq.ProtoReflect.Descriptor instead. +func (*DeleteProductItemsByReferenceIDReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{30} +} + +func (x *DeleteProductItemsByReferenceIDReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type IncDecSalesCountRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IncDecSalesCountRequest) Reset() { + *x = IncDecSalesCountRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IncDecSalesCountRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IncDecSalesCountRequest) ProtoMessage() {} + +func (x *IncDecSalesCountRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IncDecSalesCountRequest.ProtoReflect.Descriptor instead. +func (*IncDecSalesCountRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{31} +} + +func (x *IncDecSalesCountRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *IncDecSalesCountRequest) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +type UpdateProductItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name *string `protobuf:"bytes,2,opt,name=name,proto3,oneof" json:"name,omitempty"` + Description *string `protobuf:"bytes,3,opt,name=description,proto3,oneof" json:"description,omitempty"` + ShortDescription *string `protobuf:"bytes,4,opt,name=short_description,json=shortDescription,proto3,oneof" json:"short_description,omitempty"` + IsUnLimit *bool `protobuf:"varint,5,opt,name=is_un_limit,json=isUnLimit,proto3,oneof" json:"is_un_limit,omitempty"` + IsFree *bool `protobuf:"varint,6,opt,name=is_free,json=isFree,proto3,oneof" json:"is_free,omitempty"` + Stock *uint64 `protobuf:"varint,7,opt,name=stock,proto3,oneof" json:"stock,omitempty"` + Price *string `protobuf:"bytes,8,opt,name=price,proto3,oneof" json:"price,omitempty"` + Sku *string `protobuf:"bytes,9,opt,name=sku,proto3,oneof" json:"sku,omitempty"` + TimeSeries *string `protobuf:"bytes,10,opt,name=time_series,json=timeSeries,proto3,oneof" json:"time_series,omitempty"` + Media []*Media `protobuf:"bytes,11,rep,name=media,proto3" json:"media,omitempty"` + Status *string `protobuf:"bytes,12,opt,name=status,proto3,oneof" json:"status,omitempty"` + Freight []*CustomField `protobuf:"bytes,13,rep,name=freight,proto3" json:"freight,omitempty"` + CustomFields []*CustomField `protobuf:"bytes,14,rep,name=custom_fields,json=customFields,proto3" json:"custom_fields,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateProductItemRequest) Reset() { + *x = UpdateProductItemRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateProductItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateProductItemRequest) ProtoMessage() {} + +func (x *UpdateProductItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateProductItemRequest.ProtoReflect.Descriptor instead. +func (*UpdateProductItemRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{32} +} + +func (x *UpdateProductItemRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateProductItemRequest) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *UpdateProductItemRequest) GetDescription() string { + if x != nil && x.Description != nil { + return *x.Description + } + return "" +} + +func (x *UpdateProductItemRequest) GetShortDescription() string { + if x != nil && x.ShortDescription != nil { + return *x.ShortDescription + } + return "" +} + +func (x *UpdateProductItemRequest) GetIsUnLimit() bool { + if x != nil && x.IsUnLimit != nil { + return *x.IsUnLimit + } + return false +} + +func (x *UpdateProductItemRequest) GetIsFree() bool { + if x != nil && x.IsFree != nil { + return *x.IsFree + } + return false +} + +func (x *UpdateProductItemRequest) GetStock() uint64 { + if x != nil && x.Stock != nil { + return *x.Stock + } + return 0 +} + +func (x *UpdateProductItemRequest) GetPrice() string { + if x != nil && x.Price != nil { + return *x.Price + } + return "" +} + +func (x *UpdateProductItemRequest) GetSku() string { + if x != nil && x.Sku != nil { + return *x.Sku + } + return "" +} + +func (x *UpdateProductItemRequest) GetTimeSeries() string { + if x != nil && x.TimeSeries != nil { + return *x.TimeSeries + } + return "" +} + +func (x *UpdateProductItemRequest) GetMedia() []*Media { + if x != nil { + return x.Media + } + return nil +} + +func (x *UpdateProductItemRequest) GetStatus() string { + if x != nil && x.Status != nil { + return *x.Status + } + return "" +} + +func (x *UpdateProductItemRequest) GetFreight() []*CustomField { + if x != nil { + return x.Freight + } + return nil +} + +func (x *UpdateProductItemRequest) GetCustomFields() []*CustomField { + if x != nil { + return x.CustomFields + } + return nil +} + +type UpdateStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStatusRequest) Reset() { + *x = UpdateStatusRequest{} + mi := &file_generate_protobuf_product_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStatusRequest) ProtoMessage() {} + +func (x *UpdateStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStatusRequest.ProtoReflect.Descriptor instead. +func (*UpdateStatusRequest) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{33} +} + +func (x *UpdateStatusRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateStatusRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + var File_generate_protobuf_product_proto protoreflect.FileDescriptor var file_generate_protobuf_product_proto_rawDesc = string([]byte{ @@ -1851,67 +2707,239 @@ var file_generate_protobuf_product_proto_rawDesc = string([]byte{ 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xa4, 0x07, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, - 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x3d, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4d, 0x6f, 0x64, - 0x69, 0x66, 0x79, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0f, - 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x37, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x74, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, - 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, - 0x12, 0x43, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, - 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x35, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x61, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x35, 0x0a, 0x0a, - 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x61, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x61, 0x67, 0x73, 0x52, - 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, - 0x65, 0x73, 0x70, 0x12, 0x2f, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, - 0x73, 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xf7, 0x04, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x73, 0x68, 0x6f, 0x72, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x75, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x55, 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x69, 0x73, 0x46, 0x72, 0x65, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x6f, + 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x12, + 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x6b, 0x75, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x73, 0x6b, 0x75, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x69, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x05, 0x6d, 0x65, 0x64, 0x69, + 0x61, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x52, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x66, 0x72, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x66, + 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x39, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x6c, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x61, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x09, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, + 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x22, + 0x4f, 0x0a, 0x05, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, + 0x73, 0x6f, 0x72, 0x74, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x73, 0x6f, 0x72, 0x74, + 0x22, 0x35, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x27, 0x0a, + 0x15, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xfe, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x21, 0x0a, + 0x0c, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x23, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x75, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x69, 0x73, 0x55, 0x6e, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x66, 0x72, 0x65, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x06, 0x69, 0x73, 0x46, 0x72, 0x65, 0x65, + 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, + 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x69, 0x73, 0x5f, 0x75, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x59, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x34, + 0x0a, 0x22, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, + 0x74, 0x65, 0x6d, 0x73, 0x42, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, + 0x44, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x22, 0x3f, 0x0a, 0x17, 0x49, 0x6e, 0x63, 0x44, 0x65, 0x63, 0x53, 0x61, + 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82, 0x05, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, + 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, + 0x10, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x75, 0x6e, 0x5f, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x09, 0x69, 0x73, 0x55, + 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x69, 0x73, 0x5f, + 0x66, 0x72, 0x65, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x06, 0x69, 0x73, + 0x46, 0x72, 0x65, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x63, 0x6b, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x48, 0x05, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x88, + 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x06, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x15, 0x0a, + 0x03, 0x73, 0x6b, 0x75, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07, 0x52, 0x03, 0x73, 0x6b, + 0x75, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x08, 0x52, 0x0a, 0x74, 0x69, 0x6d, + 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x05, 0x6d, 0x65, + 0x64, 0x69, 0x61, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x2e, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x52, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, + 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, + 0x07, 0x66, 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x66, 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x39, 0x0a, + 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0e, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x69, 0x73, 0x5f, 0x75, + 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, 0x73, 0x5f, 0x66, + 0x72, 0x65, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x42, 0x08, 0x0a, + 0x06, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x73, 0x6b, 0x75, 0x42, + 0x0e, 0x0a, 0x0c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3d, 0x0a, 0x13, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0xbf, 0x0c, 0x0a, 0x07, 0x50, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, - 0x71, 0x1a, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, - 0x12, 0x37, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x14, 0x2e, 0x70, - 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, - 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x33, 0x0a, 0x09, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, - 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, - 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x42, - 0x79, 0x55, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x46, - 0x69, 0x6e, 0x64, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x42, 0x79, 0x55, 0x49, - 0x44, 0x52, 0x65, 0x71, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4b, - 0x59, 0x43, 0x12, 0x34, 0x0a, 0x0b, 0x46, 0x69, 0x6e, 0x64, 0x4b, 0x59, 0x43, 0x42, 0x79, 0x49, - 0x44, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, - 0x4b, 0x59, 0x43, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4b, 0x59, 0x43, 0x12, 0x34, 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, - 0x4b, 0x59, 0x43, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3f, - 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x59, 0x43, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x0f, - 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x3b, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4b, 0x59, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0b, 0x5a, 0x09, - 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, + 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x61, 0x74, + 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x36, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x2e, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x1a, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x12, 0x43, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x19, + 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x74, + 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x35, 0x0a, 0x0a, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, + 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, + 0x12, 0x35, 0x0a, 0x0a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x61, 0x67, 0x73, 0x12, 0x16, + 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, + 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2f, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x54, + 0x61, 0x67, 0x73, 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x54, 0x61, + 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x54, 0x61, 0x67, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x67, 0x73, + 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x33, 0x0a, + 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x52, 0x65, + 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x42, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x4b, 0x59, 0x43, 0x42, 0x79, 0x55, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4b, 0x59, 0x43, + 0x42, 0x79, 0x55, 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x2e, 0x4b, 0x59, 0x43, 0x12, 0x34, 0x0a, 0x0b, 0x46, 0x69, 0x6e, 0x64, 0x4b, 0x59, + 0x43, 0x42, 0x79, 0x49, 0x44, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x46, 0x69, 0x6e, 0x64, 0x4b, 0x59, 0x43, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x0c, + 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4b, 0x59, 0x43, 0x12, 0x34, 0x0a, 0x07, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x3f, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x3b, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, + 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, + 0x12, 0x40, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x21, + 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x46, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x5f, 0x0a, 0x1a, 0x47, 0x65, + 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x42, 0x79, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x44, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, + 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x12, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, + 0x73, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, + 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5f, 0x0a, 0x1f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x42, 0x79, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x49, 0x74, 0x65, 0x6d, 0x73, 0x42, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, + 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0d, 0x49, 0x6e, 0x63, 0x53, 0x61, 0x6c, + 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x49, 0x6e, 0x63, 0x44, 0x65, 0x63, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0d, 0x44, 0x65, + 0x63, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x49, 0x6e, 0x63, 0x44, 0x65, 0x63, 0x53, 0x61, 0x6c, 0x65, + 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3c, + 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0c, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x2e, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x2e, 0x4f, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0b, 0x5a, 0x09, 0x2e, + 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -1926,72 +2954,110 @@ func file_generate_protobuf_product_proto_rawDescGZIP() []byte { return file_generate_protobuf_product_proto_rawDescData } -var file_generate_protobuf_product_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_generate_protobuf_product_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_generate_protobuf_product_proto_goTypes = []any{ - (*OKResp)(nil), // 0: product.OKResp - (*NoneReq)(nil), // 1: product.NoneReq - (*CreateCategoryReq)(nil), // 2: product.CreateCategoryReq - (*ModifyCategoryReq)(nil), // 3: product.ModifyCategoryReq - (*CategoryReq)(nil), // 4: product.CategoryReq - (*Category)(nil), // 5: product.Category - (*ListCategoryReq)(nil), // 6: product.ListCategoryReq - (*ListCategoryResp)(nil), // 7: product.ListCategoryResp - (*CreateTagsReq)(nil), // 8: product.CreateTagsReq - (*ModifyTagsReq)(nil), // 9: product.ModifyTagsReq - (*TagsReq)(nil), // 10: product.TagsReq - (*Tags)(nil), // 11: product.Tags - (*ListTagsReq)(nil), // 12: product.ListTagsReq - (*ListTagsResp)(nil), // 13: product.ListTagsResp - (*KYC)(nil), // 14: product.KYC - (*CreateKYCReq)(nil), // 15: product.CreateKYCReq - (*FindLatestKYCByUIDReq)(nil), // 16: product.FindLatestKYCByUIDReq - (*FindKYCByIDReq)(nil), // 17: product.FindKYCByIDReq - (*ListKYCReq)(nil), // 18: product.ListKYCReq - (*ListKYCResp)(nil), // 19: product.ListKYCResp - (*UpdateKYCStatusReq)(nil), // 20: product.UpdateKYCStatusReq - (*UpdateKYCInfoReq)(nil), // 21: product.UpdateKYCInfoReq + (*OKResp)(nil), // 0: product.OKResp + (*NoneReq)(nil), // 1: product.NoneReq + (*CreateCategoryReq)(nil), // 2: product.CreateCategoryReq + (*ModifyCategoryReq)(nil), // 3: product.ModifyCategoryReq + (*CategoryReq)(nil), // 4: product.CategoryReq + (*Category)(nil), // 5: product.Category + (*ListCategoryReq)(nil), // 6: product.ListCategoryReq + (*ListCategoryResp)(nil), // 7: product.ListCategoryResp + (*CreateTagsReq)(nil), // 8: product.CreateTagsReq + (*ModifyTagsReq)(nil), // 9: product.ModifyTagsReq + (*TagsReq)(nil), // 10: product.TagsReq + (*Tags)(nil), // 11: product.Tags + (*ListTagsReq)(nil), // 12: product.ListTagsReq + (*ListTagsResp)(nil), // 13: product.ListTagsResp + (*KYC)(nil), // 14: product.KYC + (*CreateKYCReq)(nil), // 15: product.CreateKYCReq + (*FindLatestKYCByUIDReq)(nil), // 16: product.FindLatestKYCByUIDReq + (*FindKYCByIDReq)(nil), // 17: product.FindKYCByIDReq + (*ListKYCReq)(nil), // 18: product.ListKYCReq + (*ListKYCResp)(nil), // 19: product.ListKYCResp + (*UpdateKYCStatusReq)(nil), // 20: product.UpdateKYCStatusReq + (*UpdateKYCInfoReq)(nil), // 21: product.UpdateKYCInfoReq + (*ProductItem)(nil), // 22: product.ProductItem + (*Media)(nil), // 23: product.Media + (*CustomField)(nil), // 24: product.CustomField + (*CreateProductItemRequest)(nil), // 25: product.CreateProductItemRequest + (*GetProductItemRequest)(nil), // 26: product.GetProductItemRequest + (*ListProductItemRequest)(nil), // 27: product.ListProductItemRequest + (*ListProductItemResponse)(nil), // 28: product.ListProductItemResponse + (*DeleteProductItemRequest)(nil), // 29: product.DeleteProductItemRequest + (*DeleteProductItemsByReferenceIDReq)(nil), // 30: product.DeleteProductItemsByReferenceIDReq + (*IncDecSalesCountRequest)(nil), // 31: product.IncDecSalesCountRequest + (*UpdateProductItemRequest)(nil), // 32: product.UpdateProductItemRequest + (*UpdateStatusRequest)(nil), // 33: product.UpdateStatusRequest } var file_generate_protobuf_product_proto_depIdxs = []int32{ 5, // 0: product.ListCategoryResp.data:type_name -> product.Category 11, // 1: product.ListTagsResp.data:type_name -> product.Tags 14, // 2: product.ListKYCResp.list:type_name -> product.KYC - 2, // 3: product.Product.CreateCategory:input_type -> product.CreateCategoryReq - 3, // 4: product.Product.ModifyCategory:input_type -> product.ModifyCategoryReq - 4, // 5: product.Product.DeleteCategory:input_type -> product.CategoryReq - 4, // 6: product.Product.GetCategory:input_type -> product.CategoryReq - 6, // 7: product.Product.ListCategory:input_type -> product.ListCategoryReq - 8, // 8: product.Product.CreateTags:input_type -> product.CreateTagsReq - 9, // 9: product.Product.ModifyTags:input_type -> product.ModifyTagsReq - 10, // 10: product.Product.DeleteTags:input_type -> product.TagsReq - 10, // 11: product.Product.GetTags:input_type -> product.TagsReq - 12, // 12: product.Product.ListTags:input_type -> product.ListTagsReq - 15, // 13: product.Product.CreateKYC:input_type -> product.CreateKYCReq - 16, // 14: product.Product.FindLatestKYCByUID:input_type -> product.FindLatestKYCByUIDReq - 17, // 15: product.Product.FindKYCByID:input_type -> product.FindKYCByIDReq - 18, // 16: product.Product.ListKYC:input_type -> product.ListKYCReq - 20, // 17: product.Product.UpdateKYCStatus:input_type -> product.UpdateKYCStatusReq - 21, // 18: product.Product.UpdateKYCInfo:input_type -> product.UpdateKYCInfoReq - 0, // 19: product.Product.CreateCategory:output_type -> product.OKResp - 0, // 20: product.Product.ModifyCategory:output_type -> product.OKResp - 0, // 21: product.Product.DeleteCategory:output_type -> product.OKResp - 5, // 22: product.Product.GetCategory:output_type -> product.Category - 7, // 23: product.Product.ListCategory:output_type -> product.ListCategoryResp - 0, // 24: product.Product.CreateTags:output_type -> product.OKResp - 0, // 25: product.Product.ModifyTags:output_type -> product.OKResp - 0, // 26: product.Product.DeleteTags:output_type -> product.OKResp - 11, // 27: product.Product.GetTags:output_type -> product.Tags - 13, // 28: product.Product.ListTags:output_type -> product.ListTagsResp - 0, // 29: product.Product.CreateKYC:output_type -> product.OKResp - 14, // 30: product.Product.FindLatestKYCByUID:output_type -> product.KYC - 14, // 31: product.Product.FindKYCByID:output_type -> product.KYC - 19, // 32: product.Product.ListKYC:output_type -> product.ListKYCResp - 0, // 33: product.Product.UpdateKYCStatus:output_type -> product.OKResp - 0, // 34: product.Product.UpdateKYCInfo:output_type -> product.OKResp - 19, // [19:35] is the sub-list for method output_type - 3, // [3:19] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 23, // 3: product.ProductItem.media:type_name -> product.Media + 24, // 4: product.ProductItem.freight:type_name -> product.CustomField + 24, // 5: product.ProductItem.custom_fields:type_name -> product.CustomField + 22, // 6: product.CreateProductItemRequest.item:type_name -> product.ProductItem + 22, // 7: product.ListProductItemResponse.data:type_name -> product.ProductItem + 23, // 8: product.UpdateProductItemRequest.media:type_name -> product.Media + 24, // 9: product.UpdateProductItemRequest.freight:type_name -> product.CustomField + 24, // 10: product.UpdateProductItemRequest.custom_fields:type_name -> product.CustomField + 2, // 11: product.Product.CreateCategory:input_type -> product.CreateCategoryReq + 3, // 12: product.Product.ModifyCategory:input_type -> product.ModifyCategoryReq + 4, // 13: product.Product.DeleteCategory:input_type -> product.CategoryReq + 4, // 14: product.Product.GetCategory:input_type -> product.CategoryReq + 6, // 15: product.Product.ListCategory:input_type -> product.ListCategoryReq + 8, // 16: product.Product.CreateTags:input_type -> product.CreateTagsReq + 9, // 17: product.Product.ModifyTags:input_type -> product.ModifyTagsReq + 10, // 18: product.Product.DeleteTags:input_type -> product.TagsReq + 10, // 19: product.Product.GetTags:input_type -> product.TagsReq + 12, // 20: product.Product.ListTags:input_type -> product.ListTagsReq + 15, // 21: product.Product.CreateKYC:input_type -> product.CreateKYCReq + 16, // 22: product.Product.FindLatestKYCByUID:input_type -> product.FindLatestKYCByUIDReq + 17, // 23: product.Product.FindKYCByID:input_type -> product.FindKYCByIDReq + 18, // 24: product.Product.ListKYC:input_type -> product.ListKYCReq + 20, // 25: product.Product.UpdateKYCStatus:input_type -> product.UpdateKYCStatusReq + 21, // 26: product.Product.UpdateKYCInfo:input_type -> product.UpdateKYCInfoReq + 25, // 27: product.Product.CreateItem:input_type -> product.CreateProductItemRequest + 26, // 28: product.Product.GetProductItem:input_type -> product.GetProductItemRequest + 27, // 29: product.Product.GetProductItemsByProductID:input_type -> product.ListProductItemRequest + 29, // 30: product.Product.DeleteProductItems:input_type -> product.DeleteProductItemRequest + 30, // 31: product.Product.DeleteProductItemsByReferenceID:input_type -> product.DeleteProductItemsByReferenceIDReq + 31, // 32: product.Product.IncSalesCount:input_type -> product.IncDecSalesCountRequest + 31, // 33: product.Product.DecSalesCount:input_type -> product.IncDecSalesCountRequest + 32, // 34: product.Product.Update:input_type -> product.UpdateProductItemRequest + 33, // 35: product.Product.UpdateStatus:input_type -> product.UpdateStatusRequest + 0, // 36: product.Product.CreateCategory:output_type -> product.OKResp + 0, // 37: product.Product.ModifyCategory:output_type -> product.OKResp + 0, // 38: product.Product.DeleteCategory:output_type -> product.OKResp + 5, // 39: product.Product.GetCategory:output_type -> product.Category + 7, // 40: product.Product.ListCategory:output_type -> product.ListCategoryResp + 0, // 41: product.Product.CreateTags:output_type -> product.OKResp + 0, // 42: product.Product.ModifyTags:output_type -> product.OKResp + 0, // 43: product.Product.DeleteTags:output_type -> product.OKResp + 11, // 44: product.Product.GetTags:output_type -> product.Tags + 13, // 45: product.Product.ListTags:output_type -> product.ListTagsResp + 0, // 46: product.Product.CreateKYC:output_type -> product.OKResp + 14, // 47: product.Product.FindLatestKYCByUID:output_type -> product.KYC + 14, // 48: product.Product.FindKYCByID:output_type -> product.KYC + 19, // 49: product.Product.ListKYC:output_type -> product.ListKYCResp + 0, // 50: product.Product.UpdateKYCStatus:output_type -> product.OKResp + 0, // 51: product.Product.UpdateKYCInfo:output_type -> product.OKResp + 0, // 52: product.Product.CreateItem:output_type -> product.OKResp + 22, // 53: product.Product.GetProductItem:output_type -> product.ProductItem + 28, // 54: product.Product.GetProductItemsByProductID:output_type -> product.ListProductItemResponse + 0, // 55: product.Product.DeleteProductItems:output_type -> product.OKResp + 0, // 56: product.Product.DeleteProductItemsByReferenceID:output_type -> product.OKResp + 0, // 57: product.Product.IncSalesCount:output_type -> product.OKResp + 0, // 58: product.Product.DecSalesCount:output_type -> product.OKResp + 0, // 59: product.Product.Update:output_type -> product.OKResp + 0, // 60: product.Product.UpdateStatus:output_type -> product.OKResp + 36, // [36:61] is the sub-list for method output_type + 11, // [11:36] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_generate_protobuf_product_proto_init() } @@ -2005,13 +3071,17 @@ func file_generate_protobuf_product_proto_init() { file_generate_protobuf_product_proto_msgTypes[18].OneofWrappers = []any{} file_generate_protobuf_product_proto_msgTypes[20].OneofWrappers = []any{} file_generate_protobuf_product_proto_msgTypes[21].OneofWrappers = []any{} + file_generate_protobuf_product_proto_msgTypes[22].OneofWrappers = []any{} + file_generate_protobuf_product_proto_msgTypes[23].OneofWrappers = []any{} + file_generate_protobuf_product_proto_msgTypes[27].OneofWrappers = []any{} + file_generate_protobuf_product_proto_msgTypes[32].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_generate_protobuf_product_proto_rawDesc), len(file_generate_protobuf_product_proto_rawDesc)), NumEnums: 0, - NumMessages: 22, + NumMessages: 34, NumExtensions: 0, NumServices: 1, }, diff --git a/gen_result/pb/product/product_grpc.pb.go b/gen_result/pb/product/product_grpc.pb.go index 64ad7c3..6c434b1 100644 --- a/gen_result/pb/product/product_grpc.pb.go +++ b/gen_result/pb/product/product_grpc.pb.go @@ -19,22 +19,31 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Product_CreateCategory_FullMethodName = "/product.Product/CreateCategory" - Product_ModifyCategory_FullMethodName = "/product.Product/ModifyCategory" - Product_DeleteCategory_FullMethodName = "/product.Product/DeleteCategory" - Product_GetCategory_FullMethodName = "/product.Product/GetCategory" - Product_ListCategory_FullMethodName = "/product.Product/ListCategory" - Product_CreateTags_FullMethodName = "/product.Product/CreateTags" - Product_ModifyTags_FullMethodName = "/product.Product/ModifyTags" - Product_DeleteTags_FullMethodName = "/product.Product/DeleteTags" - Product_GetTags_FullMethodName = "/product.Product/GetTags" - Product_ListTags_FullMethodName = "/product.Product/ListTags" - Product_CreateKYC_FullMethodName = "/product.Product/CreateKYC" - Product_FindLatestKYCByUID_FullMethodName = "/product.Product/FindLatestKYCByUID" - Product_FindKYCByID_FullMethodName = "/product.Product/FindKYCByID" - Product_ListKYC_FullMethodName = "/product.Product/ListKYC" - Product_UpdateKYCStatus_FullMethodName = "/product.Product/UpdateKYCStatus" - Product_UpdateKYCInfo_FullMethodName = "/product.Product/UpdateKYCInfo" + Product_CreateCategory_FullMethodName = "/product.Product/CreateCategory" + Product_ModifyCategory_FullMethodName = "/product.Product/ModifyCategory" + Product_DeleteCategory_FullMethodName = "/product.Product/DeleteCategory" + Product_GetCategory_FullMethodName = "/product.Product/GetCategory" + Product_ListCategory_FullMethodName = "/product.Product/ListCategory" + Product_CreateTags_FullMethodName = "/product.Product/CreateTags" + Product_ModifyTags_FullMethodName = "/product.Product/ModifyTags" + Product_DeleteTags_FullMethodName = "/product.Product/DeleteTags" + Product_GetTags_FullMethodName = "/product.Product/GetTags" + Product_ListTags_FullMethodName = "/product.Product/ListTags" + Product_CreateKYC_FullMethodName = "/product.Product/CreateKYC" + Product_FindLatestKYCByUID_FullMethodName = "/product.Product/FindLatestKYCByUID" + Product_FindKYCByID_FullMethodName = "/product.Product/FindKYCByID" + Product_ListKYC_FullMethodName = "/product.Product/ListKYC" + Product_UpdateKYCStatus_FullMethodName = "/product.Product/UpdateKYCStatus" + Product_UpdateKYCInfo_FullMethodName = "/product.Product/UpdateKYCInfo" + Product_CreateItem_FullMethodName = "/product.Product/CreateItem" + Product_GetProductItem_FullMethodName = "/product.Product/GetProductItem" + Product_GetProductItemsByProductID_FullMethodName = "/product.Product/GetProductItemsByProductID" + Product_DeleteProductItems_FullMethodName = "/product.Product/DeleteProductItems" + Product_DeleteProductItemsByReferenceID_FullMethodName = "/product.Product/DeleteProductItemsByReferenceID" + Product_IncSalesCount_FullMethodName = "/product.Product/IncSalesCount" + Product_DecSalesCount_FullMethodName = "/product.Product/DecSalesCount" + Product_Update_FullMethodName = "/product.Product/Update" + Product_UpdateStatus_FullMethodName = "/product.Product/UpdateStatus" ) // ProductClient is the client API for Product service. @@ -78,6 +87,26 @@ type ProductClient interface { UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) // UpdateKYCInfo 更新使用者的 KYC(尚未審核) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) + // ====================== Know You Customer Service End ====================== + // ====================== ProductItem Service Start ====================== + // CreateItem 建立 ProductItem + CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // GetProductItem 取得 ProductItem + GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) + // GetProductItemsByProductID 使用 ProductID 取得 ProductItems + GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) + // DeleteProductItems 刪除 Delete Product Item + DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item + DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) + // IncSalesCount 增加賣出數量 + IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) + // DecSalesCount 減少賣出數量 + DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) + // Update 更新 Item + Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) + // UpdateStatus 更新 Item status + UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) } type productClient struct { @@ -248,6 +277,96 @@ func (c *productClient) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, return out, nil } +func (c *productClient) CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_CreateItem_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ProductItem) + err := c.cc.Invoke(ctx, Product_GetProductItem_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListProductItemResponse) + err := c.cc.Invoke(ctx, Product_GetProductItemsByProductID_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_DeleteProductItems_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_DeleteProductItemsByReferenceID_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_IncSalesCount_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_DecSalesCount_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_Update_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_UpdateStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // ProductServer is the server API for Product service. // All implementations must embed UnimplementedProductServer // for forward compatibility. @@ -289,6 +408,26 @@ type ProductServer interface { UpdateKYCStatus(context.Context, *UpdateKYCStatusReq) (*OKResp, error) // UpdateKYCInfo 更新使用者的 KYC(尚未審核) UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error) + // ====================== Know You Customer Service End ====================== + // ====================== ProductItem Service Start ====================== + // CreateItem 建立 ProductItem + CreateItem(context.Context, *CreateProductItemRequest) (*OKResp, error) + // GetProductItem 取得 ProductItem + GetProductItem(context.Context, *GetProductItemRequest) (*ProductItem, error) + // GetProductItemsByProductID 使用 ProductID 取得 ProductItems + GetProductItemsByProductID(context.Context, *ListProductItemRequest) (*ListProductItemResponse, error) + // DeleteProductItems 刪除 Delete Product Item + DeleteProductItems(context.Context, *DeleteProductItemRequest) (*OKResp, error) + // DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item + DeleteProductItemsByReferenceID(context.Context, *DeleteProductItemsByReferenceIDReq) (*OKResp, error) + // IncSalesCount 增加賣出數量 + IncSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) + // DecSalesCount 減少賣出數量 + DecSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) + // Update 更新 Item + Update(context.Context, *UpdateProductItemRequest) (*OKResp, error) + // UpdateStatus 更新 Item status + UpdateStatus(context.Context, *UpdateStatusRequest) (*OKResp, error) mustEmbedUnimplementedProductServer() } @@ -347,6 +486,33 @@ func (UnimplementedProductServer) UpdateKYCStatus(context.Context, *UpdateKYCSta func (UnimplementedProductServer) UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateKYCInfo not implemented") } +func (UnimplementedProductServer) CreateItem(context.Context, *CreateProductItemRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateItem not implemented") +} +func (UnimplementedProductServer) GetProductItem(context.Context, *GetProductItemRequest) (*ProductItem, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetProductItem not implemented") +} +func (UnimplementedProductServer) GetProductItemsByProductID(context.Context, *ListProductItemRequest) (*ListProductItemResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetProductItemsByProductID not implemented") +} +func (UnimplementedProductServer) DeleteProductItems(context.Context, *DeleteProductItemRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteProductItems not implemented") +} +func (UnimplementedProductServer) DeleteProductItemsByReferenceID(context.Context, *DeleteProductItemsByReferenceIDReq) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteProductItemsByReferenceID not implemented") +} +func (UnimplementedProductServer) IncSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method IncSalesCount not implemented") +} +func (UnimplementedProductServer) DecSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method DecSalesCount not implemented") +} +func (UnimplementedProductServer) Update(context.Context, *UpdateProductItemRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Update not implemented") +} +func (UnimplementedProductServer) UpdateStatus(context.Context, *UpdateStatusRequest) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateStatus not implemented") +} func (UnimplementedProductServer) mustEmbedUnimplementedProductServer() {} func (UnimplementedProductServer) testEmbeddedByValue() {} @@ -656,6 +822,168 @@ func _Product_UpdateKYCInfo_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Product_CreateItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateProductItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).CreateItem(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_CreateItem_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).CreateItem(ctx, req.(*CreateProductItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_GetProductItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetProductItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).GetProductItem(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_GetProductItem_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).GetProductItem(ctx, req.(*GetProductItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_GetProductItemsByProductID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListProductItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).GetProductItemsByProductID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_GetProductItemsByProductID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).GetProductItemsByProductID(ctx, req.(*ListProductItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_DeleteProductItems_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteProductItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).DeleteProductItems(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_DeleteProductItems_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).DeleteProductItems(ctx, req.(*DeleteProductItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_DeleteProductItemsByReferenceID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteProductItemsByReferenceIDReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).DeleteProductItemsByReferenceID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_DeleteProductItemsByReferenceID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).DeleteProductItemsByReferenceID(ctx, req.(*DeleteProductItemsByReferenceIDReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_IncSalesCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IncDecSalesCountRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).IncSalesCount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_IncSalesCount_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).IncSalesCount(ctx, req.(*IncDecSalesCountRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_DecSalesCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IncDecSalesCountRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).DecSalesCount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_DecSalesCount_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).DecSalesCount(ctx, req.(*IncDecSalesCountRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateProductItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).Update(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_Update_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).Update(ctx, req.(*UpdateProductItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_UpdateStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).UpdateStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_UpdateStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).UpdateStatus(ctx, req.(*UpdateStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Product_ServiceDesc is the grpc.ServiceDesc for Product service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -727,6 +1055,42 @@ var Product_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpdateKYCInfo", Handler: _Product_UpdateKYCInfo_Handler, }, + { + MethodName: "CreateItem", + Handler: _Product_CreateItem_Handler, + }, + { + MethodName: "GetProductItem", + Handler: _Product_GetProductItem_Handler, + }, + { + MethodName: "GetProductItemsByProductID", + Handler: _Product_GetProductItemsByProductID_Handler, + }, + { + MethodName: "DeleteProductItems", + Handler: _Product_DeleteProductItems_Handler, + }, + { + MethodName: "DeleteProductItemsByReferenceID", + Handler: _Product_DeleteProductItemsByReferenceID_Handler, + }, + { + MethodName: "IncSalesCount", + Handler: _Product_IncSalesCount_Handler, + }, + { + MethodName: "DecSalesCount", + Handler: _Product_DecSalesCount_Handler, + }, + { + MethodName: "Update", + Handler: _Product_Update_Handler, + }, + { + MethodName: "UpdateStatus", + Handler: _Product_UpdateStatus_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "generate/protobuf/product.proto", diff --git a/generate/protobuf/product.proto b/generate/protobuf/product.proto index d7107ae..f14fd1b 100644 --- a/generate/protobuf/product.proto +++ b/generate/protobuf/product.proto @@ -174,8 +174,95 @@ message UpdateKYCInfoReq { optional string bank_account = 14; } +// ====================== Product Item Param ====================== +message ProductItem { + optional string id = 1; + string reference_id = 2; + string name = 3; + string description = 4; + string short_description = 5; + bool is_un_limit = 6; + bool is_free = 7; + uint64 stock = 8; + string price = 9; + string sku = 10; + string time_series = 11; + repeated Media media = 12; + string status = 13; + repeated CustomField freight = 14; + repeated CustomField custom_fields = 15; + uint64 sales_count = 16; + optional string updated_at = 17; + optional string created_at = 18; +} +message Media { + string url = 1; + string type = 2; + optional uint64 sort=3; +} + +message CustomField { + string key = 1; + string value = 2; +} + +message CreateProductItemRequest { + ProductItem item = 1; +} + +message GetProductItemRequest { + string id = 1; +} + +message ListProductItemRequest { + int64 page_size = 1; + int64 page_index = 2; + string reference_id = 3; + optional bool is_un_limit = 4; + optional bool is_free = 5; + optional string status = 6; +} + +message ListProductItemResponse{ + repeated ProductItem data = 1; + int64 total = 2; +} + +message DeleteProductItemRequest { + repeated string id = 1; +} + +message DeleteProductItemsByReferenceIDReq { + string id = 1; +} + +message IncDecSalesCountRequest { + string id = 1; + uint64 count = 2; +} +message UpdateProductItemRequest { + string id = 1; + optional string name = 2; + optional string description = 3; + optional string short_description = 4; + optional bool is_un_limit = 5; + optional bool is_free = 6; + optional uint64 stock = 7; + optional string price = 8; + optional string sku = 9; + optional string time_series = 10; + repeated Media media = 11; + optional string status = 12; + repeated CustomField freight = 13; + repeated CustomField custom_fields = 14; +} + +message UpdateStatusRequest { + string id = 1; + string status = 2; +} service Product { @@ -216,5 +303,25 @@ service Product { rpc UpdateKYCStatus (UpdateKYCStatusReq) returns (OKResp); // UpdateKYCInfo 更新使用者的 KYC(尚未審核) rpc UpdateKYCInfo (UpdateKYCInfoReq) returns (OKResp); - // ====================== Know You Customer Service End ====================== + // ====================== Know You Customer Service End ====================== + // ====================== ProductItem Service Start ====================== + // CreateItem 建立 ProductItem + rpc CreateItem(CreateProductItemRequest) returns (OKResp); + // GetProductItem 取得 ProductItem + rpc GetProductItem(GetProductItemRequest) returns (ProductItem); + // GetProductItemsByProductID 使用 ProductID 取得 ProductItems + rpc GetProductItemsByProductID(ListProductItemRequest) returns (ListProductItemResponse); + // DeleteProductItems 刪除 Delete Product Item + rpc DeleteProductItems(DeleteProductItemRequest) returns (OKResp); + // DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item + rpc DeleteProductItemsByReferenceID(DeleteProductItemsByReferenceIDReq) returns (OKResp); + // IncSalesCount 增加賣出數量 + rpc IncSalesCount(IncDecSalesCountRequest) returns (OKResp); + // DecSalesCount 減少賣出數量 + rpc DecSalesCount(IncDecSalesCountRequest) returns (OKResp); + // Update 更新 Item + rpc Update(UpdateProductItemRequest) returns (OKResp); + // UpdateStatus 更新 Item status + rpc UpdateStatus(UpdateStatusRequest) returns (OKResp); + // ====================== ProductItem Service End ====================== } diff --git a/go.mod b/go.mod index 5e46a1f..13d5c2c 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( code.30cm.net/digimon/library-go/errs v1.2.14 code.30cm.net/digimon/library-go/mongo v0.0.9 github.com/alicebob/miniredis/v2 v2.34.0 + github.com/golang/snappy v0.0.4 github.com/shopspring/decimal v1.4.0 github.com/stretchr/testify v1.10.0 github.com/testcontainers/testcontainers-go v0.34.0 @@ -48,7 +49,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect diff --git a/internal/logic/product/create_item_logic.go b/internal/logic/product/create_item_logic.go new file mode 100644 index 0000000..d8c0b92 --- /dev/null +++ b/internal/logic/product/create_item_logic.go @@ -0,0 +1,96 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/internal/utils" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + "context" + + PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateItemLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewCreateItemLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateItemLogic { + return &CreateItemLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *CreateItemLogic) CreateItem(in *PB.CreateProductItemRequest) (*PB.OKResp, error) { + insert := &usecase.ProductItems{ + ReferenceID: in.GetItem().ReferenceId, // 對應的專案 ID + Name: in.GetItem().Name, // 名稱 + Description: utils.EncodeToBase64Snappy(in.GetItem().Description), // 描述 + ShortDescription: utils.EncodeToBase64Snappy(in.GetItem().ShortDescription), // 封面簡短描述 + IsUnLimit: in.GetItem().IsUnLimit, // 是否沒有數量上限 + IsFree: in.GetItem().IsFree, // 是否為免費品項(贈品) -> 開啟就是自訂金額 + Stock: in.GetItem().Stock, // 庫存總數 + Price: in.GetItem().Price, // 價格 + SKU: in.GetItem().Sku, // 型號:對應顯示 Item 的 FK + SalesCount: 0, // 已賣出數量(相反,減到零就不能在賣) + } + if len(in.GetItem().Media) > 0 { + // 專案動態內容(圖片或者影片) + m := make([]usecase.Media, 0, len(in.GetItem().Media)) + for _, item := range in.GetItem().Media { + m = append(m, usecase.Media{ + URL: item.Url, + Type: item.Type, + }) + } + insert.Media = m + } + if len(in.GetItem().CustomFields) > 0 { + // 自定義屬性 + c := make([]usecase.CustomFields, 0, len(in.GetItem().CustomFields)) + for _, cItem := range in.GetItem().CustomFields { + c = append(c, usecase.CustomFields{ + Key: cItem.Key, + Value: cItem.Value, + }) + } + insert.CustomFields = c + } + if len(in.GetItem().Freight) > 0 { + // 運費 + f := make([]usecase.CustomFields, 0, len(in.GetItem().Freight)) + for _, fItem := range in.GetItem().Freight { + f = append(f, usecase.CustomFields{ + Key: fItem.Key, + Value: fItem.Value, + }) + } + insert.Freight = f + } + + status, e := product.StringToItemStatus(in.GetItem().Status) + if !e { + return nil, errs.InvalidFormat("failed to convert string to item status") + } + insert.Status = status + + timeSeries, te := product.StringToTimeSeries(in.GetItem().TimeSeries) + if !te { + return nil, errs.InvalidFormat("failed to convert string to time series") + } + insert.TimeSeries = timeSeries + + err := l.svcCtx.ProductItemUseCase.Create(l.ctx, insert) + + if err != nil { + return nil, err + } + + return &PB.OKResp{}, nil +} diff --git a/internal/logic/product/dec_sales_count_logic.go b/internal/logic/product/dec_sales_count_logic.go new file mode 100644 index 0000000..ef88d04 --- /dev/null +++ b/internal/logic/product/dec_sales_count_logic.go @@ -0,0 +1,35 @@ +package productlogic + +import ( + "context" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DecSalesCountLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewDecSalesCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DecSalesCountLogic { + return &DecSalesCountLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// DecSalesCount 減少賣出數量 +func (l *DecSalesCountLogic) DecSalesCount(in *product.IncDecSalesCountRequest) (*product.OKResp, error) { + // TODO 有問題可以在這邊加瑣 + err := l.svcCtx.ProductItemUseCase.DecSalesCount(l.ctx, in.GetId(), in.GetCount()) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/delete_product_items_by_reference_i_d_logic.go b/internal/logic/product/delete_product_items_by_reference_i_d_logic.go new file mode 100644 index 0000000..1087f77 --- /dev/null +++ b/internal/logic/product/delete_product_items_by_reference_i_d_logic.go @@ -0,0 +1,34 @@ +package productlogic + +import ( + "context" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteProductItemsByReferenceIDLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewDeleteProductItemsByReferenceIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductItemsByReferenceIDLogic { + return &DeleteProductItemsByReferenceIDLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item +func (l *DeleteProductItemsByReferenceIDLogic) DeleteProductItemsByReferenceID(in *product.DeleteProductItemsByReferenceIDReq) (*product.OKResp, error) { + err := l.svcCtx.ProductItemUseCase.DeleteByReferenceID(l.ctx, in.GetId()) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/delete_product_items_logic.go b/internal/logic/product/delete_product_items_logic.go new file mode 100644 index 0000000..45fa1a2 --- /dev/null +++ b/internal/logic/product/delete_product_items_logic.go @@ -0,0 +1,34 @@ +package productlogic + +import ( + "context" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteProductItemsLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewDeleteProductItemsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductItemsLogic { + return &DeleteProductItemsLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// DeleteProductItems 刪除 Delete Product Item +func (l *DeleteProductItemsLogic) DeleteProductItems(in *product.DeleteProductItemRequest) (*product.OKResp, error) { + err := l.svcCtx.ProductItemUseCase.Delete(l.ctx, in.GetId()) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/get_product_item_logic.go b/internal/logic/product/get_product_item_logic.go new file mode 100644 index 0000000..d7cfdbe --- /dev/null +++ b/internal/logic/product/get_product_item_logic.go @@ -0,0 +1,83 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/internal/utils" + "context" + "google.golang.org/protobuf/proto" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetProductItemLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGetProductItemLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductItemLogic { + return &GetProductItemLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// GetProductItem 取得 ProductItem +func (l *GetProductItemLogic) GetProductItem(in *product.GetProductItemRequest) (*product.ProductItem, error) { + item, err := l.svcCtx.ProductItemUseCase.Get(l.ctx, in.GetId()) + if err != nil { + return nil, err + } + + result := &product.ProductItem{ + Id: proto.String(item.ID), + ReferenceId: item.ReferenceID, + Name: item.Name, + Description: utils.DecodeToBase64Snappy(item.Description), + ShortDescription: utils.DecodeToBase64Snappy(item.ShortDescription), + IsUnLimit: item.IsUnLimit, + IsFree: item.IsFree, + Stock: item.Stock, + Price: item.Price, + Sku: item.SKU, + TimeSeries: item.TimeSeries.ToString(), + SalesCount: item.SalesCount, + Status: item.Status.ToString(), + UpdatedAt: proto.String(item.UpdatedAt), + CreatedAt: proto.String(item.CreatedAt), + } + media := make([]*product.Media, 0, len(item.Media)) + for _, pi := range item.Media { + media = append(media, &product.Media{ + Sort: proto.Uint64(pi.Sort), + Url: pi.URL, + Type: pi.Type, + }) + } + result.Media = media + + // 運費 + f := make([]*product.CustomField, 0, len(item.Freight)) + for _, fItem := range item.Freight { + f = append(f, &product.CustomField{ + Key: fItem.Key, + Value: fItem.Value, + }) + } + result.Freight = f + + // 運費 + c := make([]*product.CustomField, 0, len(item.CustomFields)) + for _, fItem := range item.CustomFields { + f = append(f, &product.CustomField{ + Key: fItem.Key, + Value: fItem.Value, + }) + } + result.CustomFields = c + + return result, nil +} diff --git a/internal/logic/product/get_product_items_by_product_i_d_logic.go b/internal/logic/product/get_product_items_by_product_i_d_logic.go new file mode 100644 index 0000000..26a209b --- /dev/null +++ b/internal/logic/product/get_product_items_by_product_i_d_logic.go @@ -0,0 +1,112 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/internal/utils" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + "context" + "google.golang.org/protobuf/proto" + + PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetProductItemsByProductIDLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGetProductItemsByProductIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductItemsByProductIDLogic { + return &GetProductItemsByProductIDLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// GetProductItemsByProductID 使用 ProductID 取得 ProductItems +func (l *GetProductItemsByProductIDLogic) GetProductItemsByProductID(in *PB.ListProductItemRequest) (*PB.ListProductItemResponse, error) { + filter := usecase.QueryProductItemParam{ + PageSize: in.GetPageSize(), + PageIndex: in.GetPageIndex(), + ReferenceID: proto.String(in.GetReferenceId()), + } + if in.Status != nil { + status, e := product.StringToItemStatus(in.GetStatus()) + if !e { + return nil, errs.InvalidFormat("failed to convert string to item status") + } + filter.Status = &status + } + if in.IsFree != nil { + filter.IsFree = in.IsFree + } + if in.IsUnLimit != nil { + filter.IsUnLimit = in.IsUnLimit + } + + list, total, err := l.svcCtx.ProductItemUseCase.List(l.ctx, filter) + if err != nil { + return nil, err + } + + result := make([]*PB.ProductItem, 0) + for _, item := range list { + pi := &PB.ProductItem{ + Id: proto.String(item.ID), + ReferenceId: item.ReferenceID, + Name: item.Name, + Description: utils.DecodeToBase64Snappy(item.Description), + ShortDescription: utils.DecodeToBase64Snappy(item.ShortDescription), + IsUnLimit: item.IsUnLimit, + IsFree: item.IsFree, + Stock: item.Stock, + Price: item.Price, + Sku: item.SKU, + TimeSeries: item.TimeSeries.ToString(), + SalesCount: item.SalesCount, + Status: item.Status.ToString(), + UpdatedAt: proto.String(item.UpdatedAt), + CreatedAt: proto.String(item.CreatedAt), + } + + media := make([]*PB.Media, 0, len(item.Media)) + for _, pi := range item.Media { + media = append(media, &PB.Media{ + Sort: proto.Uint64(pi.Sort), + Url: pi.URL, + Type: pi.Type, + }) + } + pi.Media = media + // 運費 + f := make([]*PB.CustomField, 0, len(item.Freight)) + for _, fItem := range item.Freight { + f = append(f, &PB.CustomField{ + Key: fItem.Key, + Value: fItem.Value, + }) + } + pi.Freight = f + + // 運費 + c := make([]*PB.CustomField, 0, len(item.CustomFields)) + for _, fItem := range item.CustomFields { + f = append(f, &PB.CustomField{ + Key: fItem.Key, + Value: fItem.Value, + }) + } + pi.CustomFields = c + + result = append(result, pi) + } + return &PB.ListProductItemResponse{ + Total: total, + Data: result, + }, nil +} diff --git a/internal/logic/product/inc_sales_count_logic.go b/internal/logic/product/inc_sales_count_logic.go new file mode 100644 index 0000000..afab98f --- /dev/null +++ b/internal/logic/product/inc_sales_count_logic.go @@ -0,0 +1,35 @@ +package productlogic + +import ( + "context" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type IncSalesCountLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewIncSalesCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IncSalesCountLogic { + return &IncSalesCountLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// IncSalesCount 增加賣出數量 +func (l *IncSalesCountLogic) IncSalesCount(in *product.IncDecSalesCountRequest) (*product.OKResp, error) { + // TODO 有問題可以在這邊加瑣 + err := l.svcCtx.ProductItemUseCase.IncSalesCount(l.ctx, in.GetId(), in.GetCount()) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/update_logic.go b/internal/logic/product/update_logic.go new file mode 100644 index 0000000..604998a --- /dev/null +++ b/internal/logic/product/update_logic.go @@ -0,0 +1,37 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" + "context" + + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateLogic { + return &UpdateLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// Update 更新 Item +func (l *UpdateLogic) Update(in *product.UpdateProductItemRequest) (*product.OKResp, error) { + update := &usecase.UpdateProductItems{} + + err := l.svcCtx.ProductItemUseCase.Update(l.ctx, in.GetId(), update) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/update_status_logic.go b/internal/logic/product/update_status_logic.go new file mode 100644 index 0000000..423ff5d --- /dev/null +++ b/internal/logic/product/update_status_logic.go @@ -0,0 +1,41 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product" + "code.30cm.net/digimon/library-go/errs" + "context" + + PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateStatusLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateStatusLogic { + return &UpdateStatusLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// UpdateStatus 更新 Item status +func (l *UpdateStatusLogic) UpdateStatus(in *PB.UpdateStatusRequest) (*PB.OKResp, error) { + status, e := product.StringToItemStatus(in.GetStatus()) + if !e { + return nil, errs.InvalidFormat("failed to convert string to item status") + } + + err := l.svcCtx.ProductItemUseCase.UpdateStatus(l.ctx, in.GetId(), status) + if err != nil { + return nil, err + } + + return &PB.OKResp{}, nil +} diff --git a/internal/server/product/product_server.go b/internal/server/product/product_server.go index 24fbe79..a6a8b64 100644 --- a/internal/server/product/product_server.go +++ b/internal/server/product/product_server.go @@ -118,3 +118,57 @@ func (s *ProductServer) UpdateKYCInfo(ctx context.Context, in *product.UpdateKYC l := productlogic.NewUpdateKYCInfoLogic(ctx, s.svcCtx) return l.UpdateKYCInfo(in) } + +// ====================== Know You Customer Service End ====================== +func (s *ProductServer) CreateItem(ctx context.Context, in *product.CreateProductItemRequest) (*product.OKResp, error) { + l := productlogic.NewCreateItemLogic(ctx, s.svcCtx) + return l.CreateItem(in) +} + +// GetProductItem 取得 ProductItem +func (s *ProductServer) GetProductItem(ctx context.Context, in *product.GetProductItemRequest) (*product.ProductItem, error) { + l := productlogic.NewGetProductItemLogic(ctx, s.svcCtx) + return l.GetProductItem(in) +} + +// GetProductItemsByProductID 使用 ProductID 取得 ProductItems +func (s *ProductServer) GetProductItemsByProductID(ctx context.Context, in *product.ListProductItemRequest) (*product.ListProductItemResponse, error) { + l := productlogic.NewGetProductItemsByProductIDLogic(ctx, s.svcCtx) + return l.GetProductItemsByProductID(in) +} + +// DeleteProductItems 刪除 Delete Product Item +func (s *ProductServer) DeleteProductItems(ctx context.Context, in *product.DeleteProductItemRequest) (*product.OKResp, error) { + l := productlogic.NewDeleteProductItemsLogic(ctx, s.svcCtx) + return l.DeleteProductItems(in) +} + +// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item +func (s *ProductServer) DeleteProductItemsByReferenceID(ctx context.Context, in *product.DeleteProductItemsByReferenceIDReq) (*product.OKResp, error) { + l := productlogic.NewDeleteProductItemsByReferenceIDLogic(ctx, s.svcCtx) + return l.DeleteProductItemsByReferenceID(in) +} + +// IncSalesCount 增加賣出數量 +func (s *ProductServer) IncSalesCount(ctx context.Context, in *product.IncDecSalesCountRequest) (*product.OKResp, error) { + l := productlogic.NewIncSalesCountLogic(ctx, s.svcCtx) + return l.IncSalesCount(in) +} + +// DecSalesCount 減少賣出數量 +func (s *ProductServer) DecSalesCount(ctx context.Context, in *product.IncDecSalesCountRequest) (*product.OKResp, error) { + l := productlogic.NewDecSalesCountLogic(ctx, s.svcCtx) + return l.DecSalesCount(in) +} + +// Update 更新 Item +func (s *ProductServer) Update(ctx context.Context, in *product.UpdateProductItemRequest) (*product.OKResp, error) { + l := productlogic.NewUpdateLogic(ctx, s.svcCtx) + return l.Update(in) +} + +// UpdateStatus 更新 Item status +func (s *ProductServer) UpdateStatus(ctx context.Context, in *product.UpdateStatusRequest) (*product.OKResp, error) { + l := productlogic.NewUpdateStatusLogic(ctx, s.svcCtx) + return l.UpdateStatus(in) +} diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 603c7c6..e85ee1d 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -11,10 +11,11 @@ import ( ) type ServiceContext struct { - Config config.Config - CategoryUseCase usecase.CategoryUseCase - TagsUseCase usecase.ProductBaseTags - KYCUseCase usecase.KYCUseCase + Config config.Config + CategoryUseCase usecase.CategoryUseCase + TagsUseCase usecase.ProductBaseTags + KYCUseCase usecase.KYCUseCase + ProductItemUseCase usecase.ProductItemUseCase } func NewServiceContext(c config.Config) *ServiceContext { @@ -145,3 +146,43 @@ func MustKYC(c config.Config) usecase.KYCUseCase { return uc.MustKYCUseCase(uc.KYCUseCaseParam{ KYCRepo: kycRepo}) } + +func MustProductItem(c config.Config) usecase.ProductItemUseCase { + // 準備Mongo Config + conf := &mgo.Conf{ + Schema: c.Mongo.Schema, + Host: c.Mongo.Host, + Database: c.Mongo.Database, + MaxStaleness: c.Mongo.MaxStaleness, + MaxPoolSize: c.Mongo.MaxPoolSize, + MinPoolSize: c.Mongo.MinPoolSize, + MaxConnIdleTime: c.Mongo.MaxConnIdleTime, + Compressors: c.Mongo.Compressors, + EnableStandardReadWriteSplitMode: c.Mongo.EnableStandardReadWriteSplitMode, + ConnectTimeoutMs: c.Mongo.ConnectTimeoutMs, + } + if c.Mongo.User != "" { + conf.User = c.Mongo.User + conf.Password = c.Mongo.Password + } + + // 快取選項 + cacheOpts := []cache.Option{ + cache.WithExpiry(c.CacheExpireTime), + cache.WithNotFoundExpiry(c.CacheWithNotFoundExpiry), + } + dbOpts := []mon.Option{ + mgo.SetCustomDecimalType(), + mgo.InitMongoOptions(*conf), + } + + productItemRepo := repo.NewProductItemRepository(repo.ProductItemRepositoryParam{ + Conf: conf, + CacheConf: c.Cache, + CacheOpts: cacheOpts, + DBOpts: dbOpts, + }) + + return uc.MustProductItemUseCase(uc.ProductItemUseCaseParam{ + ProductItems: productItemRepo}) +} diff --git a/internal/utils/encode.go b/internal/utils/encode.go new file mode 100755 index 0000000..3c4b817 --- /dev/null +++ b/internal/utils/encode.go @@ -0,0 +1,23 @@ +package utils + +import ( + "encoding/base64" + + "github.com/golang/snappy" +) + +// EncodeToBase64Snappy 將字串進行 Base64 和 Snappy 編碼 +func EncodeToBase64Snappy(data string) string { + snappyData := snappy.Encode(nil, []byte(data)) + encoded := base64.StdEncoding.EncodeToString(snappyData) + + return encoded +} + +// DecodeToBase64Snappy 將字串進行 Base64 和 Snappy 解碼 +func DecodeToBase64Snappy(data string) string { + decodeB64Content, _ := base64.StdEncoding.DecodeString(data) + snappyContent, _ := snappy.Decode(nil, decodeB64Content) + + return string(snappyContent) +} diff --git a/pkg/domain/product/time_series.go b/pkg/domain/product/time_series.go index 770dd9e..85f8ee3 100644 --- a/pkg/domain/product/time_series.go +++ b/pkg/domain/product/time_series.go @@ -8,3 +8,41 @@ const ( TimeSeriesHalfHour // 每半小時 TimeSeriesOneHour // 每小時 ) + +func (t *TimeSeries) ToString() string { + s, _ := TimeSeriesToString(*t) + return s +} + +const ( + TimeSeriesUnknownStr = "unknown" + TimeSeriesTenMinutesStr = "ten_minutes" + TimeSeriesHalfHourStr = "half_hour" + TimeSeriesOneHourStr = "one_hour" +) + +var timeSeriesToStringMap = map[TimeSeries]string{ + TimeSeriesUnknown: TimeSeriesUnknownStr, + TimeSeriesTenMinutes: TimeSeriesTenMinutesStr, + TimeSeriesHalfHour: TimeSeriesHalfHourStr, + TimeSeriesOneHour: TimeSeriesOneHourStr, +} + +var stringToTimeSeriesMap = map[string]TimeSeries{ + TimeSeriesUnknownStr: TimeSeriesUnknown, + TimeSeriesTenMinutesStr: TimeSeriesTenMinutes, + TimeSeriesHalfHourStr: TimeSeriesHalfHour, + TimeSeriesOneHourStr: TimeSeriesOneHour, +} + +// TimeSeriesToString 將 TimeSeries 轉換為字串 +func TimeSeriesToString(ts TimeSeries) (string, bool) { + str, ok := timeSeriesToStringMap[ts] + return str, ok +} + +// StringToTimeSeries 將字串轉換為 TimeSeries +func StringToTimeSeries(str string) (TimeSeries, bool) { + ts, ok := stringToTimeSeriesMap[str] + return ts, ok +} diff --git a/pkg/domain/usecase/product_item.go b/pkg/domain/usecase/product_item.go index fd69054..91f865b 100644 --- a/pkg/domain/usecase/product_item.go +++ b/pkg/domain/usecase/product_item.go @@ -20,9 +20,11 @@ type ProductItemUseCase interface { // DecSalesCount 更新商品資訊 DecSalesCount(ctx context.Context, id string, saleCount uint64) error // Delete ID 刪除商品 - Delete(ctx context.Context, id string) error + Delete(ctx context.Context, ids []string) error // List 列出符合條件的商品,可根據需求加入分頁或其他條件參數 List(ctx context.Context, filter QueryProductItemParam) ([]*ProductItems, int64, error) + // DeleteByReferenceID 刪除某Project 下所有 + DeleteByReferenceID(ctx context.Context, id string) error } type ProductItems struct { diff --git a/pkg/usecase/product_item.go b/pkg/usecase/product_item.go index 39b0c14..1abc796 100644 --- a/pkg/usecase/product_item.go +++ b/pkg/usecase/product_item.go @@ -177,6 +177,19 @@ func (use *ProductItemUseCase) Get(ctx context.Context, id string) (*usecase.Pro return fromEntity(ent), nil } +func (use *ProductItemUseCase) DeleteByReferenceID(ctx context.Context, id string) error { + err := use.ProductItems.DeleteByReferenceID(ctx, id) + if err != nil { + return errs.DBErrorL(logx.WithContext(ctx), + []logx.LogField{ + {Key: "id", Value: id}, + {Key: "func", Value: "ProductItemUseCaseParam.ProductItems.DeleteByReferenceID"}, + {Key: "err", Value: err.Error()}, + }, "failed to delete product items") + } + return nil +} + func (use *ProductItemUseCase) Update(ctx context.Context, id string, data *usecase.UpdateProductItems) error { // 構建更新參數(僅更新部分欄位) update := &repository.ProductUpdateItem{} @@ -303,12 +316,12 @@ func (use *ProductItemUseCase) DecSalesCount(ctx context.Context, id string, sal return nil } -func (use *ProductItemUseCase) Delete(ctx context.Context, id string) error { +func (use *ProductItemUseCase) Delete(ctx context.Context, ids []string) error { // repository.Delete 接收 slice,因此將 id 放入 slice 中 - if err := use.ProductItemUseCaseParam.ProductItems.Delete(ctx, []string{id}); err != nil { + if err := use.ProductItemUseCaseParam.ProductItems.Delete(ctx, ids); err != nil { return errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ - {Key: "id", Value: id}, + {Key: "id", Value: ids}, {Key: "func", Value: "ProductItemUseCaseParam.ProductItems.Delete"}, {Key: "err", Value: err.Error()}, }, "failed to delete product item") diff --git a/pkg/usecase/product_item_test.go b/pkg/usecase/product_item_test.go index 85bcbd4..fde4dd1 100644 --- a/pkg/usecase/product_item_test.go +++ b/pkg/usecase/product_item_test.go @@ -228,13 +228,13 @@ func TestProductItemUseCase_Delete(t *testing.T) { t.Run("刪除成功", func(t *testing.T) { mockItemRepo.EXPECT().Delete(ctx, []string{id}).Return(nil) - err := useCase.Delete(ctx, id) + err := useCase.Delete(ctx, []string{id}) assert.NoError(t, err) }) t.Run("資料庫錯誤", func(t *testing.T) { mockItemRepo.EXPECT().Delete(ctx, []string{id}).Return(errors.New("db error")) - err := useCase.Delete(ctx, id) + err := useCase.Delete(ctx, []string{id}) assert.Error(t, err) assert.Contains(t, err.Error(), "failed to delete product item") })