2025-07-15 13:21:34 +08:00
|
|
|
|
package product
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
2025-07-20 20:53:26 +08:00
|
|
|
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
"tyapi-server/internal/application/product/dto/commands"
|
|
|
|
|
|
appQueries "tyapi-server/internal/application/product/dto/queries"
|
|
|
|
|
|
"tyapi-server/internal/application/product/dto/responses"
|
|
|
|
|
|
"tyapi-server/internal/domains/product/entities"
|
2025-07-20 20:53:26 +08:00
|
|
|
|
product_service "tyapi-server/internal/domains/product/services"
|
2025-07-15 13:21:34 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ProductApplicationServiceImpl 产品应用服务实现
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 负责业务流程编排、事务管理、数据转换,不直接操作仓库
|
2025-07-15 13:21:34 +08:00
|
|
|
|
type ProductApplicationServiceImpl struct {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productManagementService *product_service.ProductManagementService
|
|
|
|
|
|
productSubscriptionService *product_service.ProductSubscriptionService
|
|
|
|
|
|
logger *zap.Logger
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewProductApplicationService 创建产品应用服务
|
|
|
|
|
|
func NewProductApplicationService(
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productManagementService *product_service.ProductManagementService,
|
|
|
|
|
|
productSubscriptionService *product_service.ProductSubscriptionService,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
logger *zap.Logger,
|
|
|
|
|
|
) ProductApplicationService {
|
|
|
|
|
|
return &ProductApplicationServiceImpl{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productManagementService: productManagementService,
|
|
|
|
|
|
productSubscriptionService: productSubscriptionService,
|
|
|
|
|
|
logger: logger,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CreateProduct 创建产品
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 构建产品实体 2. 创建产品
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) CreateProduct(ctx context.Context, cmd *commands.CreateProductCommand) error {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 1. 构建产品实体
|
2025-07-15 13:21:34 +08:00
|
|
|
|
product := &entities.Product{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
Name: cmd.Name,
|
|
|
|
|
|
Code: cmd.Code,
|
|
|
|
|
|
Description: cmd.Description,
|
|
|
|
|
|
Content: cmd.Content,
|
|
|
|
|
|
CategoryID: cmd.CategoryID,
|
|
|
|
|
|
Price: cmd.Price,
|
|
|
|
|
|
IsEnabled: cmd.IsEnabled,
|
|
|
|
|
|
IsVisible: cmd.IsVisible,
|
|
|
|
|
|
IsPackage: cmd.IsPackage,
|
|
|
|
|
|
SEOTitle: cmd.SEOTitle,
|
|
|
|
|
|
SEODescription: cmd.SEODescription,
|
|
|
|
|
|
SEOKeywords: cmd.SEOKeywords,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 2. 创建产品
|
|
|
|
|
|
_, err := s.productManagementService.CreateProduct(ctx, product)
|
|
|
|
|
|
return err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateProduct 更新产品
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取现有产品 2. 更新产品信息 3. 保存产品
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) UpdateProduct(ctx context.Context, cmd *commands.UpdateProductCommand) error {
|
|
|
|
|
|
// 1. 获取现有产品
|
2025-07-20 20:53:26 +08:00
|
|
|
|
existingProduct, err := s.productManagementService.GetProductByID(ctx, cmd.ID)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 2. 更新产品信息
|
|
|
|
|
|
existingProduct.Name = cmd.Name
|
|
|
|
|
|
existingProduct.Code = cmd.Code
|
|
|
|
|
|
existingProduct.Description = cmd.Description
|
|
|
|
|
|
existingProduct.Content = cmd.Content
|
|
|
|
|
|
existingProduct.CategoryID = cmd.CategoryID
|
|
|
|
|
|
existingProduct.Price = cmd.Price
|
|
|
|
|
|
existingProduct.IsEnabled = cmd.IsEnabled
|
|
|
|
|
|
existingProduct.IsVisible = cmd.IsVisible
|
|
|
|
|
|
existingProduct.IsPackage = cmd.IsPackage
|
|
|
|
|
|
existingProduct.SEOTitle = cmd.SEOTitle
|
|
|
|
|
|
existingProduct.SEODescription = cmd.SEODescription
|
|
|
|
|
|
existingProduct.SEOKeywords = cmd.SEOKeywords
|
2025-07-15 13:21:34 +08:00
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 3. 保存产品
|
|
|
|
|
|
return s.productManagementService.UpdateProduct(ctx, existingProduct)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// DeleteProduct 删除产品
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 删除产品
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) DeleteProduct(ctx context.Context, cmd *commands.DeleteProductCommand) error {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return s.productManagementService.DeleteProduct(ctx, cmd.ID)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ListProducts 获取产品列表
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取产品列表 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) ListProducts(ctx context.Context, query *appQueries.ListProductsQuery) (*responses.ProductListResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 根据查询条件获取产品列表
|
|
|
|
|
|
var products []*entities.Product
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
|
|
if query.CategoryID != "" {
|
|
|
|
|
|
products, err = s.productManagementService.GetProductsByCategory(ctx, query.CategoryID)
|
|
|
|
|
|
} else if query.IsVisible != nil && *query.IsVisible {
|
|
|
|
|
|
products, err = s.productManagementService.GetVisibleProducts(ctx)
|
|
|
|
|
|
} else if query.IsEnabled != nil && *query.IsEnabled {
|
|
|
|
|
|
products, err = s.productManagementService.GetEnabledProducts(ctx)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 默认获取可见产品
|
|
|
|
|
|
products, err = s.productManagementService.GetVisibleProducts(ctx)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return nil, err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为响应对象
|
|
|
|
|
|
items := make([]responses.ProductInfoResponse, len(products))
|
|
|
|
|
|
for i := range products {
|
|
|
|
|
|
items[i] = *s.convertToProductInfoResponse(products[i])
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &responses.ProductListResponse{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
Total: int64(len(items)),
|
2025-07-15 13:21:34 +08:00
|
|
|
|
Page: query.Page,
|
|
|
|
|
|
Size: query.PageSize,
|
|
|
|
|
|
Items: items,
|
|
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetProductsByIDs 根据ID列表获取产品
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取产品列表 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) GetProductsByIDs(ctx context.Context, query *appQueries.GetProductsByIDsQuery) ([]*responses.ProductInfoResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 这里需要扩展领域服务来支持批量获取
|
|
|
|
|
|
// 暂时返回空列表
|
|
|
|
|
|
return []*responses.ProductInfoResponse{}, nil
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// GetSubscribableProducts 获取可订阅产品列表
|
|
|
|
|
|
// 业务流程:1. 获取启用产品 2. 过滤可订阅产品 3. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) GetSubscribableProducts(ctx context.Context, query *appQueries.GetSubscribableProductsQuery) ([]*responses.ProductInfoResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
products, err := s.productManagementService.GetEnabledProducts(ctx)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
if err != nil {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return nil, err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 过滤可订阅的产品
|
|
|
|
|
|
var subscribableProducts []*entities.Product
|
|
|
|
|
|
for _, product := range products {
|
|
|
|
|
|
if product.CanBeSubscribed() {
|
|
|
|
|
|
subscribableProducts = append(subscribableProducts, product)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为响应对象
|
2025-07-20 20:53:26 +08:00
|
|
|
|
items := make([]*responses.ProductInfoResponse, len(subscribableProducts))
|
|
|
|
|
|
for i := range subscribableProducts {
|
|
|
|
|
|
items[i] = s.convertToProductInfoResponse(subscribableProducts[i])
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return items, nil
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// GetProductByID 根据ID获取产品
|
|
|
|
|
|
// 业务流程:1. 获取产品信息 2. 构建响应数据
|
|
|
|
|
|
func (s *ProductApplicationServiceImpl) GetProductByID(ctx context.Context, query *appQueries.GetProductQuery) (*responses.ProductInfoResponse, error) {
|
|
|
|
|
|
product, err := s.productManagementService.GetProductWithCategory(ctx, query.ID)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
if err != nil {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return nil, err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return s.convertToProductInfoResponse(product), nil
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// GetProductStats 获取产品统计信息
|
|
|
|
|
|
// 业务流程:1. 获取产品统计 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) GetProductStats(ctx context.Context) (*responses.ProductStatsResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
stats, err := s.productSubscriptionService.GetProductStats(ctx)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
if err != nil {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return nil, err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &responses.ProductStatsResponse{
|
|
|
|
|
|
TotalProducts: stats["total"],
|
|
|
|
|
|
EnabledProducts: stats["enabled"],
|
|
|
|
|
|
VisibleProducts: stats["visible"],
|
|
|
|
|
|
PackageProducts: 0, // 需要单独统计
|
|
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// convertToProductInfoResponse 转换为产品信息响应
|
|
|
|
|
|
func (s *ProductApplicationServiceImpl) convertToProductInfoResponse(product *entities.Product) *responses.ProductInfoResponse {
|
|
|
|
|
|
response := &responses.ProductInfoResponse{
|
|
|
|
|
|
ID: product.ID,
|
|
|
|
|
|
Name: product.Name,
|
|
|
|
|
|
Code: product.Code,
|
|
|
|
|
|
Description: product.Description,
|
|
|
|
|
|
Content: product.Content,
|
|
|
|
|
|
CategoryID: product.CategoryID,
|
|
|
|
|
|
Price: product.Price,
|
|
|
|
|
|
IsEnabled: product.IsEnabled,
|
|
|
|
|
|
IsVisible: product.IsVisible,
|
|
|
|
|
|
IsPackage: product.IsPackage,
|
|
|
|
|
|
SEOTitle: product.SEOTitle,
|
|
|
|
|
|
SEODescription: product.SEODescription,
|
|
|
|
|
|
SEOKeywords: product.SEOKeywords,
|
|
|
|
|
|
CreatedAt: product.CreatedAt,
|
|
|
|
|
|
UpdatedAt: product.UpdatedAt,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 添加分类信息
|
|
|
|
|
|
if product.Category != nil {
|
|
|
|
|
|
response.Category = s.convertToCategoryInfoResponse(product.Category)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
return response
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// convertToCategoryInfoResponse 转换为分类信息响应
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *ProductApplicationServiceImpl) convertToCategoryInfoResponse(category *entities.ProductCategory) *responses.CategoryInfoResponse {
|
|
|
|
|
|
return &responses.CategoryInfoResponse{
|
|
|
|
|
|
ID: category.ID,
|
|
|
|
|
|
Name: category.Name,
|
|
|
|
|
|
Description: category.Description,
|
|
|
|
|
|
IsEnabled: category.IsEnabled,
|
|
|
|
|
|
CreatedAt: category.CreatedAt,
|
|
|
|
|
|
UpdatedAt: category.UpdatedAt,
|
|
|
|
|
|
}
|
2025-07-20 20:53:26 +08:00
|
|
|
|
}
|