package services import ( "context" "errors" "fmt" "go.uber.org/zap" "tyapi-server/internal/domains/product/entities" "tyapi-server/internal/domains/product/repositories" ) // ProductSubscriptionService 产品订阅领域服务 // 负责产品订阅相关的业务逻辑,包括订阅验证、订阅管理等 type ProductSubscriptionService struct { productRepo repositories.ProductRepository subscriptionRepo repositories.SubscriptionRepository logger *zap.Logger } // NewProductSubscriptionService 创建产品订阅领域服务 func NewProductSubscriptionService( productRepo repositories.ProductRepository, subscriptionRepo repositories.SubscriptionRepository, logger *zap.Logger, ) *ProductSubscriptionService { return &ProductSubscriptionService{ productRepo: productRepo, subscriptionRepo: subscriptionRepo, logger: logger, } } // CanUserSubscribeProduct 检查用户是否可以订阅产品 func (s *ProductSubscriptionService) CanUserSubscribeProduct(ctx context.Context, userID string, productID string) (bool, error) { // 检查产品是否存在且可订阅 product, err := s.productRepo.GetByID(ctx, productID) if err != nil { return false, fmt.Errorf("产品不存在: %w", err) } if !product.CanBeSubscribed() { return false, errors.New("产品不可订阅") } // 检查用户是否已有该产品的订阅 existingSubscription, err := s.subscriptionRepo.FindByUserAndProduct(ctx, userID, productID) if err == nil && existingSubscription != nil { return false, errors.New("用户已有该产品的订阅") } return true, nil } // CreateSubscription 创建订阅 func (s *ProductSubscriptionService) CreateSubscription(ctx context.Context, userID, productID string) (*entities.Subscription, error) { // 检查是否可以订阅 canSubscribe, err := s.CanUserSubscribeProduct(ctx, userID, productID) if err != nil { return nil, err } if !canSubscribe { return nil, errors.New("无法订阅该产品") } // 获取产品信息以获取价格 product, err := s.productRepo.GetByID(ctx, productID) if err != nil { return nil, fmt.Errorf("产品不存在: %w", err) } // 创建订阅 subscription := &entities.Subscription{ UserID: userID, ProductID: productID, Price: product.Price, } createdSubscription, err := s.subscriptionRepo.Create(ctx, *subscription) if err != nil { s.logger.Error("创建订阅失败", zap.Error(err)) return nil, fmt.Errorf("创建订阅失败: %w", err) } s.logger.Info("订阅创建成功", zap.String("subscription_id", createdSubscription.ID), zap.String("user_id", userID), zap.String("product_id", productID), ) return &createdSubscription, nil } // GetUserSubscriptions 获取用户订阅列表 func (s *ProductSubscriptionService) GetUserSubscriptions(ctx context.Context, userID string) ([]*entities.Subscription, error) { return s.subscriptionRepo.FindByUserID(ctx, userID) } // GetSubscriptionByID 根据ID获取订阅 func (s *ProductSubscriptionService) GetSubscriptionByID(ctx context.Context, subscriptionID string) (*entities.Subscription, error) { subscription, err := s.subscriptionRepo.GetByID(ctx, subscriptionID) if err != nil { return nil, fmt.Errorf("订阅不存在: %w", err) } return &subscription, nil } // CancelSubscription 取消订阅 func (s *ProductSubscriptionService) CancelSubscription(ctx context.Context, subscriptionID string) error { // 由于订阅实体没有状态字段,这里直接删除订阅 if err := s.subscriptionRepo.Delete(ctx, subscriptionID); err != nil { s.logger.Error("取消订阅失败", zap.Error(err)) return fmt.Errorf("取消订阅失败: %w", err) } s.logger.Info("订阅取消成功", zap.String("subscription_id", subscriptionID), ) return nil } // GetProductStats 获取产品统计信息 func (s *ProductSubscriptionService) GetProductStats(ctx context.Context) (map[string]int64, error) { stats := make(map[string]int64) total, err := s.productRepo.CountByCategory(ctx, "") if err == nil { stats["total"] = total } enabled, err := s.productRepo.CountEnabled(ctx) if err == nil { stats["enabled"] = enabled } visible, err := s.productRepo.CountVisible(ctx) if err == nil { stats["visible"] = visible } return stats, nil }