package product import ( "context" "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" repoQueries "tyapi-server/internal/domains/product/repositories/queries" product_service "tyapi-server/internal/domains/product/services" user_repositories "tyapi-server/internal/domains/user/repositories" ) // SubscriptionApplicationServiceImpl 订阅应用服务实现 // 负责业务流程编排、事务管理、数据转换,不直接操作仓库 type SubscriptionApplicationServiceImpl struct { productSubscriptionService *product_service.ProductSubscriptionService userRepo user_repositories.UserRepository logger *zap.Logger } // NewSubscriptionApplicationService 创建订阅应用服务 func NewSubscriptionApplicationService( productSubscriptionService *product_service.ProductSubscriptionService, userRepo user_repositories.UserRepository, logger *zap.Logger, ) SubscriptionApplicationService { return &SubscriptionApplicationServiceImpl{ productSubscriptionService: productSubscriptionService, userRepo: userRepo, logger: logger, } } // UpdateSubscriptionPrice 更新订阅价格 // 业务流程:1. 获取订阅 2. 更新价格 3. 保存订阅 func (s *SubscriptionApplicationServiceImpl) UpdateSubscriptionPrice(ctx context.Context, cmd *commands.UpdateSubscriptionPriceCommand) error { return s.productSubscriptionService.UpdateSubscriptionPrice(ctx, cmd.ID, cmd.Price) } // BatchUpdateSubscriptionPrices 一键改价 // 业务流程:1. 获取用户所有订阅 2. 根据范围筛选 3. 批量更新价格 func (s *SubscriptionApplicationServiceImpl) BatchUpdateSubscriptionPrices(ctx context.Context, cmd *commands.BatchUpdateSubscriptionPricesCommand) error { subscriptions, _, err := s.productSubscriptionService.ListSubscriptions(ctx, &repoQueries.ListSubscriptionsQuery{ UserID: cmd.UserID, Page: 1, PageSize: 1000, }) if err != nil { return err } // 根据范围筛选订阅 var targetSubscriptions []*entities.Subscription for _, sub := range subscriptions { if cmd.Scope == "all" { // 所有订阅都修改 targetSubscriptions = append(targetSubscriptions, sub) } else if cmd.Scope == "undiscounted" { // 只修改未打折的订阅(价格等于产品原价) if sub.Product != nil && sub.Price.Equal(sub.Product.Price) { targetSubscriptions = append(targetSubscriptions, sub) } } } // 批量更新价格 for _, sub := range targetSubscriptions { if sub.Product != nil { // 计算折扣后的价格 discountRatio := cmd.Discount / 10 newPrice := sub.Product.Price.Mul(decimal.NewFromFloat(discountRatio)) // 四舍五入到2位小数 newPrice = newPrice.Round(2) err := s.productSubscriptionService.UpdateSubscriptionPrice(ctx, sub.ID, newPrice.InexactFloat64()) if err != nil { s.logger.Error("批量更新订阅价格失败", zap.String("subscription_id", sub.ID), zap.Error(err)) // 继续处理其他订阅,不中断整个流程 } } } return nil } // CreateSubscription 创建订阅 // 业务流程:1. 创建订阅 func (s *SubscriptionApplicationServiceImpl) CreateSubscription(ctx context.Context, cmd *commands.CreateSubscriptionCommand) error { _, err := s.productSubscriptionService.CreateSubscription(ctx, cmd.UserID, cmd.ProductID) return err } // GetSubscriptionByID 根据ID获取订阅 // 业务流程:1. 获取订阅信息 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetSubscriptionByID(ctx context.Context, query *appQueries.GetSubscriptionQuery) (*responses.SubscriptionInfoResponse, error) { subscription, err := s.productSubscriptionService.GetSubscriptionByID(ctx, query.ID) if err != nil { return nil, err } return s.convertToSubscriptionInfoResponse(subscription), nil } // ListSubscriptions 获取订阅列表(管理员用) // 业务流程:1. 获取订阅列表 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) ListSubscriptions(ctx context.Context, query *appQueries.ListSubscriptionsQuery) (*responses.SubscriptionListResponse, error) { repoQuery := &repoQueries.ListSubscriptionsQuery{ Page: query.Page, PageSize: query.PageSize, UserID: query.UserID, // 管理员可以按用户筛选 Keyword: query.Keyword, SortBy: query.SortBy, SortOrder: query.SortOrder, CompanyName: query.CompanyName, ProductName: query.ProductName, StartTime: query.StartTime, EndTime: query.EndTime, } subscriptions, total, err := s.productSubscriptionService.ListSubscriptions(ctx, repoQuery) if err != nil { return nil, err } items := make([]responses.SubscriptionInfoResponse, len(subscriptions)) for i := range subscriptions { resp := s.convertToSubscriptionInfoResponse(subscriptions[i]) if resp != nil { items[i] = *resp // 解引用指针 } } return &responses.SubscriptionListResponse{ Total: total, Page: query.Page, Size: query.PageSize, Items: items, }, nil } // ListMySubscriptions 获取我的订阅列表(用户用) // 业务流程:1. 获取用户订阅列表 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) ListMySubscriptions(ctx context.Context, userID string, query *appQueries.ListSubscriptionsQuery) (*responses.SubscriptionListResponse, error) { repoQuery := &repoQueries.ListSubscriptionsQuery{ Page: query.Page, PageSize: query.PageSize, UserID: userID, // 强制设置为当前用户ID Keyword: query.Keyword, SortBy: query.SortBy, SortOrder: query.SortOrder, CompanyName: query.CompanyName, ProductName: query.ProductName, StartTime: query.StartTime, EndTime: query.EndTime, } subscriptions, total, err := s.productSubscriptionService.ListSubscriptions(ctx, repoQuery) if err != nil { return nil, err } items := make([]responses.SubscriptionInfoResponse, len(subscriptions)) for i := range subscriptions { resp := s.convertToSubscriptionInfoResponse(subscriptions[i]) if resp != nil { items[i] = *resp // 解引用指针 } } return &responses.SubscriptionListResponse{ Total: total, Page: query.Page, Size: query.PageSize, Items: items, }, nil } // GetUserSubscriptions 获取用户订阅 // 业务流程:1. 获取用户订阅 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetUserSubscriptions(ctx context.Context, query *appQueries.GetUserSubscriptionsQuery) ([]*responses.SubscriptionInfoResponse, error) { subscriptions, err := s.productSubscriptionService.GetUserSubscriptions(ctx, query.UserID) if err != nil { return nil, err } // 转换为响应对象 items := make([]*responses.SubscriptionInfoResponse, len(subscriptions)) for i := range subscriptions { items[i] = s.convertToSubscriptionInfoResponse(subscriptions[i]) } return items, nil } // GetProductSubscriptions 获取产品订阅 // 业务流程:1. 获取产品订阅 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetProductSubscriptions(ctx context.Context, query *appQueries.GetProductSubscriptionsQuery) ([]*responses.SubscriptionInfoResponse, error) { // 这里需要扩展领域服务来支持按产品查询订阅 // 暂时返回空列表 return []*responses.SubscriptionInfoResponse{}, nil } // GetSubscriptionUsage 获取订阅使用情况 // 业务流程:1. 获取订阅使用情况 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetSubscriptionUsage(ctx context.Context, subscriptionID string) (*responses.SubscriptionUsageResponse, error) { subscription, err := s.productSubscriptionService.GetSubscriptionByID(ctx, subscriptionID) if err != nil { return nil, err } return &responses.SubscriptionUsageResponse{ ID: subscription.ID, ProductID: subscription.ProductID, APIUsed: subscription.APIUsed, }, nil } // GetSubscriptionStats 获取订阅统计信息 // 业务流程:1. 获取订阅统计 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetSubscriptionStats(ctx context.Context) (*responses.SubscriptionStatsResponse, error) { stats, err := s.productSubscriptionService.GetSubscriptionStats(ctx) if err != nil { return nil, err } return &responses.SubscriptionStatsResponse{ TotalSubscriptions: stats["total_subscriptions"].(int64), TotalRevenue: stats["total_revenue"].(float64), }, nil } // GetMySubscriptionStats 获取我的订阅统计信息 // 业务流程:1. 获取用户订阅统计 2. 构建响应数据 func (s *SubscriptionApplicationServiceImpl) GetMySubscriptionStats(ctx context.Context, userID string) (*responses.SubscriptionStatsResponse, error) { stats, err := s.productSubscriptionService.GetUserSubscriptionStats(ctx, userID) if err != nil { return nil, err } return &responses.SubscriptionStatsResponse{ TotalSubscriptions: stats["total_subscriptions"].(int64), TotalRevenue: stats["total_revenue"].(float64), }, nil } // convertToSubscriptionInfoResponse 转换为订阅信息响应 func (s *SubscriptionApplicationServiceImpl) convertToSubscriptionInfoResponse(subscription *entities.Subscription) *responses.SubscriptionInfoResponse { // 查询用户信息 var userInfo *responses.UserSimpleResponse if subscription.UserID != "" { user, err := s.userRepo.GetByIDWithEnterpriseInfo(context.Background(), subscription.UserID) if err == nil { companyName := "未知公司" if user.EnterpriseInfo != nil { companyName = user.EnterpriseInfo.CompanyName } userInfo = &responses.UserSimpleResponse{ ID: user.ID, CompanyName: companyName, Phone: user.Phone, } } } var productResponse *responses.ProductSimpleResponse if subscription.Product != nil { productResponse = s.convertToProductSimpleResponse(subscription.Product) } return &responses.SubscriptionInfoResponse{ ID: subscription.ID, UserID: subscription.UserID, ProductID: subscription.ProductID, Price: subscription.Price.InexactFloat64(), User: userInfo, Product: productResponse, APIUsed: subscription.APIUsed, CreatedAt: subscription.CreatedAt, UpdatedAt: subscription.UpdatedAt, } } // convertToProductSimpleResponse 转换为产品简单信息响应 func (s *SubscriptionApplicationServiceImpl) convertToProductSimpleResponse(product *entities.Product) *responses.ProductSimpleResponse { var categoryResponse *responses.CategorySimpleResponse if product.Category != nil { categoryResponse = s.convertToCategorySimpleResponse(product.Category) } return &responses.ProductSimpleResponse{ ID: product.ID, OldID: product.OldID, Name: product.Name, Code: product.Code, Description: product.Description, Price: product.Price.InexactFloat64(), Category: categoryResponse, IsPackage: product.IsPackage, } } // convertToCategorySimpleResponse 转换为分类简单信息响应 func (s *SubscriptionApplicationServiceImpl) convertToCategorySimpleResponse(category *entities.ProductCategory) *responses.CategorySimpleResponse { if category == nil { return nil } return &responses.CategorySimpleResponse{ ID: category.ID, Name: category.Name, } }