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/chapa"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/currency"
|
"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/event"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||||
|
|
@ -206,7 +207,12 @@ func main() {
|
||||||
|
|
||||||
// Start cron jobs for automated reporting
|
// Start cron jobs for automated reporting
|
||||||
|
|
||||||
// Initialize wallet monitoring
|
enetPulseSvc := enetpulse.New(
|
||||||
|
*cfg,
|
||||||
|
store,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initialize wallet monitoring service
|
||||||
walletMonitorSvc := monitor.NewService(
|
walletMonitorSvc := monitor.NewService(
|
||||||
*walletSvc,
|
*walletSvc,
|
||||||
*branchSvc,
|
*branchSvc,
|
||||||
|
|
@ -246,6 +252,7 @@ func main() {
|
||||||
|
|
||||||
// Initialize and start HTTP server
|
// Initialize and start HTTP server
|
||||||
app := httpserver.NewApp(
|
app := httpserver.NewApp(
|
||||||
|
enetPulseSvc,
|
||||||
atlasVirtualGameService,
|
atlasVirtualGameService,
|
||||||
veliVirtualGameService,
|
veliVirtualGameService,
|
||||||
telebirrSvc,
|
telebirrSvc,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@ var (
|
||||||
ErrMissingTwilioSenderPhoneNumber = errors.New("missing twilio sender phone number")
|
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 {
|
type AleaPlayConfig struct {
|
||||||
Enabled bool `mapstructure:"enabled"`
|
Enabled bool `mapstructure:"enabled"`
|
||||||
BaseURL string `mapstructure:"base_url"` // "https://api.aleaplay.com"
|
BaseURL string `mapstructure:"base_url"` // "https://api.aleaplay.com"
|
||||||
|
|
@ -132,6 +137,7 @@ type Config struct {
|
||||||
CHAPA_CALLBACK_URL string
|
CHAPA_CALLBACK_URL string
|
||||||
CHAPA_RETURN_URL string
|
CHAPA_RETURN_URL string
|
||||||
Bet365Token string
|
Bet365Token string
|
||||||
|
EnetPulseConfig EnetPulseConfig
|
||||||
PopOK domain.PopOKConfig
|
PopOK domain.PopOKConfig
|
||||||
AleaPlay AleaPlayConfig `mapstructure:"alea_play"`
|
AleaPlay AleaPlayConfig `mapstructure:"alea_play"`
|
||||||
Atlas AtlasConfig `mapstructure:"atlas"`
|
Atlas AtlasConfig `mapstructure:"atlas"`
|
||||||
|
|
@ -171,6 +177,9 @@ func (c *Config) loadEnv() error {
|
||||||
|
|
||||||
c.RedisAddr = os.Getenv("REDIS_ADDR")
|
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_TRANSFER_TYPE = os.Getenv("CHAPA_TRANSFER_TYPE")
|
||||||
c.CHAPA_PAYMENT_TYPE = os.Getenv("CHAPA_PAYMENT_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 ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInt(v interface{}) int {
|
func GetInt(v interface{}) int {
|
||||||
if f, ok := v.(float64); ok {
|
if f, ok := v.(float64); ok {
|
||||||
return int(f)
|
return int(f)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInt32(v interface{}) int32 {
|
func GetInt32(v interface{}) int32 {
|
||||||
if n, err := strconv.Atoi(getString(v)); err == nil {
|
if n, err := strconv.Atoi(getString(v)); err == nil {
|
||||||
return int32(n)
|
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 {
|
func (s *service) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
|
||||||
return s.store.UpdateFinalScore(ctx, eventID, fullScore, status)
|
return s.store.UpdateFinalScore(ctx, eventID, fullScore, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error {
|
func (s *service) UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error {
|
||||||
return s.store.UpdateEventStatus(ctx, eventID, status)
|
return s.store.UpdateEventStatus(ctx, eventID, status)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,23 @@ func (s *Service) AddProviders(ctx context.Context, req domain.ProviderRequest)
|
||||||
Enabled: true,
|
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 {
|
if _, err := s.repo.CreateVirtualGameProvider(ctx, popokParams); err != nil {
|
||||||
logger.Error("failed to add popok provider", zap.Any("popokParams", popokParams), zap.Error(err))
|
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)
|
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
|
// Optionally also append it to the response for consistency
|
||||||
// res.Items = append(res.Items, domain.VirtualGameProvider{
|
// res.Items = append(res.Items, domain.VirtualGameProvider{
|
||||||
// ProviderID: uuid.New().String(),
|
// ProviderID: uuid.New().String(),
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/chapa"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/currency"
|
"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/event"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||||
|
|
@ -45,6 +46,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
|
enetPulseSvc *enetpulse.Service
|
||||||
atlasVirtualGameService atlas.AtlasVirtualGameService
|
atlasVirtualGameService atlas.AtlasVirtualGameService
|
||||||
veliVirtualGameService veli.VeliVirtualGameService
|
veliVirtualGameService veli.VeliVirtualGameService
|
||||||
telebirrSvc *telebirr.TelebirrService
|
telebirrSvc *telebirr.TelebirrService
|
||||||
|
|
@ -86,6 +88,7 @@ type App struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApp(
|
func NewApp(
|
||||||
|
enetPulseSvc *enetpulse.Service,
|
||||||
atlasVirtualGameService atlas.AtlasVirtualGameService,
|
atlasVirtualGameService atlas.AtlasVirtualGameService,
|
||||||
veliVirtualGameService veli.VeliVirtualGameService,
|
veliVirtualGameService veli.VeliVirtualGameService,
|
||||||
telebirrSvc *telebirr.TelebirrService,
|
telebirrSvc *telebirr.TelebirrService,
|
||||||
|
|
@ -140,6 +143,7 @@ func NewApp(
|
||||||
app.Static("/static", "./static")
|
app.Static("/static", "./static")
|
||||||
|
|
||||||
s := &App{
|
s := &App{
|
||||||
|
enetPulseSvc: enetPulseSvc,
|
||||||
atlasVirtualGameService: atlasVirtualGameService,
|
atlasVirtualGameService: atlasVirtualGameService,
|
||||||
veliVirtualGameService: veliVirtualGameService,
|
veliVirtualGameService: veliVirtualGameService,
|
||||||
telebirrSvc: telebirrSvc,
|
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/chapa"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/currency"
|
"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/event"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||||
|
|
@ -40,6 +41,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
enetPulseSvc *enetpulse.Service
|
||||||
telebirrSvc *telebirr.TelebirrService
|
telebirrSvc *telebirr.TelebirrService
|
||||||
arifpaySvc *arifpay.ArifpayService
|
arifpaySvc *arifpay.ArifpayService
|
||||||
santimpaySvc *santimpay.SantimPayService
|
santimpaySvc *santimpay.SantimPayService
|
||||||
|
|
@ -78,6 +80,7 @@ type Handler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
|
enetPulseSvc *enetpulse.Service,
|
||||||
telebirrSvc *telebirr.TelebirrService,
|
telebirrSvc *telebirr.TelebirrService,
|
||||||
arifpaySvc *arifpay.ArifpayService,
|
arifpaySvc *arifpay.ArifpayService,
|
||||||
santimpaySvc *santimpay.SantimPayService,
|
santimpaySvc *santimpay.SantimPayService,
|
||||||
|
|
@ -115,6 +118,7 @@ func New(
|
||||||
mongoLoggerSvc *zap.Logger,
|
mongoLoggerSvc *zap.Logger,
|
||||||
) *Handler {
|
) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
|
enetPulseSvc: enetPulseSvc,
|
||||||
telebirrSvc: telebirrSvc,
|
telebirrSvc: telebirrSvc,
|
||||||
arifpaySvc: arifpaySvc,
|
arifpaySvc: arifpaySvc,
|
||||||
santimpaySvc: santimpaySvc,
|
santimpaySvc: santimpaySvc,
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
|
|
||||||
func (a *App) initAppRoutes() {
|
func (a *App) initAppRoutes() {
|
||||||
h := handlers.New(
|
h := handlers.New(
|
||||||
|
a.enetPulseSvc,
|
||||||
a.telebirrSvc,
|
a.telebirrSvc,
|
||||||
a.arifpaySvc,
|
a.arifpaySvc,
|
||||||
a.santimpaySvc,
|
a.santimpaySvc,
|
||||||
|
|
@ -268,6 +269,9 @@ func (a *App) initAppRoutes() {
|
||||||
tenant.Get("/top-leagues", h.GetTopLeagues)
|
tenant.Get("/top-leagues", h.GetTopLeagues)
|
||||||
tenant.Put("/events/:id/settings", h.UpdateEventSettings)
|
tenant.Put("/events/:id/settings", h.UpdateEventSettings)
|
||||||
|
|
||||||
|
//EnetPulse
|
||||||
|
groupV1.Get("/odds/pre-match", h.GetPreMatchOdds)
|
||||||
|
|
||||||
// Leagues
|
// Leagues
|
||||||
tenant.Get("/leagues", h.GetAllLeagues)
|
tenant.Get("/leagues", h.GetAllLeagues)
|
||||||
tenant.Put("/leagues/:id/set-active", h.SetLeagueActive)
|
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