161 lines
4.3 KiB
Go
161 lines
4.3 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"go.uber.org/zap"
|
|
|
|
"tyapi-server/internal/domains/finance/entities"
|
|
"tyapi-server/internal/domains/finance/repositories"
|
|
)
|
|
|
|
// FinanceService 财务领域服务
|
|
// 负责财务相关的业务逻辑,包括钱包管理、余额操作等
|
|
type FinanceService struct {
|
|
walletRepo repositories.WalletRepository
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewFinanceService 创建财务领域服务
|
|
func NewFinanceService(
|
|
walletRepo repositories.WalletRepository,
|
|
logger *zap.Logger,
|
|
) *FinanceService {
|
|
return &FinanceService{
|
|
walletRepo: walletRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// CreateWallet 创建钱包
|
|
func (s *FinanceService) CreateWallet(ctx context.Context, userID string) (*entities.Wallet, error) {
|
|
// 检查用户是否已有钱包
|
|
existingWallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err == nil && existingWallet != nil {
|
|
return nil, fmt.Errorf("用户已有钱包")
|
|
}
|
|
|
|
// 创建钱包
|
|
wallet := &entities.Wallet{
|
|
UserID: userID,
|
|
Balance: decimal.Zero,
|
|
IsActive: true,
|
|
WalletType: "MAIN",
|
|
}
|
|
|
|
createdWallet, err := s.walletRepo.Create(ctx, *wallet)
|
|
if err != nil {
|
|
s.logger.Error("创建钱包失败", zap.Error(err))
|
|
return nil, fmt.Errorf("创建钱包失败: %w", err)
|
|
}
|
|
|
|
s.logger.Info("钱包创建成功",
|
|
zap.String("wallet_id", createdWallet.ID),
|
|
zap.String("user_id", userID),
|
|
)
|
|
|
|
return &createdWallet, nil
|
|
}
|
|
|
|
// GetWallet 获取钱包信息
|
|
func (s *FinanceService) GetWallet(ctx context.Context, userID string) (*entities.Wallet, error) {
|
|
wallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
return wallet, nil
|
|
}
|
|
|
|
// GetWalletByID 根据ID获取钱包
|
|
func (s *FinanceService) GetWalletByID(ctx context.Context, walletID string) (*entities.Wallet, error) {
|
|
wallet, err := s.walletRepo.GetByID(ctx, walletID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
return &wallet, nil
|
|
}
|
|
|
|
// RechargeWallet 充值钱包
|
|
func (s *FinanceService) RechargeWallet(ctx context.Context, userID string, amount float64) error {
|
|
if amount <= 0 {
|
|
return fmt.Errorf("充值金额必须大于0")
|
|
}
|
|
|
|
wallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err != nil {
|
|
return fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
|
|
// 更新余额
|
|
amountDecimal := decimal.NewFromFloat(amount)
|
|
wallet.AddBalance(amountDecimal)
|
|
|
|
if err := s.walletRepo.Update(ctx, *wallet); err != nil {
|
|
s.logger.Error("充值失败", zap.Error(err))
|
|
return fmt.Errorf("充值失败: %w", err)
|
|
}
|
|
|
|
s.logger.Info("钱包充值成功",
|
|
zap.String("wallet_id", wallet.ID),
|
|
zap.String("user_id", userID),
|
|
zap.Float64("amount", amount),
|
|
zap.String("new_balance", wallet.GetFormattedBalance()),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeductWallet 扣减钱包余额
|
|
func (s *FinanceService) DeductWallet(ctx context.Context, userID string, amount float64) error {
|
|
if amount <= 0 {
|
|
return fmt.Errorf("扣减金额必须大于0")
|
|
}
|
|
|
|
wallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err != nil {
|
|
return fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
|
|
amountDecimal := decimal.NewFromFloat(amount)
|
|
if err := wallet.SubtractBalance(amountDecimal); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.walletRepo.Update(ctx, *wallet); err != nil {
|
|
s.logger.Error("扣减失败", zap.Error(err))
|
|
return fmt.Errorf("扣减失败: %w", err)
|
|
}
|
|
|
|
s.logger.Info("钱包扣减成功",
|
|
zap.String("wallet_id", wallet.ID),
|
|
zap.String("user_id", userID),
|
|
zap.Float64("amount", amount),
|
|
zap.String("new_balance", wallet.GetFormattedBalance()),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetWalletBalance 获取钱包余额
|
|
func (s *FinanceService) GetWalletBalance(ctx context.Context, userID string) (float64, error) {
|
|
wallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
balance, _ := wallet.Balance.Float64()
|
|
return balance, nil
|
|
}
|
|
|
|
// CheckWalletBalance 检查钱包余额是否足够
|
|
func (s *FinanceService) CheckWalletBalance(ctx context.Context, userID string, amount float64) (bool, error) {
|
|
wallet, err := s.walletRepo.GetByUserID(ctx, userID)
|
|
if err != nil {
|
|
return false, fmt.Errorf("钱包不存在: %w", err)
|
|
}
|
|
|
|
amountDecimal := decimal.NewFromFloat(amount)
|
|
return wallet.HasSufficientBalance(amountDecimal), nil
|
|
}
|