From 89e3d7de781dd03240dcc520c340a4a435c73752 Mon Sep 17 00:00:00 2001 From: Asher Samuel Date: Mon, 1 Sep 2025 23:47:27 +0300 Subject: [PATCH 1/2] raffle service structure --- db/migrations/000001_fortune.up.sql | 18 ++- db/query/raffle.sql | 36 ++++++ gen/db/models.go | 17 +++ gen/db/raffle.sql.go | 190 ++++++++++++++++++++++++++++ internal/domain/raffle.go | 36 ++++++ internal/repository/reffel.go | 123 ++++++++++++++++++ internal/services/raffle/port.go | 18 +++ internal/services/raffle/service.go | 45 +++++++ internal/web_server/routes.go | 4 - 9 files changed, 482 insertions(+), 5 deletions(-) create mode 100644 db/query/raffle.sql create mode 100644 gen/db/raffle.sql.go create mode 100644 internal/domain/raffle.go create mode 100644 internal/repository/reffel.go create mode 100644 internal/services/raffle/port.go create mode 100644 internal/services/raffle/service.go diff --git a/db/migrations/000001_fortune.up.sql b/db/migrations/000001_fortune.up.sql index d05dcbe..f2f852d 100644 --- a/db/migrations/000001_fortune.up.sql +++ b/db/migrations/000001_fortune.up.sql @@ -498,6 +498,22 @@ CREATE TABLE IF NOT EXISTS supported_operations ( name VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL ); +CREATE TABLE IF NOT EXISTS raffles ( + id SERIAL PRIMARY KEY, + company_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + expires_at TIMESTAMP NOT NULL, + type VARCHAR(50) NOT NULL CHECK (type IN ('virtual', 'sport')), + status VARCHAR(50) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'completed')) +); +CREATE TABLE IF NOT EXISTS raffle_tickets ( + id SERIAL PRIMARY KEY, + raffle_id INT NOT NULL REFERENCES raffles(id) ON DELETE CASCADE, + user_id INT NOT NULL, + is_active BOOL DEFAULT true, + UNIQUE (raffle_id, user_id) +); CREATE VIEW bet_with_outcomes AS SELECT bets.*, CONCAT(users.first_name, ' ', users.last_name) AS full_name, @@ -686,4 +702,4 @@ ADD CONSTRAINT fk_event_settings_company FOREIGN KEY (company_id) REFERENCES com ADD CONSTRAINT fk_event_settings_event FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE; ALTER TABLE company_odd_settings ADD CONSTRAINT fk_odds_settings_company FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE, - ADD CONSTRAINT fk_odds_settings_odds_market FOREIGN KEY (odds_market_id) REFERENCES odds_market(id) ON DELETE CASCADE; \ No newline at end of file + ADD CONSTRAINT fk_odds_settings_odds_market FOREIGN KEY (odds_market_id) REFERENCES odds_market(id) ON DELETE CASCADE; diff --git a/db/query/raffle.sql b/db/query/raffle.sql new file mode 100644 index 0000000..4e900fd --- /dev/null +++ b/db/query/raffle.sql @@ -0,0 +1,36 @@ +-- name: CreateRaffle :one +INSERT INTO raffles (company_id, name, expires_at, type) +VALUES ($1, $2, $3, $4) +RETURNING *; + +-- name: GetRafflesOfCompany :many +SELECT * FROM raffles WHERE company_id = $1; + +-- name: UpdateRaffle :exec +UPDATE raffles +SET name = $1, + expires_at = $2, + status = $3 +WHERE id = $4; + +-- name: UpdateRaffleTicketStatus :exec +UPDATE raffle_tickets +SET is_active = $1 +WHERE id = $2; + +-- name: CreateRaffleTicket :one +INSERT INTO raffle_tickets (raffle_id, user_id) +VALUES ($1, $2) +RETURNING *; + +-- name: GetUserRaffleTickets :many +SELECT + rt.id AS ticket_id, + rt.user_id, + r.name, + r.type, + r.expires_at, + r.status +FROM raffle_tickets rt +JOIN raffles r ON rt.raffle_id = r.id +WHERE rt.user_id = $1; diff --git a/gen/db/models.go b/gen/db/models.go index d91961f..0d18e73 100644 --- a/gen/db/models.go +++ b/gen/db/models.go @@ -538,6 +538,23 @@ type Otp struct { ExpiresAt pgtype.Timestamptz `json:"expires_at"` } +type Raffle struct { + ID int32 `json:"id"` + CompanyID int32 `json:"company_id"` + Name string `json:"name"` + CreatedAt pgtype.Timestamp `json:"created_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + Type string `json:"type"` + Status string `json:"status"` +} + +type RaffleTicket struct { + ID int32 `json:"id"` + RaffleID int32 `json:"raffle_id"` + UserID int32 `json:"user_id"` + IsActive pgtype.Bool `json:"is_active"` +} + type Referral struct { ID int64 `json:"id"` ReferralCode string `json:"referral_code"` diff --git a/gen/db/raffle.sql.go b/gen/db/raffle.sql.go new file mode 100644 index 0000000..64fdd88 --- /dev/null +++ b/gen/db/raffle.sql.go @@ -0,0 +1,190 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: raffle.sql + +package dbgen + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const CreateRaffle = `-- name: CreateRaffle :one +INSERT INTO raffles (company_id, name, expires_at, type) +VALUES ($1, $2, $3, $4) +RETURNING id, company_id, name, created_at, expires_at, type, status +` + +type CreateRaffleParams struct { + CompanyID int32 `json:"company_id"` + Name string `json:"name"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + Type string `json:"type"` +} + +func (q *Queries) CreateRaffle(ctx context.Context, arg CreateRaffleParams) (Raffle, error) { + row := q.db.QueryRow(ctx, CreateRaffle, + arg.CompanyID, + arg.Name, + arg.ExpiresAt, + arg.Type, + ) + var i Raffle + err := row.Scan( + &i.ID, + &i.CompanyID, + &i.Name, + &i.CreatedAt, + &i.ExpiresAt, + &i.Type, + &i.Status, + ) + return i, err +} + +const CreateRaffleTicket = `-- name: CreateRaffleTicket :one +INSERT INTO raffle_tickets (raffle_id, user_id) +VALUES ($1, $2) +RETURNING id, raffle_id, user_id, is_active +` + +type CreateRaffleTicketParams struct { + RaffleID int32 `json:"raffle_id"` + UserID int32 `json:"user_id"` +} + +func (q *Queries) CreateRaffleTicket(ctx context.Context, arg CreateRaffleTicketParams) (RaffleTicket, error) { + row := q.db.QueryRow(ctx, CreateRaffleTicket, arg.RaffleID, arg.UserID) + var i RaffleTicket + err := row.Scan( + &i.ID, + &i.RaffleID, + &i.UserID, + &i.IsActive, + ) + return i, err +} + +const GetRafflesOfCompany = `-- name: GetRafflesOfCompany :many +SELECT id, company_id, name, created_at, expires_at, type, status FROM raffles WHERE company_id = $1 +` + +func (q *Queries) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]Raffle, error) { + rows, err := q.db.Query(ctx, GetRafflesOfCompany, companyID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Raffle + for rows.Next() { + var i Raffle + if err := rows.Scan( + &i.ID, + &i.CompanyID, + &i.Name, + &i.CreatedAt, + &i.ExpiresAt, + &i.Type, + &i.Status, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const GetUserRaffleTickets = `-- name: GetUserRaffleTickets :many +SELECT + rt.id AS ticket_id, + rt.user_id, + r.name, + r.type, + r.expires_at, + r.status +FROM raffle_tickets rt +JOIN raffles r ON rt.raffle_id = r.id +WHERE rt.user_id = $1 +` + +type GetUserRaffleTicketsRow struct { + TicketID int32 `json:"ticket_id"` + UserID int32 `json:"user_id"` + Name string `json:"name"` + Type string `json:"type"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + Status string `json:"status"` +} + +func (q *Queries) GetUserRaffleTickets(ctx context.Context, userID int32) ([]GetUserRaffleTicketsRow, error) { + rows, err := q.db.Query(ctx, GetUserRaffleTickets, userID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetUserRaffleTicketsRow + for rows.Next() { + var i GetUserRaffleTicketsRow + if err := rows.Scan( + &i.TicketID, + &i.UserID, + &i.Name, + &i.Type, + &i.ExpiresAt, + &i.Status, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const UpdateRaffle = `-- name: UpdateRaffle :exec +UPDATE raffles +SET name = $1, + expires_at = $2, + status = $3 +WHERE id = $4 +` + +type UpdateRaffleParams struct { + Name string `json:"name"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + Status string `json:"status"` + ID int32 `json:"id"` +} + +func (q *Queries) UpdateRaffle(ctx context.Context, arg UpdateRaffleParams) error { + _, err := q.db.Exec(ctx, UpdateRaffle, + arg.Name, + arg.ExpiresAt, + arg.Status, + arg.ID, + ) + return err +} + +const UpdateRaffleTicketStatus = `-- name: UpdateRaffleTicketStatus :exec +UPDATE raffle_tickets +SET is_active = $1 +WHERE id = $2 +` + +type UpdateRaffleTicketStatusParams struct { + IsActive pgtype.Bool `json:"is_active"` + ID int32 `json:"id"` +} + +func (q *Queries) UpdateRaffleTicketStatus(ctx context.Context, arg UpdateRaffleTicketStatusParams) error { + _, err := q.db.Exec(ctx, UpdateRaffleTicketStatus, arg.IsActive, arg.ID) + return err +} diff --git a/internal/domain/raffle.go b/internal/domain/raffle.go new file mode 100644 index 0000000..b4b1e70 --- /dev/null +++ b/internal/domain/raffle.go @@ -0,0 +1,36 @@ +package domain + +import "time" + +type Raffle struct { + ID int32 + CompanyID int32 + Name string + CreatedAt time.Time + ExpiresAt time.Time + Type string + Status string +} + +type RaffleTicket struct { + ID int32 + RaffleID int32 + UserID int32 + IsActive bool +} + +type RaffleTicketRes struct { + TicketID int32 + UserID int32 + Name string + Type string + ExpiresAt time.Time + Status string +} + +type CreateRaffle struct { + CompanyID int32 + Name string + ExpiresAt time.Time + Type string +} diff --git a/internal/repository/reffel.go b/internal/repository/reffel.go new file mode 100644 index 0000000..a28096a --- /dev/null +++ b/internal/repository/reffel.go @@ -0,0 +1,123 @@ +package repository + +import ( + "context" + + dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/jackc/pgx/v5/pgtype" +) + +func convertRaffleOutcome(raffle dbgen.Raffle) domain.Raffle { + return domain.Raffle{ + ID: raffle.ID, + CompanyID: raffle.CompanyID, + Name: raffle.Name, + CreatedAt: raffle.CreatedAt.Time, + ExpiresAt: raffle.ExpiresAt.Time, + Type: raffle.Type, + Status: raffle.Status, + } +} + +func convertRaffleTicketOutcome(raffle dbgen.RaffleTicket) domain.RaffleTicket { + return domain.RaffleTicket{ + ID: raffle.ID, + RaffleID: raffle.RaffleID, + UserID: raffle.UserID, + IsActive: raffle.IsActive.Bool, + } +} + +func convertJoinedRaffleTicketOutcome(raffle dbgen.GetUserRaffleTicketsRow) domain.RaffleTicketRes { + return domain.RaffleTicketRes{ + TicketID: raffle.TicketID, + UserID: raffle.UserID, + Name: raffle.Name, + Type: raffle.Type, + ExpiresAt: raffle.ExpiresAt.Time, + Status: raffle.Status, + } +} + +func convertCreateRaffle(raffle domain.CreateRaffle) dbgen.CreateRaffleParams { + return dbgen.CreateRaffleParams{ + CompanyID: raffle.CompanyID, + Name: raffle.Name, + ExpiresAt: pgtype.Timestamp{ + Time: raffle.ExpiresAt, + Valid: true, + }, + Type: raffle.Type, + } +} + +func (s *Store) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) { + raffleRes, err := s.queries.CreateRaffle(ctx, convertCreateRaffle(raffle)) + if err != nil { + return domain.Raffle{}, err + } + + return convertRaffleOutcome(raffleRes), nil +} + +func (s *Store) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) { + raffles, err := s.queries.GetRafflesOfCompany(ctx, companyID) + if err != nil { + return nil, err + } + + return raffles, nil +} + +func (s *Store) UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error { + return s.queries.UpdateRaffle(ctx, raffleParams) +} + +func (s *Store) SuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ + ID: raffleID, + IsActive: pgtype.Bool{ + Bool: false, + Valid: true, + }, + }) +} + +func (s *Store) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ + ID: raffleID, + IsActive: pgtype.Bool{ + Bool: true, + Valid: true, + }, + }) +} + +// TODO: could also add -> suspend a specific user's raffle tickets + +func (s *Store) CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) { + raffleTicket, err := s.queries.CreateRaffleTicket(ctx, dbgen.CreateRaffleTicketParams{ + RaffleID: raffleID, + UserID: userID, + }) + if err != nil { + return domain.RaffleTicket{}, err + } + + return convertRaffleTicketOutcome(raffleTicket), nil +} + +func (s *Store) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) { + raffleTickets, err := s.queries.GetUserRaffleTickets(ctx, userID) + if err != nil { + return nil, err + } + + res := []domain.RaffleTicketRes{} + for _, raffle := range raffleTickets { + res = append(res, convertJoinedRaffleTicketOutcome(raffle)) + } + + return res, nil +} diff --git a/internal/services/raffle/port.go b/internal/services/raffle/port.go new file mode 100644 index 0000000..a457f66 --- /dev/null +++ b/internal/services/raffle/port.go @@ -0,0 +1,18 @@ +package raffle + +import ( + "context" + + dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" +) + +type RaffleStore interface { + CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) + GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) + UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error + SuspendRaffleTicket(ctx context.Context, raffleID int32) error + UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error + CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) + GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) +} diff --git a/internal/services/raffle/service.go b/internal/services/raffle/service.go new file mode 100644 index 0000000..6048ca7 --- /dev/null +++ b/internal/services/raffle/service.go @@ -0,0 +1,45 @@ +package raffle + +import ( + "context" + + dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" +) + +type Service struct { + raffleStore RaffleStore +} + +func NewService(raffleStore RaffleStore) *Service { + return &Service{ + raffleStore: raffleStore, + } +} + +func (s *Service) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) { + return s.raffleStore.CreateRaffle(ctx, raffle) +} + +func (s *Service) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) { + return s.GetRafflesOfCompany(ctx, companyID) +} +func (s *Service) UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error { + return s.raffleStore.UpdateRaffle(ctx, raffleParams) +} + +func (s *Service) SuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.raffleStore.SuspendRaffleTicket(ctx, raffleID) +} + +func (s *Service) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.raffleStore.UnSuspendRaffleTicket(ctx, raffleID) +} + +func (s *Service) CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) { + return s.raffleStore.CreateRaffleTicket(ctx, raffleID, userID) +} + +func (s *Service) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) { + return s.raffleStore.GetUserRaffleTickets(ctx, userID) +} diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index c6c1f7f..82e49e8 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -71,7 +71,6 @@ func (a *App) initAppRoutes() { groupV1.Post("/direct_deposit", a.authMiddleware, h.InitiateDirectDeposit) groupV1.Post("/direct_deposit/verify", a.authMiddleware, h.VerifyDirectDeposit) groupV1.Get("/direct_deposit/pending", a.authMiddleware, h.GetPendingDirectDeposits) - // Swagger a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler()) @@ -141,9 +140,6 @@ func (a *App) initAppRoutes() { // groupV1.Post("/arifpay/transaction-id/verify-transaction", a.authMiddleware, h.ArifpayVerifyByTransactionIDHandler) // groupV1.Get("/arifpay/session-id/verify-transaction/:session_id", a.authMiddleware, h.ArifpayVerifyBySessionIDHandler) - - - // User Routes tenant.Post("/user/resetPassword", h.ResetPassword) tenant.Post("/user/sendResetCode", h.SendResetCode) From d78a100f27a0f09ef9506af68ba7f6230b1f399b Mon Sep 17 00:00:00 2001 From: Asher Samuel Date: Wed, 3 Sep 2025 16:06:01 +0300 Subject: [PATCH 2/2] raffle service implementation --- cmd/main.go | 3 + db/query/raffle.sql | 10 +- gen/db/auth.sql.go | 2 +- gen/db/bet.sql.go | 2 +- gen/db/bet_stat.sql.go | 2 +- gen/db/bonus.sql.go | 2 +- gen/db/branch.sql.go | 2 +- gen/db/cashier.sql.go | 2 +- gen/db/company.sql.go | 2 +- gen/db/copyfrom.go | 2 +- gen/db/db.go | 2 +- gen/db/direct_deposit.sql.go | 2 +- gen/db/disabled_odds.sql.go | 2 +- gen/db/event_history.sql.go | 2 +- gen/db/events.sql.go | 2 +- gen/db/events_stat.sql.go | 2 +- gen/db/flags.sql.go | 2 +- gen/db/institutions.sql.go | 2 +- gen/db/issue_reporting.sql.go | 2 +- gen/db/leagues.sql.go | 2 +- gen/db/location.sql.go | 2 +- gen/db/models.go | 2 +- gen/db/monitor.sql.go | 2 +- gen/db/notification.sql.go | 2 +- gen/db/odd_history.sql.go | 2 +- gen/db/odds.sql.go | 2 +- gen/db/otp.sql.go | 2 +- gen/db/raffle.sql.go | 48 ++-- gen/db/referal.sql.go | 2 +- gen/db/report.sql.go | 2 +- gen/db/result.sql.go | 2 +- gen/db/result_log.sql.go | 2 +- gen/db/settings.sql.go | 2 +- gen/db/shop_transactions.sql.go | 2 +- gen/db/ticket.sql.go | 2 +- gen/db/transfer.sql.go | 2 +- gen/db/user.sql.go | 2 +- gen/db/virtual_games.sql.go | 2 +- gen/db/wallet.sql.go | 2 +- internal/domain/raffle.go | 20 +- internal/repository/{reffel.go => raffel.go} | 65 +++--- internal/repository/settings.go | 4 +- internal/services/raffle/port.go | 8 +- internal/services/raffle/service.go | 29 +-- internal/web_server/app.go | 22 +- internal/web_server/cron.go | 2 - internal/web_server/handlers/bet_handler.go | 2 + internal/web_server/handlers/handlers.go | 4 + .../web_server/handlers/raffle_handler.go | 216 ++++++++++++++++++ internal/web_server/routes.go | 11 +- 50 files changed, 382 insertions(+), 134 deletions(-) rename internal/repository/{reffel.go => raffel.go} (82%) create mode 100644 internal/web_server/handlers/raffle_handler.go diff --git a/cmd/main.go b/cmd/main.go index fe39dff..9d25945 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -45,6 +45,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/report" @@ -150,6 +151,7 @@ func main() { recommendationRepo := repository.NewRecommendationRepository(store) referalSvc := referralservice.New(referalRepo, *walletSvc, store, cfg, logger) + raffleSvc := raffle.NewService(store) virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) veliCLient := veli.NewClient(cfg, walletSvc) @@ -274,6 +276,7 @@ func main() { eventSvc, leagueSvc, referalSvc, + raffleSvc, bonusSvc, virtualGameSvc, aleaService, diff --git a/db/query/raffle.sql b/db/query/raffle.sql index 4e900fd..4c43a10 100644 --- a/db/query/raffle.sql +++ b/db/query/raffle.sql @@ -6,12 +6,10 @@ RETURNING *; -- name: GetRafflesOfCompany :many SELECT * FROM raffles WHERE company_id = $1; --- name: UpdateRaffle :exec -UPDATE raffles -SET name = $1, - expires_at = $2, - status = $3 -WHERE id = $4; +-- name: DeleteRaffle :one +DELETE FROM raffles +WHERE id = $1 +RETURNING *; -- name: UpdateRaffleTicketStatus :exec UPDATE raffle_tickets diff --git a/gen/db/auth.sql.go b/gen/db/auth.sql.go index 1817514..c5984b9 100644 --- a/gen/db/auth.sql.go +++ b/gen/db/auth.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: auth.sql package dbgen diff --git a/gen/db/bet.sql.go b/gen/db/bet.sql.go index ff64087..573c4c2 100644 --- a/gen/db/bet.sql.go +++ b/gen/db/bet.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: bet.sql package dbgen diff --git a/gen/db/bet_stat.sql.go b/gen/db/bet_stat.sql.go index 275ef07..9a7b494 100644 --- a/gen/db/bet_stat.sql.go +++ b/gen/db/bet_stat.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: bet_stat.sql package dbgen diff --git a/gen/db/bonus.sql.go b/gen/db/bonus.sql.go index 12677b8..f62227b 100644 --- a/gen/db/bonus.sql.go +++ b/gen/db/bonus.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: bonus.sql package dbgen diff --git a/gen/db/branch.sql.go b/gen/db/branch.sql.go index a9a57b8..89d2959 100644 --- a/gen/db/branch.sql.go +++ b/gen/db/branch.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: branch.sql package dbgen diff --git a/gen/db/cashier.sql.go b/gen/db/cashier.sql.go index c15f497..e262575 100644 --- a/gen/db/cashier.sql.go +++ b/gen/db/cashier.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: cashier.sql package dbgen diff --git a/gen/db/company.sql.go b/gen/db/company.sql.go index 506eaca..18bc509 100644 --- a/gen/db/company.sql.go +++ b/gen/db/company.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: company.sql package dbgen diff --git a/gen/db/copyfrom.go b/gen/db/copyfrom.go index 1212253..f7a4793 100644 --- a/gen/db/copyfrom.go +++ b/gen/db/copyfrom.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: copyfrom.go package dbgen diff --git a/gen/db/db.go b/gen/db/db.go index 84de07c..8134784 100644 --- a/gen/db/db.go +++ b/gen/db/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 package dbgen diff --git a/gen/db/direct_deposit.sql.go b/gen/db/direct_deposit.sql.go index be02750..ff5a3b2 100644 --- a/gen/db/direct_deposit.sql.go +++ b/gen/db/direct_deposit.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: direct_deposit.sql package dbgen diff --git a/gen/db/disabled_odds.sql.go b/gen/db/disabled_odds.sql.go index 85dcd2e..917acce 100644 --- a/gen/db/disabled_odds.sql.go +++ b/gen/db/disabled_odds.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: disabled_odds.sql package dbgen diff --git a/gen/db/event_history.sql.go b/gen/db/event_history.sql.go index ab29359..64762c3 100644 --- a/gen/db/event_history.sql.go +++ b/gen/db/event_history.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: event_history.sql package dbgen diff --git a/gen/db/events.sql.go b/gen/db/events.sql.go index 313b240..2bdb5b8 100644 --- a/gen/db/events.sql.go +++ b/gen/db/events.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: events.sql package dbgen diff --git a/gen/db/events_stat.sql.go b/gen/db/events_stat.sql.go index 677fa2a..615e2fa 100644 --- a/gen/db/events_stat.sql.go +++ b/gen/db/events_stat.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: events_stat.sql package dbgen diff --git a/gen/db/flags.sql.go b/gen/db/flags.sql.go index 653543f..4b82cac 100644 --- a/gen/db/flags.sql.go +++ b/gen/db/flags.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: flags.sql package dbgen diff --git a/gen/db/institutions.sql.go b/gen/db/institutions.sql.go index 324ac3e..61ca108 100644 --- a/gen/db/institutions.sql.go +++ b/gen/db/institutions.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: institutions.sql package dbgen diff --git a/gen/db/issue_reporting.sql.go b/gen/db/issue_reporting.sql.go index 7fcb4af..e35fba1 100644 --- a/gen/db/issue_reporting.sql.go +++ b/gen/db/issue_reporting.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: issue_reporting.sql package dbgen diff --git a/gen/db/leagues.sql.go b/gen/db/leagues.sql.go index 5d49d4d..6c0ae07 100644 --- a/gen/db/leagues.sql.go +++ b/gen/db/leagues.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: leagues.sql package dbgen diff --git a/gen/db/location.sql.go b/gen/db/location.sql.go index 008aa61..254c73a 100644 --- a/gen/db/location.sql.go +++ b/gen/db/location.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: location.sql package dbgen diff --git a/gen/db/models.go b/gen/db/models.go index 0d18e73..91e56e7 100644 --- a/gen/db/models.go +++ b/gen/db/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 package dbgen diff --git a/gen/db/monitor.sql.go b/gen/db/monitor.sql.go index a9a7ecb..b5f248f 100644 --- a/gen/db/monitor.sql.go +++ b/gen/db/monitor.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: monitor.sql package dbgen diff --git a/gen/db/notification.sql.go b/gen/db/notification.sql.go index ba9882b..9ce7e42 100644 --- a/gen/db/notification.sql.go +++ b/gen/db/notification.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: notification.sql package dbgen diff --git a/gen/db/odd_history.sql.go b/gen/db/odd_history.sql.go index 0a0333d..dd69a51 100644 --- a/gen/db/odd_history.sql.go +++ b/gen/db/odd_history.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: odd_history.sql package dbgen diff --git a/gen/db/odds.sql.go b/gen/db/odds.sql.go index 33fcde8..f7dec2b 100644 --- a/gen/db/odds.sql.go +++ b/gen/db/odds.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: odds.sql package dbgen diff --git a/gen/db/otp.sql.go b/gen/db/otp.sql.go index 7dba175..c96aaaa 100644 --- a/gen/db/otp.sql.go +++ b/gen/db/otp.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: otp.sql package dbgen diff --git a/gen/db/raffle.sql.go b/gen/db/raffle.sql.go index 64fdd88..4b77106 100644 --- a/gen/db/raffle.sql.go +++ b/gen/db/raffle.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: raffle.sql package dbgen @@ -67,6 +67,27 @@ func (q *Queries) CreateRaffleTicket(ctx context.Context, arg CreateRaffleTicket return i, err } +const DeleteRaffle = `-- name: DeleteRaffle :one +DELETE FROM raffles +WHERE id = $1 +RETURNING id, company_id, name, created_at, expires_at, type, status +` + +func (q *Queries) DeleteRaffle(ctx context.Context, id int32) (Raffle, error) { + row := q.db.QueryRow(ctx, DeleteRaffle, id) + var i Raffle + err := row.Scan( + &i.ID, + &i.CompanyID, + &i.Name, + &i.CreatedAt, + &i.ExpiresAt, + &i.Type, + &i.Status, + ) + return i, err +} + const GetRafflesOfCompany = `-- name: GetRafflesOfCompany :many SELECT id, company_id, name, created_at, expires_at, type, status FROM raffles WHERE company_id = $1 ` @@ -148,31 +169,6 @@ func (q *Queries) GetUserRaffleTickets(ctx context.Context, userID int32) ([]Get return items, nil } -const UpdateRaffle = `-- name: UpdateRaffle :exec -UPDATE raffles -SET name = $1, - expires_at = $2, - status = $3 -WHERE id = $4 -` - -type UpdateRaffleParams struct { - Name string `json:"name"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - Status string `json:"status"` - ID int32 `json:"id"` -} - -func (q *Queries) UpdateRaffle(ctx context.Context, arg UpdateRaffleParams) error { - _, err := q.db.Exec(ctx, UpdateRaffle, - arg.Name, - arg.ExpiresAt, - arg.Status, - arg.ID, - ) - return err -} - const UpdateRaffleTicketStatus = `-- name: UpdateRaffleTicketStatus :exec UPDATE raffle_tickets SET is_active = $1 diff --git a/gen/db/referal.sql.go b/gen/db/referal.sql.go index b5ceeed..3313a9b 100644 --- a/gen/db/referal.sql.go +++ b/gen/db/referal.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: referal.sql package dbgen diff --git a/gen/db/report.sql.go b/gen/db/report.sql.go index 1a1ccde..d6193c1 100644 --- a/gen/db/report.sql.go +++ b/gen/db/report.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: report.sql package dbgen diff --git a/gen/db/result.sql.go b/gen/db/result.sql.go index bff7b1e..899561b 100644 --- a/gen/db/result.sql.go +++ b/gen/db/result.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: result.sql package dbgen diff --git a/gen/db/result_log.sql.go b/gen/db/result_log.sql.go index 468795e..3f11e16 100644 --- a/gen/db/result_log.sql.go +++ b/gen/db/result_log.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: result_log.sql package dbgen diff --git a/gen/db/settings.sql.go b/gen/db/settings.sql.go index f67fecc..eb50e0e 100644 --- a/gen/db/settings.sql.go +++ b/gen/db/settings.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: settings.sql package dbgen diff --git a/gen/db/shop_transactions.sql.go b/gen/db/shop_transactions.sql.go index bcd884e..7664dbb 100644 --- a/gen/db/shop_transactions.sql.go +++ b/gen/db/shop_transactions.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: shop_transactions.sql package dbgen diff --git a/gen/db/ticket.sql.go b/gen/db/ticket.sql.go index bc9bb5f..45603ba 100644 --- a/gen/db/ticket.sql.go +++ b/gen/db/ticket.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: ticket.sql package dbgen diff --git a/gen/db/transfer.sql.go b/gen/db/transfer.sql.go index 35e38d4..926fc8c 100644 --- a/gen/db/transfer.sql.go +++ b/gen/db/transfer.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: transfer.sql package dbgen diff --git a/gen/db/user.sql.go b/gen/db/user.sql.go index 0d4c33b..b15d8a2 100644 --- a/gen/db/user.sql.go +++ b/gen/db/user.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: user.sql package dbgen diff --git a/gen/db/virtual_games.sql.go b/gen/db/virtual_games.sql.go index 79bce9e..51da52d 100644 --- a/gen/db/virtual_games.sql.go +++ b/gen/db/virtual_games.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: virtual_games.sql package dbgen diff --git a/gen/db/wallet.sql.go b/gen/db/wallet.sql.go index 7e3eb7f..f41a944 100644 --- a/gen/db/wallet.sql.go +++ b/gen/db/wallet.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: wallet.sql package dbgen diff --git a/internal/domain/raffle.go b/internal/domain/raffle.go index b4b1e70..c6adc2c 100644 --- a/internal/domain/raffle.go +++ b/internal/domain/raffle.go @@ -29,8 +29,20 @@ type RaffleTicketRes struct { } type CreateRaffle struct { - CompanyID int32 - Name string - ExpiresAt time.Time - Type string + CompanyID int32 `json:"company_id" validate:"required"` + Name string `json:"name" validate:"required"` + ExpiresAt *time.Time `json:"expires_at" validate:"required"` + Type string `json:"type" validate:"required"` +} + +type CreateRaffleTicket struct { + RaffleID int32 `json:"raffle_id" validate:"required"` + UserID int32 `json:"user_id" validate:"required"` +} + +// aside from ID, atleast one of the fields should be required +type UpdateRaffleParams struct { + ID int32 `json:"id" validate:"required"` + Name string `json:"name" validate:"required_without_all=ExpiresAt"` + ExpiresAt *time.Time `json:"expires_at" validate:"required_without_all=Name"` } diff --git a/internal/repository/reffel.go b/internal/repository/raffel.go similarity index 82% rename from internal/repository/reffel.go rename to internal/repository/raffel.go index a28096a..db230bd 100644 --- a/internal/repository/reffel.go +++ b/internal/repository/raffel.go @@ -45,7 +45,7 @@ func convertCreateRaffle(raffle domain.CreateRaffle) dbgen.CreateRaffleParams { CompanyID: raffle.CompanyID, Name: raffle.Name, ExpiresAt: pgtype.Timestamp{ - Time: raffle.ExpiresAt, + Time: *raffle.ExpiresAt, Valid: true, }, Type: raffle.Type, @@ -61,6 +61,15 @@ func (s *Store) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (d return convertRaffleOutcome(raffleRes), nil } +func (s *Store) DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error) { + raffleRes, err := s.queries.DeleteRaffle(ctx, raffleID) + if err != nil { + return domain.Raffle{}, err + } + + return convertRaffleOutcome(raffleRes), nil +} + func (s *Store) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) { raffles, err := s.queries.GetRafflesOfCompany(ctx, companyID) if err != nil { @@ -70,36 +79,10 @@ func (s *Store) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbg return raffles, nil } -func (s *Store) UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error { - return s.queries.UpdateRaffle(ctx, raffleParams) -} - -func (s *Store) SuspendRaffleTicket(ctx context.Context, raffleID int32) error { - return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ - ID: raffleID, - IsActive: pgtype.Bool{ - Bool: false, - Valid: true, - }, - }) -} - -func (s *Store) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { - return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ - ID: raffleID, - IsActive: pgtype.Bool{ - Bool: true, - Valid: true, - }, - }) -} - -// TODO: could also add -> suspend a specific user's raffle tickets - -func (s *Store) CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) { +func (s *Store) CreateRaffleTicket(ctx context.Context, raffleTicketParams domain.CreateRaffleTicket) (domain.RaffleTicket, error) { raffleTicket, err := s.queries.CreateRaffleTicket(ctx, dbgen.CreateRaffleTicketParams{ - RaffleID: raffleID, - UserID: userID, + RaffleID: raffleTicketParams.RaffleID, + UserID: raffleTicketParams.UserID, }) if err != nil { return domain.RaffleTicket{}, err @@ -121,3 +104,25 @@ func (s *Store) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domai return res, nil } + +func (s *Store) SuspendRaffleTicket(ctx context.Context, raffleTicketID int32) error { + return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ + ID: raffleTicketID, + IsActive: pgtype.Bool{ + Bool: false, + Valid: true, + }, + }) +} + +func (s *Store) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.queries.UpdateRaffleTicketStatus(ctx, dbgen.UpdateRaffleTicketStatusParams{ + ID: raffleID, + IsActive: pgtype.Bool{ + Bool: true, + Valid: true, + }, + }) +} + +// TODO: could also add -> suspend a specific user's raffle tickets diff --git a/internal/repository/settings.go b/internal/repository/settings.go index 333f280..f456bff 100644 --- a/internal/repository/settings.go +++ b/internal/repository/settings.go @@ -165,9 +165,9 @@ func (s *Store) GetOverrideSettingsList(ctx context.Context, companyID int64) (d func (s *Store) DeleteCompanySetting(ctx context.Context, companyID int64, key string) error { return s.queries.DeleteCompanySetting(ctx, dbgen.DeleteCompanySettingParams{ CompanyID: companyID, - Key: key, + Key: key, }) } -func (s *Store) DeleteAllCompanySetting(ctx context.Context, companyID int64,) error { +func (s *Store) DeleteAllCompanySetting(ctx context.Context, companyID int64) error { return s.queries.DeleteAllCompanySetting(ctx, companyID) } diff --git a/internal/services/raffle/port.go b/internal/services/raffle/port.go index a457f66..c8c4b8e 100644 --- a/internal/services/raffle/port.go +++ b/internal/services/raffle/port.go @@ -9,10 +9,10 @@ import ( type RaffleStore interface { CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) + DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) - UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error - SuspendRaffleTicket(ctx context.Context, raffleID int32) error - UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error - CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) + CreateRaffleTicket(ctx context.Context, raffleTicketParams domain.CreateRaffleTicket) (domain.RaffleTicket, error) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) + SuspendRaffleTicket(ctx context.Context, raffleTicketID int32) error + UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error } diff --git a/internal/services/raffle/service.go b/internal/services/raffle/service.go index 6048ca7..1246fb7 100644 --- a/internal/services/raffle/service.go +++ b/internal/services/raffle/service.go @@ -21,25 +21,26 @@ func (s *Service) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) return s.raffleStore.CreateRaffle(ctx, raffle) } +func (s *Service) DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error) { + return s.raffleStore.DeleteRaffle(ctx, raffleID) +} + func (s *Service) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) { - return s.GetRafflesOfCompany(ctx, companyID) -} -func (s *Service) UpdateRaffle(ctx context.Context, raffleParams dbgen.UpdateRaffleParams) error { - return s.raffleStore.UpdateRaffle(ctx, raffleParams) + return s.raffleStore.GetRafflesOfCompany(ctx, companyID) } -func (s *Service) SuspendRaffleTicket(ctx context.Context, raffleID int32) error { - return s.raffleStore.SuspendRaffleTicket(ctx, raffleID) -} - -func (s *Service) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { - return s.raffleStore.UnSuspendRaffleTicket(ctx, raffleID) -} - -func (s *Service) CreateRaffleTicket(ctx context.Context, raffleID, userID int32) (domain.RaffleTicket, error) { - return s.raffleStore.CreateRaffleTicket(ctx, raffleID, userID) +func (s *Service) CreateRaffleTicket(ctx context.Context, raffleTicketParams domain.CreateRaffleTicket) (domain.RaffleTicket, error) { + return s.raffleStore.CreateRaffleTicket(ctx, raffleTicketParams) } func (s *Service) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) { return s.raffleStore.GetUserRaffleTickets(ctx, userID) } + +func (s *Service) SuspendRaffleTicket(ctx context.Context, raffleTicketID int32) error { + return s.raffleStore.SuspendRaffleTicket(ctx, raffleTicketID) +} + +func (s *Service) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error { + return s.raffleStore.UnSuspendRaffleTicket(ctx, raffleID) +} diff --git a/internal/web_server/app.go b/internal/web_server/app.go index fa016c0..1d7adf6 100644 --- a/internal/web_server/app.go +++ b/internal/web_server/app.go @@ -18,6 +18,7 @@ import ( issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/report" @@ -57,6 +58,7 @@ type App struct { logger *slog.Logger NotidicationStore *notificationservice.Service referralSvc referralservice.ReferralStore + raffleSvc raffle.RaffleStore bonusSvc *bonus.Service port int settingSvc *settings.Service @@ -108,6 +110,7 @@ func NewApp( eventSvc event.Service, leagueSvc league.Service, referralSvc referralservice.ReferralStore, + raffleSvc raffle.RaffleStore, bonusSvc *bonus.Service, virtualGameSvc virtualgameservice.VirtualGameService, aleaVirtualGameService alea.AleaVirtualGameService, @@ -132,15 +135,15 @@ func NewApp( })) s := &App{ - veliVirtualGameService: veliVirtualGameService, - telebirrSvc: telebirrSvc, - arifpaySvc: arifpaySvc, - santimpaySvc: santimpaySvc, - issueReportingSvc: issueReportingSvc, - instSvc: instSvc, - currSvc: currSvc, - fiber: app, - port: port, + veliVirtualGameService: veliVirtualGameService, + telebirrSvc: telebirrSvc, + arifpaySvc: arifpaySvc, + santimpaySvc: santimpaySvc, + issueReportingSvc: issueReportingSvc, + instSvc: instSvc, + currSvc: currSvc, + fiber: app, + port: port, settingSvc: settingSvc, authSvc: authSvc, @@ -158,6 +161,7 @@ func NewApp( companySvc: companySvc, NotidicationStore: notidicationStore, referralSvc: referralSvc, + raffleSvc: raffleSvc, bonusSvc: bonusSvc, Logger: logger, prematchSvc: prematchSvc, diff --git a/internal/web_server/cron.go b/internal/web_server/cron.go index c18bbe5..ea828e5 100644 --- a/internal/web_server/cron.go +++ b/internal/web_server/cron.go @@ -254,8 +254,6 @@ func SetupReportandVirtualGameCronJobs( log.Printf("Cron jobs started. Reports will be saved to: %s", outputDir) } - - func ProcessBetCashback(ctx context.Context, betService *betSvc.Service) { c := cron.New(cron.WithSeconds()) diff --git a/internal/web_server/handlers/bet_handler.go b/internal/web_server/handlers/bet_handler.go index 31dac1b..b081512 100644 --- a/internal/web_server/handlers/bet_handler.go +++ b/internal/web_server/handlers/bet_handler.go @@ -224,6 +224,8 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI return domain.CreateBetRes{}, err } + // create raffle ticket here + return res, nil } diff --git a/internal/web_server/handlers/handlers.go b/internal/web_server/handlers/handlers.go index a59dbc9..673a871 100644 --- a/internal/web_server/handlers/handlers.go +++ b/internal/web_server/handlers/handlers.go @@ -18,6 +18,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/report" @@ -49,6 +50,7 @@ type Handler struct { notificationSvc *notificationservice.Service userSvc *user.Service referralSvc referralservice.ReferralStore + raffleSvc raffle.RaffleStore bonusSvc *bonus.Service reportSvc report.ReportStore chapaSvc *chapa.Service @@ -88,6 +90,7 @@ func New( chapaSvc *chapa.Service, walletSvc *wallet.Service, referralSvc referralservice.ReferralStore, + raffleSvc raffle.RaffleStore, bonusSvc *bonus.Service, virtualGameSvc virtualgameservice.VirtualGameService, aleaVirtualGameSvc alea.AleaVirtualGameService, @@ -122,6 +125,7 @@ func New( chapaSvc: chapaSvc, walletSvc: walletSvc, referralSvc: referralSvc, + raffleSvc: raffleSvc, bonusSvc: bonusSvc, validator: validator, userSvc: userSvc, diff --git a/internal/web_server/handlers/raffle_handler.go b/internal/web_server/handlers/raffle_handler.go new file mode 100644 index 0000000..d1b59ba --- /dev/null +++ b/internal/web_server/handlers/raffle_handler.go @@ -0,0 +1,216 @@ +package handlers + +import ( + "fmt" + "strconv" + "time" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" + "github.com/gofiber/fiber/v2" + "go.uber.org/zap" +) + +func (h *Handler) CreateRaffle(c *fiber.Ctx) error { + var req domain.CreateRaffle + if err := c.BodyParser(&req); err != nil { + h.mongoLoggerSvc.Info("Failed to parse raffle request", + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") + } + + if valErrs, ok := h.validator.Validate(c, req); !ok { + var errMsg string + for field, msg := range valErrs { + errMsg += fmt.Sprintf("%s: %s; ", field, msg) + } + h.mongoLoggerSvc.Info("Failed to validate settings", + zap.String("errMsg", errMsg), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, errMsg) + } + + raffle, err := h.raffleSvc.CreateRaffle(c.Context(), req) + if err != nil { + h.mongoLoggerSvc.Error("Failed to create raffle", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to create raffle") + } + + return response.WriteJSON(c, fiber.StatusOK, "Raffle created successfully", raffle, nil) +} + +func (h *Handler) DeleteRaffle(c *fiber.Ctx) error { + stringRaffleID := c.Params("id") + raffleID, err := strconv.Atoi(stringRaffleID) + if err != nil { + h.mongoLoggerSvc.Info("failed to parse raffle id", + zap.String("stringRaffleID", stringRaffleID), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid raffle id") + } + + raffle, err := h.raffleSvc.DeleteRaffle(c.Context(), int32(raffleID)) + if err != nil { + fmt.Println("raffle delete error: ", err) + h.mongoLoggerSvc.Error("Failed to delete raffle", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete raffle") + } + + return response.WriteJSON(c, fiber.StatusOK, "Raffle deleted successfully", raffle, nil) +} + +func (h *Handler) GetRafflesOfCompany(c *fiber.Ctx) error { + stringCompanyID := c.Params("id") + companyID, err := strconv.Atoi(stringCompanyID) + if err != nil || companyID == 0 { + h.mongoLoggerSvc.Info("failed to parse company id", + zap.String("stringCompanyID", stringCompanyID), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid company ID") + } + + companyRaffles, err := h.raffleSvc.GetRafflesOfCompany(c.Context(), int32(companyID)) + 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) CreateRaffleTicket(c *fiber.Ctx) error { + var req domain.CreateRaffleTicket + if err := c.BodyParser(&req); err != nil { + h.mongoLoggerSvc.Info("Failed to parse raffle ticket request", + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") + } + + if valErrs, ok := h.validator.Validate(c, req); !ok { + var errMsg string + for field, msg := range valErrs { + errMsg += fmt.Sprintf("%s: %s; ", field, msg) + } + h.mongoLoggerSvc.Info("Failed to validate settings", + zap.String("errMsg", errMsg), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, errMsg) + } + + raffleTicket, err := h.raffleSvc.CreateRaffleTicket(c.Context(), req) + if err != nil { + h.mongoLoggerSvc.Error("Failed to create raffle ticket", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to create raffle ticket") + } + + return response.WriteJSON(c, fiber.StatusOK, "Raffle created successfully", raffleTicket, nil) +} + +func (h *Handler) GetUserRaffleTickets(c *fiber.Ctx) error { + stringUserID := c.Params("id") + userID, err := strconv.Atoi(stringUserID) + if err != nil { + h.mongoLoggerSvc.Info("failed to parse company id", + zap.String("stringUserID", stringUserID), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + + raffleTickets, err := h.raffleSvc.GetUserRaffleTickets(c.Context(), int32(userID)) + if err != nil { + h.mongoLoggerSvc.Error("Failed to fetch user raffle tickets", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch user raffle tickets") + } + + return response.WriteJSON(c, fiber.StatusOK, "User raffle tickets fetched successfully", raffleTickets, nil) +} + +func (h *Handler) SuspendRaffleTicket(c *fiber.Ctx) error { + stringRaffleTicketID := c.Params("id") + raffleTicketID, err := strconv.Atoi(stringRaffleTicketID) + if err != nil { + h.mongoLoggerSvc.Info("failed to parse raffle ticket id", + zap.String("stringUserID", stringRaffleTicketID), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid raffel ticket id") + } + + if err := h.raffleSvc.SuspendRaffleTicket(c.Context(), int32(raffleTicketID)); err != nil { + h.mongoLoggerSvc.Error("Failed to suspend raffle ticket", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to suspend raffle ticket") + } + + return response.WriteJSON(c, fiber.StatusOK, "User raffle tickets suspended successfully", nil, nil) +} + +func (h *Handler) UnSuspendRaffleTicket(c *fiber.Ctx) error { + stringRaffleTicketID := c.Params("id") + raffleTicketID, err := strconv.Atoi(stringRaffleTicketID) + if err != nil { + h.mongoLoggerSvc.Info("failed to parse raffle ticket id", + zap.String("stringUserID", stringRaffleTicketID), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid raffel ticket id") + } + + if err := h.raffleSvc.UnSuspendRaffleTicket(c.Context(), int32(raffleTicketID)); err != nil { + h.mongoLoggerSvc.Error("Failed to unsuspend raffle ticket", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to unsuspend raffle ticket") + } + + return response.WriteJSON(c, fiber.StatusOK, "User raffle tickets unsuspended successfully", nil, nil) + +} diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index 82e49e8..d9bfdf0 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -34,6 +34,7 @@ func (a *App) initAppRoutes() { a.chapaSvc, a.walletSvc, a.referralSvc, + a.raffleSvc, a.bonusSvc, a.virtualGameSvc, a.aleaVirtualGameService, @@ -163,6 +164,15 @@ func (a *App) initAppRoutes() { groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings) groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings) + // Raffle Routes + 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.Post("/raffle-ticket/create", a.authMiddleware, h.CreateRaffleTicket) + a.fiber.Get("/raffle-ticket/:id", a.authMiddleware, h.GetUserRaffleTickets) + a.fiber.Get("/raffle-ticket/suspend/:id", a.authMiddleware, h.SuspendRaffleTicket) + a.fiber.Get("/raffle-ticket/unsuspend/:id", a.authMiddleware, h.UnSuspendRaffleTicket) + // Bonus Routes groupV1.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier) groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier) @@ -254,7 +264,6 @@ func (a *App) initAppRoutes() { tenant.Get("/ticket/:id", h.GetTicketByID) // Bet Routes - tenantAuth.Post("/sport/bet", h.CreateBet) tenantAuth.Post("/sport/bet/fastcode", h.CreateBetWithFastCode) tenant.Get("/sport/bet/fastcode/:fast_code", h.GetBetByFastCode) tenantAuth.Get("/sport/bet", h.GetAllBet)