This commit is contained in:
2025-07-28 01:46:39 +08:00
parent b03129667a
commit 357639462a
219 changed files with 21634 additions and 8138 deletions

View File

@@ -0,0 +1,98 @@
package repositories
import (
"context"
"errors"
"tyapi-server/internal/domains/finance/entities"
domain_finance_repo "tyapi-server/internal/domains/finance/repositories"
"tyapi-server/internal/shared/database"
"go.uber.org/zap"
"gorm.io/gorm"
)
const (
AlipayOrdersTable = "alipay_orders"
)
type GormAlipayOrderRepository struct {
*database.CachedBaseRepositoryImpl
}
var _ domain_finance_repo.AlipayOrderRepository = (*GormAlipayOrderRepository)(nil)
func NewGormAlipayOrderRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.AlipayOrderRepository {
return &GormAlipayOrderRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, AlipayOrdersTable),
}
}
func (r *GormAlipayOrderRepository) Create(ctx context.Context, order entities.AlipayOrder) (entities.AlipayOrder, error) {
err := r.CreateEntity(ctx, &order)
return order, err
}
func (r *GormAlipayOrderRepository) GetByID(ctx context.Context, id string) (entities.AlipayOrder, error) {
var order entities.AlipayOrder
err := r.SmartGetByID(ctx, id, &order)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return entities.AlipayOrder{}, gorm.ErrRecordNotFound
}
return entities.AlipayOrder{}, err
}
return order, nil
}
func (r *GormAlipayOrderRepository) GetByOutTradeNo(ctx context.Context, outTradeNo string) (*entities.AlipayOrder, error) {
var order entities.AlipayOrder
err := r.GetDB(ctx).Where("out_trade_no = ?", outTradeNo).First(&order).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &order, nil
}
func (r *GormAlipayOrderRepository) GetByRechargeID(ctx context.Context, rechargeID string) (*entities.AlipayOrder, error) {
var order entities.AlipayOrder
err := r.GetDB(ctx).Where("recharge_id = ?", rechargeID).First(&order).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &order, nil
}
func (r *GormAlipayOrderRepository) GetByUserID(ctx context.Context, userID string) ([]entities.AlipayOrder, error) {
var orders []entities.AlipayOrder
err := r.GetDB(ctx).
Joins("JOIN recharge_records ON alipay_orders.recharge_id = recharge_records.id").
Where("recharge_records.user_id = ?", userID).
Order("alipay_orders.created_at DESC").
Find(&orders).Error
return orders, err
}
func (r *GormAlipayOrderRepository) Update(ctx context.Context, order entities.AlipayOrder) error {
return r.UpdateEntity(ctx, &order)
}
func (r *GormAlipayOrderRepository) UpdateStatus(ctx context.Context, id string, status entities.AlipayOrderStatus) error {
return r.GetDB(ctx).Model(&entities.AlipayOrder{}).Where("id = ?", id).Update("status", status).Error
}
func (r *GormAlipayOrderRepository) Delete(ctx context.Context, id string) error {
return r.GetDB(ctx).Delete(&entities.AlipayOrder{}, "id = ?", id).Error
}
func (r *GormAlipayOrderRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.GetDB(ctx).Model(&entities.AlipayOrder{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}

View File

@@ -1,697 +0,0 @@
package repositories
import (
"context"
"errors"
"time"
"github.com/shopspring/decimal"
"go.uber.org/zap"
"gorm.io/gorm"
"tyapi-server/internal/domains/finance/entities"
domain_finance_repo "tyapi-server/internal/domains/finance/repositories"
"tyapi-server/internal/domains/finance/repositories/queries"
"tyapi-server/internal/shared/interfaces"
)
// GormWalletRepository 钱包GORM仓储实现
type GormWalletRepository struct {
db *gorm.DB
logger *zap.Logger
}
// 编译时检查接口实现
var _ domain_finance_repo.WalletRepository = (*GormWalletRepository)(nil)
// NewGormWalletRepository 创建钱包GORM仓储
func NewGormWalletRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.WalletRepository {
return &GormWalletRepository{
db: db,
logger: logger,
}
}
// Create 创建钱包
func (r *GormWalletRepository) Create(ctx context.Context, wallet entities.Wallet) (entities.Wallet, error) {
r.logger.Info("创建钱包", zap.String("user_id", wallet.UserID))
err := r.db.WithContext(ctx).Create(&wallet).Error
return wallet, err
}
// GetByID 根据ID获取钱包
func (r *GormWalletRepository) GetByID(ctx context.Context, id string) (entities.Wallet, error) {
var wallet entities.Wallet
err := r.db.WithContext(ctx).Where("id = ?", id).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return entities.Wallet{}, gorm.ErrRecordNotFound
}
return entities.Wallet{}, err
}
return wallet, err
}
// Update 更新钱包
func (r *GormWalletRepository) Update(ctx context.Context, wallet entities.Wallet) error {
r.logger.Info("更新钱包", zap.String("id", wallet.ID))
return r.db.WithContext(ctx).Save(&wallet).Error
}
// Delete 删除钱包
func (r *GormWalletRepository) Delete(ctx context.Context, id string) error {
r.logger.Info("删除钱包", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.Wallet{}, "id = ?", id).Error
}
// SoftDelete 软删除钱包
func (r *GormWalletRepository) SoftDelete(ctx context.Context, id string) error {
r.logger.Info("软删除钱包", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.Wallet{}, "id = ?", id).Error
}
// Restore 恢复钱包
func (r *GormWalletRepository) Restore(ctx context.Context, id string) error {
r.logger.Info("恢复钱包", zap.String("id", id))
return r.db.WithContext(ctx).Unscoped().Model(&entities.Wallet{}).Where("id = ?", id).Update("deleted_at", nil).Error
}
// Count 统计钱包数量
func (r *GormWalletRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
var count int64
query := r.db.WithContext(ctx).Model(&entities.Wallet{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ?", "%"+options.Search+"%")
}
return count, query.Count(&count).Error
}
// Exists 检查钱包是否存在
func (r *GormWalletRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}
// CreateBatch 批量创建钱包
func (r *GormWalletRepository) CreateBatch(ctx context.Context, wallets []entities.Wallet) error {
r.logger.Info("批量创建钱包", zap.Int("count", len(wallets)))
return r.db.WithContext(ctx).Create(&wallets).Error
}
// GetByIDs 根据ID列表获取钱包
func (r *GormWalletRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.Wallet, error) {
var wallets []entities.Wallet
err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&wallets).Error
return wallets, err
}
// UpdateBatch 批量更新钱包
func (r *GormWalletRepository) UpdateBatch(ctx context.Context, wallets []entities.Wallet) error {
r.logger.Info("批量更新钱包", zap.Int("count", len(wallets)))
return r.db.WithContext(ctx).Save(&wallets).Error
}
// DeleteBatch 批量删除钱包
func (r *GormWalletRepository) DeleteBatch(ctx context.Context, ids []string) error {
r.logger.Info("批量删除钱包", zap.Strings("ids", ids))
return r.db.WithContext(ctx).Delete(&entities.Wallet{}, "id IN ?", ids).Error
}
// List 获取钱包列表
func (r *GormWalletRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.Wallet, error) {
var wallets []entities.Wallet
query := r.db.WithContext(ctx).Model(&entities.Wallet{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ?", "%"+options.Search+"%")
}
if options.Sort != "" {
order := "ASC"
if options.Order != "" {
order = options.Order
}
query = query.Order(options.Sort + " " + order)
}
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
return wallets, query.Find(&wallets).Error
}
// WithTx 使用事务
func (r *GormWalletRepository) WithTx(tx interface{}) interfaces.Repository[entities.Wallet] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormWalletRepository{
db: gormTx,
logger: r.logger,
}
}
return r
}
// FindByUserID 根据用户ID查找钱包
func (r *GormWalletRepository) FindByUserID(ctx context.Context, userID string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.db.WithContext(ctx).Where("user_id = ?", userID).First(&wallet).Error
if err != nil {
return nil, err
}
return &wallet, nil
}
// ExistsByUserID 检查用户钱包是否存在
func (r *GormWalletRepository) ExistsByUserID(ctx context.Context, userID string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Count(&count).Error
return count > 0, err
}
// GetTotalBalance 获取总余额
func (r *GormWalletRepository) GetTotalBalance(ctx context.Context) (interface{}, error) {
var total decimal.Decimal
err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Select("COALESCE(SUM(balance), 0)").Scan(&total).Error
return total, err
}
// GetActiveWalletCount 获取激活钱包数量
func (r *GormWalletRepository) GetActiveWalletCount(ctx context.Context) (int64, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("is_active = ?", true).Count(&count).Error
return count, err
}
// ================ 接口要求的方法 ================
// GetByUserID 根据用户ID获取钱包
func (r *GormWalletRepository) GetByUserID(ctx context.Context, userID string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.db.WithContext(ctx).Where("user_id = ?", userID).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &wallet, nil
}
// GetByWalletAddress 根据钱包地址获取钱包
func (r *GormWalletRepository) GetByWalletAddress(ctx context.Context, walletAddress string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.db.WithContext(ctx).Where("wallet_address = ?", walletAddress).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &wallet, nil
}
// GetByWalletType 根据钱包类型获取钱包
func (r *GormWalletRepository) GetByWalletType(ctx context.Context, userID string, walletType string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.db.WithContext(ctx).Where("user_id = ? AND wallet_type = ?", userID, walletType).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &wallet, nil
}
// ListWallets 获取钱包列表(带分页和筛选)
func (r *GormWalletRepository) ListWallets(ctx context.Context, query *queries.ListWalletsQuery) ([]*entities.Wallet, int64, error) {
var wallets []entities.Wallet
var total int64
dbQuery := r.db.WithContext(ctx).Model(&entities.Wallet{})
// 应用筛选条件
if query.UserID != "" {
dbQuery = dbQuery.Where("user_id = ?", query.UserID)
}
if query.WalletType != "" {
dbQuery = dbQuery.Where("wallet_type = ?", query.WalletType)
}
if query.WalletAddress != "" {
dbQuery = dbQuery.Where("wallet_address LIKE ?", "%"+query.WalletAddress+"%")
}
if query.IsActive != nil {
dbQuery = dbQuery.Where("is_active = ?", *query.IsActive)
}
if query.StartDate != "" {
dbQuery = dbQuery.Where("created_at >= ?", query.StartDate)
}
if query.EndDate != "" {
dbQuery = dbQuery.Where("created_at <= ?", query.EndDate)
}
// 统计总数
if err := dbQuery.Count(&total).Error; err != nil {
return nil, 0, err
}
// 应用分页
offset := (query.Page - 1) * query.PageSize
dbQuery = dbQuery.Offset(offset).Limit(query.PageSize)
// 默认排序
dbQuery = dbQuery.Order("created_at DESC")
// 查询数据
if err := dbQuery.Find(&wallets).Error; err != nil {
return nil, 0, err
}
// 转换为指针切片
walletPtrs := make([]*entities.Wallet, len(wallets))
for i := range wallets {
walletPtrs[i] = &wallets[i]
}
return walletPtrs, total, nil
}
// UpdateBalance 更新钱包余额
func (r *GormWalletRepository) UpdateBalance(ctx context.Context, walletID string, balance string) error {
return r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("balance", balance).Error
}
// AddBalance 增加钱包余额
func (r *GormWalletRepository) AddBalance(ctx context.Context, walletID string, amount string) error {
return r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("balance", gorm.Expr("balance + ?", amount)).Error
}
// SubtractBalance 减少钱包余额
func (r *GormWalletRepository) SubtractBalance(ctx context.Context, walletID string, amount string) error {
return r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("balance", gorm.Expr("balance - ?", amount)).Error
}
// ActivateWallet 激活钱包
func (r *GormWalletRepository) ActivateWallet(ctx context.Context, walletID string) error {
return r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("is_active", true).Error
}
// DeactivateWallet 停用钱包
func (r *GormWalletRepository) DeactivateWallet(ctx context.Context, walletID string) error {
return r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("is_active", false).Error
}
// GetStats 获取财务统计信息
func (r *GormWalletRepository) GetStats(ctx context.Context) (*domain_finance_repo.FinanceStats, error) {
var stats domain_finance_repo.FinanceStats
// 总钱包数
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Count(&stats.TotalWallets).Error; err != nil {
return nil, err
}
// 激活钱包数
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("is_active = ?", true).Count(&stats.ActiveWallets).Error; err != nil {
return nil, err
}
// 总余额
var totalBalance decimal.Decimal
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Select("COALESCE(SUM(balance), 0)").Scan(&totalBalance).Error; err != nil {
return nil, err
}
stats.TotalBalance = totalBalance.String()
// 今日交易数(这里需要根据实际业务逻辑实现)
stats.TodayTransactions = 0
return &stats, nil
}
// GetUserWalletStats 获取用户钱包统计信息
func (r *GormWalletRepository) GetUserWalletStats(ctx context.Context, userID string) (*domain_finance_repo.FinanceStats, error) {
var stats domain_finance_repo.FinanceStats
// 用户钱包数
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Count(&stats.TotalWallets).Error; err != nil {
return nil, err
}
// 用户激活钱包数
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("user_id = ? AND is_active = ?", userID, true).Count(&stats.ActiveWallets).Error; err != nil {
return nil, err
}
// 用户总余额
var totalBalance decimal.Decimal
if err := r.db.WithContext(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Select("COALESCE(SUM(balance), 0)").Scan(&totalBalance).Error; err != nil {
return nil, err
}
stats.TotalBalance = totalBalance.String()
// 用户今日交易数(这里需要根据实际业务逻辑实现)
stats.TodayTransactions = 0
return &stats, nil
}
// GormUserSecretsRepository 用户密钥GORM仓储实现
type GormUserSecretsRepository struct {
db *gorm.DB
logger *zap.Logger
}
// 编译时检查接口实现
var _ domain_finance_repo.UserSecretsRepository = (*GormUserSecretsRepository)(nil)
// NewGormUserSecretsRepository 创建用户密钥GORM仓储
func NewGormUserSecretsRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.UserSecretsRepository {
return &GormUserSecretsRepository{
db: db,
logger: logger,
}
}
// Create 创建用户密钥
func (r *GormUserSecretsRepository) Create(ctx context.Context, secrets entities.UserSecrets) (entities.UserSecrets, error) {
r.logger.Info("创建用户密钥", zap.String("user_id", secrets.UserID))
err := r.db.WithContext(ctx).Create(&secrets).Error
return secrets, err
}
// GetByID 根据ID获取用户密钥
func (r *GormUserSecretsRepository) GetByID(ctx context.Context, id string) (entities.UserSecrets, error) {
var secrets entities.UserSecrets
err := r.db.WithContext(ctx).Where("id = ?", id).First(&secrets).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return entities.UserSecrets{}, gorm.ErrRecordNotFound
}
return entities.UserSecrets{}, err
}
return secrets, err
}
// Update 更新用户密钥
func (r *GormUserSecretsRepository) Update(ctx context.Context, secrets entities.UserSecrets) error {
r.logger.Info("更新用户密钥", zap.String("id", secrets.ID))
return r.db.WithContext(ctx).Save(&secrets).Error
}
// Delete 删除用户密钥
func (r *GormUserSecretsRepository) Delete(ctx context.Context, id string) error {
r.logger.Info("删除用户密钥", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.UserSecrets{}, "id = ?", id).Error
}
// SoftDelete 软删除用户密钥
func (r *GormUserSecretsRepository) SoftDelete(ctx context.Context, id string) error {
r.logger.Info("软删除用户密钥", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.UserSecrets{}, "id = ?", id).Error
}
// Restore 恢复用户密钥
func (r *GormUserSecretsRepository) Restore(ctx context.Context, id string) error {
r.logger.Info("恢复用户密钥", zap.String("id", id))
return r.db.WithContext(ctx).Unscoped().Model(&entities.UserSecrets{}).Where("id = ?", id).Update("deleted_at", nil).Error
}
// Count 统计用户密钥数量
func (r *GormUserSecretsRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
var count int64
query := r.db.WithContext(ctx).Model(&entities.UserSecrets{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ? OR access_id LIKE ?", "%"+options.Search+"%", "%"+options.Search+"%")
}
return count, query.Count(&count).Error
}
// Exists 检查用户密钥是否存在
func (r *GormUserSecretsRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}
// CreateBatch 批量创建用户密钥
func (r *GormUserSecretsRepository) CreateBatch(ctx context.Context, secrets []entities.UserSecrets) error {
r.logger.Info("批量创建用户密钥", zap.Int("count", len(secrets)))
return r.db.WithContext(ctx).Create(&secrets).Error
}
// GetByIDs 根据ID列表获取用户密钥
func (r *GormUserSecretsRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.UserSecrets, error) {
var secrets []entities.UserSecrets
err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&secrets).Error
return secrets, err
}
// UpdateBatch 批量更新用户密钥
func (r *GormUserSecretsRepository) UpdateBatch(ctx context.Context, secrets []entities.UserSecrets) error {
r.logger.Info("批量更新用户密钥", zap.Int("count", len(secrets)))
return r.db.WithContext(ctx).Save(&secrets).Error
}
// DeleteBatch 批量删除用户密钥
func (r *GormUserSecretsRepository) DeleteBatch(ctx context.Context, ids []string) error {
r.logger.Info("批量删除用户密钥", zap.Strings("ids", ids))
return r.db.WithContext(ctx).Delete(&entities.UserSecrets{}, "id IN ?", ids).Error
}
// List 获取用户密钥列表
func (r *GormUserSecretsRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.UserSecrets, error) {
var secrets []entities.UserSecrets
query := r.db.WithContext(ctx).Model(&entities.UserSecrets{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ? OR access_id LIKE ?", "%"+options.Search+"%", "%"+options.Search+"%")
}
if options.Sort != "" {
order := "ASC"
if options.Order != "" {
order = options.Order
}
query = query.Order(options.Sort + " " + order)
}
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
return secrets, query.Find(&secrets).Error
}
// WithTx 使用事务
func (r *GormUserSecretsRepository) WithTx(tx interface{}) interfaces.Repository[entities.UserSecrets] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormUserSecretsRepository{
db: gormTx,
logger: r.logger,
}
}
return r
}
// FindByUserID 根据用户ID查找用户密钥
func (r *GormUserSecretsRepository) FindByUserID(ctx context.Context, userID string) (*entities.UserSecrets, error) {
var secrets entities.UserSecrets
err := r.db.WithContext(ctx).Where("user_id = ?", userID).First(&secrets).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &secrets, nil
}
// FindByAccessID 根据访问ID查找用户密钥
func (r *GormUserSecretsRepository) FindByAccessID(ctx context.Context, accessID string) (*entities.UserSecrets, error) {
var secrets entities.UserSecrets
err := r.db.WithContext(ctx).Where("access_id = ?", accessID).First(&secrets).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &secrets, nil
}
// ExistsByUserID 检查用户密钥是否存在
func (r *GormUserSecretsRepository) ExistsByUserID(ctx context.Context, userID string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("user_id = ?", userID).Count(&count).Error
return count > 0, err
}
// ExistsByAccessID 检查访问ID是否存在
func (r *GormUserSecretsRepository) ExistsByAccessID(ctx context.Context, accessID string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("access_id = ?", accessID).Count(&count).Error
return count > 0, err
}
// UpdateLastUsedAt 更新最后使用时间
func (r *GormUserSecretsRepository) UpdateLastUsedAt(ctx context.Context, accessID string) error {
return r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("access_id = ?", accessID).Update("last_used_at", time.Now()).Error
}
// DeactivateByUserID 停用用户密钥
func (r *GormUserSecretsRepository) DeactivateByUserID(ctx context.Context, userID string) error {
return r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("user_id = ?", userID).Update("is_active", false).Error
}
// RegenerateAccessKey 重新生成访问密钥
func (r *GormUserSecretsRepository) RegenerateAccessKey(ctx context.Context, userID string, accessID, accessKey string) error {
return r.db.WithContext(ctx).Model(&entities.UserSecrets{}).Where("user_id = ?", userID).Updates(map[string]interface{}{
"access_id": accessID,
"access_key": accessKey,
"updated_at": time.Now(),
}).Error
}
// GetExpiredSecrets 获取过期的密钥
func (r *GormUserSecretsRepository) GetExpiredSecrets(ctx context.Context) ([]entities.UserSecrets, error) {
var secrets []entities.UserSecrets
err := r.db.WithContext(ctx).Where("expires_at IS NOT NULL AND expires_at < ?", time.Now()).Find(&secrets).Error
return secrets, err
}
// DeleteExpiredSecrets 删除过期的密钥
func (r *GormUserSecretsRepository) DeleteExpiredSecrets(ctx context.Context) error {
return r.db.WithContext(ctx).Where("expires_at < ?", time.Now()).Delete(&entities.UserSecrets{}).Error
}
// ================ 接口要求的方法 ================
// GetByUserID 根据用户ID获取用户密钥
func (r *GormUserSecretsRepository) GetByUserID(ctx context.Context, userID string) (*entities.UserSecrets, error) {
var secrets entities.UserSecrets
err := r.db.WithContext(ctx).Where("user_id = ?", userID).First(&secrets).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &secrets, nil
}
// GetBySecretType 根据用户ID和密钥类型获取用户密钥
func (r *GormUserSecretsRepository) GetBySecretType(ctx context.Context, userID string, secretType string) (*entities.UserSecrets, error) {
var secrets entities.UserSecrets
err := r.db.WithContext(ctx).Where("user_id = ? AND secret_type = ?", userID, secretType).First(&secrets).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &secrets, nil
}
// ListUserSecrets 获取用户密钥列表(带分页和筛选)
func (r *GormUserSecretsRepository) ListUserSecrets(ctx context.Context, query *queries.ListUserSecretsQuery) ([]*entities.UserSecrets, int64, error) {
var secrets []entities.UserSecrets
var total int64
dbQuery := r.db.WithContext(ctx).Model(&entities.UserSecrets{})
// 应用筛选条件
if query.UserID != "" {
dbQuery = dbQuery.Where("user_id = ?", query.UserID)
}
if query.SecretType != "" {
dbQuery = dbQuery.Where("secret_type = ?", query.SecretType)
}
if query.IsActive != nil {
dbQuery = dbQuery.Where("is_active = ?", *query.IsActive)
}
if query.StartDate != "" {
dbQuery = dbQuery.Where("created_at >= ?", query.StartDate)
}
if query.EndDate != "" {
dbQuery = dbQuery.Where("created_at <= ?", query.EndDate)
}
// 统计总数
if err := dbQuery.Count(&total).Error; err != nil {
return nil, 0, err
}
// 应用分页
offset := (query.Page - 1) * query.PageSize
dbQuery = dbQuery.Offset(offset).Limit(query.PageSize)
// 默认排序
dbQuery = dbQuery.Order("created_at DESC")
// 查询数据
if err := dbQuery.Find(&secrets).Error; err != nil {
return nil, 0, err
}
// 转换为指针切片
secretPtrs := make([]*entities.UserSecrets, len(secrets))
for i := range secrets {
secretPtrs[i] = &secrets[i]
}
return secretPtrs, total, nil
}
// UpdateSecret 更新密钥
func (r *GormUserSecretsRepository) UpdateSecret(ctx context.Context, userID string, secretType string, secretValue string) error {
return r.db.WithContext(ctx).Model(&entities.UserSecrets{}).
Where("user_id = ? AND secret_type = ?", userID, secretType).
Update("secret_value", secretValue).Error
}
// DeleteSecret 删除密钥
func (r *GormUserSecretsRepository) DeleteSecret(ctx context.Context, userID string, secretType string) error {
return r.db.WithContext(ctx).Where("user_id = ? AND secret_type = ?", userID, secretType).
Delete(&entities.UserSecrets{}).Error
}
// ValidateSecret 验证密钥
func (r *GormUserSecretsRepository) ValidateSecret(ctx context.Context, userID string, secretType string, secretValue string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.UserSecrets{}).
Where("user_id = ? AND secret_type = ? AND secret_value = ?", userID, secretType, secretValue).
Count(&count).Error
return count > 0, err
}

View File

@@ -0,0 +1,178 @@
package repositories
import (
"context"
"errors"
"tyapi-server/internal/domains/finance/entities"
domain_finance_repo "tyapi-server/internal/domains/finance/repositories"
"tyapi-server/internal/shared/database"
"tyapi-server/internal/shared/interfaces"
"go.uber.org/zap"
"gorm.io/gorm"
)
const (
RechargeRecordsTable = "recharge_records"
)
type GormRechargeRecordRepository struct {
*database.CachedBaseRepositoryImpl
}
var _ domain_finance_repo.RechargeRecordRepository = (*GormRechargeRecordRepository)(nil)
func NewGormRechargeRecordRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.RechargeRecordRepository {
return &GormRechargeRecordRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, RechargeRecordsTable),
}
}
func (r *GormRechargeRecordRepository) Create(ctx context.Context, record entities.RechargeRecord) (entities.RechargeRecord, error) {
err := r.CreateEntity(ctx, &record)
return record, err
}
func (r *GormRechargeRecordRepository) GetByID(ctx context.Context, id string) (entities.RechargeRecord, error) {
var record entities.RechargeRecord
err := r.SmartGetByID(ctx, id, &record)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return entities.RechargeRecord{}, gorm.ErrRecordNotFound
}
return entities.RechargeRecord{}, err
}
return record, nil
}
func (r *GormRechargeRecordRepository) GetByUserID(ctx context.Context, userID string) ([]entities.RechargeRecord, error) {
var records []entities.RechargeRecord
err := r.GetDB(ctx).Where("user_id = ?", userID).Order("created_at DESC").Find(&records).Error
return records, err
}
func (r *GormRechargeRecordRepository) GetByAlipayOrderID(ctx context.Context, alipayOrderID string) (*entities.RechargeRecord, error) {
var record entities.RechargeRecord
err := r.GetDB(ctx).Where("alipay_order_id = ?", alipayOrderID).First(&record).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &record, nil
}
func (r *GormRechargeRecordRepository) GetByTransferOrderID(ctx context.Context, transferOrderID string) (*entities.RechargeRecord, error) {
var record entities.RechargeRecord
err := r.GetDB(ctx).Where("transfer_order_id = ?", transferOrderID).First(&record).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &record, nil
}
func (r *GormRechargeRecordRepository) Update(ctx context.Context, record entities.RechargeRecord) error {
return r.UpdateEntity(ctx, &record)
}
func (r *GormRechargeRecordRepository) UpdateStatus(ctx context.Context, id string, status entities.RechargeStatus) error {
return r.GetDB(ctx).Model(&entities.RechargeRecord{}).Where("id = ?", id).Update("status", status).Error
}
func (r *GormRechargeRecordRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
var count int64
query := r.GetDB(ctx).Model(&entities.RechargeRecord{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
}
return count, query.Count(&count).Error
}
func (r *GormRechargeRecordRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.GetDB(ctx).Model(&entities.RechargeRecord{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}
func (r *GormRechargeRecordRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.RechargeRecord, error) {
var records []entities.RechargeRecord
query := r.GetDB(ctx).Model(&entities.RechargeRecord{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
}
if options.Sort != "" {
order := "ASC"
if options.Order == "desc" || options.Order == "DESC" {
order = "DESC"
}
query = query.Order(options.Sort + " " + order)
} else {
query = query.Order("created_at DESC")
}
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
err := query.Find(&records).Error
return records, err
}
func (r *GormRechargeRecordRepository) CreateBatch(ctx context.Context, records []entities.RechargeRecord) error {
return r.GetDB(ctx).Create(&records).Error
}
func (r *GormRechargeRecordRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.RechargeRecord, error) {
var records []entities.RechargeRecord
err := r.GetDB(ctx).Where("id IN ?", ids).Find(&records).Error
return records, err
}
func (r *GormRechargeRecordRepository) UpdateBatch(ctx context.Context, records []entities.RechargeRecord) error {
return r.GetDB(ctx).Save(&records).Error
}
func (r *GormRechargeRecordRepository) DeleteBatch(ctx context.Context, ids []string) error {
return r.GetDB(ctx).Delete(&entities.RechargeRecord{}, "id IN ?", ids).Error
}
func (r *GormRechargeRecordRepository) WithTx(tx interface{}) interfaces.Repository[entities.RechargeRecord] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormRechargeRecordRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(gormTx, r.GetLogger(), RechargeRecordsTable),
}
}
return r
}
func (r *GormRechargeRecordRepository) Delete(ctx context.Context, id string) error {
return r.DeleteEntity(ctx, id, &entities.RechargeRecord{})
}
func (r *GormRechargeRecordRepository) SoftDelete(ctx context.Context, id string) error {
return r.SoftDeleteEntity(ctx, id, &entities.RechargeRecord{})
}
func (r *GormRechargeRecordRepository) Restore(ctx context.Context, id string) error {
return r.RestoreEntity(ctx, id, &entities.RechargeRecord{})
}

View File

@@ -0,0 +1,273 @@
package repositories
import (
"context"
"errors"
"fmt"
"tyapi-server/internal/domains/finance/entities"
domain_finance_repo "tyapi-server/internal/domains/finance/repositories"
"tyapi-server/internal/shared/database"
"tyapi-server/internal/shared/interfaces"
"github.com/shopspring/decimal"
"go.uber.org/zap"
"gorm.io/gorm"
)
const (
WalletsTable = "wallets"
)
type GormWalletRepository struct {
*database.CachedBaseRepositoryImpl
}
var _ domain_finance_repo.WalletRepository = (*GormWalletRepository)(nil)
func NewGormWalletRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.WalletRepository {
return &GormWalletRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, WalletsTable),
}
}
func (r *GormWalletRepository) Create(ctx context.Context, wallet entities.Wallet) (entities.Wallet, error) {
err := r.CreateEntity(ctx, &wallet)
return wallet, err
}
func (r *GormWalletRepository) GetByID(ctx context.Context, id string) (entities.Wallet, error) {
var wallet entities.Wallet
err := r.SmartGetByID(ctx, id, &wallet)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return entities.Wallet{}, gorm.ErrRecordNotFound
}
return entities.Wallet{}, err
}
return wallet, nil
}
func (r *GormWalletRepository) Update(ctx context.Context, wallet entities.Wallet) error {
return r.UpdateEntity(ctx, &wallet)
}
func (r *GormWalletRepository) Delete(ctx context.Context, id string) error {
return r.DeleteEntity(ctx, id, &entities.Wallet{})
}
func (r *GormWalletRepository) SoftDelete(ctx context.Context, id string) error {
return r.SoftDeleteEntity(ctx, id, &entities.Wallet{})
}
func (r *GormWalletRepository) Restore(ctx context.Context, id string) error {
return r.RestoreEntity(ctx, id, &entities.Wallet{})
}
func (r *GormWalletRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
var count int64
query := r.GetDB(ctx).Model(&entities.Wallet{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ?", "%"+options.Search+"%")
}
return count, query.Count(&count).Error
}
func (r *GormWalletRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}
func (r *GormWalletRepository) CreateBatch(ctx context.Context, wallets []entities.Wallet) error {
return r.GetDB(ctx).Create(&wallets).Error
}
func (r *GormWalletRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.Wallet, error) {
var wallets []entities.Wallet
err := r.GetDB(ctx).Where("id IN ?", ids).Find(&wallets).Error
return wallets, err
}
func (r *GormWalletRepository) UpdateBatch(ctx context.Context, wallets []entities.Wallet) error {
return r.GetDB(ctx).Save(&wallets).Error
}
func (r *GormWalletRepository) DeleteBatch(ctx context.Context, ids []string) error {
return r.GetDB(ctx).Delete(&entities.Wallet{}, "id IN ?", ids).Error
}
func (r *GormWalletRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.Wallet, error) {
var wallets []entities.Wallet
query := r.GetDB(ctx).Model(&entities.Wallet{})
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
if options.Search != "" {
query = query.Where("user_id LIKE ?", "%"+options.Search+"%")
}
if options.Sort != "" {
order := options.Sort
if options.Order == "desc" {
order += " DESC"
} else {
order += " ASC"
}
query = query.Order(order)
}
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
return wallets, query.Find(&wallets).Error
}
func (r *GormWalletRepository) WithTx(tx interface{}) interfaces.Repository[entities.Wallet] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormWalletRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(gormTx, r.GetLogger(), WalletsTable),
}
}
return r
}
func (r *GormWalletRepository) FindByUserID(ctx context.Context, userID string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.GetDB(ctx).Where("user_id = ?", userID).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &wallet, nil
}
func (r *GormWalletRepository) ExistsByUserID(ctx context.Context, userID string) (bool, error) {
var count int64
err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Count(&count).Error
return count > 0, err
}
func (r *GormWalletRepository) GetTotalBalance(ctx context.Context) (interface{}, error) {
var total decimal.Decimal
err := r.GetDB(ctx).Model(&entities.Wallet{}).Select("COALESCE(SUM(balance), 0)").Scan(&total).Error
return total, err
}
func (r *GormWalletRepository) GetActiveWalletCount(ctx context.Context) (int64, error) {
var count int64
err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("is_active = ?", true).Count(&count).Error
return count, err
}
// ================ 接口要求的方法 ================
func (r *GormWalletRepository) GetByUserID(ctx context.Context, userID string) (*entities.Wallet, error) {
var wallet entities.Wallet
err := r.GetDB(ctx).Where("user_id = ?", userID).First(&wallet).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, gorm.ErrRecordNotFound
}
return nil, err
}
return &wallet, nil
}
// UpdateBalanceWithVersionRetry 乐观锁自动重试最大重试maxRetry次
func (r *GormWalletRepository) UpdateBalanceWithVersion(ctx context.Context, walletID string, newBalance string, oldVersion int64) (bool, error) {
maxRetry := 10
for i := 0; i < maxRetry; i++ {
result := r.GetDB(ctx).Model(&entities.Wallet{}).
Where("id = ? AND version = ?", walletID, oldVersion).
Updates(map[string]interface{}{
"balance": newBalance,
"version": oldVersion + 1,
})
if result.Error != nil {
return false, result.Error
}
if result.RowsAffected == 1 {
return true, nil
}
// 并发冲突重试前重新查version
var wallet entities.Wallet
err := r.GetDB(ctx).Where("id = ?", walletID).First(&wallet).Error
if err != nil {
return false, err
}
oldVersion = wallet.Version
}
return false, fmt.Errorf("高并发下余额变动失败,请重试")
}
func (r *GormWalletRepository) UpdateBalance(ctx context.Context, walletID string, balance string) error {
return r.GetDB(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("balance", balance).Error
}
func (r *GormWalletRepository) ActivateWallet(ctx context.Context, walletID string) error {
return r.GetDB(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("is_active", true).Error
}
func (r *GormWalletRepository) DeactivateWallet(ctx context.Context, walletID string) error {
return r.GetDB(ctx).Model(&entities.Wallet{}).Where("id = ?", walletID).Update("is_active", false).Error
}
func (r *GormWalletRepository) GetStats(ctx context.Context) (*domain_finance_repo.FinanceStats, error) {
var stats domain_finance_repo.FinanceStats
// 总钱包数
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Count(&stats.TotalWallets).Error; err != nil {
return nil, err
}
// 激活钱包数
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("is_active = ?", true).Count(&stats.ActiveWallets).Error; err != nil {
return nil, err
}
// 总余额
var totalBalance decimal.Decimal
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Select("COALESCE(SUM(balance), 0)").Scan(&totalBalance).Error; err != nil {
return nil, err
}
stats.TotalBalance = totalBalance.String()
// 今日交易数(这里需要根据实际业务逻辑实现)
stats.TodayTransactions = 0
return &stats, nil
}
func (r *GormWalletRepository) GetUserWalletStats(ctx context.Context, userID string) (*domain_finance_repo.FinanceStats, error) {
var stats domain_finance_repo.FinanceStats
// 用户钱包数
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Count(&stats.TotalWallets).Error; err != nil {
return nil, err
}
// 用户激活钱包数
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("user_id = ? AND is_active = ?", userID, true).Count(&stats.ActiveWallets).Error; err != nil {
return nil, err
}
// 用户总余额
var totalBalance decimal.Decimal
if err := r.GetDB(ctx).Model(&entities.Wallet{}).Where("user_id = ?", userID).Select("COALESCE(SUM(balance), 0)").Scan(&totalBalance).Error; err != nil {
return nil, err
}
stats.TotalBalance = totalBalance.String()
// 用户今日交易数(这里需要根据实际业务逻辑实现)
stats.TodayTransactions = 0
return &stats, nil
}

View File

@@ -0,0 +1,296 @@
package repositories
import (
"context"
"time"
"tyapi-server/internal/domains/finance/entities"
domain_finance_repo "tyapi-server/internal/domains/finance/repositories"
"tyapi-server/internal/shared/database"
"tyapi-server/internal/shared/interfaces"
"go.uber.org/zap"
"gorm.io/gorm"
)
// WalletTransactionWithProduct 包含产品名称的钱包交易记录
type WalletTransactionWithProduct struct {
entities.WalletTransaction
ProductName string `json:"product_name" gorm:"column:product_name"`
}
const (
WalletTransactionsTable = "wallet_transactions"
)
type GormWalletTransactionRepository struct {
*database.CachedBaseRepositoryImpl
}
var _ domain_finance_repo.WalletTransactionRepository = (*GormWalletTransactionRepository)(nil)
func NewGormWalletTransactionRepository(db *gorm.DB, logger *zap.Logger) domain_finance_repo.WalletTransactionRepository {
return &GormWalletTransactionRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, WalletTransactionsTable),
}
}
func (r *GormWalletTransactionRepository) Create(ctx context.Context, transaction entities.WalletTransaction) (entities.WalletTransaction, error) {
err := r.CreateEntity(ctx, &transaction)
return transaction, err
}
func (r *GormWalletTransactionRepository) Update(ctx context.Context, transaction entities.WalletTransaction) error {
return r.UpdateEntity(ctx, &transaction)
}
func (r *GormWalletTransactionRepository) GetByID(ctx context.Context, id string) (entities.WalletTransaction, error) {
var transaction entities.WalletTransaction
err := r.SmartGetByID(ctx, id, &transaction)
return transaction, err
}
func (r *GormWalletTransactionRepository) GetByUserID(ctx context.Context, userID string, limit, offset int) ([]*entities.WalletTransaction, error) {
var transactions []*entities.WalletTransaction
options := database.CacheListOptions{
Where: "user_id = ?",
Args: []interface{}{userID},
Order: "created_at DESC",
Limit: limit,
Offset: offset,
}
err := r.ListWithCache(ctx, &transactions, 10*time.Minute, options)
return transactions, err
}
func (r *GormWalletTransactionRepository) GetByApiCallID(ctx context.Context, apiCallID string) (*entities.WalletTransaction, error) {
var transaction entities.WalletTransaction
err := r.FindOne(ctx, &transaction, "api_call_id = ?", apiCallID)
if err != nil {
return nil, err
}
return &transaction, nil
}
func (r *GormWalletTransactionRepository) ListByUserId(ctx context.Context, userId string, options interfaces.ListOptions) ([]*entities.WalletTransaction, int64, error) {
var transactions []*entities.WalletTransaction
var total int64
// 构建查询条件
whereCondition := "user_id = ?"
whereArgs := []interface{}{userId}
// 获取总数
count, err := r.CountWhere(ctx, &entities.WalletTransaction{}, whereCondition, whereArgs...)
if err != nil {
return nil, 0, err
}
total = count
// 使用基础仓储的分页查询方法
err = r.ListWithOptions(ctx, &entities.WalletTransaction{}, &transactions, options)
return transactions, total, err
}
func (r *GormWalletTransactionRepository) ListByUserIdWithFilters(ctx context.Context, userId string, filters map[string]interface{}, options interfaces.ListOptions) ([]*entities.WalletTransaction, int64, error) {
var transactions []*entities.WalletTransaction
var total int64
// 构建基础查询条件
whereCondition := "user_id = ?"
whereArgs := []interface{}{userId}
// 应用筛选条件
if filters != nil {
// 时间范围筛选
if startTime, ok := filters["start_time"].(time.Time); ok {
whereCondition += " AND created_at >= ?"
whereArgs = append(whereArgs, startTime)
}
if endTime, ok := filters["end_time"].(time.Time); ok {
whereCondition += " AND created_at <= ?"
whereArgs = append(whereArgs, endTime)
}
// 关键词筛选支持transaction_id和product_name
if keyword, ok := filters["keyword"].(string); ok && keyword != "" {
whereCondition += " AND (transaction_id LIKE ? OR product_id IN (SELECT id FROM product WHERE name LIKE ?))"
whereArgs = append(whereArgs, "%"+keyword+"%", "%"+keyword+"%")
}
// API调用ID筛选
if apiCallId, ok := filters["api_call_id"].(string); ok && apiCallId != "" {
whereCondition += " AND api_call_id LIKE ?"
whereArgs = append(whereArgs, "%"+apiCallId+"%")
}
// 金额范围筛选
if minAmount, ok := filters["min_amount"].(string); ok && minAmount != "" {
whereCondition += " AND amount >= ?"
whereArgs = append(whereArgs, minAmount)
}
if maxAmount, ok := filters["max_amount"].(string); ok && maxAmount != "" {
whereCondition += " AND amount <= ?"
whereArgs = append(whereArgs, maxAmount)
}
}
// 获取总数
count, err := r.CountWhere(ctx, &entities.WalletTransaction{}, whereCondition, whereArgs...)
if err != nil {
return nil, 0, err
}
total = count
// 使用基础仓储的分页查询方法
err = r.ListWithOptions(ctx, &entities.WalletTransaction{}, &transactions, options)
return transactions, total, err
}
func (r *GormWalletTransactionRepository) CountByUserId(ctx context.Context, userId string) (int64, error) {
return r.CountWhere(ctx, &entities.WalletTransaction{}, "user_id = ?", userId)
}
// 实现interfaces.Repository接口的其他方法
func (r *GormWalletTransactionRepository) Delete(ctx context.Context, id string) error {
return r.DeleteEntity(ctx, id, &entities.WalletTransaction{})
}
func (r *GormWalletTransactionRepository) Exists(ctx context.Context, id string) (bool, error) {
return r.ExistsEntity(ctx, id, &entities.WalletTransaction{})
}
func (r *GormWalletTransactionRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.WalletTransaction, error) {
var transactions []entities.WalletTransaction
err := r.ListWithOptions(ctx, &entities.WalletTransaction{}, &transactions, options)
return transactions, err
}
func (r *GormWalletTransactionRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
return r.CountWithOptions(ctx, &entities.WalletTransaction{}, options)
}
func (r *GormWalletTransactionRepository) CreateBatch(ctx context.Context, transactions []entities.WalletTransaction) error {
return r.CreateBatchEntity(ctx, &transactions)
}
func (r *GormWalletTransactionRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.WalletTransaction, error) {
var transactions []entities.WalletTransaction
err := r.GetEntitiesByIDs(ctx, ids, &transactions)
return transactions, err
}
func (r *GormWalletTransactionRepository) UpdateBatch(ctx context.Context, transactions []entities.WalletTransaction) error {
return r.UpdateBatchEntity(ctx, &transactions)
}
func (r *GormWalletTransactionRepository) DeleteBatch(ctx context.Context, ids []string) error {
return r.DeleteBatchEntity(ctx, ids, &entities.WalletTransaction{})
}
func (r *GormWalletTransactionRepository) WithTx(tx interface{}) interfaces.Repository[entities.WalletTransaction] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormWalletTransactionRepository{
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(gormTx, r.GetLogger(), WalletTransactionsTable),
}
}
return r
}
func (r *GormWalletTransactionRepository) SoftDelete(ctx context.Context, id string) error {
return r.SoftDeleteEntity(ctx, id, &entities.WalletTransaction{})
}
func (r *GormWalletTransactionRepository) Restore(ctx context.Context, id string) error {
return r.RestoreEntity(ctx, id, &entities.WalletTransaction{})
}
func (r *GormWalletTransactionRepository) ListByUserIdWithFiltersAndProductName(ctx context.Context, userId string, filters map[string]interface{}, options interfaces.ListOptions) (map[string]string, []*entities.WalletTransaction, int64, error) {
var transactionsWithProduct []*WalletTransactionWithProduct
var total int64
// 构建基础查询条件
whereCondition := "wt.user_id = ?"
whereArgs := []interface{}{userId}
// 应用筛选条件
if filters != nil {
// 时间范围筛选
if startTime, ok := filters["start_time"].(time.Time); ok {
whereCondition += " AND wt.created_at >= ?"
whereArgs = append(whereArgs, startTime)
}
if endTime, ok := filters["end_time"].(time.Time); ok {
whereCondition += " AND wt.created_at <= ?"
whereArgs = append(whereArgs, endTime)
}
// 交易ID筛选
if transactionId, ok := filters["transaction_id"].(string); ok && transactionId != "" {
whereCondition += " AND wt.transaction_id LIKE ?"
whereArgs = append(whereArgs, "%"+transactionId+"%")
}
// 产品名称筛选
if productName, ok := filters["product_name"].(string); ok && productName != "" {
whereCondition += " AND p.name LIKE ?"
whereArgs = append(whereArgs, "%"+productName+"%")
}
// 金额范围筛选
if minAmount, ok := filters["min_amount"].(string); ok && minAmount != "" {
whereCondition += " AND wt.amount >= ?"
whereArgs = append(whereArgs, minAmount)
}
if maxAmount, ok := filters["max_amount"].(string); ok && maxAmount != "" {
whereCondition += " AND wt.amount <= ?"
whereArgs = append(whereArgs, maxAmount)
}
}
// 构建JOIN查询
query := r.GetDB(ctx).Table("wallet_transactions wt").
Select("wt.*, p.name as product_name").
Joins("LEFT JOIN product p ON wt.product_id = p.id").
Where(whereCondition, whereArgs...)
// 获取总数
var count int64
err := query.Count(&count).Error
if err != nil {
return nil, nil, 0, err
}
total = count
// 应用排序和分页
if options.Sort != "" {
query = query.Order("wt." + options.Sort + " " + options.Order)
} else {
query = query.Order("wt.created_at DESC")
}
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
// 执行查询
err = query.Find(&transactionsWithProduct).Error
if err != nil {
return nil, nil, 0, err
}
// 转换为entities.WalletTransaction并构建产品名称映射
var transactions []*entities.WalletTransaction
productNameMap := make(map[string]string)
for _, t := range transactionsWithProduct {
transaction := t.WalletTransaction
transactions = append(transactions, &transaction)
// 构建产品ID到产品名称的映射
if t.ProductName != "" {
productNameMap[transaction.ProductID] = t.ProductName
}
}
return productNameMap, transactions, total, nil
}