merge with main

This commit is contained in:
Samuel Tariku 2025-09-18 22:36:30 +03:00
commit 6f5de3a0e5
9 changed files with 80 additions and 18 deletions

View File

@ -351,3 +351,29 @@ SET name = EXCLUDED.name,
is_active = EXCLUDED.is_active, is_active = EXCLUDED.is_active,
created_at = EXCLUDED.created_at, created_at = EXCLUDED.created_at,
updated_at = EXCLUDED.updated_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

@ -455,7 +455,7 @@ CREATE TABLE IF NOT EXISTS company_settings (
PRIMARY KEY (company_id, key) PRIMARY KEY (company_id, key)
); );
CREATE TABLE user_bonuses ( CREATE TABLE user_bonuses (
id BIGINT NOT NULL, id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
type TEXT NOT NULL, type TEXT NOT NULL,
@ -463,7 +463,7 @@ CREATE TABLE user_bonuses (
reward_amount BIGINT NOT NULL, reward_amount BIGINT NOT NULL,
is_claimed BOOLEAN NOT NULL DEFAULT false, is_claimed BOOLEAN NOT NULL DEFAULT false,
expires_at TIMESTAMP NOT NULL, expires_at TIMESTAMP NOT NULL,
claimed_at TIMESTAMP NOT NULL, claimed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_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 FROM company_settings
WHERE key = $1; WHERE key = $1;
-- name: GetOverrideSettings :many -- name: GetOverrideSettings :many
SELECT gs.*, SELECT gs.key,
gs.created_at,
gs.updated_at,
COALESCE(cs.value, gs.value) AS value COALESCE(cs.value, gs.value) AS value
FROM global_settings gs FROM global_settings gs
LEFT JOIN company_settings cs ON cs.key = gs.key 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 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 COALESCE(cs.value, gs.value) AS value
FROM global_settings gs FROM global_settings gs
LEFT JOIN company_settings cs ON cs.key = gs.key LEFT JOIN company_settings cs ON cs.key = gs.key
@ -190,10 +192,9 @@ FROM global_settings gs
type GetOverrideSettingsRow struct { type GetOverrideSettingsRow struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_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) { 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 var i GetOverrideSettingsRow
if err := rows.Scan( if err := rows.Scan(
&i.Key, &i.Key,
&i.Value,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
&i.Value_2, &i.Value,
); err != nil { ); err != nil {
return nil, err return nil, err
} }

View File

@ -22,6 +22,16 @@ type RaffleStanding struct {
TicketCount int64 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 { type RaffleWinnerParams struct {
RaffleID int32 RaffleID int32
UserID int32 UserID int32

View File

@ -72,6 +72,7 @@ func (s *Service) CreateWelcomeBonus(ctx context.Context, amount domain.Currency
Name: "Welcome Bonus", Name: "Welcome Bonus",
Description: fmt.Sprintf("Awarded for deposit number (%v / %v)", stats.TotalDeposits, settingsList.WelcomeBonusCount), Description: fmt.Sprintf("Awarded for deposit number (%v / %v)", stats.TotalDeposits, settingsList.WelcomeBonusCount),
UserID: userID, UserID: userID,
Type: domain.WelcomeBonus,
RewardAmount: domain.Currency(newBalance), RewardAmount: domain.Currency(newBalance),
ExpiresAt: time.Now().Add(time.Duration(settingsList.WelcomeBonusExpire) * 24 * time.Hour), 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.BranchID = branchId
// User.Role = string(domain.RoleBranchManager) // User.Role = string(domain.RoleBranchManager)
// } // }
hashedPassword, err := hashPassword(User.Password) hashedPassword, err := hashPassword(User.Password)
if err != nil { if err != nil {
return domain.User{}, err return domain.User{}, err

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) 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 { func (h *Handler) GetRaffleStanding(c *fiber.Ctx) error {
raffleIDStr := c.Params("id") raffleIDStr := c.Params("id")
limitStr := c.Params("limit") 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") return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch raffle standing")
} }
maskedRaffleStanding := []domain.RaffleStanding{} maskedRaffleStanding := make([]domain.RaffleStandingRes, 0, len(raffleStanding))
for _, standing := range raffleStanding { for _, standing := range raffleStanding {
maskedStanding := domain.RaffleStanding{ maskedStanding := domain.RaffleStandingRes{
UserID: standing.UserID, UserID: standing.UserID,
RaffleID: standing.RaffleID, RaffleID: standing.RaffleID,
FirstName: standing.FirstName, FirstName: standing.FirstName,

View File

@ -60,7 +60,7 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/", func(c *fiber.Ctx) error { a.fiber.Get("/", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{ return c.JSON(fiber.Map{
"message": "Welcome to the FortuneBet API", "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) // groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
// Raffle Routes // 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.Post("/raffle/create", a.authMiddleware, h.CreateRaffle)
a.fiber.Get("/raffle/delete/:id", a.authMiddleware, h.DeleteRaffle) a.fiber.Get("/raffle/delete/:id", a.authMiddleware, h.DeleteRaffle)
a.fiber.Get("/raffle/company/:id", a.authMiddleware, h.GetRafflesOfCompany) 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.Get("raffle/winners/:id/:limit", a.authMiddleware, h.GetRaffleWinners)
a.fiber.Post("/raffle-ticket/create", a.authMiddleware, h.CreateRaffleTicket) a.fiber.Post("/raffle-ticket/create", a.authMiddleware, h.CreateRaffleTicket)
a.fiber.Get("/raffle-ticket/:id", a.authMiddleware, h.GetUserRaffleTickets) 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) a.fiber.Get("/raffle-ticket/unsuspend/:id", a.authMiddleware, h.UnSuspendRaffleTicket)
// Bonus Routes // Bonus Routes
groupV1.Get("/bonus", a.authMiddleware, h.GetBonusesByUserID) tenant.Get("/bonus", a.authMiddleware, h.GetBonusesByUserID)
groupV1.Get("/bonus/stats", a.authMiddleware, h.GetBonusStats) tenant.Get("/bonus/stats", a.authMiddleware, h.GetBonusStats)
groupV1.Post("/bonus/claim/:id", a.authMiddleware, h.ClaimBonus) tenant.Post("/bonus/claim/:id", a.authMiddleware, h.ClaimBonus)
// groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier) // groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
// groupV1.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier) // 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", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID) groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
groupV1.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer) 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", a.authMiddleware, h.GetAllAdmins)
groupV1.Get("/admin/:id", a.authMiddleware, h.GetAdminByID) 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.Get("/settings/:key", a.authMiddleware, a.SuperAdminOnly, h.GetGlobalSettingByKey)
groupV1.Put("/settings", a.authMiddleware, a.SuperAdminOnly, h.UpdateGlobalSettingList) groupV1.Put("/settings", a.authMiddleware, a.SuperAdminOnly, h.UpdateGlobalSettingList)
tenant.Post("/settings", a.authMiddleware, h.SaveCompanySettingList)
tenant.Get("/settings", a.authMiddleware, h.GetCompanySettingList) 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/:key", a.authMiddleware, h.DeleteCompanySetting)
tenant.Delete("/settings", a.authMiddleware, h.DeleteAllCompanySetting) tenant.Delete("/settings", a.authMiddleware, h.DeleteAllCompanySetting)