package repository import ( "context" "database/sql" "errors" "strconv" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" ) type ReferralRepository interface { CreateReferral(ctx context.Context, referral *domain.Referral) error GetReferralByCode(ctx context.Context, code string) (*domain.Referral, error) UpdateReferral(ctx context.Context, referral *domain.Referral) error GetReferralStats(ctx context.Context, userID string) (*domain.ReferralStats, error) GetSettings(ctx context.Context) (*domain.ReferralSettings, error) UpdateSettings(ctx context.Context, settings *domain.ReferralSettings) error CreateSettings(ctx context.Context, settings *domain.ReferralSettings) error GetReferralByReferredID(ctx context.Context, referredID string) (*domain.Referral, error) // New method UpdateUserReferalCode(ctx context.Context, codedata domain.UpdateUserReferalCode) error } type ReferralRepo struct { store *Store } func NewReferralRepository(store *Store) ReferralRepository { return &ReferralRepo{store: store} } func (r *ReferralRepo) UpdateUserReferalCode(ctx context.Context, codedata domain.UpdateUserReferalCode) error { params := dbgen.UpdateReferralCodeParams{ ID: codedata.UserID, ReferralCode: pgtype.Text{ String: codedata.Code, Valid: true, }, } return r.store.queries.UpdateReferralCode(ctx, params) } func (r *ReferralRepo) CreateReferral(ctx context.Context, referral *domain.Referral) error { rewardAmount := pgtype.Numeric{} if err := rewardAmount.Scan(strconv.Itoa(int(referral.RewardAmount))); err != nil { return err } params := dbgen.CreateReferralParams{ ReferralCode: referral.ReferralCode, ReferrerID: referral.ReferrerID, Status: dbgen.Referralstatus(referral.Status), RewardAmount: rewardAmount, ExpiresAt: pgtype.Timestamptz{Time: referral.ExpiresAt, Valid: true}, } _, err := r.store.queries.CreateReferral(ctx, params) return err } func (r *ReferralRepo) GetReferralByCode(ctx context.Context, code string) (*domain.Referral, error) { dbReferral, err := r.store.queries.GetReferralByCode(ctx, code) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return r.mapToDomainReferral(&dbReferral), nil } func (r *ReferralRepo) UpdateReferral(ctx context.Context, referral *domain.Referral) error { var referredID pgtype.Text if referral.ReferredID != nil { referredID = pgtype.Text{String: *referral.ReferredID, Valid: true} } params := dbgen.UpdateReferralParams{ ID: referral.ID, ReferredID: referredID, Status: dbgen.Referralstatus(referral.Status), } _, err := r.store.queries.UpdateReferral(ctx, params) return err } func (r *ReferralRepo) GetReferralStats(ctx context.Context, userID string) (*domain.ReferralStats, error) { stats, err := r.store.queries.GetReferralStats(ctx, userID) if err != nil { return nil, err } return &domain.ReferralStats{ TotalReferrals: int(stats.TotalReferrals), CompletedReferrals: int(stats.CompletedReferrals), TotalRewardEarned: stats.TotalRewardEarned.(float64), PendingRewards: stats.PendingRewards.(float64), }, nil } func (r *ReferralRepo) GetSettings(ctx context.Context) (*domain.ReferralSettings, error) { settings, err := r.store.queries.GetReferralSettings(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return r.mapToDomainSettings(&settings), nil } func (r *ReferralRepo) UpdateSettings(ctx context.Context, settings *domain.ReferralSettings) error { rewardAmount := pgtype.Numeric{} if err := rewardAmount.Scan(settings.ReferralRewardAmount); err != nil { return err } cashbackPercentage := pgtype.Numeric{} if err := cashbackPercentage.Scan(settings.CashbackPercentage); err != nil { return err } betReferralBonusPercentage := pgtype.Numeric{} if err := betReferralBonusPercentage.Scan(settings.BetReferralBonusPercentage); err != nil { return err } params := dbgen.UpdateReferralSettingsParams{ ID: settings.ID, ReferralRewardAmount: rewardAmount, CashbackPercentage: cashbackPercentage, BetReferralBonusPercentage: betReferralBonusPercentage, // New field MaxReferrals: settings.MaxReferrals, ExpiresAfterDays: settings.ExpiresAfterDays, UpdatedBy: settings.UpdatedBy, } _, err := r.store.queries.UpdateReferralSettings(ctx, params) return err } func (r *ReferralRepo) CreateSettings(ctx context.Context, settings *domain.ReferralSettings) error { rewardAmount := pgtype.Numeric{} if err := rewardAmount.Scan(settings.ReferralRewardAmount); err != nil { return err } cashbackPercentage := pgtype.Numeric{} if err := cashbackPercentage.Scan(settings.CashbackPercentage); err != nil { return err } betReferralBonusPercentage := pgtype.Numeric{} if err := betReferralBonusPercentage.Scan(settings.BetReferralBonusPercentage); err != nil { return err } params := dbgen.CreateReferralSettingsParams{ ReferralRewardAmount: rewardAmount, CashbackPercentage: cashbackPercentage, BetReferralBonusPercentage: betReferralBonusPercentage, // New field MaxReferrals: settings.MaxReferrals, ExpiresAfterDays: settings.ExpiresAfterDays, UpdatedBy: settings.UpdatedBy, } _, err := r.store.queries.CreateReferralSettings(ctx, params) return err } func (r *ReferralRepo) GetReferralByReferredID(ctx context.Context, referredID string) (*domain.Referral, error) { dbReferral, err := r.store.queries.GetReferralByReferredID(ctx, pgtype.Text{String: referredID, Valid: true}) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return r.mapToDomainReferral(&dbReferral), nil } func (r *ReferralRepo) mapToDomainReferral(dbRef *dbgen.Referral) *domain.Referral { var referredID *string if dbRef.ReferredID.Valid { referredID = &dbRef.ReferredID.String } rewardAmount := 0.0 if dbRef.RewardAmount.Valid { if f8, err := dbRef.RewardAmount.Float64Value(); err == nil { rewardAmount = f8.Float64 } } cashbackAmount := 0.0 if dbRef.CashbackAmount.Valid { if f8, err := dbRef.CashbackAmount.Float64Value(); err == nil { cashbackAmount = f8.Float64 } } return &domain.Referral{ ID: dbRef.ID, ReferralCode: dbRef.ReferralCode, ReferrerID: dbRef.ReferrerID, ReferredID: referredID, Status: domain.ReferralStatus(dbRef.Status), RewardAmount: rewardAmount, CashbackAmount: cashbackAmount, CreatedAt: dbRef.CreatedAt.Time, UpdatedAt: dbRef.UpdatedAt.Time, ExpiresAt: dbRef.ExpiresAt.Time, } } func (r *ReferralRepo) mapToDomainSettings(dbSettings *dbgen.ReferralSetting) *domain.ReferralSettings { rewardAmount := 0.0 if dbSettings.ReferralRewardAmount.Valid { if f8, err := dbSettings.ReferralRewardAmount.Float64Value(); err == nil { rewardAmount = f8.Float64 } } cashbackPercentage := 0.0 if dbSettings.CashbackPercentage.Valid { if f8, err := dbSettings.CashbackPercentage.Float64Value(); err == nil { cashbackPercentage = f8.Float64 } } betReferralBonusPercentage := 0.0 if dbSettings.BetReferralBonusPercentage.Valid { if f8, err := dbSettings.BetReferralBonusPercentage.Float64Value(); err == nil { betReferralBonusPercentage = f8.Float64 } } return &domain.ReferralSettings{ ID: dbSettings.ID, ReferralRewardAmount: rewardAmount, CashbackPercentage: cashbackPercentage, BetReferralBonusPercentage: betReferralBonusPercentage, // New field MaxReferrals: dbSettings.MaxReferrals, ExpiresAfterDays: dbSettings.ExpiresAfterDays, UpdatedBy: dbSettings.UpdatedBy, CreatedAt: dbSettings.CreatedAt.Time, UpdatedAt: dbSettings.UpdatedAt.Time, Version: dbSettings.Version, } }