Files
tyapi-server/internal/application/user/user_application_service_impl.go

468 lines
16 KiB
Go
Raw Normal View History

2025-07-13 16:36:20 +08:00
package user
import (
"context"
"fmt"
"go.uber.org/zap"
"tyapi-server/internal/application/user/dto/commands"
"tyapi-server/internal/application/user/dto/queries"
"tyapi-server/internal/application/user/dto/responses"
2025-07-28 01:46:39 +08:00
finance_service "tyapi-server/internal/domains/finance/services"
2025-07-13 16:36:20 +08:00
"tyapi-server/internal/domains/user/entities"
"tyapi-server/internal/domains/user/events"
user_service "tyapi-server/internal/domains/user/services"
"tyapi-server/internal/shared/interfaces"
"tyapi-server/internal/shared/middleware"
)
// UserApplicationServiceImpl 用户应用服务实现
2025-07-20 20:53:26 +08:00
// 负责业务流程编排、事务管理、数据转换,不直接操作仓库
2025-07-13 16:36:20 +08:00
type UserApplicationServiceImpl struct {
2025-07-28 01:46:39 +08:00
userAggregateService user_service.UserAggregateService
userAuthService *user_service.UserAuthService
smsCodeService *user_service.SMSCodeService
walletService finance_service.WalletAggregateService
2025-08-02 02:54:21 +08:00
contractService user_service.ContractAggregateService
2025-07-28 01:46:39 +08:00
eventBus interfaces.EventBus
jwtAuth *middleware.JWTAuthMiddleware
logger *zap.Logger
2025-07-13 16:36:20 +08:00
}
// NewUserApplicationService 创建用户应用服务
func NewUserApplicationService(
2025-07-28 01:46:39 +08:00
userAggregateService user_service.UserAggregateService,
2025-07-20 20:53:26 +08:00
userAuthService *user_service.UserAuthService,
2025-07-13 16:36:20 +08:00
smsCodeService *user_service.SMSCodeService,
2025-07-28 01:46:39 +08:00
walletService finance_service.WalletAggregateService,
2025-08-02 02:54:21 +08:00
contractService user_service.ContractAggregateService,
2025-07-13 16:36:20 +08:00
eventBus interfaces.EventBus,
jwtAuth *middleware.JWTAuthMiddleware,
logger *zap.Logger,
) UserApplicationService {
return &UserApplicationServiceImpl{
2025-07-28 01:46:39 +08:00
userAggregateService: userAggregateService,
userAuthService: userAuthService,
smsCodeService: smsCodeService,
walletService: walletService,
2025-08-02 02:54:21 +08:00
contractService: contractService,
2025-07-28 01:46:39 +08:00
eventBus: eventBus,
jwtAuth: jwtAuth,
logger: logger,
2025-07-13 16:36:20 +08:00
}
}
// Register 用户注册
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 创建用户 3. 发布注册事件
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) Register(ctx context.Context, cmd *commands.RegisterUserCommand) (*responses.RegisterUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-13 16:36:20 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneRegister); err != nil {
return nil, fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 创建用户
2025-07-28 01:46:39 +08:00
user, err := s.userAggregateService.CreateUser(ctx, cmd.Phone, cmd.Password)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 发布用户注册事件
2025-07-13 16:36:20 +08:00
event := events.NewUserRegisteredEvent(user, "")
if err := s.eventBus.Publish(ctx, event); err != nil {
s.logger.Warn("发布用户注册事件失败", zap.Error(err))
}
s.logger.Info("用户注册成功", zap.String("user_id", user.ID), zap.String("phone", user.Phone))
return &responses.RegisterUserResponse{
2025-07-20 20:53:26 +08:00
ID: user.ID,
2025-07-13 16:36:20 +08:00
Phone: user.Phone,
}, nil
}
// LoginWithPassword 密码登录
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证用户密码 2. 生成访问令牌 3. 更新登录统计 4. 获取用户权限
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) LoginWithPassword(ctx context.Context, cmd *commands.LoginWithPasswordCommand) (*responses.LoginUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证用户密码
user, err := s.userAuthService.ValidatePassword(ctx, cmd.Phone, cmd.Password)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 2. 生成包含用户类型的token
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
if err != nil {
s.logger.Error("生成令牌失败", zap.Error(err))
return nil, fmt.Errorf("生成访问令牌失败")
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 如果是管理员,更新登录统计
if user.IsAdmin() {
2025-07-28 01:46:39 +08:00
if err := s.userAggregateService.UpdateLoginStats(ctx, user.ID); err != nil {
2025-07-20 20:53:26 +08:00
s.logger.Error("更新登录统计失败", zap.Error(err))
}
// 重新获取用户信息以获取最新的登录统计
2025-07-28 01:46:39 +08:00
updatedUser, err := s.userAggregateService.GetUserByID(ctx, user.ID)
2025-07-20 20:53:26 +08:00
if err != nil {
s.logger.Error("重新获取用户信息失败", zap.Error(err))
} else {
user = updatedUser
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 4. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 5. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
return &responses.LoginUserResponse{
User: userProfile,
AccessToken: accessToken,
TokenType: "Bearer",
ExpiresIn: 86400, // 24h
LoginMethod: "password",
}, nil
}
// LoginWithSMS 短信验证码登录
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 验证用户登录状态 3. 生成访问令牌 4. 更新登录统计 5. 获取用户权限
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) LoginWithSMS(ctx context.Context, cmd *commands.LoginWithSMSCommand) (*responses.LoginUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-13 16:36:20 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneLogin); err != nil {
return nil, fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 验证用户登录状态
user, err := s.userAuthService.ValidateUserLogin(ctx, cmd.Phone)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 生成包含用户类型的token
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
2025-07-13 16:36:20 +08:00
if err != nil {
s.logger.Error("生成令牌失败", zap.Error(err))
return nil, fmt.Errorf("生成访问令牌失败")
}
2025-07-20 20:53:26 +08:00
// 4. 如果是管理员,更新登录统计
if user.IsAdmin() {
2025-07-28 01:46:39 +08:00
if err := s.userAggregateService.UpdateLoginStats(ctx, user.ID); err != nil {
2025-07-20 20:53:26 +08:00
s.logger.Error("更新登录统计失败", zap.Error(err))
}
// 重新获取用户信息以获取最新的登录统计
2025-07-28 01:46:39 +08:00
updatedUser, err := s.userAggregateService.GetUserByID(ctx, user.ID)
2025-07-20 20:53:26 +08:00
if err != nil {
s.logger.Error("重新获取用户信息失败", zap.Error(err))
} else {
user = updatedUser
}
}
// 5. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
}
// 6. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
return &responses.LoginUserResponse{
User: userProfile,
AccessToken: accessToken,
TokenType: "Bearer",
2025-07-20 20:53:26 +08:00
ExpiresIn: int64(s.jwtAuth.GetExpiresIn().Seconds()), // 168h
2025-07-13 16:36:20 +08:00
LoginMethod: "sms",
}, nil
}
2025-07-20 20:53:26 +08:00
// SendSMS 发送短信验证码
// 业务流程1. 发送短信验证码
func (s *UserApplicationServiceImpl) SendSMS(ctx context.Context, cmd *commands.SendCodeCommand) error {
return s.smsCodeService.SendCode(ctx, cmd.Phone, entities.SMSScene(cmd.Scene), "", "")
}
2025-07-13 16:36:20 +08:00
// ChangePassword 修改密码
2025-07-20 20:53:26 +08:00
// 业务流程1. 修改用户密码
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) ChangePassword(ctx context.Context, cmd *commands.ChangePasswordCommand) error {
2025-07-20 20:53:26 +08:00
return s.userAuthService.ChangePassword(ctx, cmd.UserID, cmd.OldPassword, cmd.NewPassword)
2025-07-13 16:36:20 +08:00
}
2025-07-15 13:21:34 +08:00
// ResetPassword 重置密码
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 重置用户密码
2025-07-15 13:21:34 +08:00
func (s *UserApplicationServiceImpl) ResetPassword(ctx context.Context, cmd *commands.ResetPasswordCommand) error {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-15 13:21:34 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneResetPassword); err != nil {
return fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 重置用户密码
return s.userAuthService.ResetPassword(ctx, cmd.Phone, cmd.NewPassword)
2025-07-15 13:21:34 +08:00
}
2025-07-20 20:53:26 +08:00
// GetUserProfile 获取用户资料
// 业务流程1. 获取用户信息 2. 获取企业信息 3. 构建响应数据
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) GetUserProfile(ctx context.Context, userID string) (*responses.UserProfileResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 获取用户信息(包含企业信息)
2025-07-28 01:46:39 +08:00
user, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, userID)
2025-07-20 20:53:26 +08:00
if err != nil {
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 2. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
2025-07-28 01:46:39 +08:00
IsCertified: user.IsCertified,
2025-07-20 20:53:26 +08:00
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 4. 添加企业信息
if user.EnterpriseInfo != nil {
userProfile.EnterpriseInfo = &responses.EnterpriseInfoResponse{
ID: user.EnterpriseInfo.ID,
CompanyName: user.EnterpriseInfo.CompanyName,
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
LegalPersonID: user.EnterpriseInfo.LegalPersonID,
2025-07-28 01:46:39 +08:00
LegalPersonPhone: user.EnterpriseInfo.LegalPersonPhone,
EnterpriseAddress: user.EnterpriseInfo.EnterpriseAddress,
2025-07-20 20:53:26 +08:00
CreatedAt: user.EnterpriseInfo.CreatedAt,
UpdatedAt: user.EnterpriseInfo.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
}
2025-07-20 20:53:26 +08:00
return userProfile, nil
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// GetUser 获取用户信息
// 业务流程1. 获取用户信息 2. 构建响应数据
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) GetUser(ctx context.Context, query *queries.GetUserQuery) (*responses.UserProfileResponse, error) {
2025-07-28 01:46:39 +08:00
user, err := s.userAggregateService.GetUserByID(ctx, query.UserID)
2025-07-20 20:53:26 +08:00
if err != nil {
return nil, err
}
return &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}, nil
2025-07-13 16:36:20 +08:00
}
2025-07-28 01:46:39 +08:00
// ListUsers 获取用户列表(管理员功能)
// 业务流程1. 查询用户列表 2. 构建响应数据
func (s *UserApplicationServiceImpl) ListUsers(ctx context.Context, query *queries.ListUsersQuery) (*responses.UserListResponse, error) {
// 1. 查询用户列表
users, total, err := s.userAggregateService.ListUsers(ctx, query.ToDomainQuery())
if err != nil {
return nil, err
}
// 2. 构建响应数据
items := make([]*responses.UserListItem, 0, len(users))
for _, user := range users {
item := &responses.UserListItem{
ID: user.ID,
Phone: user.Phone,
UserType: user.UserType,
Username: user.Username,
IsActive: user.Active,
IsCertified: user.IsCertified,
LoginCount: user.LoginCount,
LastLoginAt: user.LastLoginAt,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}
// 添加企业信息
if user.EnterpriseInfo != nil {
item.EnterpriseInfo = &responses.EnterpriseInfoItem{
ID: user.EnterpriseInfo.ID,
CompanyName: user.EnterpriseInfo.CompanyName,
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
LegalPersonPhone: user.EnterpriseInfo.LegalPersonPhone,
EnterpriseAddress: user.EnterpriseInfo.EnterpriseAddress,
CreatedAt: user.EnterpriseInfo.CreatedAt,
}
2025-08-02 02:54:21 +08:00
// 获取企业合同信息
contracts, err := s.contractService.FindByUserID(ctx, user.ID)
if err == nil && len(contracts) > 0 {
contractItems := make([]*responses.ContractInfoItem, 0, len(contracts))
for _, contract := range contracts {
contractItems = append(contractItems, &responses.ContractInfoItem{
ID: contract.ID,
ContractName: contract.ContractName,
ContractType: string(contract.ContractType),
ContractTypeName: contract.GetContractTypeName(),
ContractFileURL: contract.ContractFileURL,
CreatedAt: contract.CreatedAt,
})
}
item.EnterpriseInfo.Contracts = contractItems
}
2025-07-28 01:46:39 +08:00
}
// 添加钱包余额信息
wallet, err := s.walletService.LoadWalletByUserId(ctx, user.ID)
if err == nil && wallet != nil {
item.WalletBalance = wallet.Balance.String()
} else {
item.WalletBalance = "0"
}
items = append(items, item)
}
return &responses.UserListResponse{
Items: items,
Total: total,
Page: query.Page,
Size: query.PageSize,
}, nil
}
2025-08-02 02:54:21 +08:00
// GetUserDetail 获取用户详情(管理员功能)
// 业务流程1. 查询用户详情 2. 构建响应数据
func (s *UserApplicationServiceImpl) GetUserDetail(ctx context.Context, userID string) (*responses.UserDetailResponse, error) {
// 1. 查询用户详情(包含企业信息)
user, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, userID)
if err != nil {
return nil, err
}
// 2. 构建响应数据
item := &responses.UserListItem{
ID: user.ID,
Phone: user.Phone,
UserType: user.UserType,
Username: user.Username,
IsActive: user.Active,
IsCertified: user.IsCertified,
LoginCount: user.LoginCount,
LastLoginAt: user.LastLoginAt,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}
// 添加企业信息
if user.EnterpriseInfo != nil {
item.EnterpriseInfo = &responses.EnterpriseInfoItem{
ID: user.EnterpriseInfo.ID,
CompanyName: user.EnterpriseInfo.CompanyName,
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
LegalPersonPhone: user.EnterpriseInfo.LegalPersonPhone,
EnterpriseAddress: user.EnterpriseInfo.EnterpriseAddress,
CreatedAt: user.EnterpriseInfo.CreatedAt,
}
// 获取企业合同信息
contracts, err := s.contractService.FindByUserID(ctx, user.ID)
if err == nil && len(contracts) > 0 {
contractItems := make([]*responses.ContractInfoItem, 0, len(contracts))
for _, contract := range contracts {
contractItems = append(contractItems, &responses.ContractInfoItem{
ID: contract.ID,
ContractName: contract.ContractName,
ContractType: string(contract.ContractType),
ContractTypeName: contract.GetContractTypeName(),
ContractFileURL: contract.ContractFileURL,
CreatedAt: contract.CreatedAt,
})
}
item.EnterpriseInfo.Contracts = contractItems
}
}
// 添加钱包余额信息
wallet, err := s.walletService.LoadWalletByUserId(ctx, user.ID)
if err == nil && wallet != nil {
item.WalletBalance = wallet.Balance.String()
} else {
item.WalletBalance = "0"
}
return &responses.UserDetailResponse{
UserListItem: item,
}, nil
}
2025-07-28 01:46:39 +08:00
// GetUserStats 获取用户统计信息(管理员功能)
// 业务流程1. 查询用户统计信息 2. 构建响应数据
func (s *UserApplicationServiceImpl) GetUserStats(ctx context.Context) (*responses.UserStatsResponse, error) {
// 1. 查询用户统计信息
stats, err := s.userAggregateService.GetUserStats(ctx)
if err != nil {
return nil, err
}
// 2. 构建响应数据
return &responses.UserStatsResponse{
TotalUsers: stats.TotalUsers,
ActiveUsers: stats.ActiveUsers,
CertifiedUsers: stats.CertifiedUsers,
}, nil
}