v0.1
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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{})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user