app-cloudep-product-service/pkg/usecase/product.go

638 lines
20 KiB
Go
Raw Normal View History

2025-03-21 09:12:08 +00:00
package usecase
import (
2025-04-06 02:08:46 +00:00
"context"
"errors"
2025-03-21 09:12:08 +00:00
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/usecase"
2025-03-31 13:24:40 +00:00
repo "code.30cm.net/digimon/app-cloudep-product-service/pkg/repository"
2025-03-23 16:08:32 +00:00
"code.30cm.net/digimon/app-cloudep-product-service/pkg/utils"
2025-03-25 07:58:02 +00:00
"code.30cm.net/digimon/library-go/errs"
2025-03-23 16:08:32 +00:00
"github.com/zeromicro/go-zero/core/logx"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
2025-03-21 09:12:08 +00:00
)
type ProductUseCaseParam struct {
ProductRepo repository.ProductRepository
TagRepo repository.TagRepo
TagBinding repository.TagBindingRepo
ProductStatisticsRepo repository.ProductStatisticsRepo
}
type ProductUseCase struct {
ProductUseCaseParam
}
func MustProductUseCase(param ProductUseCaseParam) usecase.ProductUseCase {
return &ProductUseCase{
param,
}
}
func (use *ProductUseCase) Create(ctx context.Context, product *usecase.Product) error {
2025-03-31 13:24:40 +00:00
insert := convertUseCaseToEntity(product)
2025-03-23 16:08:32 +00:00
// Transaction 設定:只做必要寫入
opts := options.Transaction().SetReadConcern(readconcern.Local())
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-23 16:08:32 +00:00
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
if err := use.ProductRepo.Insert(sessCtx, insert); err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "ProductRepo.Insert", []logx.LogField{{Key: "req", Value: product}}, err, "failed to create product")
2025-03-23 16:08:32 +00:00
}
if err := use.ProductStatisticsRepo.Create(sessCtx, &entity.ProductStatistics{
ProductID: insert.ID.Hex(),
Orders: 0,
OrdersUpdateTime: 0,
AverageRating: 0,
AverageRatingUpdateTime: 0,
FansCount: 0,
FansCountUpdateTime: 0,
}); err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "ProductStatisticsRepo.Create", []logx.LogField{{Key: "ProductID", Value: insert.ID.Hex()}}, err, "failed to create product statistics")
2025-03-23 16:08:32 +00:00
}
2025-03-31 13:24:40 +00:00
tagsBinding := buildTagsBinding(insert.ID.Hex(), product.Tags)
2025-03-25 09:28:05 +00:00
if err := use.TagBinding.BindTags(sessCtx, tagsBinding); err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: insert.ID.Hex()}, {Key: "tags", Value: product.Tags}}, err, "failed to bind product tags")
2025-03-25 09:28:05 +00:00
}
2025-03-23 16:08:32 +00:00
2025-04-06 02:08:46 +00:00
return struct{}{}, nil
2025-03-23 16:08:32 +00:00
}, opts)
2025-03-21 09:12:08 +00:00
if err != nil {
return err
}
2025-03-23 16:08:32 +00:00
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) Update(ctx context.Context, id string, product *usecase.Product) error {
2025-03-31 13:24:40 +00:00
update := convertUseCaseToUpdateParams(product)
tagsBinding := buildTagsBinding(id, product.Tags)
2025-03-25 09:28:05 +00:00
opts := options.Transaction().SetReadConcern(readconcern.Local())
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-25 09:28:05 +00:00
_, err := use.ProductRepo.Update(sessCtx, id, update)
if err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "ProductRepo.Update", []logx.LogField{{Key: "req", Value: product}}, err, "failed to update product")
2025-03-25 09:28:05 +00:00
}
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-25 09:28:05 +00:00
if err := use.TagBinding.UnbindTagByReferenceID(sessCtx, id); err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "TagBinding.UnbindTagByReferenceID", []logx.LogField{{Key: "ReferenceID", Value: id}}, err, "failed to unbind tags")
2025-03-25 09:28:05 +00:00
}
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-25 09:28:05 +00:00
if err := use.TagBinding.BindTags(sessCtx, tagsBinding); err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "TagBinding.BindTags", []logx.LogField{{Key: "ReferenceID", Value: id}, {Key: "tags", Value: product.Tags}}, err, "failed to bind tags")
2025-03-25 09:28:05 +00:00
}
2025-04-06 02:08:46 +00:00
return struct{}{}, nil
2025-03-25 09:28:05 +00:00
}, opts)
2025-03-31 13:24:40 +00:00
return err
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) Delete(ctx context.Context, id string) error {
2025-03-25 09:28:05 +00:00
// Transaction 設定:只做必要寫入
opts := options.Transaction().SetReadConcern(readconcern.Local())
err := use.ProductRepo.Transaction(ctx, func(sessCtx mongo.SessionContext) (any, error) {
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-25 09:28:05 +00:00
err := use.ProductRepo.Delete(sessCtx, id)
if err != nil {
e := errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "ReferenceID", Value: id},
{Key: "func", Value: "ProductRepo.Delete"},
{Key: "err", Value: err.Error()},
}, "failed to delete product")
return nil, e
}
2025-04-06 02:08:46 +00:00
//nolint:contextcheck
2025-03-25 09:28:05 +00:00
err = use.TagRepo.UnbindTagByReferenceID(sessCtx, id)
if err != nil {
e := errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "ReferenceID", Value: id},
{Key: "func", Value: "TagBinding.UnbindTagByReferenceID"},
{Key: "err", Value: err.Error()},
}, "failed to unbind tags")
return nil, e
}
2025-04-06 02:08:46 +00:00
return struct{}{}, nil
2025-03-25 09:28:05 +00:00
}, opts)
if err != nil {
return err
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) Get(ctx context.Context, id string) (*usecase.ProductResp, error) {
2025-03-25 09:28:05 +00:00
product, err := use.ProductRepo.FindOneByID(ctx, id)
if err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "ProductRepo.FindOneByID", []logx.LogField{{Key: "product_id", Value: id}}, err, "failed to find product")
2025-03-25 09:28:05 +00:00
}
2025-03-31 13:24:40 +00:00
stats, err := use.ProductStatisticsRepo.GetByID(ctx, id)
2025-03-25 09:28:05 +00:00
if err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "ProductStatisticsRepo.GetByID", []logx.LogField{{Key: "product_id", Value: id}}, err, "failed to get product statistics")
2025-03-25 09:28:05 +00:00
}
2025-03-31 13:24:40 +00:00
bindings, err := use.TagRepo.GetBindingsByReference(ctx, id)
2025-03-25 09:28:05 +00:00
if err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "TagRepo.GetBindingsByReference", []logx.LogField{{Key: "product_id", Value: id}}, err, "failed to get tag bindings")
2025-03-25 09:28:05 +00:00
}
2025-03-31 13:24:40 +00:00
tagIDs := make([]string, 0, len(bindings))
for _, item := range bindings {
tagIDs = append(tagIDs, item.TagID)
2025-03-25 09:28:05 +00:00
}
2025-03-31 13:24:40 +00:00
tags, err := use.TagRepo.GetByIDs(ctx, tagIDs)
2025-03-25 09:28:05 +00:00
if err != nil {
2025-03-31 13:24:40 +00:00
return nil, logDBError(ctx, "TagRepo.GetByIDs", []logx.LogField{{Key: "product_id", Value: id}}, err, "failed to get tags")
2025-03-25 09:28:05 +00:00
}
2025-03-31 13:24:40 +00:00
return convertEntityToResp(product, stats, tags), nil
2025-03-21 09:12:08 +00:00
}
2025-03-31 13:24:40 +00:00
// TODO 效能有問題這邊優先改List 會有N + 1 問題
2025-03-21 09:12:08 +00:00
func (use *ProductUseCase) List(ctx context.Context, data usecase.ProductQueryParams) ([]*usecase.ProductResp, int64, error) {
2025-03-25 09:28:05 +00:00
query := &repository.ProductQueryParams{
PageSize: data.PageSize,
PageIndex: data.PageIndex,
}
if data.Slug != nil {
query.Slug = data.Slug
}
if data.UID != nil {
query.UID = data.UID
}
if data.IsPublished != nil {
query.IsPublished = data.IsPublished
}
if data.Category != nil {
query.Category = data.Category
}
if data.StartTime != nil {
query.StartTime = data.StartTime
}
2025-03-31 13:24:40 +00:00
if data.EndTime != nil {
query.EndTime = data.EndTime
}
2025-03-25 09:28:05 +00:00
2025-03-31 13:24:40 +00:00
products, total, err := use.ProductRepo.ListProduct(ctx, query)
2025-03-25 09:28:05 +00:00
if err != nil {
return nil, 0, err
}
2025-03-31 13:24:40 +00:00
result := make([]*usecase.ProductResp, 0, len(products))
for _, p := range products {
// 查詢統計資料
stats, _ := use.ProductStatisticsRepo.GetByID(ctx, p.ID.Hex())
// 查詢 Tag 資訊
tags, _ := use.TagRepo.GetBindingsByReference(ctx, p.ID.Hex())
tagIDs := make([]string, 0, len(tags))
for _, t := range tags {
tagIDs = append(tagIDs, t.TagID)
}
tagsInfo, _ := use.TagRepo.GetByIDs(ctx, tagIDs)
// 組合 Tags 回應
respTags := make([]usecase.Tags, 0, len(tagsInfo))
for _, tag := range tagsInfo {
item := usecase.Tags{
ID: tag.ID.Hex(),
Types: tag.Types,
Name: tag.Name,
ShowType: tag.ShowType,
UpdatedAt: utils.UnixToRfc3339(tag.UpdatedAt),
CreatedAt: utils.UnixToRfc3339(tag.CreatedAt),
}
if tag.Cover != nil {
item.Cover = *tag.Cover
}
respTags = append(respTags, item)
}
// Media & CustomFields
media := make([]usecase.Media, 0, len(p.Media))
for _, m := range p.Media {
media = append(media, usecase.Media{
Sort: m.Sort,
URL: m.URL,
Type: m.Type,
})
}
customFields := make([]usecase.CustomFields, 0, len(p.CustomFields))
for _, f := range p.CustomFields {
customFields = append(customFields, usecase.CustomFields{
Key: f.Key,
Value: f.Value,
})
}
resp := &usecase.ProductResp{
ID: p.ID.Hex(),
UID: p.UID,
Title: p.Title,
ShortTitle: utils.ToValue(p.ShortTitle),
Details: utils.ToValue(p.Details),
ShortDescription: p.ShortDescription,
Media: media,
Slug: utils.ToValue(p.Slug),
IsPublished: p.IsPublished,
Amount: p.Amount,
StartTime: utils.UnixToRfc3339(utils.ToValue(p.StartTime)),
EndTime: utils.UnixToRfc3339(utils.ToValue(p.EndTime)),
Category: p.Category,
CustomFields: customFields,
Tags: respTags,
Orders: stats.Orders,
OrdersUpdateTime: utils.UnixToRfc3339(stats.OrdersUpdateTime),
AverageRating: stats.AverageRating,
AverageRatingUpdateTime: utils.UnixToRfc3339(stats.AverageRatingUpdateTime),
FansCount: stats.FansCount,
FansCountUpdateTime: utils.UnixToRfc3339(stats.FansCountUpdateTime),
UpdatedAt: utils.UnixToRfc3339(p.UpdatedAt),
CreatedAt: utils.UnixToRfc3339(p.CreatedAt),
}
result = append(result, resp)
}
return result, total, nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) IncOrders(ctx context.Context, productID string, count int64) error {
2025-03-31 13:24:40 +00:00
err := use.ProductStatisticsRepo.IncOrders(ctx, productID, count)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "product_id", Value: productID},
{Key: "func", Value: "ProductStatisticsRepo.IncOrders"},
{Key: "err", Value: err.Error()},
}, "failed to inc order")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) DecOrders(ctx context.Context, productID string, count int64) error {
2025-03-31 13:24:40 +00:00
err := use.ProductStatisticsRepo.DecOrders(ctx, productID, count)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "product_id", Value: productID},
{Key: "func", Value: "ProductStatisticsRepo.DecOrders"},
{Key: "err", Value: err.Error()},
}, "failed to dec order")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) UpdateAverageRating(ctx context.Context, productID string, averageRating float64) error {
2025-03-31 13:24:40 +00:00
err := use.ProductStatisticsRepo.UpdateAverageRating(ctx, productID, averageRating)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "product_id", Value: productID},
{Key: "func", Value: "ProductStatisticsRepo.UpdateAverageRating"},
{Key: "err", Value: err.Error()},
}, "failed to update average rating")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) IncFansCount(ctx context.Context, productID string, fansCount uint64) error {
2025-03-31 13:24:40 +00:00
err := use.ProductStatisticsRepo.IncFansCount(ctx, productID, fansCount)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "product_id", Value: productID},
{Key: "func", Value: "ProductStatisticsRepo.IncFansCount"},
{Key: "err", Value: err.Error()},
}, "failed to inc fans count")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) DecFansCount(ctx context.Context, productID string, fansCount uint64) error {
2025-03-31 13:24:40 +00:00
err := use.ProductStatisticsRepo.DecFansCount(ctx, productID, fansCount)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "product_id", Value: productID},
{Key: "func", Value: "ProductStatisticsRepo.DecFansCount"},
{Key: "err", Value: err.Error()},
}, "failed to dec fans count")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) BindTag(ctx context.Context, binding usecase.TagsBindingTable) error {
2025-03-31 13:24:40 +00:00
_, err := use.TagRepo.GetByID(ctx, binding.TagID)
if err != nil {
if errors.Is(err, repo.ErrNotFound) {
return errs.ResourceNotFound("failed to get tags")
}
return err
}
_, err = use.ProductRepo.FindOneByID(ctx, binding.ReferenceID)
if err != nil {
if errors.Is(err, repo.ErrNotFound) {
return errs.ResourceNotFound("failed to get tags")
}
return err
}
err = use.TagBinding.BindTags(ctx, []*entity.TagsBindingTable{{ReferenceID: binding.ReferenceID, TagID: binding.TagID}})
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "binding", Value: binding},
{Key: "func", Value: "TagBinding.BindTags"},
{Key: "err", Value: err.Error()},
}, "failed to bind tags")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) UnbindTag(ctx context.Context, binding usecase.TagsBindingTable) error {
2025-03-31 13:24:40 +00:00
_, err := use.TagRepo.GetByID(ctx, binding.TagID)
if err != nil {
if errors.Is(err, repo.ErrNotFound) {
return errs.ResourceNotFound("failed to get tags")
}
return err
}
_, err = use.ProductRepo.FindOneByID(ctx, binding.ReferenceID)
if err != nil {
if errors.Is(err, repo.ErrNotFound) {
return errs.ResourceNotFound("failed to get tags")
}
return err
}
err = use.TagBinding.UnbindTag(ctx, binding.TagID, binding.ReferenceID)
if err != nil {
return errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "binding", Value: binding},
{Key: "func", Value: "TagBinding.UnbindTag"},
{Key: "err", Value: err.Error()},
}, "failed to unbind tags")
}
return nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) GetBindingsByReference(ctx context.Context, referenceID string) ([]usecase.TagsBindingTableResp, error) {
2025-03-31 13:24:40 +00:00
ref, err := use.TagBinding.GetBindingsByReference(ctx, referenceID)
if err != nil {
return nil, errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "referenceID", Value: referenceID},
{Key: "func", Value: "TagBinding.GetBindingsByReference"},
{Key: "err", Value: err.Error()},
}, "failed to get bindings by reference")
}
result := make([]usecase.TagsBindingTableResp, 0, len(ref))
for _, bind := range ref {
result = append(result, usecase.TagsBindingTableResp{
ID: bind.ID.Hex(),
ReferenceID: bind.ReferenceID,
TagID: bind.TagID,
CreatedAt: utils.UnixToRfc3339(bind.CreatedAt),
UpdatedAt: utils.UnixToRfc3339(bind.UpdatedAt),
})
}
return result, nil
2025-03-21 09:12:08 +00:00
}
func (use *ProductUseCase) ListTagBinding(ctx context.Context, params usecase.TagBindingQueryParams) ([]usecase.TagsBindingTableResp, int64, error) {
2025-03-31 13:24:40 +00:00
ref, total, err := use.TagBinding.ListTagBinding(ctx, repository.TagBindingQueryParams{
ReferenceID: params.ReferenceID,
TagID: params.TagID,
PageIndex: params.PageIndex,
PageSize: params.PageSize,
})
if err != nil {
return nil, 0, errs.DBErrorL(logx.WithContext(ctx),
[]logx.LogField{
{Key: "params", Value: params},
{Key: "func", Value: "TagBinding.ListTagBinding"},
{Key: "err", Value: err.Error()},
}, "failed to list tags")
}
result := make([]usecase.TagsBindingTableResp, 0, len(ref))
for _, bind := range ref {
result = append(result, usecase.TagsBindingTableResp{
ID: bind.ID.Hex(),
ReferenceID: bind.ReferenceID,
TagID: bind.TagID,
CreatedAt: utils.UnixToRfc3339(bind.CreatedAt),
UpdatedAt: utils.UnixToRfc3339(bind.UpdatedAt),
})
}
return result, total, nil
}
func logDBError(ctx context.Context, funcName string, fields []logx.LogField, err error, msg string) error {
return errs.DBErrorL(logx.WithContext(ctx), append(fields, logx.Field("func", funcName), logx.Field("err", err.Error())), msg)
}
func buildTagsBinding(referenceID string, tags []string) []*entity.TagsBindingTable {
binding := make([]*entity.TagsBindingTable, 0, len(tags))
for _, tag := range tags {
binding = append(binding, &entity.TagsBindingTable{
ReferenceID: referenceID,
TagID: tag,
})
}
2025-04-06 02:08:46 +00:00
2025-03-31 13:24:40 +00:00
return binding
}
func convertUseCaseToEntity(product *usecase.Product) *entity.Product {
insert := &entity.Product{}
if product.UID != nil {
insert.UID = *product.UID
}
if product.Title != nil {
insert.Title = *product.Title
}
if product.IsPublished != nil {
insert.IsPublished = *product.IsPublished
}
if product.Category != nil {
insert.Category = *product.Category
}
if product.ShortTitle != nil {
insert.ShortTitle = product.ShortTitle
}
if product.Details != nil {
insert.Details = product.Details
}
if product.ShortDescription != nil {
insert.ShortDescription = *product.ShortDescription
}
if product.Slug != nil {
insert.Slug = product.Slug
}
if product.Amount != 0 {
insert.Amount = product.Amount
}
if product.StartTime != nil {
st := utils.Rfc3339ToUnix(utils.ToValue(product.StartTime))
insert.StartTime = &st
}
if product.EndTime != nil {
et := utils.Rfc3339ToUnix(utils.ToValue(product.EndTime))
insert.EndTime = &et
}
if len(product.Media) > 0 {
medias := make([]entity.Media, 0, len(product.Media))
for _, m := range product.Media {
medias = append(medias, entity.Media{Sort: m.Sort, URL: m.URL, Type: m.Type})
}
insert.Media = medias
}
if len(product.CustomFields) > 0 {
cf := make([]entity.CustomFields, 0, len(product.CustomFields))
for _, field := range product.CustomFields {
cf = append(cf, entity.CustomFields{Key: field.Key, Value: field.Value})
}
insert.CustomFields = cf
}
return insert
}
func convertUseCaseToUpdateParams(product *usecase.Product) *repository.ProductUpdateParams {
update := &repository.ProductUpdateParams{}
if product.Title != nil {
update.Title = product.Title
}
if product.IsPublished != nil {
update.IsPublished = product.IsPublished
}
if product.Category != nil {
update.Category = product.Category
}
if product.ShortTitle != nil {
update.ShortTitle = product.ShortTitle
}
if product.Details != nil {
update.Details = product.Details
}
if product.ShortDescription != nil {
update.ShortDescription = *product.ShortDescription
}
if product.Slug != nil {
update.Slug = product.Slug
}
if product.Amount != 0 {
update.Amount = &product.Amount
}
if product.StartTime != nil {
st := utils.Rfc3339ToUnix(utils.ToValue(product.StartTime))
update.StartTime = &st
}
if product.EndTime != nil {
et := utils.Rfc3339ToUnix(utils.ToValue(product.EndTime))
update.EndTime = &et
}
if len(product.Media) > 0 {
medias := make([]entity.Media, 0, len(product.Media))
for _, m := range product.Media {
medias = append(medias, entity.Media{Sort: m.Sort, URL: m.URL, Type: m.Type})
}
update.Media = medias
}
if len(product.CustomFields) > 0 {
cf := make([]entity.CustomFields, 0, len(product.CustomFields))
for _, field := range product.CustomFields {
cf = append(cf, entity.CustomFields{Key: field.Key, Value: field.Value})
}
update.CustomFields = cf
}
2025-04-06 02:08:46 +00:00
2025-03-31 13:24:40 +00:00
return update
}
func convertEntityToResp(p *entity.Product, stats *entity.ProductStatistics, tags []*entity.Tags) *usecase.ProductResp {
tagsResp := make([]usecase.Tags, 0, len(tags))
for _, tag := range tags {
item := usecase.Tags{
ID: tag.ID.Hex(),
Types: tag.Types,
Name: tag.Name,
ShowType: tag.ShowType,
UpdatedAt: utils.UnixToRfc3339(tag.UpdatedAt),
CreatedAt: utils.UnixToRfc3339(tag.CreatedAt),
}
if tag.Cover != nil {
item.Cover = *tag.Cover
}
tagsResp = append(tagsResp, item)
}
media := make([]usecase.Media, 0, len(p.Media))
for _, m := range p.Media {
media = append(media, usecase.Media{Sort: m.Sort, URL: m.URL, Type: m.Type})
}
cf := make([]usecase.CustomFields, 0, len(p.CustomFields))
for _, field := range p.CustomFields {
cf = append(cf, usecase.CustomFields{Key: field.Key, Value: field.Value})
}
return &usecase.ProductResp{
ID: p.ID.Hex(),
UID: p.UID,
Title: p.Title,
ShortTitle: utils.ToValue(p.ShortTitle),
Details: utils.ToValue(p.Details),
ShortDescription: p.ShortDescription,
Slug: utils.ToValue(p.Slug),
IsPublished: p.IsPublished,
Amount: p.Amount,
StartTime: utils.UnixToRfc3339(utils.ToValue(p.StartTime)),
EndTime: utils.UnixToRfc3339(utils.ToValue(p.EndTime)),
Category: p.Category,
Media: media,
CustomFields: cf,
Tags: tagsResp,
Orders: stats.Orders,
OrdersUpdateTime: utils.UnixToRfc3339(stats.OrdersUpdateTime),
AverageRating: stats.AverageRating,
AverageRatingUpdateTime: utils.UnixToRfc3339(stats.AverageRatingUpdateTime),
FansCount: stats.FansCount,
FansCountUpdateTime: utils.UnixToRfc3339(stats.FansCountUpdateTime),
UpdatedAt: utils.UnixToRfc3339(p.UpdatedAt),
CreatedAt: utils.UnixToRfc3339(p.CreatedAt),
}
2025-03-21 09:12:08 +00:00
}