261 lines
8.9 KiB
Go
261 lines
8.9 KiB
Go
package referralservice
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/config"
|
|
"Yimaru-Backend/internal/domain"
|
|
"Yimaru-Backend/internal/ports"
|
|
"Yimaru-Backend/internal/services/settings"
|
|
"context"
|
|
"crypto/rand"
|
|
"encoding/base32"
|
|
"errors"
|
|
"log/slog"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type Service struct {
|
|
repo ports.ReferralStore
|
|
settingSvc settings.Service
|
|
config *config.Config
|
|
logger *slog.Logger
|
|
mongoLogger *zap.Logger
|
|
}
|
|
|
|
func New(
|
|
repo ports.ReferralStore,
|
|
settingSvc settings.Service,
|
|
cfg *config.Config,
|
|
logger *slog.Logger,
|
|
mongoLogger *zap.Logger,
|
|
) *Service {
|
|
return &Service{
|
|
repo: repo,
|
|
settingSvc: settingSvc,
|
|
config: cfg,
|
|
logger: logger,
|
|
mongoLogger: mongoLogger,
|
|
}
|
|
}
|
|
|
|
var (
|
|
ErrInvalidReferral = errors.New("invalid or expired referral")
|
|
ErrUserNotFound = errors.New("user not found")
|
|
ErrNoReferralFound = errors.New("no referral found for this user")
|
|
ErrUserAlreadyHasReferralCode = errors.New("user already has an active referral code")
|
|
ErrMaxReferralCountLimitReached = errors.New("referral count limit has been reached")
|
|
)
|
|
|
|
func (s *Service) GenerateReferralCode() (string, error) {
|
|
b := make([]byte, 8)
|
|
if _, err := rand.Read(b); err != nil {
|
|
s.mongoLogger.Error("Failed to generate random bytes for referral code", zap.Error(err))
|
|
return "", err
|
|
}
|
|
code := base32.StdEncoding.EncodeToString(b)[:10]
|
|
s.mongoLogger.Debug("Generated referral code", zap.String("code", code))
|
|
return code, nil
|
|
}
|
|
|
|
func (s *Service) CreateReferralCode(ctx context.Context, userID int64, companyID int64) (domain.ReferralCode, error) {
|
|
|
|
settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID)
|
|
|
|
if err != nil {
|
|
s.mongoLogger.Error("Failed to fetch settings", zap.Error(err))
|
|
return domain.ReferralCode{}, err
|
|
}
|
|
|
|
// check if user already has an active referral code
|
|
referralCodes, err := s.repo.GetReferralCodesByUser(ctx, userID)
|
|
if err != nil {
|
|
s.mongoLogger.Error("Failed to check if user already has active referral code", zap.Int64("userID", userID), zap.Error(err))
|
|
return domain.ReferralCode{}, err
|
|
}
|
|
if len(referralCodes) != 0 {
|
|
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
|
|
}
|
|
|
|
code, err := s.GenerateReferralCode()
|
|
if err != nil {
|
|
return domain.ReferralCode{}, err
|
|
}
|
|
|
|
newReferralCode, err := s.repo.CreateReferralCode(ctx, domain.CreateReferralCode{
|
|
ReferrerID: userID,
|
|
ReferralCode: code,
|
|
CompanyID: companyID,
|
|
NumberOfReferrals: settingsList.DefaultMaxReferrals,
|
|
RewardAmount: settingsList.ReferralRewardAmount,
|
|
})
|
|
|
|
if err != nil {
|
|
return domain.ReferralCode{}, err
|
|
}
|
|
|
|
return newReferralCode, nil
|
|
}
|
|
|
|
func (s *Service) ProcessReferral(ctx context.Context, referredID int64, referralCode string, companyID int64) error {
|
|
paramLogger := s.mongoLogger.With(
|
|
zap.Int64("referredID", referredID),
|
|
zap.String("referralCode", referralCode),
|
|
zap.Int64("companyID", companyID),
|
|
)
|
|
referral, err := s.repo.GetReferralCode(ctx, referralCode)
|
|
if err != nil {
|
|
paramLogger.Error("Failed to get referral by code", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// wallets, err := s.walletSvc.GetCustomerWallet(ctx, referral.ReferrerID)
|
|
// if err != nil {
|
|
// paramLogger.Error("Failed to get referrer wallets", zap.Error(err))
|
|
// return err
|
|
// }
|
|
|
|
// _, err = s.walletSvc.AddToWallet(ctx, wallets.StaticID,
|
|
// referral.RewardAmount, domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
|
// fmt.Sprintf("Added %v to static wallet due to %v referral code being used", referral.RewardAmount, referral.ReferralCode),
|
|
// )
|
|
// if err != nil {
|
|
// paramLogger.Error("Failed to add referral reward to static wallet", zap.Int64("static_wallet_id", wallets.StaticID), zap.Error(err))
|
|
// return err
|
|
// }
|
|
|
|
_, err = s.repo.CreateUserReferral(ctx, domain.CreateUserReferrals{
|
|
ReferredID: referredID,
|
|
ReferralCodeID: referral.ID,
|
|
})
|
|
|
|
if err != nil {
|
|
paramLogger.Error("Failed to create user referral", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
paramLogger.Info("Referral processed successfully", zap.String("rewardAmount", referral.ReferralCode))
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
if err != nil {
|
|
paramLogger.Error("Failed to get referral stats", zap.Error(err))
|
|
return domain.ReferralStats{}, err
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
func (s *Service) GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error) {
|
|
count, err := s.repo.GetUserReferralCount(ctx, referrerID)
|
|
if err != nil {
|
|
s.mongoLogger.Error("Failed to get referral count", zap.Int64("referrerID", referrerID), zap.Error(err))
|
|
return 0, err
|
|
}
|
|
|
|
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 {
|
|
// settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to fetch settings", "error", err)
|
|
// return err
|
|
// }
|
|
|
|
// s.logger.Info("Processing deposit bonus", "amount", amount)
|
|
|
|
// customerWallet, err := s.walletSvc.GetCustomerWallet(ctx, userID)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to get wallets for user", "userID", userID, "error", err)
|
|
// return err
|
|
// }
|
|
|
|
// bonus := amount * settingsList.CashbackPercentage
|
|
|
|
// _, err = s.walletSvc.AddToWallet(ctx, customerWallet.StaticID, domain.ToCurrency(bonus), domain.ValidInt64{},
|
|
// domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
|
// fmt.Sprintf("Added to bonus wallet because of Deposit Cashback Bonus %d", bonus))
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to add deposit bonus to wallet", "staticWalletID", customerWallet.StaticID, "userID", userID, "bonus", bonus, "error", err)
|
|
// return err
|
|
// }
|
|
|
|
// s.logger.Info("Deposit bonus processed successfully", "bonus", bonus)
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *Service) ProcessBetReferral(ctx context.Context, userId int64, betAmount float64) error {
|
|
// s.logger.Info("Processing bet referral", "userID", userId, "betAmount", betAmount)
|
|
|
|
// settings, err := s.repo.GetSettings(ctx)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to get referral settings", "error", err)
|
|
// return err
|
|
// }
|
|
|
|
// referral, err := s.repo.GetReferralByReferredID(ctx, userId)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to get referral by referred ID", "userId", userId, "error", err)
|
|
// return err
|
|
// }
|
|
// if referral == nil || referral.Status != domain.ReferralCompleted {
|
|
// s.logger.Warn("No valid referral found", "userId", userId, "status", referral.Status)
|
|
// return ErrNoReferralFound
|
|
// }
|
|
|
|
// wallets, err := s.walletSvc.GetWalletsByUser(ctx, referral.ReferrerID)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to get wallets for referrer", "referrerID", referral.ReferrerID, "error", err)
|
|
// return err
|
|
// }
|
|
// if len(wallets) == 0 {
|
|
// s.logger.Error("Referrer has no wallet", "referrerID", referral.ReferrerID)
|
|
// return errors.New("referrer has no wallet")
|
|
// }
|
|
|
|
// bonusPercentage := settings.BetReferralBonusPercentage
|
|
// if bonusPercentage == 0 {
|
|
// bonusPercentage = 5.0
|
|
// s.logger.Debug("Using default bet referral bonus percentage", "percentage", bonusPercentage)
|
|
// }
|
|
// bonus := betAmount * (bonusPercentage / 100)
|
|
|
|
// walletID := wallets[0].ID
|
|
// currentBalance := float64(wallets[0].Balance)
|
|
// _, err = s.walletSvc.AddToWallet(ctx, walletID, domain.ToCurrency(float32(currentBalance+bonus)), domain.ValidInt64{},
|
|
// domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
|
// fmt.Sprintf("Added %v to static wallet because of bet referral", referral.RewardAmount))
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to add bet referral bonus to wallet", "walletID", walletID, "referrerID", referral.ReferrerID, "bonus", bonus, "error", err)
|
|
// return err
|
|
// }
|
|
|
|
// s.logger.Info("Bet referral processed successfully", "referrer ID", referral.ReferrerID, "referrerID", referral.ReferrerID, "bonus", bonus)
|
|
// return nil
|
|
// }
|