2025-07-15 13:21:34 +08:00
|
|
|
|
package product
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
2025-07-28 01:46:39 +08:00
|
|
|
|
|
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-28 01:46:39 +08:00
|
|
|
|
repoQueries "tyapi-server/internal/domains/product/repositories/queries"
|
2025-07-20 20:53:26 +08:00
|
|
|
|
product_service "tyapi-server/internal/domains/product/services"
|
2025-08-02 02:54:21 +08:00
|
|
|
|
user_repositories "tyapi-server/internal/domains/user/repositories"
|
2025-07-15 13:21:34 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// SubscriptionApplicationServiceImpl 订阅应用服务实现
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 负责业务流程编排、事务管理、数据转换,不直接操作仓库
|
2025-07-15 13:21:34 +08:00
|
|
|
|
type SubscriptionApplicationServiceImpl struct {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productSubscriptionService *product_service.ProductSubscriptionService
|
2025-08-02 02:54:21 +08:00
|
|
|
|
userRepo user_repositories.UserRepository
|
2025-07-20 20:53:26 +08:00
|
|
|
|
logger *zap.Logger
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewSubscriptionApplicationService 创建订阅应用服务
|
|
|
|
|
|
func NewSubscriptionApplicationService(
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productSubscriptionService *product_service.ProductSubscriptionService,
|
2025-08-02 02:54:21 +08:00
|
|
|
|
userRepo user_repositories.UserRepository,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
logger *zap.Logger,
|
|
|
|
|
|
) SubscriptionApplicationService {
|
|
|
|
|
|
return &SubscriptionApplicationServiceImpl{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
productSubscriptionService: productSubscriptionService,
|
2025-08-02 02:54:21 +08:00
|
|
|
|
userRepo: userRepo,
|
2025-07-20 20:53:26 +08:00
|
|
|
|
logger: logger,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// UpdateSubscriptionPrice 更新订阅价格
|
|
|
|
|
|
// 业务流程:1. 获取订阅 2. 更新价格 3. 保存订阅
|
|
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) UpdateSubscriptionPrice(ctx context.Context, cmd *commands.UpdateSubscriptionPriceCommand) error {
|
2025-08-02 02:54:21 +08:00
|
|
|
|
return s.productSubscriptionService.UpdateSubscriptionPrice(ctx, cmd.ID, cmd.Price)
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// CreateSubscription 创建订阅
|
|
|
|
|
|
// 业务流程:1. 创建订阅
|
|
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) CreateSubscription(ctx context.Context, cmd *commands.CreateSubscriptionCommand) error {
|
|
|
|
|
|
_, err := s.productSubscriptionService.CreateSubscription(ctx, cmd.UserID, cmd.ProductID)
|
|
|
|
|
|
return err
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetSubscriptionByID 根据ID获取订阅
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取订阅信息 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetSubscriptionByID(ctx context.Context, query *appQueries.GetSubscriptionQuery) (*responses.SubscriptionInfoResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
subscription, err := s.productSubscriptionService.GetSubscriptionByID(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.convertToSubscriptionInfoResponse(subscription), nil
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-28 23:28:24 +08:00
|
|
|
|
// ListSubscriptions 获取订阅列表(管理员用)
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取订阅列表 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) ListSubscriptions(ctx context.Context, query *appQueries.ListSubscriptionsQuery) (*responses.SubscriptionListResponse, error) {
|
2025-07-28 01:46:39 +08:00
|
|
|
|
repoQuery := &repoQueries.ListSubscriptionsQuery{
|
2025-08-02 02:54:21 +08:00
|
|
|
|
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,
|
2025-07-28 23:28:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
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{
|
2025-08-02 02:54:21 +08:00
|
|
|
|
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,
|
2025-07-28 01:46:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
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 // 解引用指针
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-15 13:21:34 +08:00
|
|
|
|
return &responses.SubscriptionListResponse{
|
2025-07-28 01:46:39 +08:00
|
|
|
|
Total: total,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
Page: query.Page,
|
|
|
|
|
|
Size: query.PageSize,
|
2025-07-28 01:46:39 +08:00
|
|
|
|
Items: items,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetUserSubscriptions 获取用户订阅
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取用户订阅 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetUserSubscriptions(ctx context.Context, query *appQueries.GetUserSubscriptionsQuery) ([]*responses.SubscriptionInfoResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
subscriptions, err := s.productSubscriptionService.GetUserSubscriptions(ctx, query.UserID)
|
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.SubscriptionInfoResponse, len(subscriptions))
|
2025-07-20 20:53:26 +08:00
|
|
|
|
for i := range subscriptions {
|
|
|
|
|
|
items[i] = s.convertToSubscriptionInfoResponse(subscriptions[i])
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return items, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetProductSubscriptions 获取产品订阅
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取产品订阅 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetProductSubscriptions(ctx context.Context, query *appQueries.GetProductSubscriptionsQuery) ([]*responses.SubscriptionInfoResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 这里需要扩展领域服务来支持按产品查询订阅
|
|
|
|
|
|
// 暂时返回空列表
|
|
|
|
|
|
return []*responses.SubscriptionInfoResponse{}, nil
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetSubscriptionUsage 获取订阅使用情况
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// 业务流程:1. 获取订阅使用情况 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetSubscriptionUsage(ctx context.Context, subscriptionID string) (*responses.SubscriptionUsageResponse, error) {
|
2025-07-20 20:53:26 +08:00
|
|
|
|
subscription, err := s.productSubscriptionService.GetSubscriptionByID(ctx, subscriptionID)
|
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.SubscriptionUsageResponse{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
ID: subscription.ID,
|
|
|
|
|
|
ProductID: subscription.ProductID,
|
|
|
|
|
|
APIUsed: subscription.APIUsed,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// GetSubscriptionStats 获取订阅统计信息
|
|
|
|
|
|
// 业务流程:1. 获取订阅统计 2. 构建响应数据
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetSubscriptionStats(ctx context.Context) (*responses.SubscriptionStatsResponse, error) {
|
2025-08-02 02:54:21 +08:00
|
|
|
|
stats, err := s.productSubscriptionService.GetSubscriptionStats(ctx)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
return &responses.SubscriptionStatsResponse{
|
2025-08-02 02:54:21 +08:00
|
|
|
|
TotalSubscriptions: stats["total_subscriptions"].(int64),
|
|
|
|
|
|
TotalRevenue: stats["total_revenue"].(float64),
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-28 23:28:24 +08:00
|
|
|
|
// GetMySubscriptionStats 获取我的订阅统计信息
|
|
|
|
|
|
// 业务流程:1. 获取用户订阅统计 2. 构建响应数据
|
|
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) GetMySubscriptionStats(ctx context.Context, userID string) (*responses.SubscriptionStatsResponse, error) {
|
2025-08-02 02:54:21 +08:00
|
|
|
|
stats, err := s.productSubscriptionService.GetUserSubscriptionStats(ctx, userID)
|
2025-07-28 23:28:24 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
2025-08-02 02:54:21 +08:00
|
|
|
|
|
2025-07-28 23:28:24 +08:00
|
|
|
|
return &responses.SubscriptionStatsResponse{
|
2025-08-02 02:54:21 +08:00
|
|
|
|
TotalSubscriptions: stats["total_subscriptions"].(int64),
|
|
|
|
|
|
TotalRevenue: stats["total_revenue"].(float64),
|
2025-07-28 23:28:24 +08:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// convertToSubscriptionInfoResponse 转换为订阅信息响应
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) convertToSubscriptionInfoResponse(subscription *entities.Subscription) *responses.SubscriptionInfoResponse {
|
2025-08-02 02:54:21 +08:00
|
|
|
|
// 查询用户信息
|
|
|
|
|
|
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,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
return &responses.SubscriptionInfoResponse{
|
2025-07-20 20:53:26 +08:00
|
|
|
|
ID: subscription.ID,
|
|
|
|
|
|
UserID: subscription.UserID,
|
|
|
|
|
|
ProductID: subscription.ProductID,
|
2025-07-28 01:46:39 +08:00
|
|
|
|
Price: subscription.Price.InexactFloat64(),
|
2025-08-02 02:54:21 +08:00
|
|
|
|
User: userInfo,
|
2025-07-28 01:46:39 +08:00
|
|
|
|
Product: s.convertToProductSimpleResponse(subscription.Product),
|
2025-07-20 20:53:26 +08:00
|
|
|
|
APIUsed: subscription.APIUsed,
|
|
|
|
|
|
CreatedAt: subscription.CreatedAt,
|
|
|
|
|
|
UpdatedAt: subscription.UpdatedAt,
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// convertToProductSimpleResponse 转换为产品简单信息响应
|
2025-07-15 13:21:34 +08:00
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) convertToProductSimpleResponse(product *entities.Product) *responses.ProductSimpleResponse {
|
|
|
|
|
|
return &responses.ProductSimpleResponse{
|
|
|
|
|
|
ID: product.ID,
|
|
|
|
|
|
Name: product.Name,
|
|
|
|
|
|
Code: product.Code,
|
|
|
|
|
|
Description: product.Description,
|
2025-07-28 01:46:39 +08:00
|
|
|
|
Price: product.Price.InexactFloat64(),
|
|
|
|
|
|
Category: s.convertToCategorySimpleResponse(product.Category),
|
2025-07-15 13:21:34 +08:00
|
|
|
|
IsPackage: product.IsPackage,
|
|
|
|
|
|
}
|
2025-07-20 20:53:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// convertToCategorySimpleResponse 转换为分类简单信息响应
|
|
|
|
|
|
func (s *SubscriptionApplicationServiceImpl) convertToCategorySimpleResponse(category *entities.ProductCategory) *responses.CategorySimpleResponse {
|
|
|
|
|
|
return &responses.CategorySimpleResponse{
|
|
|
|
|
|
ID: category.ID,
|
|
|
|
|
|
Name: category.Name,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|