package product import ( "context" "fmt" "github.com/shopspring/decimal" "go.uber.org/zap" "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" product_service "tyapi-server/internal/domains/product/services" "tyapi-server/internal/shared/interfaces" ) // ProductApplicationServiceImpl 产品应用服务实现 // 负责业务流程编排、事务管理、数据转换,不直接操作仓库 type ProductApplicationServiceImpl struct { productManagementService *product_service.ProductManagementService productSubscriptionService *product_service.ProductSubscriptionService productApiConfigAppService ProductApiConfigApplicationService logger *zap.Logger } // NewProductApplicationService 创建产品应用服务 func NewProductApplicationService( productManagementService *product_service.ProductManagementService, productSubscriptionService *product_service.ProductSubscriptionService, productApiConfigAppService ProductApiConfigApplicationService, logger *zap.Logger, ) ProductApplicationService { return &ProductApplicationServiceImpl{ productManagementService: productManagementService, productSubscriptionService: productSubscriptionService, productApiConfigAppService: productApiConfigAppService, logger: logger, } } // CreateProduct 创建产品 // 业务流程:1. 构建产品实体 2. 创建产品 func (s *ProductApplicationServiceImpl) CreateProduct(ctx context.Context, cmd *commands.CreateProductCommand) error { // 1. 构建产品实体 product := &entities.Product{ Name: cmd.Name, Code: cmd.Code, Description: cmd.Description, Content: cmd.Content, CategoryID: cmd.CategoryID, Price: decimal.NewFromFloat(cmd.Price), IsEnabled: cmd.IsEnabled, IsVisible: cmd.IsVisible, IsPackage: cmd.IsPackage, SEOTitle: cmd.SEOTitle, SEODescription: cmd.SEODescription, SEOKeywords: cmd.SEOKeywords, } // 2. 创建产品 _, err := s.productManagementService.CreateProduct(ctx, product) return err } // UpdateProduct 更新产品 // 业务流程:1. 获取现有产品 2. 更新产品信息 3. 保存产品 func (s *ProductApplicationServiceImpl) UpdateProduct(ctx context.Context, cmd *commands.UpdateProductCommand) error { // 1. 获取现有产品 existingProduct, err := s.productManagementService.GetProductByID(ctx, cmd.ID) if err != nil { return err } // 2. 更新产品信息 existingProduct.Name = cmd.Name existingProduct.Code = cmd.Code existingProduct.Description = cmd.Description existingProduct.Content = cmd.Content existingProduct.CategoryID = cmd.CategoryID existingProduct.Price = decimal.NewFromFloat(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 // 3. 保存产品 return s.productManagementService.UpdateProduct(ctx, existingProduct) } // DeleteProduct 删除产品 // 业务流程:1. 删除产品 func (s *ProductApplicationServiceImpl) DeleteProduct(ctx context.Context, cmd *commands.DeleteProductCommand) error { return s.productManagementService.DeleteProduct(ctx, cmd.ID) } // ListProducts 获取产品列表 // 业务流程:1. 获取产品列表 2. 构建响应数据 func (s *ProductApplicationServiceImpl) ListProducts(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.ProductListResponse, error) { // 检查是否有用户ID,如果有则使用带订阅状态的方法 if userID, ok := filters["user_id"].(string); ok && userID != "" { return s.ListProductsWithSubscriptionStatus(ctx, filters, options) } // 调用领域服务获取产品列表 products, total, err := s.productManagementService.ListProducts(ctx, filters, options) if err != nil { return nil, err } // 转换为响应对象 items := make([]responses.ProductInfoResponse, len(products)) for i := range products { items[i] = *s.convertToProductInfoResponse(products[i]) } return &responses.ProductListResponse{ Total: total, Page: options.Page, Size: options.PageSize, Items: items, }, nil } // ListProductsWithSubscriptionStatus 获取产品列表(包含订阅状态) // 业务流程:1. 获取产品列表和订阅状态 2. 构建响应数据 func (s *ProductApplicationServiceImpl) ListProductsWithSubscriptionStatus(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.ProductListResponse, error) { // 调用领域服务获取产品列表(包含订阅状态) products, subscriptionStatusMap, total, err := s.productManagementService.ListProductsWithSubscriptionStatus(ctx, filters, options) if err != nil { return nil, err } // 转换为响应对象 items := make([]responses.ProductInfoResponse, len(products)) for i := range products { item := s.convertToProductInfoResponse(products[i]) // 设置订阅状态 if isSubscribed, exists := subscriptionStatusMap[products[i].ID]; exists { item.IsSubscribed = &isSubscribed } items[i] = *item } return &responses.ProductListResponse{ Total: total, Page: options.Page, Size: options.PageSize, Items: items, }, nil } // GetProductsByIDs 根据ID列表获取产品 // 业务流程:1. 获取产品列表 2. 构建响应数据 func (s *ProductApplicationServiceImpl) GetProductsByIDs(ctx context.Context, query *appQueries.GetProductsByIDsQuery) ([]*responses.ProductInfoResponse, error) { // 这里需要扩展领域服务来支持批量获取 // 暂时返回空列表 return []*responses.ProductInfoResponse{}, nil } // GetSubscribableProducts 获取可订阅产品列表 // 业务流程:1. 获取启用产品 2. 过滤可订阅产品 3. 构建响应数据 func (s *ProductApplicationServiceImpl) GetSubscribableProducts(ctx context.Context, query *appQueries.GetSubscribableProductsQuery) ([]*responses.ProductInfoResponse, error) { products, err := s.productManagementService.GetEnabledProducts(ctx) if err != nil { return nil, err } // 过滤可订阅的产品 var subscribableProducts []*entities.Product for _, product := range products { if product.CanBeSubscribed() { subscribableProducts = append(subscribableProducts, product) } } // 转换为响应对象 items := make([]*responses.ProductInfoResponse, len(subscribableProducts)) for i := range subscribableProducts { items[i] = s.convertToProductInfoResponse(subscribableProducts[i]) } return items, nil } // 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) if err != nil { return nil, err } return s.convertToProductInfoResponse(product), nil } // GetProductStats 获取产品统计信息 // 业务流程:1. 获取产品统计 2. 构建响应数据 func (s *ProductApplicationServiceImpl) GetProductStats(ctx context.Context) (*responses.ProductStatsResponse, error) { stats, err := s.productSubscriptionService.GetProductStats(ctx) if err != nil { return nil, err } return &responses.ProductStatsResponse{ TotalProducts: stats["total"], EnabledProducts: stats["enabled"], VisibleProducts: stats["visible"], PackageProducts: 0, // 需要单独统计 }, nil } // AddPackageItem 添加组合包子产品 func (s *ProductApplicationServiceImpl) AddPackageItem(ctx context.Context, packageID string, cmd *commands.AddPackageItemCommand) error { // 验证组合包是否存在 packageProduct, err := s.productManagementService.GetProductByID(ctx, packageID) if err != nil { return err } if !packageProduct.IsPackage { return fmt.Errorf("产品不是组合包") } // 验证子产品是否存在且不是组合包 subProduct, err := s.productManagementService.GetProductByID(ctx, cmd.ProductID) if err != nil { return err } if subProduct.IsPackage { return fmt.Errorf("不能将组合包作为子产品") } // 检查是否已经存在 existingItems, err := s.productManagementService.GetPackageItems(ctx, packageID) if err == nil { for _, item := range existingItems { if item.ProductID == cmd.ProductID { return fmt.Errorf("该产品已在组合包中") } } } // 获取当前最大排序号 maxSortOrder := 0 if existingItems != nil { for _, item := range existingItems { if item.SortOrder > maxSortOrder { maxSortOrder = item.SortOrder } } } // 创建组合包项目 packageItem := &entities.ProductPackageItem{ PackageID: packageID, ProductID: cmd.ProductID, SortOrder: maxSortOrder + 1, } return s.productManagementService.CreatePackageItem(ctx, packageItem) } // UpdatePackageItem 更新组合包子产品 func (s *ProductApplicationServiceImpl) UpdatePackageItem(ctx context.Context, packageID, itemID string, cmd *commands.UpdatePackageItemCommand) error { // 验证组合包项目是否存在 packageItem, err := s.productManagementService.GetPackageItemByID(ctx, itemID) if err != nil { return err } if packageItem.PackageID != packageID { return fmt.Errorf("组合包项目不属于指定组合包") } // 更新项目 packageItem.SortOrder = cmd.SortOrder return s.productManagementService.UpdatePackageItem(ctx, packageItem) } // RemovePackageItem 移除组合包子产品 func (s *ProductApplicationServiceImpl) RemovePackageItem(ctx context.Context, packageID, itemID string) error { // 验证组合包项目是否存在 packageItem, err := s.productManagementService.GetPackageItemByID(ctx, itemID) if err != nil { return err } if packageItem.PackageID != packageID { return fmt.Errorf("组合包项目不属于指定组合包") } return s.productManagementService.DeletePackageItem(ctx, itemID) } // ReorderPackageItems 重新排序组合包子产品 func (s *ProductApplicationServiceImpl) ReorderPackageItems(ctx context.Context, packageID string, cmd *commands.ReorderPackageItemsCommand) error { // 验证所有项目是否属于该组合包 for i, itemID := range cmd.ItemIDs { packageItem, err := s.productManagementService.GetPackageItemByID(ctx, itemID) if err != nil { return err } if packageItem.PackageID != packageID { return fmt.Errorf("组合包项目不属于指定组合包") } // 更新排序 packageItem.SortOrder = i + 1 if err := s.productManagementService.UpdatePackageItem(ctx, packageItem); err != nil { return err } } return nil } // UpdatePackageItems 批量更新组合包子产品 func (s *ProductApplicationServiceImpl) UpdatePackageItems(ctx context.Context, packageID string, cmd *commands.UpdatePackageItemsCommand) error { // 验证组合包是否存在 packageProduct, err := s.productManagementService.GetProductByID(ctx, packageID) if err != nil { return err } if !packageProduct.IsPackage { return fmt.Errorf("产品不是组合包") } // 验证所有子产品是否存在且不是组合包 for _, item := range cmd.Items { subProduct, err := s.productManagementService.GetProductByID(ctx, item.ProductID) if err != nil { return err } if subProduct.IsPackage { return fmt.Errorf("不能将组合包作为子产品") } } // 使用事务进行批量更新 return s.productManagementService.UpdatePackageItemsBatch(ctx, packageID, cmd.Items) } // GetAvailableProducts 获取可选子产品列表 func (s *ProductApplicationServiceImpl) GetAvailableProducts(ctx context.Context, query *appQueries.GetAvailableProductsQuery) (*responses.ProductListResponse, error) { // 构建筛选条件 filters := make(map[string]interface{}) filters["is_package"] = false // 只获取非组合包产品 filters["is_enabled"] = true // 只获取启用产品 if query.Keyword != "" { filters["keyword"] = query.Keyword } if query.CategoryID != "" { filters["category_id"] = query.CategoryID } // 设置分页选项 options := interfaces.ListOptions{ Page: query.Page, PageSize: query.PageSize, Sort: "created_at", Order: "desc", } // 获取产品列表 products, total, err := s.productManagementService.ListProducts(ctx, filters, options) if err != nil { return nil, err } // 转换为响应对象 items := make([]responses.ProductInfoResponse, len(products)) for i := range products { items[i] = *s.convertToProductInfoResponse(products[i]) } return &responses.ProductListResponse{ Total: total, Page: options.Page, Size: options.PageSize, Items: items, }, nil } // 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.InexactFloat64(), IsEnabled: product.IsEnabled, IsPackage: product.IsPackage, SEOTitle: product.SEOTitle, SEODescription: product.SEODescription, SEOKeywords: product.SEOKeywords, CreatedAt: product.CreatedAt, UpdatedAt: product.UpdatedAt, } // 添加分类信息 if product.Category != nil { response.Category = s.convertToCategoryInfoResponse(product.Category) } // 转换组合包项目信息 if product.IsPackage && len(product.PackageItems) > 0 { response.PackageItems = make([]*responses.PackageItemResponse, len(product.PackageItems)) for i, item := range product.PackageItems { response.PackageItems[i] = &responses.PackageItemResponse{ ID: item.ID, ProductID: item.ProductID, ProductCode: item.Product.Code, ProductName: item.Product.Name, SortOrder: item.SortOrder, Price: item.Product.Price.InexactFloat64(), } } } return response } // convertToCategoryInfoResponse 转换为分类信息响应 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, } } // GetProductApiConfig 获取产品API配置 func (s *ProductApplicationServiceImpl) GetProductApiConfig(ctx context.Context, productID string) (*responses.ProductApiConfigResponse, error) { return s.productApiConfigAppService.GetProductApiConfig(ctx, productID) } // CreateProductApiConfig 创建产品API配置 func (s *ProductApplicationServiceImpl) CreateProductApiConfig(ctx context.Context, productID string, config *responses.ProductApiConfigResponse) error { return s.productApiConfigAppService.CreateProductApiConfig(ctx, productID, config) } // UpdateProductApiConfig 更新产品API配置 func (s *ProductApplicationServiceImpl) UpdateProductApiConfig(ctx context.Context, configID string, config *responses.ProductApiConfigResponse) error { return s.productApiConfigAppService.UpdateProductApiConfig(ctx, configID, config) } // DeleteProductApiConfig 删除产品API配置 func (s *ProductApplicationServiceImpl) DeleteProductApiConfig(ctx context.Context, configID string) error { return s.productApiConfigAppService.DeleteProductApiConfig(ctx, configID) }