package postgres import ( "context" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/redis/go-redis/v9" "gorm.io/gorm" ) type WalletStore struct { db *gorm.DB redis *redis.Client } func NewWalletStore(db *gorm.DB, redis *redis.Client) *WalletStore { return &WalletStore{ db: db, redis: redis, } } func (s *WalletStore) GetByResourceTypeAndID(ctx context.Context, resourceType string, resourceID uint, walletType string) (*model.Wallet, error) { var wallet model.Wallet err := s.db.WithContext(ctx). Where("resource_type = ? AND resource_id = ? AND wallet_type = ?", resourceType, resourceID, walletType). First(&wallet).Error if err != nil { return nil, err } return &wallet, nil } func (s *WalletStore) GetShopCommissionWallet(ctx context.Context, shopID uint) (*model.Wallet, error) { return s.GetByResourceTypeAndID(ctx, "shop", shopID, "commission") } type ShopCommissionSummary struct { ShopID uint Balance int64 FrozenBalance int64 } func (s *WalletStore) GetShopCommissionSummaryBatch(ctx context.Context, shopIDs []uint) (map[uint]*ShopCommissionSummary, error) { if len(shopIDs) == 0 { return make(map[uint]*ShopCommissionSummary), nil } var wallets []model.Wallet err := s.db.WithContext(ctx). Where("resource_type = ? AND resource_id IN ? AND wallet_type = ?", "shop", shopIDs, "commission"). Find(&wallets).Error if err != nil { return nil, err } result := make(map[uint]*ShopCommissionSummary) for _, w := range wallets { result[w.ResourceID] = &ShopCommissionSummary{ ShopID: w.ResourceID, Balance: w.Balance, FrozenBalance: w.FrozenBalance, } } return result, nil } func (s *WalletStore) GetByID(ctx context.Context, id uint) (*model.Wallet, error) { var wallet model.Wallet if err := s.db.WithContext(ctx).First(&wallet, id).Error; err != nil { return nil, err } return &wallet, nil } func (s *WalletStore) DeductFrozenBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error { result := tx.WithContext(ctx). Model(&model.Wallet{}). Where("id = ? AND frozen_balance >= ?", walletID, amount). Updates(map[string]interface{}{ "frozen_balance": gorm.Expr("frozen_balance - ?", amount), }) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } func (s *WalletStore) UnfreezeBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error { result := tx.WithContext(ctx). Model(&model.Wallet{}). Where("id = ? AND frozen_balance >= ?", walletID, amount). Updates(map[string]interface{}{ "balance": gorm.Expr("balance + ?", amount), "frozen_balance": gorm.Expr("frozen_balance - ?", amount), }) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil }