diff --git a/cmd/main.go b/cmd/main.go index cd98778..c271ec9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -23,6 +23,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/company" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" @@ -86,6 +87,7 @@ func main() { transactionSvc := transaction.NewService(store) branchSvc := branch.NewService(store) companySvc := company.NewService(store) + leagueSvc := league.New(store) betSvc := bet.NewService(store, eventSvc, oddsSvc, *walletSvc, *branchSvc, logger) resultSvc := result.NewService(store, cfg, logger, *betSvc) notificationRepo := repository.NewNotificationRepository(store) @@ -128,7 +130,7 @@ func main() { JwtAccessKey: cfg.JwtKey, JwtAccessExpiry: cfg.AccessExpiry, }, userSvc, - ticketSvc, betSvc, chapaSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, referalSvc, virtualGameSvc, aleaService, veliService, recommendationSvc, resultSvc, cfg) + ticketSvc, betSvc, chapaSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, leagueSvc, referalSvc, virtualGameSvc, aleaService, veliService, recommendationSvc, resultSvc, cfg) logger.Info("Starting server", "port", cfg.Port) if err := app.Run(); err != nil { diff --git a/db/migrations/000001_fortune.up.sql b/db/migrations/000001_fortune.up.sql index b2cb0aa..30a006b 100644 --- a/db/migrations/000001_fortune.up.sql +++ b/db/migrations/000001_fortune.up.sql @@ -240,6 +240,13 @@ CREATE TABLE leagues ( bet365_id INT, is_active BOOLEAN DEFAULT true ); +CREATE TABLE teams ( + id TEXT PRIMARY KEY, + team_name TEXT NOT NULL, + country TEXT, + bet365_id INT, + logo_url TEXT +); -- Views CREATE VIEW companies_details AS SELECT companies.*, diff --git a/db/query/leagues.sql b/db/query/leagues.sql index b4905c8..b9c0e02 100644 --- a/db/query/leagues.sql +++ b/db/query/leagues.sql @@ -21,6 +21,13 @@ SELECT id, is_active FROM leagues WHERE is_active = true; +-- name: GetAllLeagues :many +SELECT id, + name, + country_code, + bet365_id, + is_active +FROM leagues; -- name: CheckLeagueSupport :one SELECT EXISTS( SELECT 1 @@ -34,4 +41,8 @@ SET name = $1, country_code = $2, bet365_id = $3, is_active = $4 -WHERE id = $5; \ No newline at end of file +WHERE id = $5; +-- name: SetLeagueActive :exec +UPDATE leagues +SET is_active = true +WHERE id = $1; \ No newline at end of file diff --git a/gen/db/leagues.sql.go b/gen/db/leagues.sql.go index e8589dd..49c1555 100644 --- a/gen/db/leagues.sql.go +++ b/gen/db/leagues.sql.go @@ -27,6 +27,41 @@ func (q *Queries) CheckLeagueSupport(ctx context.Context, id int64) (bool, error return exists, err } +const GetAllLeagues = `-- name: GetAllLeagues :many +SELECT id, + name, + country_code, + bet365_id, + is_active +FROM leagues +` + +func (q *Queries) GetAllLeagues(ctx context.Context) ([]League, error) { + rows, err := q.db.Query(ctx, GetAllLeagues) + if err != nil { + return nil, err + } + defer rows.Close() + var items []League + for rows.Next() { + var i League + if err := rows.Scan( + &i.ID, + &i.Name, + &i.CountryCode, + &i.Bet365ID, + &i.IsActive, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const GetSupportedLeagues = `-- name: GetSupportedLeagues :many SELECT id, name, @@ -99,6 +134,17 @@ func (q *Queries) InsertLeague(ctx context.Context, arg InsertLeagueParams) erro return err } +const SetLeagueActive = `-- name: SetLeagueActive :exec +UPDATE leagues +SET is_active = true +WHERE id = $1 +` + +func (q *Queries) SetLeagueActive(ctx context.Context, id int64) error { + _, err := q.db.Exec(ctx, SetLeagueActive, id) + return err +} + const UpdateLeague = `-- name: UpdateLeague :exec UPDATE leagues SET name = $1, diff --git a/internal/repository/league.go b/internal/repository/league.go index 1bbec9c..7e5205f 100644 --- a/internal/repository/league.go +++ b/internal/repository/league.go @@ -37,20 +37,34 @@ func (s *Store) GetSupportedLeagues(ctx context.Context) ([]domain.League, error return supportedLeagues, nil } +func (s *Store) GetAllLeagues(ctx context.Context) ([]domain.League, error) { + l, err := s.queries.GetAllLeagues(ctx) + if err != nil { + return nil, err + } + + leagues := make([]domain.League, len(l)) + for i, league := range l { + leagues[i] = domain.League{ + ID: league.ID, + Name: league.Name, + CountryCode: league.CountryCode.String, + Bet365ID: league.Bet365ID.Int32, + IsActive: league.IsActive.Bool, + } + } + return leagues, nil +} + func (s *Store) CheckLeagueSupport(ctx context.Context, leagueID int64) (bool, error) { return s.queries.CheckLeagueSupport(ctx, leagueID) } -// TODO: change to only take league id instad of the whole league -func (s *Store) SetLeagueActive(ctx context.Context, l domain.League) error { - return s.queries.UpdateLeague(ctx, dbgen.UpdateLeagueParams{ - Name: l.Name, - CountryCode: pgtype.Text{String: l.CountryCode, Valid: true}, - Bet365ID: pgtype.Int4{Int32: l.Bet365ID, Valid: true}, - IsActive: pgtype.Bool{Bool: true, Valid: true}, - }) +func (s *Store) SetLeagueActive(ctx context.Context, leagueId int64) error { + return s.queries.SetLeagueActive(ctx, leagueId) } +// TODO: update based on id, no need for the entire league (same as the set active one) func (s *Store) SetLeagueInActive(ctx context.Context, l domain.League) error { return s.queries.UpdateLeague(ctx, dbgen.UpdateLeagueParams{ Name: l.Name, diff --git a/internal/services/league/port.go b/internal/services/league/port.go new file mode 100644 index 0000000..7b71a48 --- /dev/null +++ b/internal/services/league/port.go @@ -0,0 +1,12 @@ +package league + +import ( + "context" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" +) + +type Service interface { + GetAllLeagues(ctx context.Context) ([]domain.League, error) + SetLeagueActive(ctx context.Context, leagueId int64) error +} diff --git a/internal/services/league/service.go b/internal/services/league/service.go new file mode 100644 index 0000000..b1f05ed --- /dev/null +++ b/internal/services/league/service.go @@ -0,0 +1,26 @@ +package league + +import ( + "context" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/repository" +) + +type service struct { + store *repository.Store +} + +func New(store *repository.Store) Service { + return &service{ + store: store, + } +} + +func (s *service) GetAllLeagues(ctx context.Context) ([]domain.League, error) { + return s.store.GetAllLeagues(ctx) +} + +func (s *service) SetLeagueActive(ctx context.Context, leagueId int64) error { + return s.store.SetLeagueActive(ctx, leagueId) +} diff --git a/internal/web_server/app.go b/internal/web_server/app.go index d7c0b46..0a50ef7 100644 --- a/internal/web_server/app.go +++ b/internal/web_server/app.go @@ -11,6 +11,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/company" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal" @@ -56,6 +57,7 @@ type App struct { Logger *slog.Logger prematchSvc *odds.ServiceImpl eventSvc event.Service + leagueSvc league.Service resultSvc *result.Service } @@ -75,6 +77,7 @@ func NewApp( notidicationStore *notificationservice.Service, prematchSvc *odds.ServiceImpl, eventSvc event.Service, + leagueSvc league.Service, referralSvc referralservice.ReferralStore, virtualGameSvc virtualgameservice.VirtualGameService, aleaVirtualGameService alea.AleaVirtualGameService, @@ -117,6 +120,7 @@ func NewApp( Logger: logger, prematchSvc: prematchSvc, eventSvc: eventSvc, + leagueSvc: leagueSvc, virtualGameSvc: virtualGameSvc, aleaVirtualGameService: aleaVirtualGameService, veliVirtualGameService: veliVirtualGameService, diff --git a/internal/web_server/handlers/handlers.go b/internal/web_server/handlers/handlers.go index 6c42024..f6665d7 100644 --- a/internal/web_server/handlers/handlers.go +++ b/internal/web_server/handlers/handlers.go @@ -10,6 +10,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/company" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation" @@ -39,6 +40,7 @@ type Handler struct { companySvc *company.Service prematchSvc *odds.ServiceImpl eventSvc event.Service + leagueSvc league.Service virtualGameSvc virtualgameservice.VirtualGameService aleaVirtualGameSvc alea.AleaVirtualGameService veliVirtualGameSvc veli.VeliVirtualGameService @@ -70,6 +72,7 @@ func New( companySvc *company.Service, prematchSvc *odds.ServiceImpl, eventSvc event.Service, + leagueSvc league.Service, cfg *config.Config, ) *Handler { return &Handler{ @@ -87,6 +90,7 @@ func New( companySvc: companySvc, prematchSvc: prematchSvc, eventSvc: eventSvc, + leagueSvc: leagueSvc, virtualGameSvc: virtualGameSvc, aleaVirtualGameSvc: aleaVirtualGameSvc, veliVirtualGameSvc: veliVirtualGameSvc, diff --git a/internal/web_server/handlers/leagues.go b/internal/web_server/handlers/leagues.go new file mode 100644 index 0000000..d4f78ee --- /dev/null +++ b/internal/web_server/handlers/leagues.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "strconv" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" + "github.com/gofiber/fiber/v2" +) + +func (h *Handler) GetAllLeagues(c *fiber.Ctx) error { + leagues, err := h.leagueSvc.GetAllLeagues(c.Context()) + if err != nil { + return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get leagues", err, nil) + } + + return response.WriteJSON(c, fiber.StatusOK, "All leagues retrived", leagues, nil) +} + +func (h *Handler) SetLeagueActive(c *fiber.Ctx) error { + leagueIdStr := c.Params("id") + if leagueIdStr == "" { + response.WriteJSON(c, fiber.StatusBadRequest, "Missing league id", nil, nil) + } + leagueId, err := strconv.Atoi(leagueIdStr) + if err != nil { + response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil) + } + + if err := h.leagueSvc.SetLeagueActive(c.Context(), int64(leagueId)); err != nil { + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update league", err, nil) + } + + return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil) +} diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index 88e8a2f..eaa2939 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -35,6 +35,7 @@ func (a *App) initAppRoutes() { a.companySvc, a.prematchSvc, a.eventSvc, + a.leagueSvc, a.cfg, ) @@ -114,13 +115,17 @@ func (a *App) initAppRoutes() { a.fiber.Put("/managers/:id", a.authMiddleware, h.UpdateManagers) a.fiber.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID) - a.fiber.Get("/prematch/odds/:event_id", h.GetPrematchOdds) - a.fiber.Get("/prematch/odds", h.GetALLPrematchOdds) - a.fiber.Get("/prematch/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID) + a.fiber.Get("/events/odds/:event_id", h.GetPrematchOdds) + a.fiber.Get("/events/odds", h.GetALLPrematchOdds) + a.fiber.Get("/events/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID) - a.fiber.Get("/prematch/events/:id", h.GetUpcomingEventByID) - a.fiber.Get("/prematch/events", h.GetAllUpcomingEvents) - a.fiber.Get("/prematch/odds/upcoming/:upcoming_id", h.GetPrematchOddsByUpcomingID) + a.fiber.Get("/events/:id", h.GetUpcomingEventByID) + a.fiber.Get("/events", h.GetAllUpcomingEvents) + a.fiber.Get("/events/odds/upcoming/:upcoming_id", h.GetPrematchOddsByUpcomingID) + + // Leagues + a.fiber.Get("/leagues", h.GetAllLeagues) + a.fiber.Get("/leagues/:id/set-active", h.SetLeagueActive) // Swagger a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler()) diff --git a/makefile b/makefile index 303a8cc..a40a255 100644 --- a/makefile +++ b/makefile @@ -56,8 +56,6 @@ db-up: db-down: @docker compose down @docker volume rm fortunebet-backend_postgres_data -postgres: - @docker exec -it fortunebet-backend-postgres-1 psql -U root -d gh .PHONY: sqlc-gen sqlc-gen: @sqlc generate \ No newline at end of file