feat: add product item api

This commit is contained in:
王性驊 2025-04-09 17:29:56 +08:00
parent 5d4f15fe8c
commit 1a32f58515
21 changed files with 2474 additions and 171 deletions

View File

@ -18,24 +18,36 @@ type (
CategoryReq = product.CategoryReq
CreateCategoryReq = product.CreateCategoryReq
CreateKYCReq = product.CreateKYCReq
CreateProductItemRequest = product.CreateProductItemRequest
CreateTagsReq = product.CreateTagsReq
CustomField = product.CustomField
DeleteProductItemRequest = product.DeleteProductItemRequest
DeleteProductItemsByReferenceIDReq = product.DeleteProductItemsByReferenceIDReq
FindKYCByIDReq = product.FindKYCByIDReq
FindLatestKYCByUIDReq = product.FindLatestKYCByUIDReq
GetProductItemRequest = product.GetProductItemRequest
IncDecSalesCountRequest = product.IncDecSalesCountRequest
KYC = product.KYC
ListCategoryReq = product.ListCategoryReq
ListCategoryResp = product.ListCategoryResp
ListKYCReq = product.ListKYCReq
ListKYCResp = product.ListKYCResp
ListProductItemRequest = product.ListProductItemRequest
ListProductItemResponse = product.ListProductItemResponse
ListTagsReq = product.ListTagsReq
ListTagsResp = product.ListTagsResp
Media = product.Media
ModifyCategoryReq = product.ModifyCategoryReq
ModifyTagsReq = product.ModifyTagsReq
NoneReq = product.NoneReq
OKResp = product.OKResp
ProductItem = product.ProductItem
Tags = product.Tags
TagsReq = product.TagsReq
UpdateKYCInfoReq = product.UpdateKYCInfoReq
UpdateKYCStatusReq = product.UpdateKYCStatusReq
UpdateProductItemRequest = product.UpdateProductItemRequest
UpdateStatusRequest = product.UpdateStatusRequest
Product interface {
// ====================== Category Service Start ======================
@ -70,6 +82,24 @@ type (
UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error)
// UpdateKYCInfo 更新使用者的 KYC尚未審核
UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error)
// ====================== Know You Customer Service End ======================
CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// GetProductItem 取得 ProductItem
GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error)
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error)
// DeleteProductItems 刪除 Delete Product Item
DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error)
// IncSalesCount 增加賣出數量
IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error)
// DecSalesCount 減少賣出數量
DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error)
// Update 更新 Item
Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// UpdateStatus 更新 Item status
UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error)
}
defaultProduct struct {
@ -178,3 +208,57 @@ func (m *defaultProduct) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq
client := product.NewProductClient(m.cli.Conn())
return client.UpdateKYCInfo(ctx, in, opts...)
}
// ====================== Know You Customer Service End ======================
func (m *defaultProduct) CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.CreateItem(ctx, in, opts...)
}
// GetProductItem 取得 ProductItem
func (m *defaultProduct) GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) {
client := product.NewProductClient(m.cli.Conn())
return client.GetProductItem(ctx, in, opts...)
}
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
func (m *defaultProduct) GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) {
client := product.NewProductClient(m.cli.Conn())
return client.GetProductItemsByProductID(ctx, in, opts...)
}
// DeleteProductItems 刪除 Delete Product Item
func (m *defaultProduct) DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.DeleteProductItems(ctx, in, opts...)
}
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
func (m *defaultProduct) DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.DeleteProductItemsByReferenceID(ctx, in, opts...)
}
// IncSalesCount 增加賣出數量
func (m *defaultProduct) IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.IncSalesCount(ctx, in, opts...)
}
// DecSalesCount 減少賣出數量
func (m *defaultProduct) DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.DecSalesCount(ctx, in, opts...)
}
// Update 更新 Item
func (m *defaultProduct) Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.Update(ctx, in, opts...)
}
// UpdateStatus 更新 Item status
func (m *defaultProduct) UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) {
client := product.NewProductClient(m.cli.Conn())
return client.UpdateStatus(ctx, in, opts...)
}

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,15 @@ const (
Product_ListKYC_FullMethodName = "/product.Product/ListKYC"
Product_UpdateKYCStatus_FullMethodName = "/product.Product/UpdateKYCStatus"
Product_UpdateKYCInfo_FullMethodName = "/product.Product/UpdateKYCInfo"
Product_CreateItem_FullMethodName = "/product.Product/CreateItem"
Product_GetProductItem_FullMethodName = "/product.Product/GetProductItem"
Product_GetProductItemsByProductID_FullMethodName = "/product.Product/GetProductItemsByProductID"
Product_DeleteProductItems_FullMethodName = "/product.Product/DeleteProductItems"
Product_DeleteProductItemsByReferenceID_FullMethodName = "/product.Product/DeleteProductItemsByReferenceID"
Product_IncSalesCount_FullMethodName = "/product.Product/IncSalesCount"
Product_DecSalesCount_FullMethodName = "/product.Product/DecSalesCount"
Product_Update_FullMethodName = "/product.Product/Update"
Product_UpdateStatus_FullMethodName = "/product.Product/UpdateStatus"
)
// ProductClient is the client API for Product service.
@ -78,6 +87,26 @@ type ProductClient interface {
UpdateKYCStatus(ctx context.Context, in *UpdateKYCStatusReq, opts ...grpc.CallOption) (*OKResp, error)
// UpdateKYCInfo 更新使用者的 KYC尚未審核
UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq, opts ...grpc.CallOption) (*OKResp, error)
// ====================== Know You Customer Service End ======================
// ====================== ProductItem Service Start ======================
// CreateItem 建立 ProductItem
CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// GetProductItem 取得 ProductItem
GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error)
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error)
// DeleteProductItems 刪除 Delete Product Item
DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error)
// IncSalesCount 增加賣出數量
IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error)
// DecSalesCount 減少賣出數量
DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error)
// Update 更新 Item
Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error)
// UpdateStatus 更新 Item status
UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error)
}
type productClient struct {
@ -248,6 +277,96 @@ func (c *productClient) UpdateKYCInfo(ctx context.Context, in *UpdateKYCInfoReq,
return out, nil
}
func (c *productClient) CreateItem(ctx context.Context, in *CreateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_CreateItem_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) GetProductItem(ctx context.Context, in *GetProductItemRequest, opts ...grpc.CallOption) (*ProductItem, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ProductItem)
err := c.cc.Invoke(ctx, Product_GetProductItem_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) GetProductItemsByProductID(ctx context.Context, in *ListProductItemRequest, opts ...grpc.CallOption) (*ListProductItemResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListProductItemResponse)
err := c.cc.Invoke(ctx, Product_GetProductItemsByProductID_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) DeleteProductItems(ctx context.Context, in *DeleteProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_DeleteProductItems_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) DeleteProductItemsByReferenceID(ctx context.Context, in *DeleteProductItemsByReferenceIDReq, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_DeleteProductItemsByReferenceID_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) IncSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_IncSalesCount_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) DecSalesCount(ctx context.Context, in *IncDecSalesCountRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_DecSalesCount_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) Update(ctx context.Context, in *UpdateProductItemRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_Update_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productClient) UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*OKResp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OKResp)
err := c.cc.Invoke(ctx, Product_UpdateStatus_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ProductServer is the server API for Product service.
// All implementations must embed UnimplementedProductServer
// for forward compatibility.
@ -289,6 +408,26 @@ type ProductServer interface {
UpdateKYCStatus(context.Context, *UpdateKYCStatusReq) (*OKResp, error)
// UpdateKYCInfo 更新使用者的 KYC尚未審核
UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error)
// ====================== Know You Customer Service End ======================
// ====================== ProductItem Service Start ======================
// CreateItem 建立 ProductItem
CreateItem(context.Context, *CreateProductItemRequest) (*OKResp, error)
// GetProductItem 取得 ProductItem
GetProductItem(context.Context, *GetProductItemRequest) (*ProductItem, error)
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
GetProductItemsByProductID(context.Context, *ListProductItemRequest) (*ListProductItemResponse, error)
// DeleteProductItems 刪除 Delete Product Item
DeleteProductItems(context.Context, *DeleteProductItemRequest) (*OKResp, error)
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
DeleteProductItemsByReferenceID(context.Context, *DeleteProductItemsByReferenceIDReq) (*OKResp, error)
// IncSalesCount 增加賣出數量
IncSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error)
// DecSalesCount 減少賣出數量
DecSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error)
// Update 更新 Item
Update(context.Context, *UpdateProductItemRequest) (*OKResp, error)
// UpdateStatus 更新 Item status
UpdateStatus(context.Context, *UpdateStatusRequest) (*OKResp, error)
mustEmbedUnimplementedProductServer()
}
@ -347,6 +486,33 @@ func (UnimplementedProductServer) UpdateKYCStatus(context.Context, *UpdateKYCSta
func (UnimplementedProductServer) UpdateKYCInfo(context.Context, *UpdateKYCInfoReq) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateKYCInfo not implemented")
}
func (UnimplementedProductServer) CreateItem(context.Context, *CreateProductItemRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateItem not implemented")
}
func (UnimplementedProductServer) GetProductItem(context.Context, *GetProductItemRequest) (*ProductItem, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetProductItem not implemented")
}
func (UnimplementedProductServer) GetProductItemsByProductID(context.Context, *ListProductItemRequest) (*ListProductItemResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetProductItemsByProductID not implemented")
}
func (UnimplementedProductServer) DeleteProductItems(context.Context, *DeleteProductItemRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteProductItems not implemented")
}
func (UnimplementedProductServer) DeleteProductItemsByReferenceID(context.Context, *DeleteProductItemsByReferenceIDReq) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteProductItemsByReferenceID not implemented")
}
func (UnimplementedProductServer) IncSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method IncSalesCount not implemented")
}
func (UnimplementedProductServer) DecSalesCount(context.Context, *IncDecSalesCountRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method DecSalesCount not implemented")
}
func (UnimplementedProductServer) Update(context.Context, *UpdateProductItemRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (UnimplementedProductServer) UpdateStatus(context.Context, *UpdateStatusRequest) (*OKResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateStatus not implemented")
}
func (UnimplementedProductServer) mustEmbedUnimplementedProductServer() {}
func (UnimplementedProductServer) testEmbeddedByValue() {}
@ -656,6 +822,168 @@ func _Product_UpdateKYCInfo_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _Product_CreateItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateProductItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).CreateItem(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_CreateItem_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).CreateItem(ctx, req.(*CreateProductItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_GetProductItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetProductItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).GetProductItem(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_GetProductItem_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).GetProductItem(ctx, req.(*GetProductItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_GetProductItemsByProductID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListProductItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).GetProductItemsByProductID(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_GetProductItemsByProductID_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).GetProductItemsByProductID(ctx, req.(*ListProductItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_DeleteProductItems_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteProductItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).DeleteProductItems(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_DeleteProductItems_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).DeleteProductItems(ctx, req.(*DeleteProductItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_DeleteProductItemsByReferenceID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteProductItemsByReferenceIDReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).DeleteProductItemsByReferenceID(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_DeleteProductItemsByReferenceID_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).DeleteProductItemsByReferenceID(ctx, req.(*DeleteProductItemsByReferenceIDReq))
}
return interceptor(ctx, in, info, handler)
}
func _Product_IncSalesCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IncDecSalesCountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).IncSalesCount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_IncSalesCount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).IncSalesCount(ctx, req.(*IncDecSalesCountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_DecSalesCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IncDecSalesCountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).DecSalesCount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_DecSalesCount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).DecSalesCount(ctx, req.(*IncDecSalesCountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateProductItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_Update_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).Update(ctx, req.(*UpdateProductItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Product_UpdateStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateStatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductServer).UpdateStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Product_UpdateStatus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductServer).UpdateStatus(ctx, req.(*UpdateStatusRequest))
}
return interceptor(ctx, in, info, handler)
}
// Product_ServiceDesc is the grpc.ServiceDesc for Product service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -727,6 +1055,42 @@ var Product_ServiceDesc = grpc.ServiceDesc{
MethodName: "UpdateKYCInfo",
Handler: _Product_UpdateKYCInfo_Handler,
},
{
MethodName: "CreateItem",
Handler: _Product_CreateItem_Handler,
},
{
MethodName: "GetProductItem",
Handler: _Product_GetProductItem_Handler,
},
{
MethodName: "GetProductItemsByProductID",
Handler: _Product_GetProductItemsByProductID_Handler,
},
{
MethodName: "DeleteProductItems",
Handler: _Product_DeleteProductItems_Handler,
},
{
MethodName: "DeleteProductItemsByReferenceID",
Handler: _Product_DeleteProductItemsByReferenceID_Handler,
},
{
MethodName: "IncSalesCount",
Handler: _Product_IncSalesCount_Handler,
},
{
MethodName: "DecSalesCount",
Handler: _Product_DecSalesCount_Handler,
},
{
MethodName: "Update",
Handler: _Product_Update_Handler,
},
{
MethodName: "UpdateStatus",
Handler: _Product_UpdateStatus_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "generate/protobuf/product.proto",

View File

@ -174,8 +174,95 @@ message UpdateKYCInfoReq {
optional string bank_account = 14;
}
// ====================== Product Item Param ======================
message ProductItem {
optional string id = 1;
string reference_id = 2;
string name = 3;
string description = 4;
string short_description = 5;
bool is_un_limit = 6;
bool is_free = 7;
uint64 stock = 8;
string price = 9;
string sku = 10;
string time_series = 11;
repeated Media media = 12;
string status = 13;
repeated CustomField freight = 14;
repeated CustomField custom_fields = 15;
uint64 sales_count = 16;
optional string updated_at = 17;
optional string created_at = 18;
}
message Media {
string url = 1;
string type = 2;
optional uint64 sort=3;
}
message CustomField {
string key = 1;
string value = 2;
}
message CreateProductItemRequest {
ProductItem item = 1;
}
message GetProductItemRequest {
string id = 1;
}
message ListProductItemRequest {
int64 page_size = 1;
int64 page_index = 2;
string reference_id = 3;
optional bool is_un_limit = 4;
optional bool is_free = 5;
optional string status = 6;
}
message ListProductItemResponse{
repeated ProductItem data = 1;
int64 total = 2;
}
message DeleteProductItemRequest {
repeated string id = 1;
}
message DeleteProductItemsByReferenceIDReq {
string id = 1;
}
message IncDecSalesCountRequest {
string id = 1;
uint64 count = 2;
}
message UpdateProductItemRequest {
string id = 1;
optional string name = 2;
optional string description = 3;
optional string short_description = 4;
optional bool is_un_limit = 5;
optional bool is_free = 6;
optional uint64 stock = 7;
optional string price = 8;
optional string sku = 9;
optional string time_series = 10;
repeated Media media = 11;
optional string status = 12;
repeated CustomField freight = 13;
repeated CustomField custom_fields = 14;
}
message UpdateStatusRequest {
string id = 1;
string status = 2;
}
service Product {
@ -217,4 +304,24 @@ service Product {
// UpdateKYCInfo 使 KYC
rpc UpdateKYCInfo (UpdateKYCInfoReq) returns (OKResp);
// ====================== Know You Customer Service End ======================
// ====================== ProductItem Service Start ======================
// CreateItem ProductItem
rpc CreateItem(CreateProductItemRequest) returns (OKResp);
// GetProductItem ProductItem
rpc GetProductItem(GetProductItemRequest) returns (ProductItem);
// GetProductItemsByProductID 使 ProductID ProductItems
rpc GetProductItemsByProductID(ListProductItemRequest) returns (ListProductItemResponse);
// DeleteProductItems Delete Product Item
rpc DeleteProductItems(DeleteProductItemRequest) returns (OKResp);
// DeleteProductItemsByReferenceID 使 ProductID Item
rpc DeleteProductItemsByReferenceID(DeleteProductItemsByReferenceIDReq) returns (OKResp);
// IncSalesCount
rpc IncSalesCount(IncDecSalesCountRequest) returns (OKResp);
// DecSalesCount
rpc DecSalesCount(IncDecSalesCountRequest) returns (OKResp);
// Update Item
rpc Update(UpdateProductItemRequest) returns (OKResp);
// UpdateStatus Item status
rpc UpdateStatus(UpdateStatusRequest) returns (OKResp);
// ====================== ProductItem Service End ======================
}

2
go.mod
View File

@ -6,6 +6,7 @@ require (
code.30cm.net/digimon/library-go/errs v1.2.14
code.30cm.net/digimon/library-go/mongo v0.0.9
github.com/alicebob/miniredis/v2 v2.34.0
github.com/golang/snappy v0.0.4
github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.10.0
github.com/testcontainers/testcontainers-go v0.34.0
@ -48,7 +49,6 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect

View File

@ -0,0 +1,96 @@
package productlogic
import (
"code.30cm.net/digimon/app-cloudep-product-service/internal/utils"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/library-go/errs"
"context"
PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type CreateItemLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewCreateItemLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateItemLogic {
return &CreateItemLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *CreateItemLogic) CreateItem(in *PB.CreateProductItemRequest) (*PB.OKResp, error) {
insert := &usecase.ProductItems{
ReferenceID: in.GetItem().ReferenceId, // 對應的專案 ID
Name: in.GetItem().Name, // 名稱
Description: utils.EncodeToBase64Snappy(in.GetItem().Description), // 描述
ShortDescription: utils.EncodeToBase64Snappy(in.GetItem().ShortDescription), // 封面簡短描述
IsUnLimit: in.GetItem().IsUnLimit, // 是否沒有數量上限
IsFree: in.GetItem().IsFree, // 是否為免費品項(贈品) -> 開啟就是自訂金額
Stock: in.GetItem().Stock, // 庫存總數
Price: in.GetItem().Price, // 價格
SKU: in.GetItem().Sku, // 型號:對應顯示 Item 的 FK
SalesCount: 0, // 已賣出數量(相反,減到零就不能在賣)
}
if len(in.GetItem().Media) > 0 {
// 專案動態內容(圖片或者影片)
m := make([]usecase.Media, 0, len(in.GetItem().Media))
for _, item := range in.GetItem().Media {
m = append(m, usecase.Media{
URL: item.Url,
Type: item.Type,
})
}
insert.Media = m
}
if len(in.GetItem().CustomFields) > 0 {
// 自定義屬性
c := make([]usecase.CustomFields, 0, len(in.GetItem().CustomFields))
for _, cItem := range in.GetItem().CustomFields {
c = append(c, usecase.CustomFields{
Key: cItem.Key,
Value: cItem.Value,
})
}
insert.CustomFields = c
}
if len(in.GetItem().Freight) > 0 {
// 運費
f := make([]usecase.CustomFields, 0, len(in.GetItem().Freight))
for _, fItem := range in.GetItem().Freight {
f = append(f, usecase.CustomFields{
Key: fItem.Key,
Value: fItem.Value,
})
}
insert.Freight = f
}
status, e := product.StringToItemStatus(in.GetItem().Status)
if !e {
return nil, errs.InvalidFormat("failed to convert string to item status")
}
insert.Status = status
timeSeries, te := product.StringToTimeSeries(in.GetItem().TimeSeries)
if !te {
return nil, errs.InvalidFormat("failed to convert string to time series")
}
insert.TimeSeries = timeSeries
err := l.svcCtx.ProductItemUseCase.Create(l.ctx, insert)
if err != nil {
return nil, err
}
return &PB.OKResp{}, nil
}

View File

@ -0,0 +1,35 @@
package productlogic
import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type DecSalesCountLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewDecSalesCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DecSalesCountLogic {
return &DecSalesCountLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// DecSalesCount 減少賣出數量
func (l *DecSalesCountLogic) DecSalesCount(in *product.IncDecSalesCountRequest) (*product.OKResp, error) {
// TODO 有問題可以在這邊加瑣
err := l.svcCtx.ProductItemUseCase.DecSalesCount(l.ctx, in.GetId(), in.GetCount())
if err != nil {
return nil, err
}
return &product.OKResp{}, nil
}

View File

@ -0,0 +1,34 @@
package productlogic
import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type DeleteProductItemsByReferenceIDLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewDeleteProductItemsByReferenceIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductItemsByReferenceIDLogic {
return &DeleteProductItemsByReferenceIDLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
func (l *DeleteProductItemsByReferenceIDLogic) DeleteProductItemsByReferenceID(in *product.DeleteProductItemsByReferenceIDReq) (*product.OKResp, error) {
err := l.svcCtx.ProductItemUseCase.DeleteByReferenceID(l.ctx, in.GetId())
if err != nil {
return nil, err
}
return &product.OKResp{}, nil
}

View File

@ -0,0 +1,34 @@
package productlogic
import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type DeleteProductItemsLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewDeleteProductItemsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductItemsLogic {
return &DeleteProductItemsLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// DeleteProductItems 刪除 Delete Product Item
func (l *DeleteProductItemsLogic) DeleteProductItems(in *product.DeleteProductItemRequest) (*product.OKResp, error) {
err := l.svcCtx.ProductItemUseCase.Delete(l.ctx, in.GetId())
if err != nil {
return nil, err
}
return &product.OKResp{}, nil
}

View File

@ -0,0 +1,83 @@
package productlogic
import (
"code.30cm.net/digimon/app-cloudep-product-service/internal/utils"
"context"
"google.golang.org/protobuf/proto"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type GetProductItemLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetProductItemLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductItemLogic {
return &GetProductItemLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// GetProductItem 取得 ProductItem
func (l *GetProductItemLogic) GetProductItem(in *product.GetProductItemRequest) (*product.ProductItem, error) {
item, err := l.svcCtx.ProductItemUseCase.Get(l.ctx, in.GetId())
if err != nil {
return nil, err
}
result := &product.ProductItem{
Id: proto.String(item.ID),
ReferenceId: item.ReferenceID,
Name: item.Name,
Description: utils.DecodeToBase64Snappy(item.Description),
ShortDescription: utils.DecodeToBase64Snappy(item.ShortDescription),
IsUnLimit: item.IsUnLimit,
IsFree: item.IsFree,
Stock: item.Stock,
Price: item.Price,
Sku: item.SKU,
TimeSeries: item.TimeSeries.ToString(),
SalesCount: item.SalesCount,
Status: item.Status.ToString(),
UpdatedAt: proto.String(item.UpdatedAt),
CreatedAt: proto.String(item.CreatedAt),
}
media := make([]*product.Media, 0, len(item.Media))
for _, pi := range item.Media {
media = append(media, &product.Media{
Sort: proto.Uint64(pi.Sort),
Url: pi.URL,
Type: pi.Type,
})
}
result.Media = media
// 運費
f := make([]*product.CustomField, 0, len(item.Freight))
for _, fItem := range item.Freight {
f = append(f, &product.CustomField{
Key: fItem.Key,
Value: fItem.Value,
})
}
result.Freight = f
// 運費
c := make([]*product.CustomField, 0, len(item.CustomFields))
for _, fItem := range item.CustomFields {
f = append(f, &product.CustomField{
Key: fItem.Key,
Value: fItem.Value,
})
}
result.CustomFields = c
return result, nil
}

View File

@ -0,0 +1,112 @@
package productlogic
import (
"code.30cm.net/digimon/app-cloudep-product-service/internal/utils"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"code.30cm.net/digimon/library-go/errs"
"context"
"google.golang.org/protobuf/proto"
PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type GetProductItemsByProductIDLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetProductItemsByProductIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductItemsByProductIDLogic {
return &GetProductItemsByProductIDLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
func (l *GetProductItemsByProductIDLogic) GetProductItemsByProductID(in *PB.ListProductItemRequest) (*PB.ListProductItemResponse, error) {
filter := usecase.QueryProductItemParam{
PageSize: in.GetPageSize(),
PageIndex: in.GetPageIndex(),
ReferenceID: proto.String(in.GetReferenceId()),
}
if in.Status != nil {
status, e := product.StringToItemStatus(in.GetStatus())
if !e {
return nil, errs.InvalidFormat("failed to convert string to item status")
}
filter.Status = &status
}
if in.IsFree != nil {
filter.IsFree = in.IsFree
}
if in.IsUnLimit != nil {
filter.IsUnLimit = in.IsUnLimit
}
list, total, err := l.svcCtx.ProductItemUseCase.List(l.ctx, filter)
if err != nil {
return nil, err
}
result := make([]*PB.ProductItem, 0)
for _, item := range list {
pi := &PB.ProductItem{
Id: proto.String(item.ID),
ReferenceId: item.ReferenceID,
Name: item.Name,
Description: utils.DecodeToBase64Snappy(item.Description),
ShortDescription: utils.DecodeToBase64Snappy(item.ShortDescription),
IsUnLimit: item.IsUnLimit,
IsFree: item.IsFree,
Stock: item.Stock,
Price: item.Price,
Sku: item.SKU,
TimeSeries: item.TimeSeries.ToString(),
SalesCount: item.SalesCount,
Status: item.Status.ToString(),
UpdatedAt: proto.String(item.UpdatedAt),
CreatedAt: proto.String(item.CreatedAt),
}
media := make([]*PB.Media, 0, len(item.Media))
for _, pi := range item.Media {
media = append(media, &PB.Media{
Sort: proto.Uint64(pi.Sort),
Url: pi.URL,
Type: pi.Type,
})
}
pi.Media = media
// 運費
f := make([]*PB.CustomField, 0, len(item.Freight))
for _, fItem := range item.Freight {
f = append(f, &PB.CustomField{
Key: fItem.Key,
Value: fItem.Value,
})
}
pi.Freight = f
// 運費
c := make([]*PB.CustomField, 0, len(item.CustomFields))
for _, fItem := range item.CustomFields {
f = append(f, &PB.CustomField{
Key: fItem.Key,
Value: fItem.Value,
})
}
pi.CustomFields = c
result = append(result, pi)
}
return &PB.ListProductItemResponse{
Total: total,
Data: result,
}, nil
}

View File

@ -0,0 +1,35 @@
package productlogic
import (
"context"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type IncSalesCountLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewIncSalesCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IncSalesCountLogic {
return &IncSalesCountLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// IncSalesCount 增加賣出數量
func (l *IncSalesCountLogic) IncSalesCount(in *product.IncDecSalesCountRequest) (*product.OKResp, error) {
// TODO 有問題可以在這邊加瑣
err := l.svcCtx.ProductItemUseCase.IncSalesCount(l.ctx, in.GetId(), in.GetCount())
if err != nil {
return nil, err
}
return &product.OKResp{}, nil
}

View File

@ -0,0 +1,37 @@
package productlogic
import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
"context"
"code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type UpdateLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateLogic {
return &UpdateLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// Update 更新 Item
func (l *UpdateLogic) Update(in *product.UpdateProductItemRequest) (*product.OKResp, error) {
update := &usecase.UpdateProductItems{}
err := l.svcCtx.ProductItemUseCase.Update(l.ctx, in.GetId(), update)
if err != nil {
return nil, err
}
return &product.OKResp{}, nil
}

View File

@ -0,0 +1,41 @@
package productlogic
import (
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/product"
"code.30cm.net/digimon/library-go/errs"
"context"
PB "code.30cm.net/digimon/app-cloudep-product-service/gen_result/pb/product"
"code.30cm.net/digimon/app-cloudep-product-service/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type UpdateStatusLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewUpdateStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateStatusLogic {
return &UpdateStatusLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// UpdateStatus 更新 Item status
func (l *UpdateStatusLogic) UpdateStatus(in *PB.UpdateStatusRequest) (*PB.OKResp, error) {
status, e := product.StringToItemStatus(in.GetStatus())
if !e {
return nil, errs.InvalidFormat("failed to convert string to item status")
}
err := l.svcCtx.ProductItemUseCase.UpdateStatus(l.ctx, in.GetId(), status)
if err != nil {
return nil, err
}
return &PB.OKResp{}, nil
}

View File

@ -118,3 +118,57 @@ func (s *ProductServer) UpdateKYCInfo(ctx context.Context, in *product.UpdateKYC
l := productlogic.NewUpdateKYCInfoLogic(ctx, s.svcCtx)
return l.UpdateKYCInfo(in)
}
// ====================== Know You Customer Service End ======================
func (s *ProductServer) CreateItem(ctx context.Context, in *product.CreateProductItemRequest) (*product.OKResp, error) {
l := productlogic.NewCreateItemLogic(ctx, s.svcCtx)
return l.CreateItem(in)
}
// GetProductItem 取得 ProductItem
func (s *ProductServer) GetProductItem(ctx context.Context, in *product.GetProductItemRequest) (*product.ProductItem, error) {
l := productlogic.NewGetProductItemLogic(ctx, s.svcCtx)
return l.GetProductItem(in)
}
// GetProductItemsByProductID 使用 ProductID 取得 ProductItems
func (s *ProductServer) GetProductItemsByProductID(ctx context.Context, in *product.ListProductItemRequest) (*product.ListProductItemResponse, error) {
l := productlogic.NewGetProductItemsByProductIDLogic(ctx, s.svcCtx)
return l.GetProductItemsByProductID(in)
}
// DeleteProductItems 刪除 Delete Product Item
func (s *ProductServer) DeleteProductItems(ctx context.Context, in *product.DeleteProductItemRequest) (*product.OKResp, error) {
l := productlogic.NewDeleteProductItemsLogic(ctx, s.svcCtx)
return l.DeleteProductItems(in)
}
// DeleteProductItemsByReferenceID 使用 ProductID 刪除所有 Item
func (s *ProductServer) DeleteProductItemsByReferenceID(ctx context.Context, in *product.DeleteProductItemsByReferenceIDReq) (*product.OKResp, error) {
l := productlogic.NewDeleteProductItemsByReferenceIDLogic(ctx, s.svcCtx)
return l.DeleteProductItemsByReferenceID(in)
}
// IncSalesCount 增加賣出數量
func (s *ProductServer) IncSalesCount(ctx context.Context, in *product.IncDecSalesCountRequest) (*product.OKResp, error) {
l := productlogic.NewIncSalesCountLogic(ctx, s.svcCtx)
return l.IncSalesCount(in)
}
// DecSalesCount 減少賣出數量
func (s *ProductServer) DecSalesCount(ctx context.Context, in *product.IncDecSalesCountRequest) (*product.OKResp, error) {
l := productlogic.NewDecSalesCountLogic(ctx, s.svcCtx)
return l.DecSalesCount(in)
}
// Update 更新 Item
func (s *ProductServer) Update(ctx context.Context, in *product.UpdateProductItemRequest) (*product.OKResp, error) {
l := productlogic.NewUpdateLogic(ctx, s.svcCtx)
return l.Update(in)
}
// UpdateStatus 更新 Item status
func (s *ProductServer) UpdateStatus(ctx context.Context, in *product.UpdateStatusRequest) (*product.OKResp, error) {
l := productlogic.NewUpdateStatusLogic(ctx, s.svcCtx)
return l.UpdateStatus(in)
}

View File

@ -15,6 +15,7 @@ type ServiceContext struct {
CategoryUseCase usecase.CategoryUseCase
TagsUseCase usecase.ProductBaseTags
KYCUseCase usecase.KYCUseCase
ProductItemUseCase usecase.ProductItemUseCase
}
func NewServiceContext(c config.Config) *ServiceContext {
@ -145,3 +146,43 @@ func MustKYC(c config.Config) usecase.KYCUseCase {
return uc.MustKYCUseCase(uc.KYCUseCaseParam{
KYCRepo: kycRepo})
}
func MustProductItem(c config.Config) usecase.ProductItemUseCase {
// 準備Mongo Config
conf := &mgo.Conf{
Schema: c.Mongo.Schema,
Host: c.Mongo.Host,
Database: c.Mongo.Database,
MaxStaleness: c.Mongo.MaxStaleness,
MaxPoolSize: c.Mongo.MaxPoolSize,
MinPoolSize: c.Mongo.MinPoolSize,
MaxConnIdleTime: c.Mongo.MaxConnIdleTime,
Compressors: c.Mongo.Compressors,
EnableStandardReadWriteSplitMode: c.Mongo.EnableStandardReadWriteSplitMode,
ConnectTimeoutMs: c.Mongo.ConnectTimeoutMs,
}
if c.Mongo.User != "" {
conf.User = c.Mongo.User
conf.Password = c.Mongo.Password
}
// 快取選項
cacheOpts := []cache.Option{
cache.WithExpiry(c.CacheExpireTime),
cache.WithNotFoundExpiry(c.CacheWithNotFoundExpiry),
}
dbOpts := []mon.Option{
mgo.SetCustomDecimalType(),
mgo.InitMongoOptions(*conf),
}
productItemRepo := repo.NewProductItemRepository(repo.ProductItemRepositoryParam{
Conf: conf,
CacheConf: c.Cache,
CacheOpts: cacheOpts,
DBOpts: dbOpts,
})
return uc.MustProductItemUseCase(uc.ProductItemUseCaseParam{
ProductItems: productItemRepo})
}

23
internal/utils/encode.go Executable file
View File

@ -0,0 +1,23 @@
package utils
import (
"encoding/base64"
"github.com/golang/snappy"
)
// EncodeToBase64Snappy 將字串進行 Base64 和 Snappy 編碼
func EncodeToBase64Snappy(data string) string {
snappyData := snappy.Encode(nil, []byte(data))
encoded := base64.StdEncoding.EncodeToString(snappyData)
return encoded
}
// DecodeToBase64Snappy 將字串進行 Base64 和 Snappy 解碼
func DecodeToBase64Snappy(data string) string {
decodeB64Content, _ := base64.StdEncoding.DecodeString(data)
snappyContent, _ := snappy.Decode(nil, decodeB64Content)
return string(snappyContent)
}

View File

@ -8,3 +8,41 @@ const (
TimeSeriesHalfHour // 每半小時
TimeSeriesOneHour // 每小時
)
func (t *TimeSeries) ToString() string {
s, _ := TimeSeriesToString(*t)
return s
}
const (
TimeSeriesUnknownStr = "unknown"
TimeSeriesTenMinutesStr = "ten_minutes"
TimeSeriesHalfHourStr = "half_hour"
TimeSeriesOneHourStr = "one_hour"
)
var timeSeriesToStringMap = map[TimeSeries]string{
TimeSeriesUnknown: TimeSeriesUnknownStr,
TimeSeriesTenMinutes: TimeSeriesTenMinutesStr,
TimeSeriesHalfHour: TimeSeriesHalfHourStr,
TimeSeriesOneHour: TimeSeriesOneHourStr,
}
var stringToTimeSeriesMap = map[string]TimeSeries{
TimeSeriesUnknownStr: TimeSeriesUnknown,
TimeSeriesTenMinutesStr: TimeSeriesTenMinutes,
TimeSeriesHalfHourStr: TimeSeriesHalfHour,
TimeSeriesOneHourStr: TimeSeriesOneHour,
}
// TimeSeriesToString 將 TimeSeries 轉換為字串
func TimeSeriesToString(ts TimeSeries) (string, bool) {
str, ok := timeSeriesToStringMap[ts]
return str, ok
}
// StringToTimeSeries 將字串轉換為 TimeSeries
func StringToTimeSeries(str string) (TimeSeries, bool) {
ts, ok := stringToTimeSeriesMap[str]
return ts, ok
}

View File

@ -20,9 +20,11 @@ type ProductItemUseCase interface {
// DecSalesCount 更新商品資訊
DecSalesCount(ctx context.Context, id string, saleCount uint64) error
// Delete ID 刪除商品
Delete(ctx context.Context, id string) error
Delete(ctx context.Context, ids []string) error
// List 列出符合條件的商品,可根據需求加入分頁或其他條件參數
List(ctx context.Context, filter QueryProductItemParam) ([]*ProductItems, int64, error)
// DeleteByReferenceID 刪除某Project 下所有
DeleteByReferenceID(ctx context.Context, id string) error
}
type ProductItems struct {

View File

@ -177,6 +177,19 @@ func (use *ProductItemUseCase) Get(ctx context.Context, id string) (*usecase.Pro
return fromEntity(ent), nil
}
func (use *ProductItemUseCase) DeleteByReferenceID(ctx context.Context, id string) error {
err := use.ProductItems.DeleteByReferenceID(ctx, id)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "id", Value: id},
{Key: "func", Value: "ProductItemUseCaseParam.ProductItems.DeleteByReferenceID"},
{Key: "err", Value: err.Error()},
}, "failed to delete product items")
}
return nil
}
func (use *ProductItemUseCase) Update(ctx context.Context, id string, data *usecase.UpdateProductItems) error {
// 構建更新參數(僅更新部分欄位)
update := &repository.ProductUpdateItem{}
@ -303,12 +316,12 @@ func (use *ProductItemUseCase) DecSalesCount(ctx context.Context, id string, sal
return nil
}
func (use *ProductItemUseCase) Delete(ctx context.Context, id string) error {
func (use *ProductItemUseCase) Delete(ctx context.Context, ids []string) error {
// repository.Delete 接收 slice因此將 id 放入 slice 中
if err := use.ProductItemUseCaseParam.ProductItems.Delete(ctx, []string{id}); err != nil {
if err := use.ProductItemUseCaseParam.ProductItems.Delete(ctx, ids); err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "id", Value: id},
{Key: "id", Value: ids},
{Key: "func", Value: "ProductItemUseCaseParam.ProductItems.Delete"},
{Key: "err", Value: err.Error()},
}, "failed to delete product item")

View File

@ -228,13 +228,13 @@ func TestProductItemUseCase_Delete(t *testing.T) {
t.Run("刪除成功", func(t *testing.T) {
mockItemRepo.EXPECT().Delete(ctx, []string{id}).Return(nil)
err := useCase.Delete(ctx, id)
err := useCase.Delete(ctx, []string{id})
assert.NoError(t, err)
})
t.Run("資料庫錯誤", func(t *testing.T) {
mockItemRepo.EXPECT().Delete(ctx, []string{id}).Return(errors.New("db error"))
err := useCase.Delete(ctx, id)
err := useCase.Delete(ctx, []string{id})
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to delete product item")
})