144 lines
4.2 KiB
Go
144 lines
4.2 KiB
Go
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
|
|
} |