Merge remote-tracking branch 'refs/remotes/origin/main'
This commit is contained in:
commit
87b7841373
|
|
@ -37,6 +37,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/currency"
|
||||
enetpulse "github.com/SamuelTariku/FortuneBet-Backend/internal/services/enet_pulse"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||
|
|
@ -206,7 +207,12 @@ func main() {
|
|||
|
||||
// Start cron jobs for automated reporting
|
||||
|
||||
// Initialize wallet monitoring
|
||||
enetPulseSvc := enetpulse.New(
|
||||
*cfg,
|
||||
store,
|
||||
)
|
||||
|
||||
// Initialize wallet monitoring service
|
||||
walletMonitorSvc := monitor.NewService(
|
||||
*walletSvc,
|
||||
*branchSvc,
|
||||
|
|
@ -246,6 +252,7 @@ func main() {
|
|||
|
||||
// Initialize and start HTTP server
|
||||
app := httpserver.NewApp(
|
||||
enetPulseSvc,
|
||||
atlasVirtualGameService,
|
||||
veliVirtualGameService,
|
||||
telebirrSvc,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ var (
|
|||
ErrMissingTwilioSenderPhoneNumber = errors.New("missing twilio sender phone number")
|
||||
)
|
||||
|
||||
type EnetPulseConfig struct {
|
||||
UserName string `mapstructure:"username"` // "https://api.aleaplay.com"
|
||||
Token string `mapstructure:"token"` // Your operator ID with Alea
|
||||
}
|
||||
|
||||
type AleaPlayConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
BaseURL string `mapstructure:"base_url"` // "https://api.aleaplay.com"
|
||||
|
|
@ -132,6 +137,7 @@ type Config struct {
|
|||
CHAPA_CALLBACK_URL string
|
||||
CHAPA_RETURN_URL string
|
||||
Bet365Token string
|
||||
EnetPulseConfig EnetPulseConfig
|
||||
PopOK domain.PopOKConfig
|
||||
AleaPlay AleaPlayConfig `mapstructure:"alea_play"`
|
||||
Atlas AtlasConfig `mapstructure:"atlas"`
|
||||
|
|
@ -171,6 +177,9 @@ func (c *Config) loadEnv() error {
|
|||
|
||||
c.RedisAddr = os.Getenv("REDIS_ADDR")
|
||||
|
||||
c.EnetPulseConfig.Token = os.Getenv("ENETPULSE_TOKEN")
|
||||
c.EnetPulseConfig.UserName = os.Getenv("ENETPULSE_USERNAME")
|
||||
|
||||
c.CHAPA_TRANSFER_TYPE = os.Getenv("CHAPA_TRANSFER_TYPE")
|
||||
c.CHAPA_PAYMENT_TYPE = os.Getenv("CHAPA_PAYMENT_TYPE")
|
||||
|
||||
|
|
|
|||
367
internal/domain/enet_pulse.go
Normal file
367
internal/domain/enet_pulse.go
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
package domain
|
||||
|
||||
type EnetPulseSport struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
N string `json:"n"`
|
||||
UT string `json:"ut"`
|
||||
}
|
||||
|
||||
type SportsResponse struct {
|
||||
Sports map[string]EnetPulseSport `json:"sports"`
|
||||
}
|
||||
|
||||
type TournamentTemplatesResponse struct {
|
||||
TournamentTemplates map[string]TournamentTemplate `json:"tournament_templates"`
|
||||
}
|
||||
|
||||
type TournamentTemplate struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SportFK string `json:"sportFK"`
|
||||
Gender string `json:"gender"`
|
||||
N string `json:"n"`
|
||||
UT string `json:"ut"`
|
||||
}
|
||||
|
||||
type TournamentTemplateParticipantsResponse struct {
|
||||
// Map of participant entries or whatever eAPI returns
|
||||
Participants map[string]TournamentParticipant `json:"participants"`
|
||||
}
|
||||
|
||||
type TournamentTemplateParticipant struct {
|
||||
ID string `json:"id"`
|
||||
DateFrom string `json:"date_from"`
|
||||
DateTo string `json:"date_to"`
|
||||
Active string `json:"active"`
|
||||
N string `json:"n"`
|
||||
UT string `json:"ut"`
|
||||
// plus nested participant info
|
||||
Participant interface{} `json:"participant"`
|
||||
}
|
||||
|
||||
// For optional parameters
|
||||
type ParticipantsOptions struct {
|
||||
IncludeProperties bool
|
||||
IncludeParticipantProperties bool
|
||||
IncludeParticipantSports bool
|
||||
IncludeCountries bool
|
||||
IncludeCountryCodes bool
|
||||
ParticipantType string
|
||||
}
|
||||
|
||||
type Tournament struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TournamentTemplateFK string `json:"tournament_templateFK"`
|
||||
N string `json:"n"`
|
||||
UT string `json:"ut"`
|
||||
}
|
||||
|
||||
type TournamentsResponse struct {
|
||||
Tournaments map[string]Tournament `json:"tournaments"`
|
||||
}
|
||||
|
||||
type TournamentParticipant struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Gender string `json:"gender"`
|
||||
CountryFK string `json:"countryFK"`
|
||||
Country string `json:"country_name"`
|
||||
}
|
||||
|
||||
type TournamentWithParticipants struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Participants map[string]map[string]interface{} `json:"participants"` // or a typed struct
|
||||
}
|
||||
|
||||
type TournamentParticipantsResponse struct {
|
||||
Tournaments map[string]TournamentWithParticipants `json:"tournaments"`
|
||||
}
|
||||
|
||||
type TournamentStage struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TournamentFK string `json:"tournamentFK"`
|
||||
Gender string `json:"gender"`
|
||||
CountryFK string `json:"countryFK"`
|
||||
StartDate string `json:"startdate"`
|
||||
EndDate string `json:"enddate"`
|
||||
N string `json:"n"`
|
||||
UT string `json:"ut"`
|
||||
CountryName string `json:"country_name"`
|
||||
}
|
||||
|
||||
type TournamentStagesResponse struct {
|
||||
TournamentStages map[string]TournamentStage `json:"tournament_stages"`
|
||||
}
|
||||
|
||||
type TournamentStageParticipant struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Gender string `json:"gender"`
|
||||
Type string `json:"type"`
|
||||
CountryFK string `json:"countryFK"`
|
||||
Country string `json:"country_name"`
|
||||
}
|
||||
|
||||
type TournamentStageWithParticipants struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TournamentFK string `json:"tournamentFK"`
|
||||
Participants map[string]map[string]interface{} `json:"participants"` // can refine later
|
||||
}
|
||||
|
||||
type TournamentStageParticipantsResponse struct {
|
||||
TournamentStages map[string]TournamentStageWithParticipants `json:"tournament_stages"`
|
||||
}
|
||||
|
||||
type DailyEventsRequest struct {
|
||||
SportFK int // one of these three required
|
||||
TournamentTemplateFK int
|
||||
TournamentStageFK int
|
||||
Date string // YYYY-MM-DD optional
|
||||
Live string // yes/no optional
|
||||
IncludeVenue string // yes/no optional
|
||||
StatusType string // e.g. inprogress, finished...
|
||||
IncludeEventProperties string // yes/no optional
|
||||
IncludeCountryCodes string // yes/no optional
|
||||
IncludeFirstLastName string // yes/no optional
|
||||
IncludeDeleted string // yes/no optional
|
||||
}
|
||||
|
||||
type DailyEventsResponse struct {
|
||||
Events map[string]struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StartDate string `json:"startdate"`
|
||||
Status string `json:"status"`
|
||||
// add other fields you care about from API
|
||||
} `json:"events"`
|
||||
}
|
||||
|
||||
type FixturesRequest struct {
|
||||
SportFK int
|
||||
TournamentTemplateFK int
|
||||
TournamentStageFK int
|
||||
LanguageTypeFK int
|
||||
Date string // YYYY-MM-DD
|
||||
Live string // "yes" | "no"
|
||||
IncludeVenue bool
|
||||
IncludeEventProperties bool
|
||||
IncludeCountryCodes bool
|
||||
IncludeFirstLastName bool
|
||||
}
|
||||
|
||||
// Adjust according to the real API response JSON
|
||||
type FixturesResponse struct {
|
||||
Events []FixtureEvent `json:"events"`
|
||||
}
|
||||
|
||||
type FixtureEvent struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StartDate string `json:"startdate"`
|
||||
// ... add more fields as per API
|
||||
}
|
||||
|
||||
type ResultsRequest struct {
|
||||
SportFK int
|
||||
TournamentTemplateFK int
|
||||
TournamentStageFK int
|
||||
LanguageTypeFK int
|
||||
Date string // YYYY-MM-DD
|
||||
Live string // "yes" | "no"
|
||||
IncludeVenue bool
|
||||
IncludeEventProperties bool
|
||||
IncludeCountryCodes bool
|
||||
IncludeFirstLastName bool
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// Adjust fields to match API JSON exactly
|
||||
type ResultsResponse struct {
|
||||
Events []ResultEvent `json:"events"`
|
||||
}
|
||||
|
||||
type ResultEvent struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StartDate string `json:"startdate"`
|
||||
Status string `json:"status"`
|
||||
// ... add more fields based on actual API
|
||||
}
|
||||
|
||||
type EventDetailsRequest struct {
|
||||
ID int
|
||||
IncludeLineups bool
|
||||
IncludeIncidents bool
|
||||
IncludeExtendedResults bool
|
||||
IncludeProperties bool
|
||||
IncludeLivestats bool
|
||||
IncludeVenue bool
|
||||
IncludeCountryCodes bool
|
||||
IncludeFirstLastName bool
|
||||
IncludeDeleted bool
|
||||
IncludeReference bool
|
||||
IncludeObjectParticipants bool
|
||||
IncludeEventIncidentRelation bool
|
||||
IncludeTeamProperties bool
|
||||
IncludeObjectRound bool
|
||||
}
|
||||
|
||||
// Adjust fields to match the actual JSON from Enetpulse
|
||||
type EventDetailsResponse struct {
|
||||
EventID string `json:"id"`
|
||||
EventName string `json:"name"`
|
||||
StartDate string `json:"startdate"`
|
||||
// Add additional nested structs/fields as needed based on API response
|
||||
}
|
||||
|
||||
type EventListRequest struct {
|
||||
TournamentFK int // optional
|
||||
TournamentStageFK int // optional
|
||||
IncludeEventProperties bool // default true
|
||||
StatusType string // e.g. "finished", "inprogress"
|
||||
IncludeVenue bool
|
||||
IncludeDeleted bool
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
// Adjust fields to match the actual JSON structure you get from Enetpulse
|
||||
type EventListResponse struct {
|
||||
Events map[string]struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StartDate string `json:"startdate"`
|
||||
// add more fields as per response
|
||||
} `json:"events"`
|
||||
}
|
||||
|
||||
type ParticipantFixturesRequest struct {
|
||||
ParticipantFK int // required
|
||||
|
||||
SportFK int
|
||||
TournamentFK int
|
||||
TournamentTemplateFK int
|
||||
TournamentStageFK int
|
||||
Date string
|
||||
Live string
|
||||
Limit int
|
||||
Offset int
|
||||
|
||||
IncludeVenue bool
|
||||
IncludeCountryCodes bool
|
||||
IncludeFirstLastName bool
|
||||
IncludeEventProperties bool
|
||||
LanguageTypeFK int
|
||||
}
|
||||
|
||||
// Adjust this to match the actual API response structure
|
||||
type ParticipantFixturesResponse struct {
|
||||
Events []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
// ... other fields from the API
|
||||
} `json:"events"`
|
||||
}
|
||||
|
||||
type ParticipantResultsRequest struct {
|
||||
ParticipantFK int64 `json:"participantFK"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
IncludeVenue bool `json:"includeVenue,omitempty"`
|
||||
IncludeDeleted bool `json:"includeDeleted,omitempty"`
|
||||
}
|
||||
|
||||
type ParticipantResultsResponse struct {
|
||||
// Adjust to match Enetpulse’s JSON structure
|
||||
Results []struct {
|
||||
EventFK int64 `json:"eventFK"`
|
||||
ParticipantFK int64 `json:"participantFK"`
|
||||
Score string `json:"score"`
|
||||
Status string `json:"status"`
|
||||
// add more fields as needed
|
||||
} `json:"results"`
|
||||
}
|
||||
|
||||
type TeamLogoResponse struct {
|
||||
ContentType string `json:"contentType"` // e.g. "image/png"
|
||||
Data []byte `json:"-"` // raw image bytes
|
||||
URL string `json:"url,omitempty"` // optional original URL
|
||||
}
|
||||
|
||||
type TeamShirtsResponse struct {
|
||||
ContentType string `json:"contentType"` // could be "application/json" or "image/png"
|
||||
RawData []byte `json:"-"` // raw response
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type ImageResponse struct {
|
||||
ContentType string `json:"contentType"` // e.g., "image/png"
|
||||
RawData []byte `json:"-"` // raw image bytes
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type PreMatchOddsRequest struct {
|
||||
ObjectFK int64 `json:"objectFK"`
|
||||
OddsProviderFK []int64 `json:"oddsProviderFK,omitempty"`
|
||||
OutcomeTypeFK int64 `json:"outcomeTypeFK,omitempty"`
|
||||
OutcomeScopeFK int64 `json:"outcomeScopeFK,omitempty"`
|
||||
OutcomeSubtypeFK int64 `json:"outcomeSubtypeFK,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
LanguageTypeFK int64 `json:"languageTypeFK,omitempty"`
|
||||
}
|
||||
|
||||
type PreMatchOddsResponse struct {
|
||||
// Define fields according to the Enetpulse preodds response structure
|
||||
// Example:
|
||||
EventID int64 `json:"eventFK"`
|
||||
Odds []PreMatchOutcome `json:"odds"`
|
||||
}
|
||||
|
||||
type PreMatchOutcome struct {
|
||||
OutcomeFK int64 `json:"outcomeFK"`
|
||||
OutcomeValue string `json:"outcomeValue"`
|
||||
OddsValue float64 `json:"oddsValue"`
|
||||
ProviderFK int64 `json:"oddsProviderFK"`
|
||||
OutcomeTypeFK int64 `json:"outcomeTypeFK"`
|
||||
}
|
||||
|
||||
type TournamentStageOddsRequest struct {
|
||||
ObjectFK int64 `json:"objectFK"` // Tournament stage ID
|
||||
OddsProviderFK int64 `json:"oddsProviderFK,omitempty"`
|
||||
OutcomeTypeFK int64 `json:"outcomeTypeFK"` // Mandatory
|
||||
OutcomeScopeFK int64 `json:"outcomeScopeFK,omitempty"`
|
||||
OutcomeSubtypeFK int64 `json:"outcomeSubtypeFK,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
LanguageTypeFK int64 `json:"languageTypeFK,omitempty"`
|
||||
}
|
||||
|
||||
type TournamentStageOddsResponse struct {
|
||||
// Define fields according to Enetpulse response
|
||||
StageID int64 `json:"objectFK"`
|
||||
Odds []PreMatchOutcome `json:"odds"` // reuse PreMatchOutcome from pre-match odds
|
||||
}
|
||||
|
||||
type TournamentOddsRequest struct {
|
||||
ObjectFK int64 `json:"objectFK"` // Tournament ID
|
||||
OddsProviderFK int64 `json:"oddsProviderFK,omitempty"`
|
||||
OutcomeTypeFK int64 `json:"outcomeTypeFK"` // Mandatory
|
||||
OutcomeScopeFK int64 `json:"outcomeScopeFK,omitempty"`
|
||||
OutcomeSubtypeFK int64 `json:"outcomeSubtypeFK,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
LanguageTypeFK int64 `json:"languageTypeFK,omitempty"`
|
||||
}
|
||||
|
||||
type TournamentOddsResponse struct {
|
||||
TournamentID int64 `json:"objectFK"`
|
||||
Odds []PreMatchOutcome `json:"odds"` // reuse PreMatchOutcome struct from pre-match odds
|
||||
}
|
||||
16
internal/services/enet_pulse/port.go
Normal file
16
internal/services/enet_pulse/port.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package enetpulse
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
||||
type EnetPulseService interface {
|
||||
FetchSports(ctx context.Context) error
|
||||
FetchTournamentTemplates(ctx context.Context) (*domain.TournamentTemplatesResponse, error)
|
||||
FetchTournamentTemplateParticipants(ctx context.Context, templateID string, opts domain.ParticipantsOptions) (*domain.TournamentTemplateParticipantsResponse, error)
|
||||
FetchTournaments(ctx context.Context, templateID string) error
|
||||
FetchTournamentParticipants(ctx context.Context, tournamentID string) error
|
||||
FetchPreMatchOdds(ctx context.Context, params domain.PreMatchOddsRequest) (*domain.PreMatchOddsResponse, error)
|
||||
}
|
||||
1114
internal/services/enet_pulse/service.go
Normal file
1114
internal/services/enet_pulse/service.go
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -444,14 +444,14 @@ func getString(v interface{}) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func getInt(v interface{}) int {
|
||||
func GetInt(v interface{}) int {
|
||||
if f, ok := v.(float64); ok {
|
||||
return int(f)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getInt32(v interface{}) int32 {
|
||||
func GetInt32(v interface{}) int32 {
|
||||
if n, err := strconv.Atoi(getString(v)); err == nil {
|
||||
return int32(n)
|
||||
}
|
||||
|
|
@ -489,6 +489,7 @@ func (s *service) GetUpcomingEventByID(ctx context.Context, ID string) (domain.B
|
|||
func (s *service) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
|
||||
return s.store.UpdateFinalScore(ctx, eventID, fullScore, status)
|
||||
}
|
||||
|
||||
func (s *service) UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error {
|
||||
return s.store.UpdateEventStatus(ctx, eventID, status)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,11 +70,23 @@ func (s *Service) AddProviders(ctx context.Context, req domain.ProviderRequest)
|
|||
Enabled: true,
|
||||
}
|
||||
|
||||
atlasParams := dbgen.CreateVirtualGameProviderParams{
|
||||
ProviderID: "atlas",
|
||||
ProviderName: "Atlas Gaming",
|
||||
LogoDark: pgtype.Text{String: "/static/logos/atlas-dark.png", Valid: true}, // adjust as needed
|
||||
LogoLight: pgtype.Text{String: "/static/logos/atlas-light.png", Valid: true}, // adjust as needed
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
if _, err := s.repo.CreateVirtualGameProvider(ctx, popokParams); err != nil {
|
||||
logger.Error("failed to add popok provider", zap.Any("popokParams", popokParams), zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to add popok provider: %w", err)
|
||||
}
|
||||
|
||||
if _, err := s.repo.CreateVirtualGameProvider(ctx, atlasParams); err != nil {
|
||||
return nil, fmt.Errorf("failed to add atlas provider: %w", err)
|
||||
}
|
||||
|
||||
// Optionally also append it to the response for consistency
|
||||
// res.Items = append(res.Items, domain.VirtualGameProvider{
|
||||
// ProviderID: uuid.New().String(),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,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/currency"
|
||||
enetpulse "github.com/SamuelTariku/FortuneBet-Backend/internal/services/enet_pulse"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||
|
|
@ -45,6 +46,7 @@ import (
|
|||
)
|
||||
|
||||
type App struct {
|
||||
enetPulseSvc *enetpulse.Service
|
||||
atlasVirtualGameService atlas.AtlasVirtualGameService
|
||||
veliVirtualGameService veli.VeliVirtualGameService
|
||||
telebirrSvc *telebirr.TelebirrService
|
||||
|
|
@ -86,6 +88,7 @@ type App struct {
|
|||
}
|
||||
|
||||
func NewApp(
|
||||
enetPulseSvc *enetpulse.Service,
|
||||
atlasVirtualGameService atlas.AtlasVirtualGameService,
|
||||
veliVirtualGameService veli.VeliVirtualGameService,
|
||||
telebirrSvc *telebirr.TelebirrService,
|
||||
|
|
@ -140,6 +143,7 @@ func NewApp(
|
|||
app.Static("/static", "./static")
|
||||
|
||||
s := &App{
|
||||
enetPulseSvc: enetPulseSvc,
|
||||
atlasVirtualGameService: atlasVirtualGameService,
|
||||
veliVirtualGameService: veliVirtualGameService,
|
||||
telebirrSvc: telebirrSvc,
|
||||
|
|
|
|||
94
internal/web_server/handlers/enet_pulse.go
Normal file
94
internal/web_server/handlers/enet_pulse.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// GetPreMatchOdds godoc
|
||||
// @Summary Get pre-match odds for an event
|
||||
// @Description Fetches pre-match odds from EnetPulse for a given event
|
||||
// @Tags EnetPulse - PreMatch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param objectFK query int true "Event ID"
|
||||
// @Param oddsProviderFK query []int false "Odds provider IDs (comma separated)"
|
||||
// @Param outcomeTypeFK query int false "Outcome type ID"
|
||||
// @Param outcomeScopeFK query int false "Outcome scope ID"
|
||||
// @Param outcomeSubtypeFK query int false "Outcome subtype ID"
|
||||
// @Param limit query int false "Limit results"
|
||||
// @Param offset query int false "Offset results"
|
||||
// @Param languageTypeFK query int false "Language type ID"
|
||||
// @Success 200 {object} domain.Response{data=domain.PreMatchOddsResponse}
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 502 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/odds/pre-match [get]
|
||||
func (h *Handler) GetPreMatchOdds(c *fiber.Ctx) error {
|
||||
// Parse query parameters
|
||||
objectFK := c.QueryInt("objectFK")
|
||||
if objectFK == 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Event ID (objectFK) is required",
|
||||
Error: "missing or invalid objectFK",
|
||||
})
|
||||
}
|
||||
|
||||
params := domain.PreMatchOddsRequest{
|
||||
ObjectFK: int64(objectFK),
|
||||
OddsProviderFK: intSliceToInt64Slice(parseIntSlice(c.Query("oddsProviderFK"))), // convert []int to []int64
|
||||
OutcomeTypeFK: int64(c.QueryInt("outcomeTypeFK")),
|
||||
OutcomeScopeFK: int64(c.QueryInt("outcomeScopeFK")),
|
||||
OutcomeSubtypeFK: int64(c.QueryInt("outcomeSubtypeFK")),
|
||||
Limit: c.QueryInt("limit"),
|
||||
Offset: c.QueryInt("offset"),
|
||||
LanguageTypeFK: int64(c.QueryInt("languageTypeFK")),
|
||||
}
|
||||
|
||||
// Call service
|
||||
res, err := h.enetPulseSvc.FetchPreMatchOdds(c.Context(), params)
|
||||
if err != nil {
|
||||
log.Println("FetchPreMatchOdds error:", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch pre-match odds",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Pre-match odds fetched successfully",
|
||||
Data: res,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Helper: parse comma-separated string into []int
|
||||
func parseIntSlice(input string) []int {
|
||||
if input == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(input, ",")
|
||||
result := make([]int, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
if n, err := strconv.Atoi(strings.TrimSpace(p)); err == nil {
|
||||
result = append(result, n)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Helper: convert []int to []int64
|
||||
func intSliceToInt64Slice(input []int) []int64 {
|
||||
if input == nil {
|
||||
return nil
|
||||
}
|
||||
result := make([]int64, len(input))
|
||||
for i, v := range input {
|
||||
result[i] = int64(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -12,6 +12,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/currency"
|
||||
enetpulse "github.com/SamuelTariku/FortuneBet-Backend/internal/services/enet_pulse"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||
|
|
@ -40,6 +41,7 @@ import (
|
|||
)
|
||||
|
||||
type Handler struct {
|
||||
enetPulseSvc *enetpulse.Service
|
||||
telebirrSvc *telebirr.TelebirrService
|
||||
arifpaySvc *arifpay.ArifpayService
|
||||
santimpaySvc *santimpay.SantimPayService
|
||||
|
|
@ -78,6 +80,7 @@ type Handler struct {
|
|||
}
|
||||
|
||||
func New(
|
||||
enetPulseSvc *enetpulse.Service,
|
||||
telebirrSvc *telebirr.TelebirrService,
|
||||
arifpaySvc *arifpay.ArifpayService,
|
||||
santimpaySvc *santimpay.SantimPayService,
|
||||
|
|
@ -115,6 +118,7 @@ func New(
|
|||
mongoLoggerSvc *zap.Logger,
|
||||
) *Handler {
|
||||
return &Handler{
|
||||
enetPulseSvc: enetPulseSvc,
|
||||
telebirrSvc: telebirrSvc,
|
||||
arifpaySvc: arifpaySvc,
|
||||
santimpaySvc: santimpaySvc,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
func (a *App) initAppRoutes() {
|
||||
h := handlers.New(
|
||||
a.enetPulseSvc,
|
||||
a.telebirrSvc,
|
||||
a.arifpaySvc,
|
||||
a.santimpaySvc,
|
||||
|
|
@ -268,6 +269,9 @@ func (a *App) initAppRoutes() {
|
|||
tenant.Get("/top-leagues", h.GetTopLeagues)
|
||||
tenant.Put("/events/:id/settings", h.UpdateEventSettings)
|
||||
|
||||
//EnetPulse
|
||||
groupV1.Get("/odds/pre-match", h.GetPreMatchOdds)
|
||||
|
||||
// Leagues
|
||||
tenant.Get("/leagues", h.GetAllLeagues)
|
||||
tenant.Put("/leagues/:id/set-active", h.SetLeagueActive)
|
||||
|
|
|
|||
BIN
static/logos/atlas-dark.png
Normal file
BIN
static/logos/atlas-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
static/logos/atlas-light.png
Normal file
BIN
static/logos/atlas-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
Loading…
Reference in New Issue
Block a user