From b5a12ceaa228e4075b03c89650434bcd72747c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Tue, 8 Apr 2025 17:20:34 +0800 Subject: [PATCH] feat: add kyc api --- client/product/product.go | 84 +- gen_result/pb/product/product.pb.go | 1140 +++++++++++++++-- gen_result/pb/product/product_grpc.pb.go | 264 +++- generate/protobuf/product.proto | 108 +- internal/logic/product/create_k_y_c_logic.go | 53 + .../logic/product/find_k_y_c_by_i_d_logic.go | 56 + .../find_latest_k_y_c_by_u_i_d_logic.go | 56 + internal/logic/product/list_k_y_c_logic.go | 72 ++ .../logic/product/update_k_y_c_info_logic.go | 51 + .../product/update_k_y_c_status_logic.go | 34 + internal/server/product/product_server.go | 36 + internal/svc/service_context.go | 42 + pkg/domain/repository/kyc.go | 2 - pkg/domain/usecase/kyc.go | 2 - pkg/repository/kyc.go | 16 +- pkg/usecase/kyc.go | 8 +- pkg/usecase/kyc_test.go | 6 +- 17 files changed, 1902 insertions(+), 128 deletions(-) create mode 100644 internal/logic/product/create_k_y_c_logic.go create mode 100644 internal/logic/product/find_k_y_c_by_i_d_logic.go create mode 100644 internal/logic/product/find_latest_k_y_c_by_u_i_d_logic.go create mode 100644 internal/logic/product/list_k_y_c_logic.go create mode 100644 internal/logic/product/update_k_y_c_info_logic.go create mode 100644 internal/logic/product/update_k_y_c_status_logic.go diff --git a/client/product/product.go b/client/product/product.go index de72bfc..6e803d1 100644 --- a/client/product/product.go +++ b/client/product/product.go @@ -14,20 +14,28 @@ import ( ) type ( - Category = product.Category - CategoryReq = product.CategoryReq - CreateCategoryReq = product.CreateCategoryReq - CreateTagsReq = product.CreateTagsReq - ListCategoryReq = product.ListCategoryReq - ListCategoryResp = product.ListCategoryResp - ListTagsReq = product.ListTagsReq - ListTagsResp = product.ListTagsResp - ModifyCategoryReq = product.ModifyCategoryReq - ModifyTagsReq = product.ModifyTagsReq - NoneReq = product.NoneReq - OKResp = product.OKResp - Tags = product.Tags - TagsReq = product.TagsReq + 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 Product interface { // ====================== Category Service Start ====================== @@ -50,6 +58,18 @@ type ( GetTags(ctx context.Context, in *TagsReq, opts ...grpc.CallOption) (*Tags, error) // ListTags 建立 tags ListTags(ctx context.Context, in *ListTagsReq, opts ...grpc.CallOption) (*ListTagsResp, error) + // ====================== Tags Service End ====================== + CreateKYC(ctx context.Context, in *CreateKYCReq, opts ...grpc.CallOption) (*OKResp, error) + // FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 + FindLatestKYCByUID(ctx context.Context, in *FindLatestKYCByUIDReq, opts ...grpc.CallOption) (*KYC, error) + // FindKYCByID 根據 KYC ID 查詢 + FindKYCByID(ctx context.Context, in *FindKYCByIDReq, opts ...grpc.CallOption) (*KYC, error) + // ListKYC 分頁查詢 KYC 清單(後台審核用) + ListKYC(ctx context.Context, in *ListKYCReq, opts ...grpc.CallOption) (*ListKYCResp, error) + // UpdateKYCStatus 更新 KYC 審核狀態與原因 + UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) + // UpdateKYCInfo 更新使用者的 KYC(尚未審核) + UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) } defaultProduct struct { @@ -122,3 +142,39 @@ func (m *defaultProduct) ListTags(ctx context.Context, in *ListTagsReq, opts ... client := product.NewProductClient(m.cli.Conn()) return client.ListTags(ctx, in, opts...) } + +// ====================== Tags Service End ====================== +func (m *defaultProduct) CreateKYC(ctx context.Context, in *CreateKYCReq, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.CreateKYC(ctx, in, opts...) +} + +// FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 +func (m *defaultProduct) FindLatestKYCByUID(ctx context.Context, in *FindLatestKYCByUIDReq, opts ...grpc.CallOption) (*KYC, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.FindLatestKYCByUID(ctx, in, opts...) +} + +// FindKYCByID 根據 KYC ID 查詢 +func (m *defaultProduct) FindKYCByID(ctx context.Context, in *FindKYCByIDReq, opts ...grpc.CallOption) (*KYC, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.FindKYCByID(ctx, in, opts...) +} + +// ListKYC 分頁查詢 KYC 清單(後台審核用) +func (m *defaultProduct) ListKYC(ctx context.Context, in *ListKYCReq, opts ...grpc.CallOption) (*ListKYCResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.ListKYC(ctx, in, opts...) +} + +// UpdateKYCStatus 更新 KYC 審核狀態與原因 +func (m *defaultProduct) UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.UpdateKYCStatus(ctx, in, opts...) +} + +// UpdateKYCInfo 更新使用者的 KYC(尚未審核) +func (m *defaultProduct) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.UpdateKYCInfo(ctx, in, opts...) +} diff --git a/gen_result/pb/product/product.pb.go b/gen_result/pb/product/product.pb.go index af2f0c7..ef4f82b 100644 --- a/gen_result/pb/product/product.pb.go +++ b/gen_result/pb/product/product.pb.go @@ -832,6 +832,791 @@ func (x *ListTagsResp) GetData() []*Tags { return nil } +// ====================== KYC Param ====================== +type KYC struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // MongoDB ObjectID 字串格式 + Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` // 驗證人 UID + CountryRegion string `protobuf:"bytes,3,opt,name=country_region,json=countryRegion,proto3" json:"country_region,omitempty"` // 地區(例如 "TW", "JP", "US"...) + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` // 真實姓名 + Identification string `protobuf:"bytes,5,opt,name=identification,proto3" json:"identification,omitempty"` // 身分證字號 or 護照號碼 + IdentificationType string `protobuf:"bytes,6,opt,name=identification_type,json=identificationType,proto3" json:"identification_type,omitempty"` // ID 類型:ID_CARD, PASSPORT, RESIDENT_CERT + Address string `protobuf:"bytes,7,opt,name=address,proto3" json:"address,omitempty"` // 戶籍地址(或居住地址) + PostalCode string `protobuf:"bytes,8,opt,name=postal_code,json=postalCode,proto3" json:"postal_code,omitempty"` // 郵遞區號(海外使用) + IdFrontImage string `protobuf:"bytes,9,opt,name=id_front_image,json=idFrontImage,proto3" json:"id_front_image,omitempty"` // 身分證/護照 正面 + IdBackImage string `protobuf:"bytes,10,opt,name=id_back_image,json=idBackImage,proto3" json:"id_back_image,omitempty"` // 身分證/居留證 反面 + BankStatementImg string `protobuf:"bytes,11,opt,name=bank_statement_img,json=bankStatementImg,proto3" json:"bank_statement_img,omitempty"` // 銀行存摺封面照 + BankCode string `protobuf:"bytes,12,opt,name=bank_code,json=bankCode,proto3" json:"bank_code,omitempty"` // 銀行代碼(可為 SWIFT) + BankName string `protobuf:"bytes,13,opt,name=bank_name,json=bankName,proto3" json:"bank_name,omitempty"` // 銀行名稱(顯示用) + BranchCode string `protobuf:"bytes,14,opt,name=branch_code,json=branchCode,proto3" json:"branch_code,omitempty"` // 分行代碼 + BranchName string `protobuf:"bytes,15,opt,name=branch_name,json=branchName,proto3" json:"branch_name,omitempty"` // 分行名稱(顯示用) + BankAccount string `protobuf:"bytes,16,opt,name=bank_account,json=bankAccount,proto3" json:"bank_account,omitempty"` // 銀行帳號 + Status string `protobuf:"bytes,17,opt,name=status,proto3" json:"status,omitempty"` // 審核狀態:PENDING, APPROVED, REJECTED + RejectReason string `protobuf:"bytes,18,opt,name=reject_reason,json=rejectReason,proto3" json:"reject_reason,omitempty"` // 若被駁回,原因描述 + UpdatedAt int64 `protobuf:"varint,19,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` // 更新時間(timestamp) + CreatedAt int64 `protobuf:"varint,20,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // 建立時間(timestamp) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *KYC) Reset() { + *x = KYC{} + mi := &file_generate_protobuf_product_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *KYC) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KYC) ProtoMessage() {} + +func (x *KYC) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[14] + 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 KYC.ProtoReflect.Descriptor instead. +func (*KYC) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{14} +} + +func (x *KYC) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *KYC) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *KYC) GetCountryRegion() string { + if x != nil { + return x.CountryRegion + } + return "" +} + +func (x *KYC) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *KYC) GetIdentification() string { + if x != nil { + return x.Identification + } + return "" +} + +func (x *KYC) GetIdentificationType() string { + if x != nil { + return x.IdentificationType + } + return "" +} + +func (x *KYC) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *KYC) GetPostalCode() string { + if x != nil { + return x.PostalCode + } + return "" +} + +func (x *KYC) GetIdFrontImage() string { + if x != nil { + return x.IdFrontImage + } + return "" +} + +func (x *KYC) GetIdBackImage() string { + if x != nil { + return x.IdBackImage + } + return "" +} + +func (x *KYC) GetBankStatementImg() string { + if x != nil { + return x.BankStatementImg + } + return "" +} + +func (x *KYC) GetBankCode() string { + if x != nil { + return x.BankCode + } + return "" +} + +func (x *KYC) GetBankName() string { + if x != nil { + return x.BankName + } + return "" +} + +func (x *KYC) GetBranchCode() string { + if x != nil { + return x.BranchCode + } + return "" +} + +func (x *KYC) GetBranchName() string { + if x != nil { + return x.BranchName + } + return "" +} + +func (x *KYC) GetBankAccount() string { + if x != nil { + return x.BankAccount + } + return "" +} + +func (x *KYC) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *KYC) GetRejectReason() string { + if x != nil { + return x.RejectReason + } + return "" +} + +func (x *KYC) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +func (x *KYC) GetCreatedAt() int64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +type CreateKYCReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uid string `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + CountryRegion string `protobuf:"bytes,2,opt,name=country_region,json=countryRegion,proto3" json:"country_region,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Identification string `protobuf:"bytes,4,opt,name=identification,proto3" json:"identification,omitempty"` + IdentificationType string `protobuf:"bytes,5,opt,name=identification_type,json=identificationType,proto3" json:"identification_type,omitempty"` + Address string `protobuf:"bytes,6,opt,name=address,proto3" json:"address,omitempty"` + PostalCode string `protobuf:"bytes,7,opt,name=postal_code,json=postalCode,proto3" json:"postal_code,omitempty"` + IdFrontImage string `protobuf:"bytes,8,opt,name=id_front_image,json=idFrontImage,proto3" json:"id_front_image,omitempty"` + IdBackImage string `protobuf:"bytes,9,opt,name=id_back_image,json=idBackImage,proto3" json:"id_back_image,omitempty"` + BankStatementImg string `protobuf:"bytes,10,opt,name=bank_statement_img,json=bankStatementImg,proto3" json:"bank_statement_img,omitempty"` + BankCode string `protobuf:"bytes,11,opt,name=bank_code,json=bankCode,proto3" json:"bank_code,omitempty"` + BankName string `protobuf:"bytes,12,opt,name=bank_name,json=bankName,proto3" json:"bank_name,omitempty"` + BranchCode string `protobuf:"bytes,13,opt,name=branch_code,json=branchCode,proto3" json:"branch_code,omitempty"` + BranchName string `protobuf:"bytes,14,opt,name=branch_name,json=branchName,proto3" json:"branch_name,omitempty"` + BankAccount string `protobuf:"bytes,15,opt,name=bank_account,json=bankAccount,proto3" json:"bank_account,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateKYCReq) Reset() { + *x = CreateKYCReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateKYCReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateKYCReq) ProtoMessage() {} + +func (x *CreateKYCReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[15] + 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 CreateKYCReq.ProtoReflect.Descriptor instead. +func (*CreateKYCReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{15} +} + +func (x *CreateKYCReq) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *CreateKYCReq) GetCountryRegion() string { + if x != nil { + return x.CountryRegion + } + return "" +} + +func (x *CreateKYCReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreateKYCReq) GetIdentification() string { + if x != nil { + return x.Identification + } + return "" +} + +func (x *CreateKYCReq) GetIdentificationType() string { + if x != nil { + return x.IdentificationType + } + return "" +} + +func (x *CreateKYCReq) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *CreateKYCReq) GetPostalCode() string { + if x != nil { + return x.PostalCode + } + return "" +} + +func (x *CreateKYCReq) GetIdFrontImage() string { + if x != nil { + return x.IdFrontImage + } + return "" +} + +func (x *CreateKYCReq) GetIdBackImage() string { + if x != nil { + return x.IdBackImage + } + return "" +} + +func (x *CreateKYCReq) GetBankStatementImg() string { + if x != nil { + return x.BankStatementImg + } + return "" +} + +func (x *CreateKYCReq) GetBankCode() string { + if x != nil { + return x.BankCode + } + return "" +} + +func (x *CreateKYCReq) GetBankName() string { + if x != nil { + return x.BankName + } + return "" +} + +func (x *CreateKYCReq) GetBranchCode() string { + if x != nil { + return x.BranchCode + } + return "" +} + +func (x *CreateKYCReq) GetBranchName() string { + if x != nil { + return x.BranchName + } + return "" +} + +func (x *CreateKYCReq) GetBankAccount() string { + if x != nil { + return x.BankAccount + } + return "" +} + +type FindLatestKYCByUIDReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uid string `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FindLatestKYCByUIDReq) Reset() { + *x = FindLatestKYCByUIDReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FindLatestKYCByUIDReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindLatestKYCByUIDReq) ProtoMessage() {} + +func (x *FindLatestKYCByUIDReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[16] + 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 FindLatestKYCByUIDReq.ProtoReflect.Descriptor instead. +func (*FindLatestKYCByUIDReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{16} +} + +func (x *FindLatestKYCByUIDReq) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +type FindKYCByIDReq 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 *FindKYCByIDReq) Reset() { + *x = FindKYCByIDReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FindKYCByIDReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindKYCByIDReq) ProtoMessage() {} + +func (x *FindKYCByIDReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[17] + 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 FindKYCByIDReq.ProtoReflect.Descriptor instead. +func (*FindKYCByIDReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{17} +} + +func (x *FindKYCByIDReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ListKYCReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uid *string `protobuf:"bytes,1,opt,name=uid,proto3,oneof" json:"uid,omitempty"` + Country *string `protobuf:"bytes,2,opt,name=country,proto3,oneof" json:"country,omitempty"` + Status *string `protobuf:"bytes,3,opt,name=status,proto3,oneof" json:"status,omitempty"` // 可改 enum + PageSize int64 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageIndex int64 `protobuf:"varint,5,opt,name=page_index,json=pageIndex,proto3" json:"page_index,omitempty"` + SortByDate bool `protobuf:"varint,6,opt,name=sort_by_date,json=sortByDate,proto3" json:"sort_by_date,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListKYCReq) Reset() { + *x = ListKYCReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListKYCReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListKYCReq) ProtoMessage() {} + +func (x *ListKYCReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[18] + 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 ListKYCReq.ProtoReflect.Descriptor instead. +func (*ListKYCReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{18} +} + +func (x *ListKYCReq) GetUid() string { + if x != nil && x.Uid != nil { + return *x.Uid + } + return "" +} + +func (x *ListKYCReq) GetCountry() string { + if x != nil && x.Country != nil { + return *x.Country + } + return "" +} + +func (x *ListKYCReq) GetStatus() string { + if x != nil && x.Status != nil { + return *x.Status + } + return "" +} + +func (x *ListKYCReq) GetPageSize() int64 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListKYCReq) GetPageIndex() int64 { + if x != nil { + return x.PageIndex + } + return 0 +} + +func (x *ListKYCReq) GetSortByDate() bool { + if x != nil { + return x.SortByDate + } + return false +} + +type ListKYCResp struct { + state protoimpl.MessageState `protogen:"open.v1"` + List []*KYC `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListKYCResp) Reset() { + *x = ListKYCResp{} + mi := &file_generate_protobuf_product_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListKYCResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListKYCResp) ProtoMessage() {} + +func (x *ListKYCResp) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[19] + 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 ListKYCResp.ProtoReflect.Descriptor instead. +func (*ListKYCResp) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{19} +} + +func (x *ListKYCResp) GetList() []*KYC { + if x != nil { + return x.List + } + return nil +} + +func (x *ListKYCResp) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +type UpdateKYCStatusReq 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"` // 可改 enum:PENDING, APPROVED, REJECTED + Reason *string `protobuf:"bytes,3,opt,name=reason,proto3,oneof" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateKYCStatusReq) Reset() { + *x = UpdateKYCStatusReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateKYCStatusReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateKYCStatusReq) ProtoMessage() {} + +func (x *UpdateKYCStatusReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[20] + 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 UpdateKYCStatusReq.ProtoReflect.Descriptor instead. +func (*UpdateKYCStatusReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{20} +} + +func (x *UpdateKYCStatusReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateKYCStatusReq) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *UpdateKYCStatusReq) GetReason() string { + if x != nil && x.Reason != nil { + return *x.Reason + } + return "" +} + +type UpdateKYCInfoReq 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"` + Identification *string `protobuf:"bytes,3,opt,name=identification,proto3,oneof" json:"identification,omitempty"` + IdentificationType *string `protobuf:"bytes,4,opt,name=identification_type,json=identificationType,proto3,oneof" json:"identification_type,omitempty"` + Address *string `protobuf:"bytes,5,opt,name=address,proto3,oneof" json:"address,omitempty"` + PostalCode *string `protobuf:"bytes,6,opt,name=postal_code,json=postalCode,proto3,oneof" json:"postal_code,omitempty"` + IdFrontImage *string `protobuf:"bytes,7,opt,name=id_front_image,json=idFrontImage,proto3,oneof" json:"id_front_image,omitempty"` + IdBackImage *string `protobuf:"bytes,8,opt,name=id_back_image,json=idBackImage,proto3,oneof" json:"id_back_image,omitempty"` + BankStatementImg *string `protobuf:"bytes,9,opt,name=bank_statement_img,json=bankStatementImg,proto3,oneof" json:"bank_statement_img,omitempty"` + BankCode *string `protobuf:"bytes,10,opt,name=bank_code,json=bankCode,proto3,oneof" json:"bank_code,omitempty"` + BankName *string `protobuf:"bytes,11,opt,name=bank_name,json=bankName,proto3,oneof" json:"bank_name,omitempty"` + BranchCode *string `protobuf:"bytes,12,opt,name=branch_code,json=branchCode,proto3,oneof" json:"branch_code,omitempty"` + BranchName *string `protobuf:"bytes,13,opt,name=branch_name,json=branchName,proto3,oneof" json:"branch_name,omitempty"` + BankAccount *string `protobuf:"bytes,14,opt,name=bank_account,json=bankAccount,proto3,oneof" json:"bank_account,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateKYCInfoReq) Reset() { + *x = UpdateKYCInfoReq{} + mi := &file_generate_protobuf_product_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateKYCInfoReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateKYCInfoReq) ProtoMessage() {} + +func (x *UpdateKYCInfoReq) ProtoReflect() protoreflect.Message { + mi := &file_generate_protobuf_product_proto_msgTypes[21] + 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 UpdateKYCInfoReq.ProtoReflect.Descriptor instead. +func (*UpdateKYCInfoReq) Descriptor() ([]byte, []int) { + return file_generate_protobuf_product_proto_rawDescGZIP(), []int{21} +} + +func (x *UpdateKYCInfoReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateKYCInfoReq) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *UpdateKYCInfoReq) GetIdentification() string { + if x != nil && x.Identification != nil { + return *x.Identification + } + return "" +} + +func (x *UpdateKYCInfoReq) GetIdentificationType() string { + if x != nil && x.IdentificationType != nil { + return *x.IdentificationType + } + return "" +} + +func (x *UpdateKYCInfoReq) GetAddress() string { + if x != nil && x.Address != nil { + return *x.Address + } + return "" +} + +func (x *UpdateKYCInfoReq) GetPostalCode() string { + if x != nil && x.PostalCode != nil { + return *x.PostalCode + } + return "" +} + +func (x *UpdateKYCInfoReq) GetIdFrontImage() string { + if x != nil && x.IdFrontImage != nil { + return *x.IdFrontImage + } + return "" +} + +func (x *UpdateKYCInfoReq) GetIdBackImage() string { + if x != nil && x.IdBackImage != nil { + return *x.IdBackImage + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBankStatementImg() string { + if x != nil && x.BankStatementImg != nil { + return *x.BankStatementImg + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBankCode() string { + if x != nil && x.BankCode != nil { + return *x.BankCode + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBankName() string { + if x != nil && x.BankName != nil { + return *x.BankName + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBranchCode() string { + if x != nil && x.BranchCode != nil { + return *x.BranchCode + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBranchName() string { + if x != nil && x.BranchName != nil { + return *x.BranchName + } + return "" +} + +func (x *UpdateKYCInfoReq) GetBankAccount() string { + if x != nil && x.BankAccount != nil { + return *x.BankAccount + } + return "" +} + var File_generate_protobuf_product_proto protoreflect.FileDescriptor var file_generate_protobuf_product_proto_rawDesc = string([]byte{ @@ -915,45 +1700,218 @@ var file_generate_protobuf_product_proto_rawDesc = string([]byte{ 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, - 0x54, 0x61, 0x67, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xc1, 0x04, 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, + 0x54, 0x61, 0x67, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x88, 0x05, 0x0a, 0x03, 0x4b, + 0x59, 0x43, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x75, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x26, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x5f, + 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x64, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x64, 0x5f, + 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x69, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, + 0x12, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x6d, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x61, 0x6e, 0x6b, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6d, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x62, + 0x61, 0x6e, 0x6b, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x62, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x6b, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6e, + 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x6e, 0x6b, 0x5f, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, + 0x61, 0x6e, 0x6b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x86, 0x04, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4b, 0x59, 0x43, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x13, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x73, + 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x64, 0x5f, 0x66, 0x72, + 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x69, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, + 0x0d, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, + 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6d, 0x67, 0x12, + 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x62, 0x61, 0x6e, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, + 0x61, 0x6e, 0x6b, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x62, 0x61, 0x6e, 0x6b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x29, + 0x0a, 0x15, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x42, + 0x79, 0x55, 0x49, 0x44, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x46, 0x69, 0x6e, + 0x64, 0x4b, 0x59, 0x43, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xdc, 0x01, 0x0a, 0x0a, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x03, 0x75, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x75, 0x69, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x88, 0x01, 0x01, + 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x02, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x70, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x5f, + 0x75, 0x69, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x45, 0x0a, 0x0b, 0x4c, 0x69, + 0x73, 0x74, 0x4b, 0x59, 0x43, 0x52, 0x65, 0x73, 0x70, 0x12, 0x20, 0x0a, 0x04, 0x6c, 0x69, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x2e, 0x4b, 0x59, 0x43, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x22, 0x64, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x59, 0x43, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 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, 0x12, + 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xfb, 0x05, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4b, 0x59, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 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, 0x2b, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, + 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, + 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x02, 0x52, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, + 0x6c, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0a, + 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, + 0x0e, 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0c, 0x69, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x69, 0x64, 0x5f, 0x62, + 0x61, 0x63, 0x6b, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x06, 0x52, 0x0b, 0x69, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x88, 0x01, + 0x01, 0x12, 0x31, 0x0a, 0x12, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07, 0x52, + 0x10, 0x62, 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6d, + 0x67, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x08, 0x52, 0x08, 0x62, 0x61, 0x6e, 0x6b, 0x43, + 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6e, + 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0a, 0x52, + 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x24, + 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x0b, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0c, 0x52, 0x0b, 0x62, 0x61, + 0x6e, 0x6b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x0e, 0x0a, 0x0c, + 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x11, 0x0a, 0x0f, + 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x42, + 0x10, 0x0a, 0x0e, 0x5f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x69, 0x6d, 0x61, 0x67, + 0x65, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x67, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x62, 0x61, 0x6e, + 0x6b, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, + 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, 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, 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, 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, }) var ( @@ -968,51 +1926,72 @@ 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, 14) +var file_generate_protobuf_product_proto_msgTypes = make([]protoimpl.MessageInfo, 22) 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 + (*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 } 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 - 2, // 2: product.Product.CreateCategory:input_type -> product.CreateCategoryReq - 3, // 3: product.Product.ModifyCategory:input_type -> product.ModifyCategoryReq - 4, // 4: product.Product.DeleteCategory:input_type -> product.CategoryReq - 4, // 5: product.Product.GetCategory:input_type -> product.CategoryReq - 6, // 6: product.Product.ListCategory:input_type -> product.ListCategoryReq - 8, // 7: product.Product.CreateTags:input_type -> product.CreateTagsReq - 9, // 8: product.Product.ModifyTags:input_type -> product.ModifyTagsReq - 10, // 9: product.Product.DeleteTags:input_type -> product.TagsReq - 10, // 10: product.Product.GetTags:input_type -> product.TagsReq - 12, // 11: product.Product.ListTags:input_type -> product.ListTagsReq - 0, // 12: product.Product.CreateCategory:output_type -> product.OKResp - 0, // 13: product.Product.ModifyCategory:output_type -> product.OKResp - 0, // 14: product.Product.DeleteCategory:output_type -> product.OKResp - 5, // 15: product.Product.GetCategory:output_type -> product.Category - 7, // 16: product.Product.ListCategory:output_type -> product.ListCategoryResp - 0, // 17: product.Product.CreateTags:output_type -> product.OKResp - 0, // 18: product.Product.ModifyTags:output_type -> product.OKResp - 0, // 19: product.Product.DeleteTags:output_type -> product.OKResp - 11, // 20: product.Product.GetTags:output_type -> product.Tags - 13, // 21: product.Product.ListTags:output_type -> product.ListTagsResp - 12, // [12:22] is the sub-list for method output_type - 2, // [2:12] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 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 } func init() { file_generate_protobuf_product_proto_init() } @@ -1023,13 +2002,16 @@ func file_generate_protobuf_product_proto_init() { file_generate_protobuf_product_proto_msgTypes[8].OneofWrappers = []any{} file_generate_protobuf_product_proto_msgTypes[9].OneofWrappers = []any{} file_generate_protobuf_product_proto_msgTypes[12].OneofWrappers = []any{} + 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{} 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: 14, + NumMessages: 22, 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 0540cb6..64ad7c3 100644 --- a/gen_result/pb/product/product_grpc.pb.go +++ b/gen_result/pb/product/product_grpc.pb.go @@ -19,16 +19,22 @@ 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_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" ) // ProductClient is the client API for Product service. @@ -58,6 +64,20 @@ type ProductClient interface { GetTags(ctx context.Context, in *TagsReq, opts ...grpc.CallOption) (*Tags, error) // ListTags 建立 tags ListTags(ctx context.Context, in *ListTagsReq, opts ...grpc.CallOption) (*ListTagsResp, error) + // ====================== Tags Service End ====================== + // ====================== Know You Customer Service Start ====================== + // CreateKYC 建立 KYC 資料 + CreateKYC(ctx context.Context, in *CreateKYCReq, opts ...grpc.CallOption) (*OKResp, error) + // FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 + FindLatestKYCByUID(ctx context.Context, in *FindLatestKYCByUIDReq, opts ...grpc.CallOption) (*KYC, error) + // FindKYCByID 根據 KYC ID 查詢 + FindKYCByID(ctx context.Context, in *FindKYCByIDReq, opts ...grpc.CallOption) (*KYC, error) + // ListKYC 分頁查詢 KYC 清單(後台審核用) + ListKYC(ctx context.Context, in *ListKYCReq, opts ...grpc.CallOption) (*ListKYCResp, error) + // UpdateKYCStatus 更新 KYC 審核狀態與原因 + UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) + // UpdateKYCInfo 更新使用者的 KYC(尚未審核) + UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) } type productClient struct { @@ -168,6 +188,66 @@ func (c *productClient) ListTags(ctx context.Context, in *ListTagsReq, opts ...g return out, nil } +func (c *productClient) CreateKYC(ctx context.Context, in *CreateKYCReq, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_CreateKYC_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) FindLatestKYCByUID(ctx context.Context, in *FindLatestKYCByUIDReq, opts ...grpc.CallOption) (*KYC, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(KYC) + err := c.cc.Invoke(ctx, Product_FindLatestKYCByUID_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) FindKYCByID(ctx context.Context, in *FindKYCByIDReq, opts ...grpc.CallOption) (*KYC, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(KYC) + err := c.cc.Invoke(ctx, Product_FindKYCByID_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) ListKYC(ctx context.Context, in *ListKYCReq, opts ...grpc.CallOption) (*ListKYCResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListKYCResp) + err := c.cc.Invoke(ctx, Product_ListKYC_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_UpdateKYCStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *productClient) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OKResp) + err := c.cc.Invoke(ctx, Product_UpdateKYCInfo_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. @@ -195,6 +275,20 @@ type ProductServer interface { GetTags(context.Context, *TagsReq) (*Tags, error) // ListTags 建立 tags ListTags(context.Context, *ListTagsReq) (*ListTagsResp, error) + // ====================== Tags Service End ====================== + // ====================== Know You Customer Service Start ====================== + // CreateKYC 建立 KYC 資料 + CreateKYC(context.Context, *CreateKYCReq) (*OKResp, error) + // FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 + FindLatestKYCByUID(context.Context, *FindLatestKYCByUIDReq) (*KYC, error) + // FindKYCByID 根據 KYC ID 查詢 + FindKYCByID(context.Context, *FindKYCByIDReq) (*KYC, error) + // ListKYC 分頁查詢 KYC 清單(後台審核用) + ListKYC(context.Context, *ListKYCReq) (*ListKYCResp, error) + // UpdateKYCStatus 更新 KYC 審核狀態與原因 + UpdateKYCStatus(context.Context, *UpdateKYCStatusReq) (*OKResp, error) + // UpdateKYCInfo 更新使用者的 KYC(尚未審核) + UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error) mustEmbedUnimplementedProductServer() } @@ -235,6 +329,24 @@ func (UnimplementedProductServer) GetTags(context.Context, *TagsReq) (*Tags, err func (UnimplementedProductServer) ListTags(context.Context, *ListTagsReq) (*ListTagsResp, error) { return nil, status.Errorf(codes.Unimplemented, "method ListTags not implemented") } +func (UnimplementedProductServer) CreateKYC(context.Context, *CreateKYCReq) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateKYC not implemented") +} +func (UnimplementedProductServer) FindLatestKYCByUID(context.Context, *FindLatestKYCByUIDReq) (*KYC, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindLatestKYCByUID not implemented") +} +func (UnimplementedProductServer) FindKYCByID(context.Context, *FindKYCByIDReq) (*KYC, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindKYCByID not implemented") +} +func (UnimplementedProductServer) ListKYC(context.Context, *ListKYCReq) (*ListKYCResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListKYC not implemented") +} +func (UnimplementedProductServer) UpdateKYCStatus(context.Context, *UpdateKYCStatusReq) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateKYCStatus not implemented") +} +func (UnimplementedProductServer) UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateKYCInfo not implemented") +} func (UnimplementedProductServer) mustEmbedUnimplementedProductServer() {} func (UnimplementedProductServer) testEmbeddedByValue() {} @@ -436,6 +548,114 @@ func _Product_ListTags_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Product_CreateKYC_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateKYCReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).CreateKYC(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_CreateKYC_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).CreateKYC(ctx, req.(*CreateKYCReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_FindLatestKYCByUID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindLatestKYCByUIDReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).FindLatestKYCByUID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_FindLatestKYCByUID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).FindLatestKYCByUID(ctx, req.(*FindLatestKYCByUIDReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_FindKYCByID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindKYCByIDReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).FindKYCByID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_FindKYCByID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).FindKYCByID(ctx, req.(*FindKYCByIDReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_ListKYC_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListKYCReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).ListKYC(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_ListKYC_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).ListKYC(ctx, req.(*ListKYCReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_UpdateKYCStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateKYCStatusReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).UpdateKYCStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_UpdateKYCStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).UpdateKYCStatus(ctx, req.(*UpdateKYCStatusReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Product_UpdateKYCInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateKYCInfoReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).UpdateKYCInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_UpdateKYCInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).UpdateKYCInfo(ctx, req.(*UpdateKYCInfoReq)) + } + 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) @@ -483,6 +703,30 @@ var Product_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListTags", Handler: _Product_ListTags_Handler, }, + { + MethodName: "CreateKYC", + Handler: _Product_CreateKYC_Handler, + }, + { + MethodName: "FindLatestKYCByUID", + Handler: _Product_FindLatestKYCByUID_Handler, + }, + { + MethodName: "FindKYCByID", + Handler: _Product_FindKYCByID_Handler, + }, + { + MethodName: "ListKYC", + Handler: _Product_ListKYC_Handler, + }, + { + MethodName: "UpdateKYCStatus", + Handler: _Product_UpdateKYCStatus_Handler, + }, + { + MethodName: "UpdateKYCInfo", + Handler: _Product_UpdateKYCInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "generate/protobuf/product.proto", diff --git a/generate/protobuf/product.proto b/generate/protobuf/product.proto index 00304e6..d7107ae 100644 --- a/generate/protobuf/product.proto +++ b/generate/protobuf/product.proto @@ -86,6 +86,97 @@ message ListTagsResp { repeated Tags data=3; } +// ====================== KYC Param ====================== +message KYC { + string id = 1; // MongoDB ObjectID 字串格式 + string uid = 2; // 驗證人 UID + string country_region = 3; // 地區(例如 "TW", "JP", "US"...) + string name = 4; // 真實姓名 + string identification = 5; // 身分證字號 or 護照號碼 + string identification_type = 6; // ID 類型:ID_CARD, PASSPORT, RESIDENT_CERT + string address = 7; // 戶籍地址(或居住地址) + string postal_code = 8; // 郵遞區號(海外使用) + string id_front_image = 9; // 身分證/護照 正面 + string id_back_image = 10; // 身分證/居留證 反面 + string bank_statement_img = 11; // 銀行存摺封面照 + string bank_code = 12; // 銀行代碼(可為 SWIFT) + string bank_name = 13; // 銀行名稱(顯示用) + string branch_code = 14; // 分行代碼 + string branch_name = 15; // 分行名稱(顯示用) + string bank_account = 16; // 銀行帳號 + string status = 17; // 審核狀態:PENDING, APPROVED, REJECTED + string reject_reason = 18; // 若被駁回,原因描述 + int64 updated_at = 19; // 更新時間(timestamp) + int64 created_at = 20; // 建立時間(timestamp) +} + +message CreateKYCReq { + string uid = 1; + string country_region = 2; + string name = 3; + string identification = 4; + string identification_type = 5; + string address = 6; + string postal_code = 7; + string id_front_image = 8; + string id_back_image = 9; + string bank_statement_img = 10; + string bank_code = 11; + string bank_name = 12; + string branch_code = 13; + string branch_name = 14; + string bank_account = 15; +} + +message FindLatestKYCByUIDReq { + string uid = 1; +} + +message FindKYCByIDReq { + string id = 1; +} + +message ListKYCReq { + optional string uid = 1; + optional string country = 2; + optional string status = 3; // 可改 enum + int64 page_size = 4; + int64 page_index = 5; + bool sort_by_date = 6; +} + +message ListKYCResp { + repeated KYC list = 1; + int64 total = 2; +} + +message UpdateKYCStatusReq { + string id = 1; + string status = 2; // 可改 enum:PENDING, APPROVED, REJECTED + optional string reason = 3; +} + +message UpdateKYCInfoReq { + string id = 1; + + optional string name = 2; + optional string identification = 3; + optional string identification_type = 4; + optional string address = 5; + optional string postal_code = 6; + optional string id_front_image = 7; + optional string id_back_image = 8; + optional string bank_statement_img = 9; + optional string bank_code = 10; + optional string bank_name = 11; + optional string branch_code = 12; + optional string branch_name = 13; + optional string bank_account = 14; +} + + + + service Product { // ====================== Category Service Start ====================== @@ -112,5 +203,18 @@ service Product { // ListTags 建立 tags rpc ListTags(ListTagsReq) returns(ListTagsResp); // ====================== Tags Service End ====================== - -} \ No newline at end of file + // ====================== Know You Customer Service Start ====================== + // CreateKYC 建立 KYC 資料 + rpc CreateKYC (CreateKYCReq) returns (OKResp); + // FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 + rpc FindLatestKYCByUID (FindLatestKYCByUIDReq) returns (KYC); + // FindKYCByID 根據 KYC ID 查詢 + rpc FindKYCByID (FindKYCByIDReq) returns (KYC); + // ListKYC 分頁查詢 KYC 清單(後台審核用) + rpc ListKYC (ListKYCReq) returns (ListKYCResp); + // UpdateKYCStatus 更新 KYC 審核狀態與原因 + rpc UpdateKYCStatus (UpdateKYCStatusReq) returns (OKResp); + // UpdateKYCInfo 更新使用者的 KYC(尚未審核) + rpc UpdateKYCInfo (UpdateKYCInfoReq) returns (OKResp); + // ====================== Know You Customer Service End ====================== +} diff --git a/internal/logic/product/create_k_y_c_logic.go b/internal/logic/product/create_k_y_c_logic.go new file mode 100644 index 0000000..09d03ec --- /dev/null +++ b/internal/logic/product/create_k_y_c_logic.go @@ -0,0 +1,53 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product" + "code.30cm.net/digimon/app-cloudep-product-service/internal/svc" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/kyc" + "context" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateKYCLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewCreateKYCLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateKYCLogic { + return &CreateKYCLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *CreateKYCLogic) CreateKYC(in *product.CreateKYCReq) (*product.OKResp, error) { + + err := l.svcCtx.KYCUseCase.Create(l.ctx, &entity.KYC{ + UID: in.GetUid(), + CountryRegion: in.GetCountryRegion(), + Name: in.GetName(), + Identification: in.GetIdentification(), + IdentificationType: in.GetIdentificationType(), + Address: in.GetAddress(), + PostalCode: in.GetPostalCode(), + IDFrontImage: in.GetIdFrontImage(), + IDBackImage: in.GetIdBackImage(), + BankStatementImg: in.GetBankStatementImg(), + BankCode: in.GetBankCode(), + BankName: in.GetName(), + BranchCode: in.GetBranchCode(), + BranchName: in.GetBranchName(), + BankAccount: in.GetBankAccount(), + Status: kyc.StatusPending, + RejectReason: "", + }) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/find_k_y_c_by_i_d_logic.go b/internal/logic/product/find_k_y_c_by_i_d_logic.go new file mode 100644 index 0000000..1dfcc1a --- /dev/null +++ b/internal/logic/product/find_k_y_c_by_i_d_logic.go @@ -0,0 +1,56 @@ +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 FindKYCByIDLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewFindKYCByIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FindKYCByIDLogic { + return &FindKYCByIDLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// FindKYCByID 根據 KYC ID 查詢 +func (l *FindKYCByIDLogic) FindKYCByID(in *product.FindKYCByIDReq) (*product.KYC, error) { + kycInfo, err := l.svcCtx.KYCUseCase.FindByID(l.ctx, in.GetId()) + if err != nil { + return nil, err + } + + return &product.KYC{ + Id: kycInfo.ID.Hex(), + Uid: kycInfo.UID, + CountryRegion: kycInfo.CountryRegion, + Name: kycInfo.Name, + Identification: kycInfo.Identification, + IdentificationType: kycInfo.IdentificationType, + Address: kycInfo.Address, + PostalCode: kycInfo.PostalCode, + // 上傳文件網址(可為 object storage 的 URL) + IdFrontImage: kycInfo.IDFrontImage, + IdBackImage: kycInfo.IDBackImage, + BankStatementImg: kycInfo.BankStatementImg, + BankCode: kycInfo.BankCode, + BankName: kycInfo.BankName, + BranchCode: kycInfo.BranchCode, + BranchName: kycInfo.BranchName, + BankAccount: kycInfo.BankAccount, + Status: kycInfo.Status.ToString(), + RejectReason: kycInfo.RejectReason, + UpdatedAt: kycInfo.UpdatedAt, + CreatedAt: kycInfo.CreatedAt, + }, nil +} diff --git a/internal/logic/product/find_latest_k_y_c_by_u_i_d_logic.go b/internal/logic/product/find_latest_k_y_c_by_u_i_d_logic.go new file mode 100644 index 0000000..2c4edff --- /dev/null +++ b/internal/logic/product/find_latest_k_y_c_by_u_i_d_logic.go @@ -0,0 +1,56 @@ +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 FindLatestKYCByUIDLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewFindLatestKYCByUIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FindLatestKYCByUIDLogic { + return &FindLatestKYCByUIDLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 +func (l *FindLatestKYCByUIDLogic) FindLatestKYCByUID(in *product.FindLatestKYCByUIDReq) (*product.KYC, error) { + kycInfo, err := l.svcCtx.KYCUseCase.FindLatestByUID(l.ctx, in.GetUid()) + if err != nil { + return nil, err + } + + return &product.KYC{ + Id: kycInfo.ID.Hex(), + Uid: kycInfo.UID, + CountryRegion: kycInfo.CountryRegion, + Name: kycInfo.Name, + Identification: kycInfo.Identification, + IdentificationType: kycInfo.IdentificationType, + Address: kycInfo.Address, + PostalCode: kycInfo.PostalCode, + // 上傳文件網址(可為 object storage 的 URL) + IdFrontImage: kycInfo.IDFrontImage, + IdBackImage: kycInfo.IDBackImage, + BankStatementImg: kycInfo.BankStatementImg, + BankCode: kycInfo.BankCode, + BankName: kycInfo.BankName, + BranchCode: kycInfo.BranchCode, + BranchName: kycInfo.BranchName, + BankAccount: kycInfo.BankAccount, + Status: kycInfo.Status.ToString(), + RejectReason: kycInfo.RejectReason, + UpdatedAt: kycInfo.UpdatedAt, + CreatedAt: kycInfo.CreatedAt, + }, nil +} diff --git a/internal/logic/product/list_k_y_c_logic.go b/internal/logic/product/list_k_y_c_logic.go new file mode 100644 index 0000000..d2bad49 --- /dev/null +++ b/internal/logic/product/list_k_y_c_logic.go @@ -0,0 +1,72 @@ +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 ListKYCLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewListKYCLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListKYCLogic { + return &ListKYCLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// ListKYC 分頁查詢 KYC 清單(後台審核用) +func (l *ListKYCLogic) ListKYC(in *product.ListKYCReq) (*product.ListKYCResp, error) { + filter := usecase.KYCQueryParams{ + UID: in.Uid, + Country: in.Country, + Status: in.Status, + PageSize: in.GetPageSize(), + PageIndex: in.GetPageIndex(), + } + + list, total, err := l.svcCtx.KYCUseCase.List(l.ctx, filter) + if err != nil { + return nil, err + } + + result := make([]*product.KYC, 0, len(list)) + for _, kycInfo := range list { + result = append(result, &product.KYC{ + Id: kycInfo.ID.Hex(), + Uid: kycInfo.UID, + CountryRegion: kycInfo.CountryRegion, + Name: kycInfo.Name, + Identification: kycInfo.Identification, + IdentificationType: kycInfo.IdentificationType, + Address: kycInfo.Address, + PostalCode: kycInfo.PostalCode, + IdFrontImage: kycInfo.IDFrontImage, + IdBackImage: kycInfo.IDBackImage, + BankStatementImg: kycInfo.BankStatementImg, + BankCode: kycInfo.BankCode, + BankName: kycInfo.BankName, + BranchCode: kycInfo.BranchCode, + BranchName: kycInfo.BranchName, + BankAccount: kycInfo.BankAccount, + Status: kycInfo.Status.ToString(), + RejectReason: kycInfo.RejectReason, + UpdatedAt: kycInfo.UpdatedAt, + CreatedAt: kycInfo.CreatedAt, + }) + } + + return &product.ListKYCResp{ + Total: total, + List: result, + }, nil +} diff --git a/internal/logic/product/update_k_y_c_info_logic.go b/internal/logic/product/update_k_y_c_info_logic.go new file mode 100644 index 0000000..0f0e96c --- /dev/null +++ b/internal/logic/product/update_k_y_c_info_logic.go @@ -0,0 +1,51 @@ +package productlogic + +import ( + "code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase" + "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 UpdateKYCInfoLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateKYCInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateKYCInfoLogic { + return &UpdateKYCInfoLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// UpdateKYCInfo 更新使用者的 KYC(尚未審核) +func (l *UpdateKYCInfoLogic) UpdateKYCInfo(in *product.UpdateKYCInfoReq) (*product.OKResp, error) { + // 如果已完成應該不能 + err := l.svcCtx.KYCUseCase.UpdateKYCInfo(l.ctx, in.GetId(), &usecase.KYCUpdateParams{ + Name: proto.String(in.GetName()), + Identification: proto.String(in.GetIdentification()), + IdentificationType: proto.String(in.GetIdentificationType()), + Address: proto.String(in.GetAddress()), + PostalCode: proto.String(in.GetPostalCode()), + IDFrontImage: proto.String(in.GetIdFrontImage()), + IDBackImage: proto.String(in.GetIdBackImage()), + BankStatementImg: proto.String(in.GetBankStatementImg()), + BankCode: proto.String(in.GetBankCode()), + BankName: proto.String(in.GetBankName()), + BranchCode: proto.String(in.GetBranchCode()), + BranchName: proto.String(in.GetBranchName()), + BankAccount: proto.String(in.GetBankAccount()), + }) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/logic/product/update_k_y_c_status_logic.go b/internal/logic/product/update_k_y_c_status_logic.go new file mode 100644 index 0000000..10f9dbc --- /dev/null +++ b/internal/logic/product/update_k_y_c_status_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 UpdateKYCStatusLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateKYCStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateKYCStatusLogic { + return &UpdateKYCStatusLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// UpdateKYCStatus 更新 KYC 審核狀態與原因 +func (l *UpdateKYCStatusLogic) UpdateKYCStatus(in *product.UpdateKYCStatusReq) (*product.OKResp, error) { + err := l.svcCtx.KYCUseCase.UpdateStatus(l.ctx, in.GetId(), in.GetStatus(), in.GetReason()) + if err != nil { + return nil, err + } + + return &product.OKResp{}, nil +} diff --git a/internal/server/product/product_server.go b/internal/server/product/product_server.go index d6a1c9b..24fbe79 100644 --- a/internal/server/product/product_server.go +++ b/internal/server/product/product_server.go @@ -82,3 +82,39 @@ func (s *ProductServer) ListTags(ctx context.Context, in *product.ListTagsReq) ( l := productlogic.NewListTagsLogic(ctx, s.svcCtx) return l.ListTags(in) } + +// ====================== Tags Service End ====================== +func (s *ProductServer) CreateKYC(ctx context.Context, in *product.CreateKYCReq) (*product.OKResp, error) { + l := productlogic.NewCreateKYCLogic(ctx, s.svcCtx) + return l.CreateKYC(in) +} + +// FindLatestKYCByUID 根據使用者 UID 查詢最新 KYC 紀錄 +func (s *ProductServer) FindLatestKYCByUID(ctx context.Context, in *product.FindLatestKYCByUIDReq) (*product.KYC, error) { + l := productlogic.NewFindLatestKYCByUIDLogic(ctx, s.svcCtx) + return l.FindLatestKYCByUID(in) +} + +// FindKYCByID 根據 KYC ID 查詢 +func (s *ProductServer) FindKYCByID(ctx context.Context, in *product.FindKYCByIDReq) (*product.KYC, error) { + l := productlogic.NewFindKYCByIDLogic(ctx, s.svcCtx) + return l.FindKYCByID(in) +} + +// ListKYC 分頁查詢 KYC 清單(後台審核用) +func (s *ProductServer) ListKYC(ctx context.Context, in *product.ListKYCReq) (*product.ListKYCResp, error) { + l := productlogic.NewListKYCLogic(ctx, s.svcCtx) + return l.ListKYC(in) +} + +// UpdateKYCStatus 更新 KYC 審核狀態與原因 +func (s *ProductServer) UpdateKYCStatus(ctx context.Context, in *product.UpdateKYCStatusReq) (*product.OKResp, error) { + l := productlogic.NewUpdateKYCStatusLogic(ctx, s.svcCtx) + return l.UpdateKYCStatus(in) +} + +// UpdateKYCInfo 更新使用者的 KYC(尚未審核) +func (s *ProductServer) UpdateKYCInfo(ctx context.Context, in *product.UpdateKYCInfoReq) (*product.OKResp, error) { + l := productlogic.NewUpdateKYCInfoLogic(ctx, s.svcCtx) + return l.UpdateKYCInfo(in) +} diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 62a341f..603c7c6 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -14,12 +14,14 @@ type ServiceContext struct { Config config.Config CategoryUseCase usecase.CategoryUseCase TagsUseCase usecase.ProductBaseTags + KYCUseCase usecase.KYCUseCase } func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ CategoryUseCase: MustCategory(c), TagsUseCase: MustTags(c), + KYCUseCase: MustKYC(c), Config: c, } } @@ -103,3 +105,43 @@ func MustTags(c config.Config) usecase.ProductBaseTags { return uc.MustTagsUseCase(uc.TagsUseCaseParam{ TagsRepo: tagsRepo}) } + +func MustKYC(c config.Config) usecase.KYCUseCase { + // 準備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), + } + + kycRepo := repo.NewKYCRepository(repo.KYCRepositoryParam{ + Conf: conf, + CacheConf: c.Cache, + CacheOpts: cacheOpts, + DBOpts: dbOpts, + }) + + return uc.MustKYCUseCase(uc.KYCUseCaseParam{ + KYCRepo: kycRepo}) +} diff --git a/pkg/domain/repository/kyc.go b/pkg/domain/repository/kyc.go index 1f98529..79bcf11 100644 --- a/pkg/domain/repository/kyc.go +++ b/pkg/domain/repository/kyc.go @@ -38,8 +38,6 @@ type KYCUpdateParams struct { IdentificationType *string Address *string PostalCode *string - DateOfBirth *string - Gender *string IDFrontImage *string IDBackImage *string BankStatementImg *string diff --git a/pkg/domain/usecase/kyc.go b/pkg/domain/usecase/kyc.go index dd17b05..bd96d66 100644 --- a/pkg/domain/usecase/kyc.go +++ b/pkg/domain/usecase/kyc.go @@ -36,8 +36,6 @@ type KYCUpdateParams struct { IdentificationType *string Address *string PostalCode *string - DateOfBirth *string - Gender *string IDFrontImage *string IDBackImage *string BankStatementImg *string diff --git a/pkg/repository/kyc.go b/pkg/repository/kyc.go index 4f57b79..c7e5e93 100644 --- a/pkg/repository/kyc.go +++ b/pkg/repository/kyc.go @@ -104,11 +104,11 @@ func (repo *KYCRepository) List(ctx context.Context, params repository.KYCQueryP // 設置排序選項 opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize) - if params.SortByDate { - opts.SetSort(bson.E{Key: "created_at", Value: -1}) - } else { - opts.SetSort(bson.D{{Key: "updated_at", Value: -1}}) - } + //if params.SortByDate { + // opts.SetSort(bson.E{Key: "created_at", Value: -1}) + //} else { + // opts.SetSort(bson.D{{Key: "updated_at", Value: -1}}) + //} // 查詢符合條件的總數 total, err := repo.DB.GetClient().CountDocuments(ctx, filter) if err != nil { @@ -164,12 +164,6 @@ func (repo *KYCRepository) UpdateKYCInfo(ctx context.Context, id string, update if update.PostalCode != nil { setFields["postal_code"] = *update.PostalCode } - if update.DateOfBirth != nil { - setFields["date_of_birth"] = *update.DateOfBirth - } - if update.Gender != nil { - setFields["gender"] = *update.Gender - } if update.IDFrontImage != nil { setFields["id_front_image"] = *update.IDFrontImage } diff --git a/pkg/usecase/kyc.go b/pkg/usecase/kyc.go index f0083c1..b66f2bc 100644 --- a/pkg/usecase/kyc.go +++ b/pkg/usecase/kyc.go @@ -48,7 +48,7 @@ func (use *KYCUseCase) Create(ctx context.Context, data *entity.KYC) error { {Key: "param", Value: data}, {Key: "func", Value: "KYCRepo.FindLatestByUID"}, {Key: "reason", Value: "KYC already in progress or approved"}, - }, "不能重複送出 KYC 資料") + }, "KYC already in progress or approved") } // ✅ 若查不到資料(ErrNotFound),或前一筆是 REJECTED,允許建立 @@ -68,6 +68,10 @@ func (use *KYCUseCase) Create(ctx context.Context, data *entity.KYC) error { func (use *KYCUseCase) FindLatestByUID(ctx context.Context, uid string) (*entity.KYC, error) { latest, err := use.KYCRepo.FindLatestByUID(ctx, uid) + if errors.Is(err, repo.ErrNotFound) { + return nil, errs.ResourceNotFound("failed to find latest kyc") + } + if err != nil { return nil, errs.DBErrorL(logx.WithContext(ctx), []logx.LogField{ @@ -144,8 +148,6 @@ func (use *KYCUseCase) UpdateKYCInfo(ctx context.Context, id string, update *use IdentificationType: update.IdentificationType, Address: update.Address, PostalCode: update.PostalCode, - DateOfBirth: update.DateOfBirth, - Gender: update.Gender, IDFrontImage: update.IDFrontImage, IDBackImage: update.IDBackImage, BankStatementImg: update.BankStatementImg, diff --git a/pkg/usecase/kyc_test.go b/pkg/usecase/kyc_test.go index 068f419..c3bdd2e 100644 --- a/pkg/usecase/kyc_test.go +++ b/pkg/usecase/kyc_test.go @@ -82,7 +82,7 @@ func TestKYCUseCase_Create(t *testing.T) { {Key: "func", Value: "KYCRepo.FindLatestByUID"}, {Key: "reason", Value: "KYC already in progress or approved"}, }, - "不能重複送出 KYC 資料", + "KYC already in progress or approved", ), }, { @@ -473,8 +473,6 @@ func TestKYCUseCase_UpdateKYCInfo(t *testing.T) { IdentificationType: proto.String("passport"), Address: proto.String("Taipei City"), PostalCode: proto.String("100"), - DateOfBirth: proto.String("1993-04-17"), - Gender: proto.String("M"), IDFrontImage: proto.String("https://example.com/front.jpg"), IDBackImage: proto.String("https://example.com/back.jpg"), BankStatementImg: proto.String("https://example.com/bank.jpg"), @@ -503,8 +501,6 @@ func TestKYCUseCase_UpdateKYCInfo(t *testing.T) { IdentificationType: updateParams.IdentificationType, Address: updateParams.Address, PostalCode: updateParams.PostalCode, - DateOfBirth: updateParams.DateOfBirth, - Gender: updateParams.Gender, IDFrontImage: updateParams.IDFrontImage, IDBackImage: updateParams.IDBackImage, BankStatementImg: updateParams.BankStatementImg,