fix: fixed company override settings and raffle routes

This commit is contained in:
Samuel Tariku 2025-09-18 22:34:56 +03:00
parent 65df6b9ff1
commit 723ca34660
10 changed files with 145 additions and 83 deletions

View File

@ -351,3 +351,29 @@ SET name = EXCLUDED.name,
is_active = EXCLUDED.is_active,
created_at = EXCLUDED.created_at,
updated_at = EXCLUDED.updated_at;
-- Bonus
INSERT INTO user_bonuses (
id,
name,
description,
type,
user_id,
reward_amount,
expires_at
)
VALUES (
1,
'Welcome Bonus',
'Awarded for deposit number (1 / 3)',
'welcome_bonus',
1,
1000,
now() + INTERVAL '1 day'
) ON CONFLICT (id) DO
UPDATE
SET name = EXCLUDED.name,
description = EXCLUDED.description,
type = EXCLUDED.type,
user_id = EXCLUDED.user_id,
reward_amount = EXCLUDED.reward_amount,
expires_at = EXCLUDED.expires_at;

View File

@ -454,7 +454,7 @@ CREATE TABLE IF NOT EXISTS company_settings (
PRIMARY KEY (company_id, key)
);
CREATE TABLE user_bonuses (
id BIGINT NOT NULL,
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
type TEXT NOT NULL,
@ -462,7 +462,7 @@ CREATE TABLE user_bonuses (
reward_amount BIGINT NOT NULL,
is_claimed BOOLEAN NOT NULL DEFAULT false,
expires_at TIMESTAMP NOT NULL,
claimed_at TIMESTAMP NOT NULL,
claimed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -27,7 +27,9 @@ SELECT *
FROM company_settings
WHERE key = $1;
-- name: GetOverrideSettings :many
SELECT gs.*,
SELECT gs.key,
gs.created_at,
gs.updated_at,
COALESCE(cs.value, gs.value) AS value
FROM global_settings gs
LEFT JOIN company_settings cs ON cs.key = gs.key

View File

@ -181,7 +181,9 @@ func (q *Queries) GetGlobalSettings(ctx context.Context) ([]GlobalSetting, error
}
const GetOverrideSettings = `-- name: GetOverrideSettings :many
SELECT gs.key, gs.value, gs.created_at, gs.updated_at,
SELECT gs.key,
gs.created_at,
gs.updated_at,
COALESCE(cs.value, gs.value) AS value
FROM global_settings gs
LEFT JOIN company_settings cs ON cs.key = gs.key
@ -190,10 +192,9 @@ FROM global_settings gs
type GetOverrideSettingsRow struct {
Key string `json:"key"`
Value string `json:"value"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
Value_2 string `json:"value_2"`
Value string `json:"value"`
}
func (q *Queries) GetOverrideSettings(ctx context.Context, companyID int64) ([]GetOverrideSettingsRow, error) {
@ -207,10 +208,9 @@ func (q *Queries) GetOverrideSettings(ctx context.Context, companyID int64) ([]G
var i GetOverrideSettingsRow
if err := rows.Scan(
&i.Key,
&i.Value,
&i.CreatedAt,
&i.UpdatedAt,
&i.Value_2,
&i.Value,
); err != nil {
return nil, err
}

View File

@ -22,6 +22,16 @@ type RaffleStanding struct {
TicketCount int64
}
type RaffleStandingRes struct {
UserID int64 `json:"user_id"`
RaffleID int32 `json:"raffle_id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
PhoneNumber string `json:"phone_number"`
Email string `json:"email"`
TicketCount int64 `json:"ticket_count"`
}
type RaffleWinnerParams struct {
RaffleID int32
UserID int32

View File

@ -72,6 +72,7 @@ func (s *Service) CreateWelcomeBonus(ctx context.Context, amount domain.Currency
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),
})

View File

@ -19,6 +19,7 @@ func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq, is_
// User.BranchID = branchId
// User.Role = string(domain.RoleBranchManager)
// }
hashedPassword, err := hashPassword(User.Password)
if err != nil {
return domain.User{}, err

View File

@ -26,71 +26,71 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
spec string
task func()
}{
// {
// spec: "0 0 * * * *", // Every 1 hour
// task: func() {
// mongoLogger.Info("Began fetching upcoming events cron task")
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
// mongoLogger.Error("Failed to fetch upcoming events",
// zap.Error(err),
// )
// } else {
// mongoLogger.Info("Completed fetching upcoming events without errors")
// }
// },
// },
// {
// spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
// task: func() {
// mongoLogger.Info("Began fetching non live odds cron task")
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
// mongoLogger.Error("Failed to fetch non live odds",
// zap.Error(err),
// )
// } else {
// mongoLogger.Info("Completed fetching non live odds without errors")
// }
// },
// },
// {
// spec: "0 */5 * * * *", // Every 5 Minutes
// task: func() {
// mongoLogger.Info("Began update all expired events status cron task")
// if _, err := resultService.CheckAndUpdateExpiredEvents(context.Background()); err != nil {
// mongoLogger.Error("Failed to update expired events status",
// zap.Error(err),
// )
// } else {
// mongoLogger.Info("Completed expired events without errors")
// }
// },
// },
// {
// spec: "0 */15 * * * *", // Every 15 Minutes
// task: func() {
// mongoLogger.Info("Began fetching results for upcoming events cron task")
// if err := resultService.FetchAndProcessResults(context.Background()); err != nil {
// mongoLogger.Error("Failed to process result",
// zap.Error(err),
// )
// } else {
// mongoLogger.Info("Completed processing all event result outcomes without errors")
// }
// },
// },
// {
// spec: "0 0 0 * * *", // Every Day
// task: func() {
// mongoLogger.Info("Began Send daily result notification cron task")
// if err := resultService.CheckAndSendResultNotifications(context.Background(), time.Now().Add(-24*time.Hour)); err != nil {
// mongoLogger.Error("Failed to process result",
// zap.Error(err),
// )
// } else {
// mongoLogger.Info("Completed sending daily result notification without errors")
// }
// },
// },
{
spec: "0 0 * * * *", // Every 1 hour
task: func() {
mongoLogger.Info("Began fetching upcoming events cron task")
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
mongoLogger.Error("Failed to fetch upcoming events",
zap.Error(err),
)
} else {
mongoLogger.Info("Completed fetching upcoming events without errors")
}
},
},
{
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
task: func() {
mongoLogger.Info("Began fetching non live odds cron task")
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
mongoLogger.Error("Failed to fetch non live odds",
zap.Error(err),
)
} else {
mongoLogger.Info("Completed fetching non live odds without errors")
}
},
},
{
spec: "0 */5 * * * *", // Every 5 Minutes
task: func() {
mongoLogger.Info("Began update all expired events status cron task")
if _, err := resultService.CheckAndUpdateExpiredEvents(context.Background()); err != nil {
mongoLogger.Error("Failed to update expired events status",
zap.Error(err),
)
} else {
mongoLogger.Info("Completed expired events without errors")
}
},
},
{
spec: "0 */15 * * * *", // Every 15 Minutes
task: func() {
mongoLogger.Info("Began fetching results for upcoming events cron task")
if err := resultService.FetchAndProcessResults(context.Background()); err != nil {
mongoLogger.Error("Failed to process result",
zap.Error(err),
)
} else {
mongoLogger.Info("Completed processing all event result outcomes without errors")
}
},
},
{
spec: "0 0 0 * * *", // Every Day
task: func() {
mongoLogger.Info("Began Send daily result notification cron task")
if err := resultService.CheckAndSendResultNotifications(context.Background(), time.Now().Add(-24*time.Hour)); err != nil {
mongoLogger.Error("Failed to process result",
zap.Error(err),
)
} else {
mongoLogger.Info("Completed sending daily result notification without errors")
}
},
},
}
for _, job := range schedule {

View File

@ -103,6 +103,26 @@ func (h *Handler) GetRafflesOfCompany(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Company Raffles fetched successfully", companyRaffles, nil)
}
func (h *Handler) GetTenantRaffles(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
companyRaffles, err := h.raffleSvc.GetRafflesOfCompany(c.Context(), int32(companyID.Value))
if err != nil {
h.mongoLoggerSvc.Error("Failed to fetch company raffle",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch company raffle")
}
return response.WriteJSON(c, fiber.StatusOK, "Company Raffles fetched successfully", companyRaffles, nil)
}
func (h *Handler) GetRaffleStanding(c *fiber.Ctx) error {
raffleIDStr := c.Params("id")
limitStr := c.Params("limit")
@ -122,9 +142,10 @@ func (h *Handler) GetRaffleStanding(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch raffle standing")
}
maskedRaffleStanding := []domain.RaffleStanding{}
maskedRaffleStanding := make([]domain.RaffleStandingRes, 0, len(raffleStanding))
for _, standing := range raffleStanding {
maskedStanding := domain.RaffleStanding{
maskedStanding := domain.RaffleStandingRes{
UserID: standing.UserID,
RaffleID: standing.RaffleID,
FirstName: standing.FirstName,

View File

@ -60,7 +60,7 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"message": "Welcome to the FortuneBet API",
"version": "1.0.dev14",
"version": "1.0.dev15",
})
})
@ -198,10 +198,11 @@ func (a *App) initAppRoutes() {
// groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
// Raffle Routes
tenant.Get("/raffle/list", h.GetTenantRaffles)
a.fiber.Get("/raffle/standing/:id/:limit", h.GetRaffleStanding) //This needs to be accessible by non-login user
a.fiber.Post("/raffle/create", a.authMiddleware, h.CreateRaffle)
a.fiber.Get("/raffle/delete/:id", a.authMiddleware, h.DeleteRaffle)
a.fiber.Get("/raffle/company/:id", a.authMiddleware, h.GetRafflesOfCompany)
a.fiber.Get("/raffle/standing/:id/:limit", a.authMiddleware, h.GetRaffleStanding)
a.fiber.Get("raffle/winners/:id/:limit", a.authMiddleware, h.GetRaffleWinners)
a.fiber.Post("/raffle-ticket/create", a.authMiddleware, h.CreateRaffleTicket)
a.fiber.Get("/raffle-ticket/:id", a.authMiddleware, h.GetUserRaffleTickets)
@ -209,9 +210,9 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/raffle-ticket/unsuspend/:id", a.authMiddleware, h.UnSuspendRaffleTicket)
// Bonus Routes
groupV1.Get("/bonus", a.authMiddleware, h.GetBonusesByUserID)
groupV1.Get("/bonus/stats", a.authMiddleware, h.GetBonusStats)
groupV1.Post("/bonus/claim/:id", a.authMiddleware, h.ClaimBonus)
tenant.Get("/bonus", a.authMiddleware, h.GetBonusesByUserID)
tenant.Get("/bonus/stats", a.authMiddleware, h.GetBonusStats)
tenant.Post("/bonus/claim/:id", a.authMiddleware, h.ClaimBonus)
// groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
// groupV1.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
@ -228,7 +229,7 @@ func (a *App) initAppRoutes() {
groupV1.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
groupV1.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
tenant.Get("/customer/:id/bets", a.authMiddleware, h.GetCustomerBets)
groupV1.Get("/customer/:id/bets", a.authMiddleware, h.GetCustomerBets)
groupV1.Get("/admin", a.authMiddleware, h.GetAllAdmins)
groupV1.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
@ -446,8 +447,8 @@ func (a *App) initAppRoutes() {
groupV1.Get("/settings/:key", a.authMiddleware, a.SuperAdminOnly, h.GetGlobalSettingByKey)
groupV1.Put("/settings", a.authMiddleware, a.SuperAdminOnly, h.UpdateGlobalSettingList)
tenant.Post("/settings", a.authMiddleware, h.SaveCompanySettingList)
tenant.Get("/settings", a.authMiddleware, h.GetCompanySettingList)
tenant.Put("/settings", a.authMiddleware, h.SaveCompanySettingList)
tenant.Delete("/settings/:key", a.authMiddleware, h.DeleteCompanySetting)
tenant.Delete("/settings", a.authMiddleware, h.DeleteAllCompanySetting)