Yimaru-BackEnd/internal/services/bonus/service.go

171 lines
4.6 KiB
Go

package bonus
import (
"context"
"errors"
"fmt"
"math"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
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 ports.BonusStore
walletSvc *wallet.Service
settingSvc *settings.Service
notificationSvc *notificationservice.Service
mongoLogger *zap.Logger
}
func NewService(
bonusStore ports.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)
}