Merge branch 'referral-promotion'

This commit is contained in:
Asher Samuel 2025-06-29 15:20:24 +03:00
commit e47f0c9d5d
13 changed files with 254 additions and 5 deletions

View File

@ -30,6 +30,7 @@ import (
// "github.com/SamuelTariku/FortuneBet-Backend/internal/router"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bonus"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
@ -124,6 +125,7 @@ func main() {
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, logger, domain.MongoDBLogger)
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
bonusSvc := bonus.NewService(store)
referalRepo := repository.NewReferralRepository(store)
vitualGameRepo := repository.NewVirtualGameRepository(store)
recommendationRepo := repository.NewRecommendationRepository(store)
@ -255,6 +257,7 @@ func main() {
eventSvc,
leagueSvc,
referalSvc,
bonusSvc,
virtualGameSvc,
aleaService,
// veliService,

View File

@ -287,6 +287,10 @@ CREATE TABLE IF NOT EXISTS settings (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE bonus (
id BIGSERIAL PRIMARY KEY,
multiplier REAL NOT NULL
);
-- Views
CREATE VIEW companies_details AS
SELECT companies.*,

12
db/query/bonus.sql Normal file
View File

@ -0,0 +1,12 @@
-- name: CreateBonusMultiplier :exec
INSERT INTO bonus (multiplier)
VALUES ($1);
-- name: GetBonusMultiplier :many
SELECT id, multiplier
FROM bonus;
-- name: UpdateBonusMultiplier :exec
UPDATE bonus
SET multiplier = $1
WHERE id = $2;

61
gen/db/bonus.sql.go Normal file
View File

@ -0,0 +1,61 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: bonus.sql
package dbgen
import (
"context"
)
const CreateBonusMultiplier = `-- name: CreateBonusMultiplier :exec
INSERT INTO bonus (multiplier)
VALUES ($1)
`
func (q *Queries) CreateBonusMultiplier(ctx context.Context, multiplier float32) error {
_, err := q.db.Exec(ctx, CreateBonusMultiplier, multiplier)
return err
}
const GetBonusMultiplier = `-- name: GetBonusMultiplier :many
SELECT id, multiplier
FROM bonus
`
func (q *Queries) GetBonusMultiplier(ctx context.Context) ([]Bonu, error) {
rows, err := q.db.Query(ctx, GetBonusMultiplier)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Bonu
for rows.Next() {
var i Bonu
if err := rows.Scan(&i.ID, &i.Multiplier); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const UpdateBonusMultiplier = `-- name: UpdateBonusMultiplier :exec
UPDATE bonus
SET multiplier = $1
WHERE id = $2
`
type UpdateBonusMultiplierParams struct {
Multiplier float32 `json:"multiplier"`
ID int64 `json:"id"`
}
func (q *Queries) UpdateBonusMultiplier(ctx context.Context, arg UpdateBonusMultiplierParams) error {
_, err := q.db.Exec(ctx, UpdateBonusMultiplier, arg.Multiplier, arg.ID)
return err
}

View File

@ -128,6 +128,11 @@ type BetWithOutcome struct {
Outcomes []BetOutcome `json:"outcomes"`
}
type Bonu struct {
ID int64 `json:"id"`
Multiplier float32 `json:"multiplier"`
}
type Branch struct {
ID int64 `json:"id"`
Name string `json:"name"`

View File

@ -0,0 +1,22 @@
package repository
import (
"context"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
func (s *Store) CreateBonusMultiplier(ctx context.Context, multiplier float32) error {
return s.queries.CreateBonusMultiplier(ctx, multiplier)
}
func (s *Store) GetBonusMultiplier(ctx context.Context) ([]dbgen.Bonu, error) {
return s.queries.GetBonusMultiplier(ctx)
}
func (s *Store) UpdateBonusMultiplier(ctx context.Context, id int64, mulitplier float32) error {
return s.queries.UpdateBonusMultiplier(ctx, dbgen.UpdateBonusMultiplierParams{
ID: id,
Multiplier: mulitplier,
})
}

View File

@ -0,0 +1,13 @@
package bonus
import (
"context"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type BonusStore interface {
CreateBonusMultiplier(ctx context.Context, multiplier float32) error
GetBonusMultiplier(ctx context.Context) ([]dbgen.Bonu, error)
UpdateBonusMultiplier(ctx context.Context, id int64, mulitplier float32) error
}

View File

@ -0,0 +1,29 @@
package bonus
import (
"context"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type Service struct {
bonusStore BonusStore
}
func NewService(bonusStore BonusStore) *Service {
return &Service{
bonusStore: bonusStore,
}
}
func (s *Service) CreateBonusMultiplier(ctx context.Context, multiplier float32) error {
return s.bonusStore.CreateBonusMultiplier(ctx, multiplier)
}
func (s *Service) GetBonusMultiplier(ctx context.Context) ([]dbgen.Bonu, error) {
return s.bonusStore.GetBonusMultiplier(ctx)
}
func (s *Service) UpdateBonusMultiplier(ctx context.Context, id int64, mulitplier float32) error {
return s.bonusStore.UpdateBonusMultiplier(ctx, id, mulitplier)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bonus"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
@ -50,6 +51,7 @@ type App struct {
logger *slog.Logger
NotidicationStore *notificationservice.Service
referralSvc referralservice.ReferralStore
bonusSvc *bonus.Service
port int
settingSvc *settings.Service
authSvc *authentication.Service
@ -96,6 +98,7 @@ func NewApp(
eventSvc event.Service,
leagueSvc league.Service,
referralSvc referralservice.ReferralStore,
bonusSvc *bonus.Service,
virtualGameSvc virtualgameservice.VirtualGameService,
aleaVirtualGameService alea.AleaVirtualGameService,
// veliVirtualGameService veli.VeliVirtualGameService,
@ -141,6 +144,7 @@ func NewApp(
companySvc: companySvc,
NotidicationStore: notidicationStore,
referralSvc: referralSvc,
bonusSvc: bonusSvc,
Logger: logger,
prematchSvc: prematchSvc,
eventSvc: eventSvc,

View File

@ -0,0 +1,65 @@
package handlers
import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
)
func (h *Handler) CreateBonusMultiplier(c *fiber.Ctx) error {
var req struct {
Multiplier float32 `json:"multiplier"`
}
if err := c.BodyParser(&req); err != nil {
h.logger.Error("failed to parse bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
// currently only one multiplier is allowed
// we can add an active bool in the db and have mulitple bonus if needed
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
if err != nil {
h.logger.Error("failed to get bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
if len(multipliers) > 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
if err := h.bonusSvc.CreateBonusMultiplier(c.Context(), req.Multiplier); err != nil {
h.logger.Error("failed to create bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "failed to create bonus mulitplier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Create bonus mulitplier successfully", nil, nil)
}
func (h *Handler) GetBonusMultiplier(c *fiber.Ctx) error {
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
if err != nil {
h.logger.Error("failed to get bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Fetched bonus mulitplier successfully", multipliers, nil)
}
func (h *Handler) UpdateBonusMultiplier(c *fiber.Ctx) error {
var req struct {
ID int64 `json:"id"`
Multiplier float32 `json:"multiplier"`
}
if err := c.BodyParser(&req); err != nil {
h.logger.Error("failed to parse bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
if err := h.bonusSvc.UpdateBonusMultiplier(c.Context(), req.ID, req.Multiplier); err != nil {
h.logger.Error("failed to update bonus multiplier", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "failed to update bonus mulitplier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Updated bonus mulitplier successfully", nil, nil)
}

View File

@ -51,6 +51,27 @@ func (h *Handler) InitiateDeposit(c *fiber.Ctx) error {
})
}
// get static wallet of user
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), userID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
Error: err.Error(),
Message: "Failed to initiate Chapa deposit",
})
}
var multiplier float32 = 1
bonusMultiplier, err := h.bonusSvc.GetBonusMultiplier(c.Context())
if err == nil {
multiplier = bonusMultiplier[0].Multiplier
}
_, err = h.walletSvc.AddToWallet(c.Context(), wallet.StaticID, domain.ToCurrency(float32(amount)*multiplier), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
if err != nil {
h.logger.Error("Failed to add bonus to static wallet", "walletID", wallet.StaticID, "user id", userID, "error", err)
return err
}
return c.Status(fiber.StatusOK).JSON(domain.Response{
Message: "Chapa deposit process initiated successfully",
Data: checkoutURL,

View File

@ -6,6 +6,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bonus"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
@ -42,6 +43,7 @@ type Handler struct {
notificationSvc *notificationservice.Service
userSvc *user.Service
referralSvc referralservice.ReferralStore
bonusSvc *bonus.Service
reportSvc report.ReportStore
chapaSvc *chapa.Service
walletSvc *wallet.Service
@ -77,6 +79,7 @@ func New(
chapaSvc *chapa.Service,
walletSvc *wallet.Service,
referralSvc referralservice.ReferralStore,
bonusSvc *bonus.Service,
virtualGameSvc virtualgameservice.VirtualGameService,
aleaVirtualGameSvc alea.AleaVirtualGameService,
veliVirtualGameSvc veli.VeliVirtualGameService,
@ -107,6 +110,7 @@ func New(
chapaSvc: chapaSvc,
walletSvc: walletSvc,
referralSvc: referralSvc,
bonusSvc: bonusSvc,
validator: validator,
userSvc: userSvc,
transactionSvc: transactionSvc,

View File

@ -31,6 +31,7 @@ func (a *App) initAppRoutes() {
a.chapaSvc,
a.walletSvc,
a.referralSvc,
a.bonusSvc,
a.virtualGameSvc,
a.aleaVirtualGameService,
a.veliVirtualGameService,
@ -111,6 +112,11 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/referral/settings", h.GetReferralSettings)
a.fiber.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
// Bonus Routes
a.fiber.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier)
a.fiber.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
a.fiber.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
a.fiber.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
a.fiber.Get("/cashiers/:id", a.authMiddleware, h.GetCashierByID)
a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)