164 lines
4.5 KiB
Go
164 lines
4.5 KiB
Go
package bonus
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
|
"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
|
|
notificationSvc *notificationservice.Service
|
|
mongoLogger *zap.Logger
|
|
}
|
|
|
|
func NewService(bonusStore BonusStore, walletSvc *wallet.Service, settingSvc *settings.Service, notificationSvc *notificationservice.Service, mongoLogger *zap.Logger) *Service {
|
|
return &Service{
|
|
bonusStore: bonusStore,
|
|
walletSvc: walletSvc,
|
|
settingSvc: settingSvc,
|
|
notificationSvc: notificationSvc,
|
|
mongoLogger: mongoLogger,
|
|
}
|
|
}
|
|
|
|
var (
|
|
ErrWelcomeBonusNotActive = errors.New("welcome bonus is not active")
|
|
ErrWelcomeBonusCountReached = errors.New("welcome bonus max deposit count reached")
|
|
)
|
|
|
|
func (s *Service) CreateWelcomeBonus(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))
|
|
|
|
bonus, err := s.CreateUserBonus(ctx, domain.CreateBonus{
|
|
Name: "Welcome Bonus",
|
|
Description: fmt.Sprintf("Awarded for deposit number (%v / %v)", stats.TotalDeposits, settingsList.WelcomeBonusCount),
|
|
UserID: userID,
|
|
Type: domain.WelcomeBonus,
|
|
RewardAmount: domain.Currency(newBalance),
|
|
ExpiresAt: time.Now().Add(time.Duration(settingsList.WelcomeBonusExpire) * 24 * time.Hour),
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.SendBonusNotification(ctx, SendBonusNotificationParam{
|
|
BonusID: bonus.ID,
|
|
UserID: userID,
|
|
Type: domain.DepositBonus,
|
|
Amount: domain.Currency(newBalance),
|
|
SendEmail: true,
|
|
SendSMS: false,
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
ErrBonusIsAlreadyClaimed = errors.New("bonus is already claimed")
|
|
ErrBonusUserIDNotMatch = errors.New("bonus user id is not a match")
|
|
)
|
|
|
|
func (s *Service) ProcessBonusClaim(ctx context.Context, bonusID, userID int64) error {
|
|
|
|
bonus, err := s.GetBonusByID(ctx, bonusID)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if bonus.UserID != userID {
|
|
|
|
}
|
|
if bonus.IsClaimed {
|
|
return ErrBonusIsAlreadyClaimed
|
|
}
|
|
|
|
wallet, err := s.walletSvc.GetCustomerWallet(ctx, bonus.UserID)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = s.walletSvc.AddToWallet(
|
|
ctx, wallet.StaticID, bonus.RewardAmount,
|
|
domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
|
fmt.Sprintf("Added %v to bonus wallet due to %v", bonus.RewardAmount, bonus.Type),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.UpdateUserBonus(ctx, bonusID, true); 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, filter domain.BonusFilter) ([]domain.UserBonus, error) {
|
|
return s.bonusStore.GetAllUserBonuses(ctx, filter)
|
|
}
|
|
|
|
func (s *Service) GetBonusCount(ctx context.Context, filter domain.BonusFilter) (int64, error) {
|
|
return s.bonusStore.GetBonusCount(ctx, filter)
|
|
}
|
|
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)
|
|
}
|