fix: referral handlers and integration issues

This commit is contained in:
Samuel Tariku 2025-09-09 23:44:02 +03:00
parent 2ac66308d3
commit 5595600ede
14 changed files with 322 additions and 204 deletions

View File

@ -147,7 +147,7 @@ func main() {
vitualGameRepo := repository.NewVirtualGameRepository(store) vitualGameRepo := repository.NewVirtualGameRepository(store)
recommendationRepo := repository.NewRecommendationRepository(store) recommendationRepo := repository.NewRecommendationRepository(store)
referalSvc := referralservice.New(referalRepo, *walletSvc, *settingSvc, cfg, logger) referalSvc := referralservice.New(referalRepo, *walletSvc, *settingSvc, cfg, logger, domain.MongoDBLogger)
raffleSvc := raffle.NewService(store) raffleSvc := raffle.NewService(store)
virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger)
aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger)

View File

@ -83,7 +83,10 @@ VALUES ('sms_provider', 'afro_message'),
('total_winnings_limit', '1000000'), ('total_winnings_limit', '1000000'),
('amount_for_bet_referral', '1000000'), ('amount_for_bet_referral', '1000000'),
('cashback_amount_cap', '1000'), ('cashback_amount_cap', '1000'),
('default_winning_limit', '5000000') ON CONFLICT (key) DO NOTHING; ('default_winning_limit', '5000000'),
('referral_reward_amount', '10000'),
('cashback_percentage', '0.2'),
('default_max_referrals', '15') ON CONFLICT (key) DO NOTHING;
-- Users -- Users
INSERT INTO users ( INSERT INTO users (
id, id,
@ -222,7 +225,7 @@ VALUES (
), ),
( (
3, 3,
100000000 , 100000000,
TRUE, TRUE,
TRUE, TRUE,
TRUE, TRUE,
@ -338,4 +341,5 @@ SET name = EXCLUDED.name,
profit_percent = EXCLUDED.profit_percent, profit_percent = EXCLUDED.profit_percent,
is_active = EXCLUDED.is_active, is_active = EXCLUDED.is_active,
created_at = EXCLUDED.created_at, created_at = EXCLUDED.created_at,
updated_at = EXCLUDED.updated_at; updated_at = EXCLUDED.updated_at;

View File

@ -0,0 +1,31 @@
-- For each table with an id sequence
SELECT setval(
pg_get_serial_sequence('users', 'id'),
COALESCE(MAX(id), 1)
)
FROM users;
SELECT setval(
pg_get_serial_sequence('wallets', 'id'),
COALESCE(MAX(id), 1)
)
FROM wallets;
SELECT setval(
pg_get_serial_sequence('customer_wallets', 'id'),
COALESCE(MAX(id), 1)
)
FROM customer_wallets;
SELECT setval(
pg_get_serial_sequence('companies', 'id'),
COALESCE(MAX(id), 1)
)
FROM companies;
SELECT setval(
pg_get_serial_sequence('branches', 'id'),
COALESCE(MAX(id), 1)
)
FROM branches;
SELECT setval(
pg_get_serial_sequence('supported_operations', 'id'),
COALESCE(MAX(id), 1)
)
FROM supported_operations;

View File

@ -16,7 +16,6 @@
-- AND cashback_percentage <= 100 -- AND cashback_percentage <= 100
-- ) -- )
-- ); -- );
CREATE TABLE IF NOT EXISTS referral_codes ( CREATE TABLE IF NOT EXISTS referral_codes (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
referral_code VARCHAR(10) NOT NULL UNIQUE, referral_code VARCHAR(10) NOT NULL UNIQUE,
@ -29,12 +28,10 @@ CREATE TABLE IF NOT EXISTS referral_codes (
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT reward_amount_positive CHECK (reward_amount >= 0) CONSTRAINT reward_amount_positive CHECK (reward_amount >= 0)
); );
CREATE INDEX idx_referrals_referrer_id ON referrals (referrer_id); CREATE INDEX idx_referrals_referrer_id ON referral_codes (referrer_id);
CREATE INDEX idx_referrals_status ON referrals (status);
CREATE TABLE IF NOT EXISTS user_referrals ( CREATE TABLE IF NOT EXISTS user_referrals (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
referred_id BIGINT UNIQUE NOT NULL REFERENCES users (id), referred_id BIGINT UNIQUE NOT NULL REFERENCES users (id),
referral_code_id BIGINT NOT NULL REFERENCES referral_codes (id), referral_code_id BIGINT NOT NULL REFERENCES referral_codes (id),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
); );

View File

@ -30,9 +30,9 @@ SET is_active = $2,
WHERE id = $1; WHERE id = $1;
-- name: GetReferralStats :one -- name: GetReferralStats :one
SELECT COUNT(*) AS total_referrals, SELECT COUNT(*) AS total_referrals,
SUM(reward_amount) AS total_reward_earned COALESCE(SUM(reward_amount), 0)::bigint AS total_reward_earned
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referrer_id = $1 WHERE referrer_id = $1
AND company_id = $2; AND company_id = $2;
-- name: GetUserReferral :one -- name: GetUserReferral :one
@ -42,10 +42,10 @@ WHERE referred_id = $1;
-- name: GetUserReferralsByCode :many -- name: GetUserReferralsByCode :many
SELECT user_referrals.* SELECT user_referrals.*
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referral_code = $1; WHERE referral_code = $1;
-- name: GetUserReferralsCount :one -- name: GetUserReferralsCount :one
SELECT COUNT(*) SELECT COUNT(*)
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referrer_id = $1; WHERE referrer_id = $1;

View File

@ -136,9 +136,9 @@ func (q *Queries) GetReferralCodeByUser(ctx context.Context, referrerID int64) (
const GetReferralStats = `-- name: GetReferralStats :one const GetReferralStats = `-- name: GetReferralStats :one
SELECT COUNT(*) AS total_referrals, SELECT COUNT(*) AS total_referrals,
SUM(reward_amount) AS total_reward_earned COALESCE(SUM(reward_amount), 0)::bigint AS total_reward_earned
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referrer_id = $1 WHERE referrer_id = $1
AND company_id = $2 AND company_id = $2
` `
@ -181,7 +181,7 @@ func (q *Queries) GetUserReferral(ctx context.Context, referredID int64) (UserRe
const GetUserReferralsByCode = `-- name: GetUserReferralsByCode :many const GetUserReferralsByCode = `-- name: GetUserReferralsByCode :many
SELECT user_referrals.id, user_referrals.referred_id, user_referrals.referral_code_id, user_referrals.created_at SELECT user_referrals.id, user_referrals.referred_id, user_referrals.referral_code_id, user_referrals.created_at
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referral_code = $1 WHERE referral_code = $1
` `
@ -213,7 +213,7 @@ func (q *Queries) GetUserReferralsByCode(ctx context.Context, referralCode strin
const GetUserReferralsCount = `-- name: GetUserReferralsCount :one const GetUserReferralsCount = `-- name: GetUserReferralsCount :one
SELECT COUNT(*) SELECT COUNT(*)
FROM user_referrals FROM user_referrals
JOIN referral_codes ON referral_codes.id == referral_code_id JOIN referral_codes ON referral_codes.id = referral_code_id
WHERE referrer_id = $1 WHERE referrer_id = $1
` `

View File

@ -17,6 +17,17 @@ type ReferralCode struct {
UpdatedAt time.Time UpdatedAt time.Time
} }
type ReferralCodeRes struct {
ID int64 `json:"id"`
ReferrerID int64 `json:"referrer_id"`
ReferralCode string `json:"referral_code"`
CompanyID int64 `json:"company_id"`
NumberOfReferrals int64 `json:"number_of_referrals"`
RewardAmount float32 `json:"reward_amount"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateReferralCode struct { type CreateReferralCode struct {
ReferrerID int64 ReferrerID int64
ReferralCode string ReferralCode string
@ -48,6 +59,11 @@ type ReferralStats struct {
TotalRewardEarned Currency TotalRewardEarned Currency
} }
type ReferralStatsRes struct {
TotalReferrals int64 `json:"total_referrals"`
TotalRewardEarned float32 `json:"total_reward_earned"`
}
// type ReferralSettings struct { // type ReferralSettings struct {
// ID int64 // ID int64
// ReferralRewardAmount float64 // ReferralRewardAmount float64
@ -78,14 +94,16 @@ func ConvertCreateReferralCode(code CreateReferralCode) dbgen.CreateReferralCode
} }
} }
func ConvertDBReferralCode(code dbgen.ReferralCode) ReferralCode { func ConvertDBReferralCode(code dbgen.ReferralCode) ReferralCode {
return ReferralCode{ return ReferralCode{
ID: code.ID, ID: code.ID,
ReferrerID: code.ReferrerID, ReferrerID: code.ReferrerID,
ReferralCode: code.ReferralCode, ReferralCode: code.ReferralCode,
CompanyID: code.CompanyID, NumberOfReferrals: code.NumberOfReferrals,
CreatedAt: code.CreatedAt.Time, RewardAmount: Currency(code.RewardAmount),
UpdatedAt: code.UpdatedAt.Time, CompanyID: code.CompanyID,
CreatedAt: code.CreatedAt.Time,
UpdatedAt: code.UpdatedAt.Time,
} }
} }
@ -132,7 +150,37 @@ func ConvertUpdateReferralCode(referralCode UpdateReferralCode) dbgen.UpdateRefe
func ConvertDBReferralStats(stats dbgen.GetReferralStatsRow) ReferralStats { func ConvertDBReferralStats(stats dbgen.GetReferralStatsRow) ReferralStats {
return ReferralStats{ return ReferralStats{
TotalReferrals: stats.TotalReferrals, TotalReferrals: stats.TotalReferrals,
TotalRewardEarned: Currency(stats.TotalRewardEarned), TotalRewardEarned: Currency(stats.TotalRewardEarned),
} }
} }
func ConvertReferralCodeRes(referral ReferralCode) ReferralCodeRes {
return ReferralCodeRes{
ID: referral.ID,
ReferrerID: referral.ReferrerID,
ReferralCode: referral.ReferralCode,
CompanyID: referral.CompanyID,
NumberOfReferrals: referral.NumberOfReferrals,
RewardAmount: referral.RewardAmount.Float32(),
CreatedAt: referral.CreatedAt,
UpdatedAt: referral.UpdatedAt,
}
}
func ConvertReferralCodeResList(referrals []ReferralCode) []ReferralCodeRes {
result := make([]ReferralCodeRes, len(referrals))
for i, referral := range referrals {
result[i] = ConvertReferralCodeRes(referral)
}
return result
}
func ConvertReferralStatsRes(stats ReferralStats) ReferralStatsRes {
return ReferralStatsRes{
TotalReferrals: stats.TotalReferrals,
TotalRewardEarned: stats.TotalRewardEarned.Float32(),
}
}

View File

@ -13,23 +13,26 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"go.uber.org/zap"
) )
type Service struct { type Service struct {
repo repository.ReferralRepository repo repository.ReferralRepository
walletSvc wallet.Service walletSvc wallet.Service
settingSvc settings.Service settingSvc settings.Service
config *config.Config config *config.Config
logger *slog.Logger logger *slog.Logger
mongoLogger *zap.Logger
} }
func New(repo repository.ReferralRepository, walletSvc wallet.Service, settingSvc settings.Service, cfg *config.Config, logger *slog.Logger) *Service { func New(repo repository.ReferralRepository, walletSvc wallet.Service, settingSvc settings.Service, cfg *config.Config, logger *slog.Logger, mongoLogger *zap.Logger) *Service {
return &Service{ return &Service{
repo: repo, repo: repo,
walletSvc: walletSvc, walletSvc: walletSvc,
settingSvc: settingSvc, settingSvc: settingSvc,
config: cfg, config: cfg,
logger: logger, logger: logger,
mongoLogger: mongoLogger,
} }
} }
@ -44,38 +47,36 @@ var (
func (s *Service) GenerateReferralCode() (string, error) { func (s *Service) GenerateReferralCode() (string, error) {
b := make([]byte, 8) b := make([]byte, 8)
if _, err := rand.Read(b); err != nil { if _, err := rand.Read(b); err != nil {
s.logger.Error("Failed to generate random bytes for referral code", "error", err) s.mongoLogger.Error("Failed to generate random bytes for referral code", zap.Error(err))
return "", err return "", err
} }
code := base32.StdEncoding.EncodeToString(b)[:10] code := base32.StdEncoding.EncodeToString(b)[:10]
s.logger.Debug("Generated referral code", "code", code) s.mongoLogger.Debug("Generated referral code", zap.String("code", code))
return code, nil return code, nil
} }
func (s *Service) CreateReferralCode(ctx context.Context, userID int64, companyID int64) (domain.ReferralCode, error) { func (s *Service) CreateReferralCode(ctx context.Context, userID int64, companyID int64) (domain.ReferralCode, error) {
settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID) settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID)
if err != nil { if err != nil {
s.logger.Error("Failed to fetch settings", "error", err) s.mongoLogger.Error("Failed to fetch settings", zap.Error(err))
return domain.ReferralCode{}, err return domain.ReferralCode{}, err
} }
s.logger.Info("Creating referral code for user", "userID", userID)
// check if user already has an active referral code // check if user already has an active referral code
referralCodes, err := s.repo.GetReferralCodesByUser(ctx, userID) referralCodes, err := s.repo.GetReferralCodesByUser(ctx, userID)
if err != nil { if err != nil {
s.logger.Error("Failed to check if user alredy has active referral code", "error", err) s.mongoLogger.Error("Failed to check if user already has active referral code", zap.Int64("userID", userID), zap.Error(err))
return domain.ReferralCode{}, err return domain.ReferralCode{}, err
} }
if referralCodes != nil { if len(referralCodes) != 0 {
s.logger.Error("user already has an active referral code", "error", err) s.mongoLogger.Error("user already has an active referral code", zap.Int64("userID", userID), zap.Any("codes", referralCodes), zap.Error(err))
return domain.ReferralCode{}, ErrUserAlreadyHasReferralCode return domain.ReferralCode{}, ErrUserAlreadyHasReferralCode
} }
code, err := s.GenerateReferralCode() code, err := s.GenerateReferralCode()
if err != nil { if err != nil {
s.logger.Error("Failed to generate referral code", "error", err)
return domain.ReferralCode{}, err return domain.ReferralCode{}, err
} }
@ -95,18 +96,20 @@ func (s *Service) CreateReferralCode(ctx context.Context, userID int64, companyI
} }
func (s *Service) ProcessReferral(ctx context.Context, referredID int64, referralCode string, companyID int64) error { func (s *Service) ProcessReferral(ctx context.Context, referredID int64, referralCode string, companyID int64) error {
s.logger.Info("Processing referral", "referralCode", referralCode) paramLogger := s.mongoLogger.With(
zap.Int64("referredID", referredID),
zap.String("referralCode", referralCode),
zap.Int64("companyID", companyID),
)
referral, err := s.repo.GetReferralCode(ctx, referralCode) referral, err := s.repo.GetReferralCode(ctx, referralCode)
if err != nil { if err != nil {
s.logger.Error("Failed to get referral by code", "referralCode", referralCode, "error", err) paramLogger.Error("Failed to get referral by code", zap.Error(err))
return err return err
} }
wallets, err := s.walletSvc.GetCustomerWallet(ctx, referral.ReferrerID) wallets, err := s.walletSvc.GetCustomerWallet(ctx, referral.ReferrerID)
if err != nil { if err != nil {
s.logger.Error("Failed to get referrer wallets", "referrerId", referral.ReferrerID, "error", err) paramLogger.Error("Failed to get referrer wallets", zap.Error(err))
return err return err
} }
@ -115,7 +118,7 @@ func (s *Service) ProcessReferral(ctx context.Context, referredID int64, referra
fmt.Sprintf("Added %v to static wallet due to %v referral code being used", referral.RewardAmount, referral.ReferralCode), fmt.Sprintf("Added %v to static wallet due to %v referral code being used", referral.RewardAmount, referral.ReferralCode),
) )
if err != nil { if err != nil {
s.logger.Error("Failed to add referral reward to static wallet", "walletID", wallets.StaticID, "error", err) paramLogger.Error("Failed to add referral reward to static wallet", zap.Int64("static_wallet_id", wallets.StaticID), zap.Error(err))
return err return err
} }
@ -125,35 +128,56 @@ func (s *Service) ProcessReferral(ctx context.Context, referredID int64, referra
}) })
if err != nil { if err != nil {
s.logger.Error("Failed to add referral reward to static wallet", "referredID", referredID, "error", err) paramLogger.Error("Failed to create user referral", zap.Error(err))
return err return err
} }
s.logger.Info("Referral processed successfully", "referralCode", referralCode, "rewardAmount", referral.RewardAmount) paramLogger.Info("Referral processed successfully", zap.String("rewardAmount", referral.ReferralCode))
return nil return nil
} }
func (s *Service) GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error) { func (s *Service) GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error) {
paramLogger := s.mongoLogger.With(zap.Int64("userID", userID), zap.Int64("companyID", companyID))
stats, err := s.repo.GetReferralStats(ctx, userID, companyID) stats, err := s.repo.GetReferralStats(ctx, userID, companyID)
if err != nil { if err != nil {
s.logger.Error("Failed to get referral stats", "userID", userID, "error", err) paramLogger.Error("Failed to get referral stats", zap.Error(err))
return domain.ReferralStats{}, err return domain.ReferralStats{}, err
} }
s.logger.Info("Referral stats retrieved successfully", "userID", userID, "totalReferrals", stats.TotalReferrals)
return stats, nil return stats, nil
} }
func (s *Service) GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error) { func (s *Service) GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error) {
count, err := s.repo.GetUserReferralCount(ctx, referrerID) count, err := s.repo.GetUserReferralCount(ctx, referrerID)
if err != nil { if err != nil {
s.logger.Error("Failed to get referral count", "userID", referrerID, "error", err) s.mongoLogger.Error("Failed to get referral count", zap.Int64("referrerID", referrerID), zap.Error(err))
return 0, err return 0, err
} }
return count, nil return count, nil
} }
func (s *Service) GetReferralCodesByUser(ctx context.Context, userID int64) ([]domain.ReferralCode, error) {
return s.repo.GetReferralCodesByUser(ctx, userID)
}
func (s *Service) GetReferralCode(ctx context.Context, code string) (domain.ReferralCode, error) {
return s.repo.GetReferralCode(ctx, code)
}
func (s *Service) UpdateReferralCode(ctx context.Context, referral domain.UpdateReferralCode) error {
return s.repo.UpdateReferralCode(ctx, referral)
}
func (s *Service) GetUserReferral(ctx context.Context, referrerID int64) (domain.UserReferral, error) {
return s.repo.GetUserReferral(ctx, referrerID)
}
func (s *Service) GetUserReferralsByCode(ctx context.Context, code string) ([]domain.UserReferral, error) {
return s.repo.GetUserReferralsByCode(ctx, code)
}
// func (s *Service) ProcessDepositBonus(ctx context.Context, userID int64, amount float32, companyID int64) error { // func (s *Service) ProcessDepositBonus(ctx context.Context, userID int64, amount float32, companyID int64) error {
// settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID) // settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID)
// if err != nil { // if err != nil {

View File

@ -26,6 +26,7 @@ func (s *Service) CreateCustomerWallet(ctx context.Context, customerID int64) (d
IsBettable: true, IsBettable: true,
IsTransferable: true, IsTransferable: true,
UserID: customerID, UserID: customerID,
Type: domain.RegularWalletType,
}) })
if err != nil { if err != nil {
@ -37,6 +38,7 @@ func (s *Service) CreateCustomerWallet(ctx context.Context, customerID int64) (d
IsBettable: true, IsBettable: true,
IsTransferable: true, IsTransferable: true,
UserID: customerID, UserID: customerID,
Type: domain.StaticWalletType,
}) })
if err != nil { if err != nil {

View File

@ -86,6 +86,7 @@ func (h *Handler) CreateBranch(c *fiber.Ctx) error {
IsBettable: true, IsBettable: true,
IsTransferable: true, IsTransferable: true,
UserID: req.BranchManagerID, UserID: req.BranchManagerID,
Type: domain.BranchWalletType,
}) })
if err != nil { if err != nil {
@ -254,7 +255,6 @@ func (h *Handler) CreateBranchOperation(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil) return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil)
} }
// GetBranchByID godoc // GetBranchByID godoc
// @Summary Gets branch by id // @Summary Gets branch by id
// @Description Gets a single branch by id // @Description Gets a single branch by id

View File

@ -64,6 +64,7 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
IsBettable: true, IsBettable: true,
IsTransferable: true, IsTransferable: true,
UserID: req.AdminID, UserID: req.AdminID,
Type: domain.CompanyWalletType,
}) })
if err != nil { if err != nil {

View File

@ -26,9 +26,9 @@ func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
) )
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification") return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
} }
referralCode, err := h.referralSvc.CreateReferralCode(c.Context(), userID, companyID.Value); referralCode, err := h.referralSvc.CreateReferralCode(c.Context(), userID, companyID.Value)
if err != nil { if err != nil {
h.mongoLoggerSvc.Error("Failed to create referral", h.mongoLoggerSvc.Error("Failed to create referral",
zap.Int64("userID", userID), zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
@ -39,59 +39,66 @@ func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
} }
fmt.Printf("Successfully created referral!") fmt.Printf("Successfully created referral!")
return response.WriteJSON(c, fiber.StatusOK, "Referral created successfully", referralCode, nil)
res := domain.ConvertReferralCodeRes(referralCode)
return response.WriteJSON(c, fiber.StatusOK, "Referral created successfully", res, nil)
} }
// func (h *Handler) GetReferralCode(c *fiber.Ctx) error { func (h *Handler) GetReferralCode(c *fiber.Ctx) error {
// companyID := c.Locals("company_id").(domain.ValidInt64) companyID := c.Locals("company_id").(domain.ValidInt64)
// if !companyID.Valid { if !companyID.Valid {
// h.BadRequestLogger().Error("invalid company id") h.BadRequestLogger().Error("invalid company id")
// return fiber.NewError(fiber.StatusBadRequest, "invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
// } }
// userID, ok := c.Locals("user_id").(int64) userID, ok := c.Locals("user_id").(int64)
// if !ok || userID == 0 { if !ok || userID == 0 {
// h.mongoLoggerSvc.Error("Invalid user ID in context", h.mongoLoggerSvc.Error("Invalid user ID in context",
// zap.Int64("userID", userID), zap.Int64("userID", userID),
// zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
// ) )
// return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id") return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id")
// } }
// user, err := h.userSvc.GetUserByID(c.Context(), userID) user, err := h.userSvc.GetUserByID(c.Context(), userID)
// if err != nil { if err != nil {
// h.mongoLoggerSvc.Error("Failed to get user", h.mongoLoggerSvc.Error("Failed to get user",
// zap.Int64("userID", userID), zap.Int64("userID", userID),
// zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Error(err), zap.Error(err),
// zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
// ) )
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user") return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
// } }
// if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value { if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value {
// h.mongoLoggerSvc.Warn("User attempt to login to different company", h.mongoLoggerSvc.Warn("User attempt to login to different company",
// zap.Int64("userID", userID), zap.Int64("userID", userID),
// zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Error(err), zap.Error(err),
// zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
// ) )
// return fiber.NewError(fiber.StatusBadRequest, "Failed to retrieve user") return fiber.NewError(fiber.StatusBadRequest, "Failed to retrieve user")
// } }
// // referrals, err := h.referralSvc.GetReferralStats(c.Context(), user.ID) referrals, err := h.referralSvc.GetReferralCodesByUser(c.Context(), user.ID)
// if err != nil { if err != nil {
// h.mongoLoggerSvc.Error("Failed to get user referrals", h.mongoLoggerSvc.Error("Failed to get user referrals",
// zap.Int64("userID", userID), zap.Int64("userID", userID),
// zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Error(err), zap.Error(err),
// zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
// ) )
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user referral codes") return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user referral codes")
// } }
// } result := domain.ConvertReferralCodeResList(referrals)
return response.WriteJSON(c, fiber.StatusOK, "Referral Code Fetched Successfully", result, nil)
}
// GetReferralStats godoc // GetReferralStats godoc
// @Summary Get referral statistics // @Summary Get referral statistics
@ -152,107 +159,109 @@ func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve referral stats") return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve referral stats")
} }
return response.WriteJSON(c, fiber.StatusOK, "Referral stats retrieved successfully", stats, nil) res := domain.ConvertReferralStatsRes(stats)
return response.WriteJSON(c, fiber.StatusOK, "Referral stats retrieved successfully", res, nil)
} }
// UpdateReferralSettings godoc // // UpdateReferralSettings godoc
// @Summary Update referral settings // // @Summary Update referral settings
// @Description Updates referral settings (admin only) // // @Description Updates referral settings (admin only)
// @Tags referral // // @Tags referral
// @Accept json // // @Accept json
// @Produce json // // @Produce json
// @Param settings body domain.ReferralSettings true "Referral settings" // // @Param settings body domain.ReferralSettings true "Referral settings"
// @Success 200 {object} response.APIResponse // // @Success 200 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse // // @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse // // @Failure 403 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // // @Failure 500 {object} response.APIResponse
// @Security Bearer // // @Security Bearer
// @Router /api/v1/referral/settings [put] // // @Router /api/v1/referral/settings [put]
func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error { // func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error {
userID, ok := c.Locals("user_id").(int64) // userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 { // if !ok || userID == 0 {
h.logger.Error("Invalid user ID in context") // h.logger.Error("Invalid user ID in context")
h.mongoLoggerSvc.Error("Failed to delete user", // h.mongoLoggerSvc.Error("Failed to delete user",
zap.Int64("userID", userID), // zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusInternalServerError), // zap.Int("status_code", fiber.StatusInternalServerError),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id") // return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id")
} // }
user, err := h.userSvc.GetUserByID(c.Context(), userID) // user, err := h.userSvc.GetUserByID(c.Context(), userID)
if err != nil { // if err != nil {
h.mongoLoggerSvc.Error("Failed to get user", // h.mongoLoggerSvc.Error("Failed to get user",
zap.Int64("userID", userID), // zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusInternalServerError), // zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusInternalServerError, err.Error()) // return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} // }
if user.Role != domain.RoleAdmin { // if user.Role != domain.RoleAdmin {
h.mongoLoggerSvc.Error("Access Forbidden", // h.mongoLoggerSvc.Error("Access Forbidden",
zap.Int64("userID", userID), // zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusForbidden), // zap.Int("status_code", fiber.StatusForbidden),
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusForbidden, "Admin access required") // return fiber.NewError(fiber.StatusForbidden, "Admin access required")
} // }
var settings domain.ReferralSettings // var settings domain.ReferralSettings
if err := c.BodyParser(&settings); err != nil { // if err := c.BodyParser(&settings); err != nil {
h.mongoLoggerSvc.Info("Failed to parse settings", // h.mongoLoggerSvc.Info("Failed to parse settings",
zap.Int64("userID", userID), // zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusBadRequest), // zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") // return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} // }
settings.UpdatedBy = user.PhoneNumber // settings.UpdatedBy = user.PhoneNumber
if err := h.referralSvc.UpdateReferralSettings(c.Context(), &settings); err != nil { // if err := h.referralSvc.UpdateReferralSettings(c.Context(), &settings); err != nil {
h.mongoLoggerSvc.Error("Failed to update referral settings", // h.mongoLoggerSvc.Error("Failed to update referral settings",
zap.Int64("userID", userID), // zap.Int64("userID", userID),
zap.Int("status_code", fiber.StatusInternalServerError), // zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusInternalServerError, err.Error()) // return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} // }
return response.WriteJSON(c, fiber.StatusOK, "Referral settings updated successfully", nil, nil) // return response.WriteJSON(c, fiber.StatusOK, "Referral settings updated successfully", nil, nil)
} // }
// GetReferralSettings godoc // // GetReferralSettings godoc
// @Summary Get referral settings // // @Summary Get referral settings
// @Description Retrieves current referral settings (admin only) // // @Description Retrieves current referral settings (admin only)
// @Tags referral // // @Tags referral
// @Accept json // // @Accept json
// @Produce json // // @Produce json
// @Success 200 {object} domain.ReferralSettings // // @Success 200 {object} domain.ReferralSettings
// @Failure 401 {object} response.APIResponse // // @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse // // @Failure 403 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // // @Failure 500 {object} response.APIResponse
// @Security Bearer // // @Security Bearer
// @Router /api/v1/referral/settings [get] // // @Router /api/v1/referral/settings [get]
func (h *Handler) GetReferralSettings(c *fiber.Ctx) error { // func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
// userID, ok := c.Locals("user_id").(int64) // // userID, ok := c.Locals("user_id").(int64)
// if !ok || userID == 0 { // // if !ok || userID == 0 {
// h.logger.Error("Invalid user ID in context") // // h.logger.Error("Invalid user ID in context")
// return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification") // // return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
// } // // }
settings, err := h.referralSvc.GetReferralSettings(c.Context()) // settings, err := h.referralSvc.GetReferralSettings(c.Context())
if err != nil { // if err != nil {
h.mongoLoggerSvc.Error("Failed to get referral settings", // h.mongoLoggerSvc.Error("Failed to get referral settings",
zap.Int("status_code", fiber.StatusInternalServerError), // zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
return fiber.NewError(fiber.StatusInternalServerError, err.Error()) // return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} // }
return response.WriteJSON(c, fiber.StatusOK, "Referral settings retrieved successfully", settings, nil) // return response.WriteJSON(c, fiber.StatusOK, "Referral settings retrieved successfully", settings, nil)
} // }

View File

@ -248,7 +248,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
} }
if req.ReferralCode != "" { if req.ReferralCode != "" {
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferralCode, companyID.Value) err = h.referralSvc.ProcessReferral(c.Context(), newUser.ID, req.ReferralCode, companyID.Value)
if err != nil { if err != nil {
h.mongoLoggerSvc.Error("Failed to process referral during registration", h.mongoLoggerSvc.Error("Failed to process referral during registration",
zap.String("phone", req.PhoneNumber), zap.String("phone", req.PhoneNumber),

View File

@ -189,10 +189,12 @@ func (a *App) initAppRoutes() {
// Referral Routes // Referral Routes
tenant.Post("/referral/create", a.authMiddleware, h.CreateReferralCode) tenant.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
tenant.Get("/referral/code", a.authMiddleware, h.GetReferralCode)
tenant.Get("/referral/stats", a.authMiddleware, h.GetReferralStats) tenant.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
groupV1.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings) // groupV1.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings) // groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
// groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
// Raffle Routes // Raffle Routes
a.fiber.Post("/raffle/create", a.authMiddleware, h.CreateRaffle) a.fiber.Post("/raffle/create", a.authMiddleware, h.CreateRaffle)