package bonus import ( "context" "errors" "math" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "go.uber.org/zap" ) type Service struct { bonusStore BonusStore walletSvc *wallet.Service settingSvc *settings.Service mongoLogger *zap.Logger } func NewService(bonusStore BonusStore, walletSvc *wallet.Service, settingSvc *settings.Service, mongoLogger *zap.Logger) *Service { return &Service{ bonusStore: bonusStore, walletSvc: walletSvc, settingSvc: settingSvc, mongoLogger: mongoLogger, } } var ( ErrWelcomeBonusNotActive = errors.New("welcome bonus is not active") ErrWelcomeBonusCountReached = errors.New("welcome bonus max deposit count reached") ) func (s *Service) ProcessWelcomeBonus(ctx context.Context, amount domain.Currency, companyID int64, userID int64) error { settingsList, err := s.settingSvc.GetOverrideSettingsList(ctx, companyID) if err != nil { s.mongoLogger.Error("Failed to get settings", zap.Int64("companyID", companyID), zap.Error(err)) return err } if !settingsList.WelcomeBonusActive { return ErrWelcomeBonusNotActive } wallet, err := s.walletSvc.GetCustomerWallet(ctx, userID) if err != nil { return err } stats, err := s.walletSvc.GetTransferStats(ctx, wallet.ID) if err != nil { return err } if stats.TotalDeposits > settingsList.WelcomeBonusCount { return ErrWelcomeBonusCountReached } newBalance := math.Min(float64(amount)*float64(settingsList.WelcomeBonusMultiplier), float64(settingsList.WelcomeBonusCap)) _, err = s.CreateUserBonus(ctx, domain.CreateBonus{ Name: "Welcome Bonus", Description: "Awarded when the user logged in for the first time", UserID: userID, BonusCode: helpers.GenerateFastCode(), RewardAmount: domain.Currency(newBalance), ExpiresAt: time.Now().Add(time.Duration(settingsList.WelcomeBonusExpire) * 24 * time.Hour), }) if err != nil { return err } // TODO: Add a claim function that adds to the static wallet when the user inputs his bonus code // _, err = s.walletSvc.AddToWallet(ctx, wallet.StaticID, domain.ToCurrency(float32(newBalance)), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, // fmt.Sprintf("Added %v to static wallet because of deposit bonus using multiplier %v", newBalance, settingsList.WelcomeBonusMultiplier), // ) // if err != nil { // return err // } return nil } func (s *Service) CreateUserBonus(ctx context.Context, bonus domain.CreateBonus) (domain.UserBonus, error) { return s.bonusStore.CreateUserBonus(ctx, bonus) } func (s *Service) GetAllUserBonuses(ctx context.Context) ([]domain.UserBonus, error) { return s.bonusStore.GetAllUserBonuses(ctx) } func (s *Service) GetBonusesByUserID(ctx context.Context, userID int64) ([]domain.UserBonus, error) { return s.bonusStore.GetBonusesByUserID(ctx, userID) } func (s *Service) GetBonusByID(ctx context.Context, bonusID int64) (domain.UserBonus, error) { return s.bonusStore.GetBonusByID(ctx, bonusID) } func (s *Service) GetBonusStats(ctx context.Context, filter domain.BonusFilter) (domain.BonusStats, error) { return s.bonusStore.GetBonusStats(ctx, filter) } func (s *Service) UpdateUserBonus(ctx context.Context, bonusID int64, IsClaimed bool) error { return s.bonusStore.UpdateUserBonus(ctx, bonusID, IsClaimed) } func (s *Service) DeleteUserBonus(ctx context.Context, bonusID int64) error { return s.bonusStore.DeleteUserBonus(ctx, bonusID) }